Question

The API I am using has something like this:

int simpletran(LPSTRUCT req)
{
    printf("%d", req->length);
}

typedef unsigned long ULONG;

typdef struct _st {
  ULONG length;
}STRUCT, *LPSTRUCT;

My C# version of it:

[DllImport(LINUXLIB, CallingConvention=CallingConvention.Cdecl)]
public static extern simpletran(STRUCT req);

class STRUCT
{
  public UInt32 length;
}
STRUCT st = new STRUCT();
st.length = (UInt32)100;
simpletran(st);

When I call the unmanaged function I get some long negative values like -31245665!!!

I am using C# mono on a Linux machine.

Was it helpful?

Solution

I haven't tested any of this, so it may need some changes, but here's what I see off hand.

First off, STRUCT should be declared as follows:

struct STRUCT
{
    public UInt32 length;
}

Notice that we changed from class to struct so that the memory layout of the object is known and matches what the C code is expecting.

Update

After a bit of further consideration, there's an easier way of declaring and calling the method, I'll leave the original answer below for another way of doing it.

Your P/Invoke signature should be:

[DllImport(LINUXLIB, CallingConvention=CallingConvention.Cdecl)]
public static extern int simpletran(ref STRUCT req);

Notice that we changed STRUCT to ref STRUCT since STRUCT is a value type and the C code requires a pointer to that structure.

And you'd call it like this:

STRUCT st = new STRUCT();
st.length = (UInt32)100;
simpletran(ref st);

Original

[DllImport(LINUXLIB, CallingConvention=CallingConvention.Cdecl)]
public static extern int simpletran(IntPtr req);

Notice that we changed STRUCT to IntPtr since STRUCT has to be a value type and the C code requires a pointer to that structure.

And you'd call it like this:

STRUCT st = new STRUCT();
st.length = (UInt32)100;
IntPtr ptr = Marshal.AllocHGlobal(sizeof(STRUCT));
Marshal.StructureToPtr(st, ptr, false);
simpletran(ptr);
Marshal.FreeHGlobal(ptr);

Adding the extra steps in between creating the instance and calling the method for allocating a chunk of unmanaged memory to store the value of the struct in (Marshal.AllocHGlobal) and copying the value of st into that memory with Marshal.StructureToPtr(...). Be sure to free the allocated memory after the call with a call to Marshal.FreeHGlobal

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top