如何将C结构转换为托管C#等价物

时间:2017-01-26 21:02:29

标签: c# callback delegates interop unmanaged

我在C中有以下结构(示例):

typedef struct 
{
     int64      data_size;
     uint32      avgdelay;   
     int         esize;      
     void       *epayload;  
} stats_t;

托管C#等价物如下:

[StructLayout(LayoutKind.Sequential, Size = 4)]
public struct stats_t
{
    public Int64 datasize;

    public UInt32 avgdelay;

    public Int32 esize;

    public IntPtr epayload;

}

当在调用的回调委托中使用stats_t类型的参数时,我发现有必要包含一个虚拟的UInt32成员,以便能够通过委托调用回调,以保留回调签名的字节模式

[StructLayout(LayoutKind.Sequential, Size = 4)]
public struct stats_t
{
    public Int64 datasize;

    public UInt32 avgdelay;

    public Int32 esize;

    public IntPtr epayload;

    /// dummy member for alignment
    public UInt32 dummy;

}

回调签名如下:

  int Callback_Proc( stats_t stats, void *user, int final, int error, int code);

回调的委托具有以下签名:

  public delegate int Callback_Proc(stats_t stats, IntPtr user, Int32 final, Int32 error, Int32 code);

我想知道为什么需要虚拟成员才能使回调起作用。在没有虚设的情况下, final 的值被转移到 error ,并且 error 的值被转移到 code 。 感谢您的理解,希望我的解释有意义。

1 个答案:

答案 0 :(得分:1)

那是因为IntPtr的大小。我假设你的C ++代码是64位编译的,所以C ++代码预期的void *指针大小是8个字节,但.net对32位有一个非常丑陋的偏好,如果你为AnyCPU编译,项目仍然有一个( stupid)标志在编译选项上命名为“Prefer 32 bits”,因此即使代码在64位机器上执行,它也将以32位运行,导致指针长度为4个字节。

从项目中删除“prefer 32 bits”或明确编译为x64,这应该可以解决您的问题。