[C#-Windows]解决 C# 中使用联合体的问题(因为它在0偏移位置处包含一个对象字段...)

[C#-Windows]解决 C# 中使用联合体的问题(因为它在0偏移位置处包含一个对象字段...)

问题

开发的程序会使用到Windows api,因为在C 中开发图形界面程序有点麻烦,所以改为了C# ,但是这个api 里有一个数据是以联合体存储的,C# 的联合体又有一些限制。

public struct Anonymous_d34c77ee_53b2_47a5_a97c_d5c2b29c8ee3 {

    /// RAWMOUSE->tagRAWMOUSE
    [System.Runtime.InteropServices.FieldOffset(0)]
    public TagRAWMOUSE mouse;

    /// RAWKEYBOARD->tagRAWKEYBOARD
    [System.Runtime.InteropServices.FieldOffset(0)]
    public TagRAWKEYBOARD keyboard;

    /// RAWHID->tagRAWHID
    [System.Runtime.InteropServices.FieldOffset(0)]
    public TagRAWHID hid;
}

产生的错误的信息是

...因为他在0偏移位置处包含一个对象字段,该字段由一个非对象字段不正确地对齐或重叠。

经过测试,联合体如果都是一些简单类型,比如整形之类的,就没有问题。如果是这种复杂类型,就不行。

解决

耽搁了很长时间,一直想不到解决办法,有一天,突然开窍了,我把整个结构体拆成三个正常的、没有联合体地结构体不就行了,反正是操作那一片地址,如何解释还不是我说了算吗。

//原本长这样
public struct TagRAWINPUT {

    /// RAWINPUTHEADER->tagRAWINPUTHEADER
    public TagRAWINPUTHEADER header;

    /// Anonymous_d34c77ee_53b2_47a5_a97c_d5c2b29c8ee3
    public Anonymous_d34c77ee_53b2_47a5_a97c_d5c2b29c8ee3 data;
}
//改成这样
public struct TagRAWINPUTONE {
    public TagRAWINPUTHEADER header;
}

仅通过后面的header就能够了解后面的联合体具体存储地是哪一个数据,是mouse,还是keyboard,还是hid。

//原本
TagRAWINPUT rawInput = Marshal.PtrToStructure(dataBuffer);
//新的
TagRAWINPUTONE rawInputOne = Marshal.PtrToStructure(dataBuffer);

因为TagRAWINPUTONE 没有联合体,所以这段代码执行没有任何问题。根据header 判断联合体的类型,然后在通过Marshal 获取真正的结构体。

比如这个联合体存储的是TagRAWMOUSE ,那就把结果转换成TagRAWINPUT1

//另外两个以此类推
public struct TagRAWINPUT1 {

    /// RAWINPUTHEADER->tagRAWINPUTHEADER
    public TagRAWINPUTHEADER header;

    /// Anonymous_d34c77ee_53b2_47a5_a97c_d5c2b29c8ee3
    public TagRAWMOUSE mouse;
}
TagRAWINPUT1 raw = Marshal.PtrToStructure(dataBuffer);

你可能感兴趣的:([C#-Windows]解决 C# 中使用联合体的问题(因为它在0偏移位置处包含一个对象字段...))