1

我使用的 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。

4

1 回答 1

1

我还没有测试过这些,所以它可能需要一些改变,但这是我看到的。

首先,STRUCT应该声明如下:

struct STRUCT
{
    public UInt32 length;
}

请注意,我们从 更改classstruct以便对象的内存布局是已知的并且与 C 代码所期望的相匹配。

更新

经过进一步考虑,有一种更简单的方法来声明和调用该方法,我将在下面留下原始答案以另一种方法。

您的 P/Invoke 签名应该是:

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

请注意,我们更改STRUCTref STRUCTsinceSTRUCT是一个值类型,并且 C 代码需要一个指向该结构的指针。

你会这样称呼它:

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

原来的

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

请注意,我们更改STRUCTIntPtrsinceSTRUCT必须是值类型,并且 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 ) 中并使用Marshal.StructureToPtr(...)将值复制st到该内存中的方法之间添加额外的步骤. 确保在调用Marshal.FreeHGlobal后释放分配的内存

于 2013-05-24T21:36:48.687 回答