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.
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