Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Porting C struct to C#

Tags:

c

c#

pinvoke

I'm Porting C code to C# and I have some doubts.

Consider this structure:

typedef struct
{
  uint32_t       w;
  uint32_t       h;
  uint32_t       f_cc;
  uint32_t       st;
  unsigned char *pl[4];
  int32_t        strd[4];
  void         (*done)(void *thisobj);
  void          *e_cc;
  uint32_t       rsrvd2;
  uint32_t       rsrvd3;
} f_tt;

I've done this and it does not work (probably because it's wrong :-/ ):

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct f_tt
{
    public uint w;
    public uint h;
    public uint f_cc;
    public uint st;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public Byte[] pl;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public int[] strd;
    public delegate void done(IntPtr thisobj);
    public delegate void e_cc();
    public uint rsrvd2;
    public uint rsrvd3;
}

Can someone advise me how to do this i c#?

  void         (*done)(void *thisobj);
  void          *e_cc;

Thank you!

like image 585
tweellt Avatar asked Dec 22 '25 10:12

tweellt


1 Answers

Before we come to the delegates, I suspect that you are wrong to pack the struct. It's very unusual to do so. Only do that if you find the pack #pragma in the C code.

The e_cc field is not a function pointer. It's just a void pointer. In C# that is IntPtr.

The pl member is an array of 4 pointers. I'm not quite sure what they contain, but for sure you can marshal that like this:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public IntPtr[] pl;

That leaves you with manual intervention to populate the array, or read its contents. It's possible that could be done by the marshaller, but without knowing the semantics of the interop, I can't say how to do that.

As for done, you should declare the delegate outside the struct. Like this:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void doneDelegate(IntPtr thisobj);

Here I am assuming that the calling convention is cdecl since there's nothing in the C code to say otherwise.

Putting it all together you have:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void doneFunc(IntPtr thisobj);

[StructLayout(LayoutKind.Sequential)]
public struct f_tt
{
    public uint w;
    public uint h;
    public uint f_cc;
    public uint st;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public IntPtr[] pl;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public int[] strd;
    public doneDelegate done;
    public IntPtr e_cc;
    public uint rsrvd2;
    public uint rsrvd3;
}
like image 130
David Heffernan Avatar answered Dec 23 '25 22:12

David Heffernan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!