我使用的API有这样的东西:
int simpletran(LPSTRUCT req)
{
printf("%d", req->length);
}
typedef unsigned long ULONG;
typdef struct _st {
ULONG length;
}STRUCT, *LPSTRUCT;
我的C#版本:
[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);
当我调用非托管函数时,我得到一些长的负值,如-31245665 !!!
我在Linux机器上使用C#mono。
答案 0 :(得分:1)
我还没有测试过这些,所以可能需要进行一些更改,但这就是我所看到的。
首先,STRUCT
应声明如下:
struct STRUCT
{
public UInt32 length;
}
请注意,我们已从class
更改为struct
,以便对象的内存布局已知且与C代码所期望的内容相匹配。
<强>更新强>
经过一些进一步的考虑之后,有一种更简单的方式来声明和调用方法,我将在下面留下原始答案,以便采用另一种方式。
您的P / Invoke签名应为:
[DllImport(LINUXLIB, CallingConvention=CallingConvention.Cdecl)]
public static extern int simpletran(ref STRUCT req);
请注意,我们已将STRUCT
更改为ref STRUCT
,因为STRUCT
是值类型,而C代码需要指向该结构的指针。
你会这样称呼它:
STRUCT st = new STRUCT();
st.length = (UInt32)100;
simpletran(ref st);
<强>原始强>
[DllImport(LINUXLIB, CallingConvention=CallingConvention.Cdecl)]
public static extern int simpletran(IntPtr req);
请注意,我们已将STRUCT
更改为IntPtr
,因为STRUCT
必须是值类型,而C代码需要指向该结构的指针。
你会这样称呼它:
STRUCT st = new STRUCT();
st.length = (UInt32)100;
IntPtr ptr = Marshal.AllocHGlobal(sizeof(STRUCT));
Marshal.StructureToPtr(st, ptr, false);
simpletran(ptr);
Marshal.FreeHGlobal(ptr);
在创建实例和调用分配一大块非托管内存的方法之间添加额外的步骤,以便在(Marshal.AllocHGlobal)中存储结构的值,并将st
的值复制到其中内存Marshal.StructureToPtr(...)。通过拨打Marshal.FreeHGlobal