如何将带有unsigned char *的struct从C#传递给C ++?

我有一些带有struct描述的C ++ dll和一些方法:

struct MSG_STRUCT { unsigned long dataSize; unsigned char* data; } 

并且function例如:

 unsigned long ReadMsg( unsigned long msgId, MSG_STRUCT* readMsg) { readMsg->dataSize = someDataSize; readMsg->data = someData; } 

所以我想从C#中调用这个函数:

 [StructLayout(LayoutKind.Sequential)] struct MSG_STRUCT { UInt32 dataSize; byte[] data; } [DllImport("mydll.dll")] public static Int32 ReadMsg( UInt32 msgId, ref MSG_STRUCT readMsg); 

所以我试着调用C#函数:

 var readMsg = new MSG_STRUCT(); readMsg.data = new byte[4128]; Int32 res = ReadMsg( someMsgId, ref readMsg); 

但是我的数据并没有正常。 我也尝试用IntPrt类型参数调用ReadMsg ,但Marshal.PtrToStructure有时给了我AccessViolationException

我没有任何想法如何将指向MSG_STRUCT的指针从C#传递给C ++并将结果作为填充的MSG_STRUCT.data接收

最终解决方案对我有用我使用了xanatos提供的解决方案的一部分:我为我的DllImport函数设置了CallingConvention = CallingConvention.Cdecl 。 我发现我还需要改变:

 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4128)] public byte[] Data; 

谢谢大家的帮助

你可以尝试:

 [StructLayout(LayoutKind.Sequential)] public struct MSG_STRUCT { int dataSize; IntPtr data; public byte[] GetData() { var bytes = new byte[dataSize]; Marshal.Copy(data, bytes, 0, dataSize); return bytes; } } [DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)] public static extern uint ReadMsg(uint msgId, ref MSG_STRUCT readMsg); 

然后:

 MSG_STRUCT msg = new MSG_STRUCT(); uint res = ReadMsg(123, ref msg); byte[] bytes = msg.GetData(); 

您的C函数正在重新分配data指针,因此您必须将其编组回C#。 最简单的方法(对我来说)就是简单地传递一个IntPtr并做一些显式的Marshal.Copy(...)

另一种方法是让databyte[] ,但是在C端你需要memcpy(readMsg->data, someData, someDataSize)而不是简单地分配readMsg->data = someData

尝试更改属性

 [StructLayout(LayoutKind.Sequential)] 

 [StructLayout(LayoutKind.Sequential, Pack=X)] 

其中X是1,2,4,8 ..

c ++中的默认打包为8,因此请尝试设置Pack = 8