2

I am trying to use C# to use a C++ library that includes a struct that is documented as being laid out like this:

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;

Ideally I would like to implement something like this:

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;
    }
}

Of course I can't use FieldOffset or MarshalAs on structs, but I am at a loss as to how to implement this. If anybody has some ideas how to implement this in C# I would appreciate it.

Thanks!

bmprovost
  • 23
  • 1
  • 3

2 Answers2

2

[FieldOffset] is fine on struct fields. But your declaration just has nested types (note that in the C++ code, the structs are actually anonymous, but used to declare a new field...your C# code just declares a named struct, but no actual field). Note that you will also need to include [StructLayout(LayoutKind.Explicit)], as well as provide offsets for all fields in a struct.

Try something like this:

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;
}
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
1

You certainly can use FieldOffset and that is the answer. But you neeed to define the union as a distinct type.

Define each struct in the usual way. I'm going to assume you know how to do this.

Then define the union:

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

Finally put it all together:

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

The key is always to make the union a distinct type and use a field offset of zero for every member.

FWIW, C++ long on Windows is a signed 32 bit integer. That's int in C#.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490