c# - 如何将带有 unsigned char* 的结构从 C# 传递到 C++?

标签 c# c++ marshalling

我有一些带有结构描述和一些方法的 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/

相关文章:

c++ - 轮廓字体上下颠倒 - glOrtho() 设置不正确

python - 在 Schema 定义后注册 post_load 钩子(Hook)?

c# - 在组合框中填充数据源驱动程序名称

c# - Google Code Jam 2013 R1B-坠落的钻石

c++ - 如何在跨平台 C++ 或 C 中获取 U 盘的挂载点/磁盘驱动器?

C++仿函数编译错误

c# - 如何在 C# 中编码(marshal) IntPtr 的异常

用于 C 结构和函数的 C# 编码

c# - 遮蔽元素名称改变ID

c# - 在 C# 中,我如何安全地退出带有 try catch block 的锁?