poco
poco

Reputation: 3005

How do I convert c struct from dll to C#

I am converting a application from c++ to C# and have a question about the proper way to handle importing structs. I am attempting to convert a struct from a c dll into c# The struct in c looks like this

typedef struct card_info
{
  ushort r;
  ushort s;
  enum_a a;
  usinged long ul;
  ushort n;
  ushort* b;
  ushort id;
} CARD_INFO;

when i use [StructLayout(LayoutKind.Sequentaial)] the size of the array is 20 bytes in c#. However, if take a look at my working c++ code it is 24 bytes. I changed my c# to look like this:

[StructLayout(LayoutKind.Explicit)]
public struct CardInfo
{
  [FieldOffset(0) public ushort r;
  [FieldOffset(2) public ushort s;
  [FieldOffset(4) public EnumA a;
  [FieldOffset(8) public ushort ul;
  [FieldOffset(12) public ushort n;
  [FieldOffset(16) public UInt32 b;
  [FieldOffset(20) public ushort id;
}

This seems to compile but I'm not convinced this is the correct way to go about doing this. Please let me know if this is correct or if there is a better way.

Thanks

Upvotes: 1

Views: 1655

Answers (3)

Mark H
Mark H

Reputation: 13907

@Hans's answer is correct, but I'll just add some tips on debugging marshalled data so you can see the results. I just instantiate a structure and create a pointer to it like this.

CardInfo cardInfo = new CardInfo();
IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(cardInfo));
Marshal.StructureToPtr(cardInfo, pointer, false);

Stick a breakpoint on the last line of this and step into the debugger until it breaks. You should see the pointer in the locals/autos windows, and it's value should be some int value. (Hex display works best here).

Img1

Move over to the Command window, and type dc 0x0086bf30 <- the address of your pointer. It should dump out the data in that are of memory. Typing dc again will dump the next chunks of memory. You can also use da, db, dd, df, dq to dump the data as different types. Try stepping over the breakpoint next (F10), and dump the same memory again.

Img2

You can initialize the fields of your struct with particular values and observe the changes here to see if it's working as it should.

Upvotes: 1

Hans Passant
Hans Passant

Reputation: 942348

usinged long ul;

It's a typo, but that definitely isn't a ushort, it's an uint.

Don't use FieldOffset either, let the compiler figure it out. Now Marshal.SizeOf() will return 24, the proper amount of padding is inserted. The b member should be IntPtr btw.

Upvotes: 4

Sapph
Sapph

Reputation: 6208

ul is an unsigned long in the C implementation but you're using an unsigned short. That would be a good place to start, if you're wondering why your StructLayout.Sequential implementation is too small.

I'd also double check your EnumA implementation to make sure it's the right size.

Upvotes: 0

Related Questions