正在将指向C#结构的指针发送到C++DLL中

Sending pointer to C# struct into C++ DLL

本文关键字:指针 C++DLL 结构      更新时间:2023-10-16

我在DLL中有一个C++函数,它取一个指向结构JPInfo的指针,该函数中填充了从服务器接收的数据,C++结构的布局如下所示:

typedef struct JP
{
    unsigned char type;
    DWORD value;
} JP;
typedef struct JPInfo
{
    JP jps[3];
    _int16 ConT;
    _int16 CallT;
    unsigned char ret;
    unsigned char count;
    unsigned char JPOffset;
    unsigned char JPPeriod;
} JPInfo;

函数在DLL中导出如下:

__declspec(dllexport) DWORD __stdcall GetJPInfo(JPInfo* jpi, DWORD time);

该函数使用一个指向JPInfo结构的指针,我曾尝试在C#中模拟这个结构

[StructLayout(LayoutKind.Sequential, Size = 5), Serializable]
public struct JP
{
    byte type;
    int value;
}
[StructLayout(LayoutKind.Sequential,Size=23),Serializable]
public struct JPInfo
{
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}

我尝试从C#调用函数,如下所示:

[DllImport("DLLImp.dll")]
    unsafe public static extern int GetJP(ref JPInfo jpi, int time);
// then in main...
JPInfo jpi = new JPInfo;
GetJackpotValues(ref jpi, 4000);

我得到了一个类型为"System.ExecutionEngineException"的未处理异常。我的JPInfo结构中不能有一个固定大小的JP结构数组,所以我不知道如何处理这个问题。

谢谢。

您是否尝试删除结构上的Size属性?做类似的事情时,我不必指定大小。对于您的数组属性,请尝试将其归因为:

[StructLayout(LayoutKind.Sequential)]
public struct JPInfo
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}

假设C++结构是打包的,那么您的C#结构应该是这样的:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct JP
{
    byte type;
    uint value;
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct JPInfo
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}

另一方面,如果它们没有打包,则将Pack参数移除到StructLayout属性中。您应该在C++头文件中查找#pragma pack语句,以了解C++结构是否已打包。

我猜C++结构是打包的,因为您说过它们被映射到从服务器接收的数据上。

你的进口应该是这样的:

[DllImport("DLLImp.dll")]
public static extern uint GetJP(ref JPInfo jpi, uint time);

DWORD翻译成uint而不是int,这里不需要不安全的代码。