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;
}

オブジェクトのメモリ レイアウトが既知であり、C コードが期待するものと一致するように、classから に変更したことに注意してください。struct

アップデート

もう少し検討した後、メソッドを宣言して呼び出す簡単な方法があります。別の方法については、元の回答を以下に残します。

P/Invoke 署名は次のようになります。

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

は値型であり、C コードはその構造体へのポインターを必要とするため、に変更STRUCTしたことに注意してください。ref STRUCTSTRUCT

そして、あなたはそれを次のように呼びます:

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

オリジナル

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

値型でなければならず、C コードはその構造体へのポインターを必要とするため、に変更STRUCTしたことに注意してください。IntPtrSTRUCT

そして、あなたはそれを次のように呼びます:

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 に答える