如何将带有 unsigned char* 的结构从 C# 传递到 C++?
Posted
技术标签:
【中文标题】如何将带有 unsigned char* 的结构从 C# 传递到 C++?【英文标题】:How to pass struct with unsigned char* from C# to C++? 【发布时间】:2016-03-18 08:43:05 【问题描述】:我有一些带有结构描述和一些方法的 C++ dll:
struct MSG_STRUCT
unsigned long dataSize;
unsigned char* data;
还有函数举例:
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;
感谢大家的帮助
【问题讨论】:
"但我的数据并不正常。"你得到了什么,你期待什么?数据应该是字符串还是字节数组? 数据应该是字节数组。 【参考方案1】:你可以试试:
[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
。
【讨论】:
【参考方案2】:尝试改变属性
[StructLayout(LayoutKind.Sequential)]
到
[StructLayout(LayoutKind.Sequential, Pack=X)]
其中 X 是 1,2,4,8 ..
c++中默认packing是8,所以尽量设置Pack = 8
【讨论】:
我已经编辑了我的答案。它可能取决于 C++ 和 C# 中不同的结构封装。以上是关于如何将带有 unsigned char* 的结构从 C# 传递到 C++?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 const char* 转换为 unsigned int c++
SWIG 将 unsigned char* 转换为 20 字节缓冲区 Java 结构