我想导入Win32API的extern函数。
API中的代码(在C中)如下所示:
typedef struct _BLUETOOTH_ADDRESS {
union {
BTH_ADDR ullLong;
BYTE rgBytes[6];
};
} BLUETOOTH_ADDRESS;
我的C#实现如下所示:
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct BLUETOOTH_ADDRESS
{
[FieldOffset(0)]
public ulong ullLong;
[FieldOffset(2)]
public byte[] rgBytes;
};
问题是:一旦我创建了struct,它就会抛出一个TypeLoadException,错误代码: System.TypeLoadException:“无法从程序集'BleLab,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'加载类型'BLUETOOTH_ADDRESS',因为它包含偏移2处的对象字段,该字段未正确对齐或重叠对象字段。“
你有任何想法解决这个问题或问题所在吗?
祝你好运
修改 忘了提供通话方式:
var ba = new Win32API.BLUETOOTH_ADDRESS();
ba.rgBytes = new byte[6];
答案 0 :(得分:2)
试图宣布这是一个联盟真的没有意义。它是无符号的64位类型。只需使用ulong
而不是结构。
如果您永远不需要显示地址,那么您只需要选择ulong
的前6个字节。蓝牙地址是48位值,因此是6个字节。
但是出于您的目的,尝试用互操作类型表达细微差别是无法获得的。这就是为什么我建议使用ulong
进行互操作,并在必要时选择有意义的字节作为单独的操作。
答案 1 :(得分:1)
为帮助您了解错误,请注意以下事项:
C union类型的所有成员都有重叠存储,从偏移量0开始,因此C#结构中成员rgBytes
的偏移量应使用[FieldOffset(0)]
,而不是[FieldOffset(2)]
C union中rgBytes
成员的类型是一个6字节的固定数组。在C#struct中,它是byte[]
数组类型。 C#中的(普通)数组类型是“引用类型”,可以认为它类似于C指针。也就是说,对象只保存对堆上值的引用(指针)。
您可以使用fixed
关键字创建固定数组,如下所示:
fixed byte rgBytes[6];
固定数组是不安全的代码,因此上面需要声明unsafe
。它在结构中也声明为public
,因此rgBytes
成员的完整声明如下:
public unsafe fixed byte rgBytes[6];
将所有内容放在一起为BLUETOOTH_ADDRESS
提供以下C#声明:
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct BLUETOOTH_ADDRESS
{
[FieldOffset(0)]
public ulong ullLong;
[FieldOffset(0)]
public unsafe fixed byte rgBytes[6];
};
您可以省略Size = 8
部分。
根据David Heffernan的回答,你最好只使用ulong
,特别是因为这样可以避免任何“不安全”的代码。