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