We help IT Professionals succeed at work.

Pointers to C++ unions/structs in C#

EJPanyard
EJPanyard asked
on
1,047 Views
Last Modified: 2013-12-14
Does anyone know how to map the following C++ union/structs into a C# struct? I am unable to force the String member to align with the numeric and bool members.  The C# compiler forces an offset of 8 bytes for the String member.  If anyone has an idea of how I can delclare these unions in C# please give an example.

union bfdValueUnion {
    double Float;
    double Double;
    char* String;
    int Integer;
    unsigned char Boolean;
    };

typedef struct bfdValue {
    unsigned int Type;
    union bfdValueUnion Value;
    } bfdValue;
typedef union bfdValueUnion bfdValueUnion;
Comment
Watch Question

Commented:
An union is made in c# like this:

[System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]
struct TestExplicit
{
    [System.Runtime.InteropServices.FieldOffset(0)]
    public long lg;

    [System.Runtime.InteropServices.FieldOffset(0)]
    public int i1;

    [System.Runtime.InteropServices.FieldOffset(4)]
    public int i2;

    [System.Runtime.InteropServices.FieldOffset(8)]
    public double d;

    [System.Runtime.InteropServices.FieldOffset(12)]
    public char c;

    [System.Runtime.InteropServices.FieldOffset(14)]
    public byte b;
}

I have to go..I finish later if nobody has answered :)

Author

Commented:
That's close to what I have but the C# compiler will not allow char* to be aligned with an int or a double.  Is there anyway to force it.  Here is what have but I'm forced to set the offset for the char* to eight bytes which does not match the c++ structures so the calls fails

       [StructLayout(LayoutKind.Explicit)]
        public struct bfdValueUnion
        {    
            [FieldOffset(0)]
            public double Float;
            [FieldOffset(0)]
            public double Double;
            [FieldOffset(8),MarshalAs(UnmanagedType.LPStr)]
            public string String;
            [FieldOffset(0)]
            public int Integer;
            [FieldOffset(0)]
            public bool Boolean;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct bfdValue
        {
            [FieldOffset(0)]
            public int Type;
            [FieldOffset(0)]
            public bfdValueUnion Value;
        }

Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
I don't know why you need the union in C# but if you only need it for passing it to a C function you might consider using it as an xml string, e. g. like

<?xml version="1.0"?>
<.DOCTYPE bfd >
<bfd type="Double">12.345</bfd>

and pass that string as a char array to the dll. There you easily could parse it and fill the appropriate members of the bfdValue struct..

Regards, Alex

Author

Commented:
Hi,

Here is what I finally did that worked thanks for the input.  I'm splitting the points here but this is the ONLY way the I could get C# and the CLR to align the float, int, bool, with char* in the same struct.  I'm giving the points because the suggestion helped me solve the problem.  I could not change the C++ code and the whole reason I did this is so that I can call these dlls from C#. Thanks for the input.

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct bfdValueUnion
        {

    //      union bfdValueUnion {
    //      double Float;
    //      double Double;
    //      bfdStringPtr String;
    //      int Integer;
    //      unsigned char Boolean;
    //};  
       
            [FieldOffset(0)]
            public double Float;
            [FieldOffset(0)]
            public double Double;
            [FieldOffset(0), MarshalAs(UnmanagedType.LPStr)] //
            public IntPtr String;
            [FieldOffset(0)]
            public Int32 Integer;
            [FieldOffset(0)]
            public bool Boolean;

        }

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct bfdValue
        {

            //      typedef struct bfdValue {
            //      unsigned int Type;
            //      union bfdValueUnion Value;
            //      } bfdValue;



            [FieldOffset(0)]
            public UInt32 Type;
            [FieldOffset(8)]
            public bfdValueUnion Value;

        }

 To use string in C# do the following:

        string str = Marshal.PtrToStringAnsi(aValLst[nIndex].Value.String);

Author

Commented:
Here is what I finally did that worked thanks for the input.  I'm splitting the points here but this is the ONLY way the I could get C# and the CLR to align the float, int, bool, with char* in the same struct.  I'm giving the points because the suggestion helped me solve the problem.  I could not change the C++ code and the whole reason I did this is so that I can call these dlls from C#. Thanks for the input.

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct bfdValueUnion
        {

    //      union bfdValueUnion {
    //      double Float;
    //      double Double;
    //      bfdStringPtr String;
    //      int Integer;
    //      unsigned char Boolean;
    //};  
       
            [FieldOffset(0)]
            public double Float;
            [FieldOffset(0)]
            public double Double;
            [FieldOffset(0), MarshalAs(UnmanagedType.LPStr)] //
            public IntPtr String;
            [FieldOffset(0)]
            public Int32 Integer;
            [FieldOffset(0)]
            public bool Boolean;

        }

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct bfdValue
        {

            //      typedef struct bfdValue {
            //      unsigned int Type;
            //      union bfdValueUnion Value;
            //      } bfdValue;



            [FieldOffset(0)]
            public UInt32 Type;
            [FieldOffset(8)]
            public bfdValueUnion Value;

        }

 To use string in C# do the following:

        string str = Marshal.PtrToStringAnsi(aValLst[nIndex].Value.String);
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.