c# 调用 c++ dll 传机构体指针问题?

时间:2021-07-21 10:30:59
//c++ 
struct STRTEST
{
   double s1;
   STRTEST *pNext;
};
extern "C" __declspec(dllexport) int Test1(PDATA* pFirst)
{
       PDATA *p=pFirst;
       int a=0;
       while(p->pNext!=NULL)
       {
         a++;
         p->s1=a;
p=p->pNext;
       }
       return a;
}

//c# 
    [DllImport("test.dll", CharSet = CharSet.Unicode)]
    public static extern int Test1( ref IntPtr ptr);

    [StructLayout(LayoutKind.Sequential)]
    public struct STRTEST
    {
        public double s1;
        public IntPtr next;
    }
    public void test( int n )
    {
        STRTEST pFirst = new STRTEST();
        STRTEST pCur=pFirst;
        for(int i=0;i<n;i++)
        {
           if(i==0)
           {
              pCur.s1=i;
           }
           else
           {
             STRTEST pNext = new STRTEST();
             pNext.s1=i;
             IntPtr ptr = Marshal.AllocHGlobal(pNext); 
             Marshal.StructureToPtr(pNext, ptr, false);
             pCur.next=ptr; 
             pCur = pNext;
           }
        }
        IntPtr ptr1 = Marshal.AllocHGlobal(pFirst ); 
        Marshal.StructureToPtr(pFirst , ptr1, false);  
        n= Test1(ref ptr1 )
    }
 调用test(10)后提示“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
 请高手帮忙解决

5 个解决方案

#1


用unsafe代码,C#里也用指针去读。哈哈很强大~

#2


....PDATA是啥?STRTEST*么?
那么既然已经是指针了为啥还要PDATA*?你的函数里根本就不分配内存返回吧?
从你的Test1在c#里的声明来看如果STRTEST*是PDATA的话那就是一个双重指针(STRTEST**).
这样的话你C函数本身就是错的.LZ先把指针理清楚再说吧.

另外C函数默认调用规则是cdecl,DllImport默认是StdCall,必须在DllImport里指明

#3


不好意思,extern "C" __declspec(dllexport) int Test1(PDATA* pFirst)
写错了,应该是 extern "C" __declspec(dllexport) int Test1(STRTEST* pFirst)

#4


引用 3 楼 hanzhch1 的回复:
不好意思,extern "C" __declspec(dllexport) int Test1(PDATA* pFirst)
写错了,应该是 extern "C" __declspec(dllexport) int Test1(STRTEST* pFirst)
那应该就是调用规则的问题了.
C默认的cdecl是调用方负责恢复栈指针ESP,
DllImport默认的是被调用方负责恢复栈指针ESP.

#5


extern "C" __declspec(dllexport) int Test1(STRTEST* pFirst)
{
  STRTEST *p=pFirst;
  int a=0;
  while(p->pNext!=NULL)
  {
  a++;
  p->s1=a;
p=p->pNext;
  }
  return a;
}

//STRTEST 为单向链表

#1


用unsafe代码,C#里也用指针去读。哈哈很强大~

#2


....PDATA是啥?STRTEST*么?
那么既然已经是指针了为啥还要PDATA*?你的函数里根本就不分配内存返回吧?
从你的Test1在c#里的声明来看如果STRTEST*是PDATA的话那就是一个双重指针(STRTEST**).
这样的话你C函数本身就是错的.LZ先把指针理清楚再说吧.

另外C函数默认调用规则是cdecl,DllImport默认是StdCall,必须在DllImport里指明

#3


不好意思,extern "C" __declspec(dllexport) int Test1(PDATA* pFirst)
写错了,应该是 extern "C" __declspec(dllexport) int Test1(STRTEST* pFirst)

#4


引用 3 楼 hanzhch1 的回复:
不好意思,extern "C" __declspec(dllexport) int Test1(PDATA* pFirst)
写错了,应该是 extern "C" __declspec(dllexport) int Test1(STRTEST* pFirst)
那应该就是调用规则的问题了.
C默认的cdecl是调用方负责恢复栈指针ESP,
DllImport默认的是被调用方负责恢复栈指针ESP.

#5


extern "C" __declspec(dllexport) int Test1(STRTEST* pFirst)
{
  STRTEST *p=pFirst;
  int a=0;
  while(p->pNext!=NULL)
  {
  a++;
  p->s1=a;
p=p->pNext;
  }
  return a;
}

//STRTEST 为单向链表