C# 使用Win32API:结构内的联合生成TypeLoadException
我想导入Win32API的外部函数 API中的代码(在C中)如下所示:C# 使用Win32API:结构内的联合生成TypeLoadException,c#,c,winapi,structure,unions,C#,C,Winapi,Structure,Unions,我想导入Win32API的外部函数 API中的代码(在C中)如下所示: typedef struct _BLUETOOTH_ADDRESS { union { BTH_ADDR ullLong; BYTE rgBytes[6]; }; } BLUETOOTH_ADDRESS; [StructLayout(LayoutKind.Explicit, Size = 8)] public struct BLUETOOTH_ADDRESS { [FieldOffs
typedef struct _BLUETOOTH_ADDRESS {
union {
BTH_ADDR ullLong;
BYTE rgBytes[6];
};
} BLUETOOTH_ADDRESS;
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct BLUETOOTH_ADDRESS
{
[FieldOffset(0)]
public ulong ullLong;
[FieldOffset(2)]
public byte[] rgBytes;
};
我的C#实现如下所示:
typedef struct _BLUETOOTH_ADDRESS {
union {
BTH_ADDR ullLong;
BYTE rgBytes[6];
};
} BLUETOOTH_ADDRESS;
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct BLUETOOTH_ADDRESS
{
[FieldOffset(0)]
public ulong ullLong;
[FieldOffset(2)]
public byte[] rgBytes;
};
问题是:我一创建结构,它就会抛出一个TypeLoadException,错误代码:
System.TypeLoadException:“无法从程序集'BleLab,版本=1.0.0,区域性=neutral,PublicKeyToken=null'加载类型'BLUETOOTH_ADDRESS',因为它包含偏移量2处的对象字段,该字段未正确对齐或与非对象字段重叠。”
你有没有办法解决这个问题或者问题出在哪里
致意
编辑:
忘记提供呼叫方式:
var ba = new Win32API.BLUETOOTH_ADDRESS();
ba.rgBytes = new byte[6];
试图宣布这是一个联盟是毫无意义的。它是一种无符号的64位类型。只需使用
ulong
而不是struct
如果不需要显示地址,则只需选择ulong
的前6个字节。蓝牙地址是48位的值,因此是6个字节
但是,出于您的目的,尝试在用于互操作的类型中表达这种细微差别并没有什么好处。这就是为什么我建议使用
ulong
进行互操作,并在必要时选择有意义的字节作为单独的操作 试图宣布这是一个联盟是毫无意义的。它是一种无符号的64位类型。只需使用ulong
而不是struct
如果不需要显示地址,则只需选择ulong
的前6个字节。蓝牙地址是48位的值,因此是6个字节
但是,出于您的目的,尝试在用于互操作的类型中表达这种细微差别并没有什么好处。这就是为什么我建议使用
ulong
进行互操作,并在必要时选择有意义的字节作为单独的操作 为了帮助您理解错误,请注意以下几点:
rgBytes
的偏移量应该使用[FieldOffset(0)]
,而不是[FieldOffset(2)]
rgBytes
成员的类型是一个6字节的固定数组。在C#struct中,它是一种byte[]
数组类型。C#中的(普通)数组类型是一种“引用类型”,可以将其视为类似于C指针。也就是说,对象只持有一个指向堆上某个值的引用(指针)fixed
关键字创建固定数组,如下所示:
固定字节rgBytes[6]代码>
固定数组是不安全的代码,因此需要声明上述不安全。它也在结构中声明为public
,因此rgBytes
成员的完整声明可以如下所示:
公共不安全固定字节rgBytes[6]代码>
BLUETOOTH\u地址
给出了以下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
,尤其是这样可以避免任何“不安全”的代码。要帮助您理解错误,请注意以下几点:
rgBytes
的偏移量应该使用[FieldOffset(0)]
,而不是[FieldOffset(2)]
rgBytes
成员的类型是一个6字节的固定数组。在C#struct中,它是一种byte[]
数组类型。C#中的(普通)数组类型是一种“引用类型”,可以将其视为类似于C指针。也就是说,对象只持有一个指向堆上某个值的引用(指针)fixed
关键字创建固定数组,如下所示:
固定字节rgBytes[6]代码>
固定数组是不安全的代码,因此需要声明上述不安全。它也在结构中声明为public
,因此rgBytes
成员的完整声明可以如下所示:
公共不安全固定字节rgBytes[6]代码>
BLUETOOTH\u地址
给出了以下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
,特别是这样可以避免任何“不安全”的代码。你知道什么是C联盟吗?我试图理解你知道什么是C联盟吗?我试图理解谢谢你!我不知道是否可以只写ulong
。它现在起作用了!非常感谢。我不知道是否可以只写ulong
。它现在起作用了!这确实是解决问题的错误方法。如果要启用对有意义的6个字节的访问,请使用访问方法。不安全的代码,显式的布局,固定的,所有不必要的复杂性都是徒劳的。@DavidHeffernan-True,正如我在回答中提到的,OP最好避免不安全的代码,但在OP最初尝试将C联盟成员转换为C#结构时,对错误进行更正仍然是合理的。当蓝牙地址实际上是一个6字节的序列时,将其视为一个ulong
值也存在端点问题。这确实是解决问题的错误方法。如果要启用对有意义的6个字节的访问,请使用访问方法。不安全的代码,显式的布局,固定的,所有不必要的复杂性都是徒劳的。@DavidHeffernan-True,正如我在回答中提到的,OP可能最好避免不安全的代码,但对中的错误进行更正仍然是合理的