Passing pointer to pointer of array of structure from C# to C++

五迷三道 提交于 2021-02-17 00:01:12

问题


I want to pass pointer to pointer of an array of structure from C# to C++. With following code I only get the first element in c++, second and third element of the array is not passed. Why? Also, tried using StructureToPtr but didn't help. What I am doing wrong?

C++ code

 struct structure 
{
   short ps;

};
   __declspec(dllexport)short Testmethod(structure** aa)
    {
     if (aa!= 0 && aa[0]->ps == 26 && aa[1]->ps == 27)
     {          
        return 1;
      }    
      return  0;
    }

C# code

[DllImport("Wrapper.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern short Testmethod(ref IntPtr a);

     [StructLayout(LayoutKind.Sequential)]           
     public struct SampleStructure
    {
       public short ps;

    };

 SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
                        GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);
                        IntPtr ptr = gch.AddrOfPinnedObject();
                        ret = Testmethod(ref ptr);

I can't change c++ code, I don't have access to it. If change c++ code as either one of the following ways, it works. How can I make it without changing the c++ code? Updates:

Way 1: works if I change the c++ code. But I can't change the C++ code. It's not my code.

C++ Code

__declspec(dllexport)short Testmethod(structure* aa)

C# Code

            fixed (SampleStructure* pArray = dataInformation)
            {
                ret = Testmethod(pArray);
            }

Way 2: works if I change the c++ code. But I can't change the C++ code. It's not my code.

C++ Code

__declspec(dllexport)short Testmethod(structure Getcsharpval[], int size)

c# code

 public unsafe static extern short Testmethod([MarshalAs(UnmanagedType.LPArray,SizeParamIndex=3)] SampleStructure[] array);
 SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
 ret = Testmethod( data);

回答1:


I think your c function have wrong proto. Try:

_declspec(dllexport)short Testmethod(structure* aa)
{

    if (aa != 0
       && aa[0].ps == 26 && aa[1].ps == 27)

    {
        return 1;
    }

    return 0;
}

In your c# sample you have an array of struct. The array is a reference type, and you correct need to pin the memory. The array is a sequence in memory of struct that are value type (and don't need pin). So in the array you don't have pointer but direcly the struct.




回答2:


You need to pass IntPtr[] to the C++ code.

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern short Testmethod(IntPtr[] aa)

Allocate an IntPtr[] array and populate it. Do so either by pinning each structure and using the address of the pinned object. Or do so with Marshal.StructureToPtr. If you use the latter, you have to deallocate the unmanaged memory after calling.




回答3:


Okay, I solved by creating the pointer to pointers of structures using the following code.

    [DllImport("Wrapper.dll", CallingConvention = CallingConvention.StdCall)]
    public unsafe static extern short Testmethod (SampleStructure** passstructurepointer);

     unsafe
            {
                fixed(SampleStructure** p2p = new SampleStructure*[3])
                {
                    for (short i = 0; i < 3; i++)
                    {
                        var a = stackalloc SampleStructure[1];
                        a->ps = i;
                        p2p[i] = a;
                    }
                    var s= Testmethod(p2p);
                }
            }


来源:https://stackoverflow.com/questions/36093750/passing-pointer-to-pointer-of-array-of-structure-from-c-sharp-to-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!