如何使用unsigned char *将结构从C#传递到C ++? [英] How to pass struct with unsigned char* from C# to C++?
问题描述
我有一些结构描述和一些方法的 C ++ dll :
struct MSG_STRUCT {
unsigned long dataSize;
unsigned char * data;
}
并且功能例如:
$ b b
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的结果。数据
最终解决方案对我有用:
我使用xanatos提供的解决方案的一部分:
我为我的DllImport函数设置 CallingConvention = CallingConvention.Cdecl
。
我发现我还需要更改:
[MarshalAs(UnmanagedType.ByValArray,SizeConst = 4128)
public byte [] Data;感谢大家的帮助 你可以尝试: [StructLayout(LayoutKind。 Sequential)]
public struct MSG_STRUCT
{
int dataSize;
IntPtr数据;
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函数重新分配数据
指针,所以你必须把它回到C#。最简单的方法(对我来说)是简单地传递 IntPtr
并做一些明确的 Marshal.Copy(...)
。
另一种方法是使用 data
a byte []
,但是在C端你必须 memcpy(readMsg-> data,someData,someDataSize)
,而不是简单地赋值 readMsg- > data = someData
。
I have some C++ dll with struct description and some methods:
struct MSG_STRUCT {
unsigned long dataSize;
unsigned char* data;
}
And function for example:
unsigned long ReadMsg( unsigned long msgId, MSG_STRUCT* readMsg)
{
readMsg->dataSize = someDataSize;
readMsg->data = someData;
}
So I want to call this function from C#:
[StructLayout(LayoutKind.Sequential)]
struct MSG_STRUCT
{
UInt32 dataSize;
byte[] data;
}
[DllImport("mydll.dll")]
public static Int32 ReadMsg( UInt32 msgId, ref MSG_STRUCT readMsg);
So I tried to call C# function like:
var readMsg = new MSG_STRUCT();
readMsg.data = new byte[4128];
Int32 res = ReadMsg( someMsgId, ref readMsg);
But I didn't get smth normal in data.
I also tried to call ReadMsg
with IntPrt
type parameter, but Marshal.PtrToStructure
gave me AccessViolationException
sometimes.
I don't have any ideas how to pass a pointer to MSG_STRUCT
from C# to C++ and receive the result as filled MSG_STRUCT.data
The final solutionthat worked for me:
I used a part of solution offered by xanatos:
I set CallingConvention = CallingConvention.Cdecl
for my DllImport function.
I found out that I also need to change:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4128)]
public byte[] Data;
Thanks everyone for your help
解决方案 You could try with:
[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);
and then:
MSG_STRUCT msg = new MSG_STRUCT();
uint res = ReadMsg(123, ref msg);
byte[] bytes = msg.GetData();
Your C function is reassigning the data
pointer, so you have to marshal it back to C#. The easiest way (for me) is to simply pass a IntPtr
and do some explicit Marshal.Copy(...)
.
An alternative is to have data
a byte[]
, but then in C-side you have to memcpy(readMsg->data, someData, someDataSize)
instead of simply assigning readMsg->data = someData
.
这篇关于如何使用unsigned char *将结构从C#传递到C ++?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!