将结构的C ++联合转换为C#

时间:2014-10-15 19:20:38

标签: c# c++ struct pinvoke unions

我正在尝试使用C#来使用包含一个结构的C ++库,该结构被记录为如下所示:

struct {
    long outervar;
    long othervar;
    union {
        struct {
            long a;
        } firststruct;
        struct {
            long p;
            long q;
            long r;
            long s;
        } secondstruct;
        struct {
            long x;
            long y;
            long z;
        } thirdstruct;
    } myunion;
} outerstruct;

理想情况下,我想实现类似的东西:

struct outerstruct
{
    UInt32 outervar;
    UInt32 othervar;
    [FieldOffset(0)]
    struct firststruct
    {
        UInt32 a;
    }
    [FieldOffset(0)]
    struct secondstruct
    {
        UInt32 p;
        UInt32 q;
        UInt32 r;
        UInt32 s;   
    }
    [FieldOffset(0)]
    struct thirdstruct
    {
        UInt32 x;
        UInt32 y;
        UInt32 z;
    }
}

当然我不能在结构上使用FieldOffset或MarshalAs,但我不知道如何实现它。如果有人有一些想法如何在C#中实现这一点我会很感激。

谢谢!

2 个答案:

答案 0 :(得分:2)

[FieldOffset]在struct 字段上没问题。但是你的声明只有嵌套类型(请注意,在C ++代码中,结构实际上是匿名的,但用于声明一个新字段......你的C#代码只声明了一个名为结构,但没有实际领域)。请注意,您还需要包含[StructLayout(LayoutKind.Explicit)],并为结构中的所有字段提供偏移量。

尝试这样的事情:

struct firststruct
{
    UInt32 a;
}

struct secondstruct
{
    UInt32 p;
    UInt32 q;
    UInt32 r;
    UInt32 s;
}

struct thirdstruct
{
    UInt32 x;
    UInt32 y;
    UInt32 z;
}

[StructLayout(LayoutKind.Explicit)]
struct union
{
    [FieldOffset(0)]
    firststruct firststruct;
    [FieldOffset(0)]
    secondstruct secondstruct;
    [FieldOffset(0)]
    thirdstruct thirdstruct;
}

struct outerstruct
{
    UInt32 outervar;
    UInt32 othervar;
    union union;
}

答案 1 :(得分:1)

你当然可以使用FieldOffset,这就是答案。但是你需要将联合定义为一种独特的类型。

以通常的方式定义每个结构。我会假设你知道如何做到这一点。

然后定义联合:

    [StructLayout(LayoutKind.Explicit)]
public struct MyUnion
{
    [FieldOffset(0)]
    public FirstStruct firststruct;
    [FieldOffset(0)]
    public SecondStruct secondstruct;
    [FieldOffset(0)]
    public ThirdStruct thirdstruct;
}

最后把它们放在一起:

[StructLayout(LayoutKind.Sequential)]
public struct OuterStruct
{
    public int outervar;
    public int othervar;
    public MyUnion myunion;
}

关键是始终使联合成为一种不同的类型,并为每个成员使用零字段偏移量。

Windows上的FWIW,C ++ long是带符号的32位整数。那是C#中的int