如何将带有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(...)
。
另一种方法是让data
为byte[]
,但是在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