问题
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