我在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 。 感谢您的理解,希望我的解释有意义。
答案 0 :(得分:1)
那是因为IntPtr的大小。我假设你的C ++代码是64位编译的,所以C ++代码预期的void *指针大小是8个字节,但.net对32位有一个非常丑陋的偏好,如果你为AnyCPU编译,项目仍然有一个( stupid)标志在编译选项上命名为“Prefer 32 bits”,因此即使代码在64位机器上执行,它也将以32位运行,导致指针长度为4个字节。
从项目中删除“prefer 32 bits”或明确编译为x64,这应该可以解决您的问题。