【问题标题】:How to pass struct with unsigned char* from C# to C++?如何将带有 unsigned char* 的结构从 C# 传递到 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;

感谢大家的帮助

【问题讨论】:

  • "但我的数据并不正常。"你得到了什么,你期待什么?数据应该是字符串还是字节数组?
  • 数据应该是字节数组。

标签: c# c++ marshalling


【解决方案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(...)

另一种方法是使用databyte[],但是在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# 中不同的结构封装。
    猜你喜欢
    • 1970-01-01
    • 2012-11-16
    • 2011-07-05
    • 1970-01-01
    • 2023-03-17
    • 2019-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多