我有一些带有结构描述和一些方法的 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;
感谢大家的帮助
最佳答案
你可以试试:
[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
。
关于c# - 如何将带有 unsigned char* 的结构从 C# 传递到 C++?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36079751/