EJPanyard
asked on
Pointers to C++ unions/structs in C#
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;
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;
ASKER
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.E xplicit)]
public struct bfdValueUnion
{
[FieldOffset(0)]
public double Float;
[FieldOffset(0)]
public double Double;
[FieldOffset(8),MarshalAs( UnmanagedT ype.LPStr) ]
public string String;
[FieldOffset(0)]
public int Integer;
[FieldOffset(0)]
public bool Boolean;
}
[StructLayout(LayoutKind.E xplicit)]
public struct bfdValue
{
[FieldOffset(0)]
public int Type;
[FieldOffset(0)]
public bfdValueUnion Value;
}
[StructLayout(LayoutKind.E
public struct bfdValueUnion
{
[FieldOffset(0)]
public double Float;
[FieldOffset(0)]
public double Double;
[FieldOffset(8),MarshalAs(
public string String;
[FieldOffset(0)]
public int Integer;
[FieldOffset(0)]
public bool Boolean;
}
[StructLayout(LayoutKind.E
public struct bfdValue
{
[FieldOffset(0)]
public int Type;
[FieldOffset(0)]
public bfdValueUnion Value;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
<?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
ASKER
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.E xplicit, 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.LP Str)] //
public IntPtr String;
[FieldOffset(0)]
public Int32 Integer;
[FieldOffset(0)]
public bool Boolean;
}
[StructLayout(LayoutKind.E xplicit, 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(aV alLst[nInd ex].Value. String);
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.E
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.LP
public IntPtr String;
[FieldOffset(0)]
public Int32 Integer;
[FieldOffset(0)]
public bool Boolean;
}
[StructLayout(LayoutKind.E
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(aV
ASKER
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.E xplicit, 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.LP Str)] //
public IntPtr String;
[FieldOffset(0)]
public Int32 Integer;
[FieldOffset(0)]
public bool Boolean;
}
[StructLayout(LayoutKind.E xplicit, 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(aV alLst[nInd ex].Value. String);
[StructLayout(LayoutKind.E
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.LP
public IntPtr String;
[FieldOffset(0)]
public Int32 Integer;
[FieldOffset(0)]
public bool Boolean;
}
[StructLayout(LayoutKind.E
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(aV
[System.Runtime.InteropSer
struct TestExplicit
{
[System.Runtime.InteropSer
public long lg;
[System.Runtime.InteropSer
public int i1;
[System.Runtime.InteropSer
public int i2;
[System.Runtime.InteropSer
public double d;
[System.Runtime.InteropSer
public char c;
[System.Runtime.InteropSer
public byte b;
}
I have to go..I finish later if nobody has answered :)