C
calenlas
Hi all,
I'm taking my first steps into C# <--> C++ DLL Interop and
unfortunately I've run into (what seems to be) a very complicated case
as my first task. Perhaps someone here can help me.
I need to pass an array of RADIO_INFO2 structures to be filled by a
function in the DLL. This is how the structure is defined in the C++
example that comes with the DLL:
#pragma pack(1) // set byte packing
typedef struct {
unsigned __int32 bLength;
char szSerNum[9];
char szProdName[9];
unsigned __int64 MinFreq;
unsigned __int64 MaxFreq;
struct {
unsigned __int32 ExtRef:1;
unsigned __int32 FMWEnabled:1;
unsigned __int32 Reserved:30;
} Features;
} RADIO_INFO2;
#pragma pack() // set back the default packing
As you can see, there are a few obvious difficulties. First, the
nested Features struct. I think I've solved this by just defining
Features as a UInt32 and I'll handle the bit masking manually if I
need to. The second are the two char arrays. The DLL wants two 9
byte buffers to fill with character data while the marshalling code
wants to pass references. This brings me to the third problem, the
size of the structure. In C++ it's 42 bytes long: 32bits + 9bytes +
9bytes + 64bits + 64bits + 32bits = 42bytes. However, due to the
reference vs. value array problem the Marshalling code is coming up
with 32bytes: 32bits + 32bit (ref) + 32bit (ref) + 64bits + 64bits +
32bits = 32 bytes. The following is my best shot at describing this
structure in C#.
[StructLayout(LayoutKind.Sequential, Pack = 1,
CharSet = CharSet.Ansi)]
public struct RADIO_INFO2
{
public UInt32 bLength;
public Byte[] szSerNum;
public Byte[] szProdName;
public UInt64 MinFreq;
public UInt64 MaxFreq;
public UInt32 Features;
};
As stated above, this is the struct that gives me a
Marshalling.SizeOf() of 32 bytes. If, instead of the two Byte arrays,
I provide 18 individual Bytes, I get a matching size of 42 bytes, but
that seems like a heavy-handed work-around. Surely there's a Right
Way to do this.
Additionally, if instead of Byte arrays I define them as Char arrays,
I get an error from the Marshalling code complaining that the array
types don't match.
Just for reference, the actual call that consumes this struct looks
like:
[DllImport("WRG315API.DLL")]
public static extern UInt32 GetRadioList(ref RADIO_INFO2[]
lpRadioInfo,
UInt32 BufferSize,
ref UInt32 InfoSize);
Thanks in advance for any help that is offered.
Todd Pafford
(e-mail address removed)
I'm taking my first steps into C# <--> C++ DLL Interop and
unfortunately I've run into (what seems to be) a very complicated case
as my first task. Perhaps someone here can help me.
I need to pass an array of RADIO_INFO2 structures to be filled by a
function in the DLL. This is how the structure is defined in the C++
example that comes with the DLL:
#pragma pack(1) // set byte packing
typedef struct {
unsigned __int32 bLength;
char szSerNum[9];
char szProdName[9];
unsigned __int64 MinFreq;
unsigned __int64 MaxFreq;
struct {
unsigned __int32 ExtRef:1;
unsigned __int32 FMWEnabled:1;
unsigned __int32 Reserved:30;
} Features;
} RADIO_INFO2;
#pragma pack() // set back the default packing
As you can see, there are a few obvious difficulties. First, the
nested Features struct. I think I've solved this by just defining
Features as a UInt32 and I'll handle the bit masking manually if I
need to. The second are the two char arrays. The DLL wants two 9
byte buffers to fill with character data while the marshalling code
wants to pass references. This brings me to the third problem, the
size of the structure. In C++ it's 42 bytes long: 32bits + 9bytes +
9bytes + 64bits + 64bits + 32bits = 42bytes. However, due to the
reference vs. value array problem the Marshalling code is coming up
with 32bytes: 32bits + 32bit (ref) + 32bit (ref) + 64bits + 64bits +
32bits = 32 bytes. The following is my best shot at describing this
structure in C#.
[StructLayout(LayoutKind.Sequential, Pack = 1,
CharSet = CharSet.Ansi)]
public struct RADIO_INFO2
{
public UInt32 bLength;
public Byte[] szSerNum;
public Byte[] szProdName;
public UInt64 MinFreq;
public UInt64 MaxFreq;
public UInt32 Features;
};
As stated above, this is the struct that gives me a
Marshalling.SizeOf() of 32 bytes. If, instead of the two Byte arrays,
I provide 18 individual Bytes, I get a matching size of 42 bytes, but
that seems like a heavy-handed work-around. Surely there's a Right
Way to do this.
Additionally, if instead of Byte arrays I define them as Char arrays,
I get an error from the Marshalling code complaining that the array
types don't match.
Just for reference, the actual call that consumes this struct looks
like:
[DllImport("WRG315API.DLL")]
public static extern UInt32 GetRadioList(ref RADIO_INFO2[]
lpRadioInfo,
UInt32 BufferSize,
ref UInt32 InfoSize);
Thanks in advance for any help that is offered.
Todd Pafford
(e-mail address removed)