プラットフォーム呼び出しラッパーの例

更新 : 2007 年 11 月

構造体が単純な型を含む場合は、その構造体をネイティブ関数に渡すことができます。ネイティブ ルーチンは、.NET Compact Framework が構造体をパックする方法に準拠している必要があります。

1 つのパラメータ (構造体へのポインタ) を受け取るネイティブ関数 DoRequest について考えてみます。構造体には次の 2 つのフィールドが定義されています。

  • NULL で終わる ANSI 文字列を含む文字配列

  • 整数

C++ の構造体は次のとおりです。

typedef struct 
{
    char *RequestName,
    int   Count,
} ALERT_REQUEST;

int DoAlertRequest(ALERT_REQUEST *pRequest);

これに対応する C# のマネージ構造体は次のとおりです。

struct AlertRequest
{
    String RequestName;
    int    Count;
}

class AlertClass
{
    [DLLImport("ALERT.DLL", EntryPoint="DoAlertRequest", 
        CharSet=CharacterSet.Ansi)]
    public static extern int DoRequest(ref AlertRequest Req);
}

DllImportAttribute 属性は、ネイティブ メソッド呼び出しのメタデータに注釈を付けています。このクラスは、共通言語ランタイムに、DoRequest メソッドが ALERT.DLL にあることと、メソッドの名前が DoAllertRequest であることを通知し、マネージ コードのすべての文字列が Unicode 文字列であるため、文字列を ANSI にマーシャリングするように指定します。

.NET Framework での C++ によるこのメソッドの呼び出しは、次のようになります。

AlertRequest Request = new AlertRequest()
Request.RequestName = "beep";
Request.Count = 10;
AlertClass.DoRequest(ref Request);

.NET Framework の共通言語ランタイムは DoRequest 呼び出しを検出すると、動的に ALERT.DLL を読み込み、DoAlertRequest のアドレスを取得して、必要に応じて文字列を変換するアンマネージ構造体をビルドします。この構造体へのポインタをプッシュし、DoAlertRequest を呼び出します。埋め込み String オブジェクトが含まれるために、構造体へのポインタをそのまま渡すことはできません。

このような制約のために、ネイティブ DoRequest メソッドを直接呼び出すことはできません。その代わり、中間サンク呼び出しで DoRequest をラップする必要があります。C# コード例は次のとおりです。

class AlertClass
{
    [DllImport("ALERT.DLL", EntryPoint="DoAlertRequestThunk")]
    private static extern int DoRequestThunk(String RequestName, int Count);

    public static int DoRequest(ref AlertRequst Req)
        {
            return DoRequestThunk(Req.RequestName, Req.Count);
        }
}

AlertClass には、依然として .NET Framework のメソッドと同じシグネチャのメソッドが含まれています。.NET Compact Framework DoRequest は、プライベート ネイティブ ルーチンを呼び出すマネージ ルーチンです。構造体内の String オブジェクトはマーシャリングされないため、構造体のフィールドは、ネイティブ ルーチンの呼び出しで個別の引数に分割されます。サンクによって、ネイティブ DoRequest がラップされます。C++ の次のコード例に示すように、アンマネージ構造体がビルドされ、文字列の変換が実行されます。

int DoRequestThunk(wchar_t *RequestNameW, int Count)
{
    ALERT_REQUEST Req;
    int ReturnCode;
       
    // CreateAnsiFromUnicodeString allocates and builds an ANSI
    // version of the Unicode string.
    Req.RequestName = CreateAnsiFromUnicodeString(RequestNameW);
    if (Req.RequestName == NULL) 
        Return 0;

    Req.Count = Count;

    // This is the native DoRequest, not to be confused
    // with the managed method of the same name.
    ReturnCode = DoAlertRequest(&Req);

    free(Req.RequestName)
    return ReturnCode;
}

参照

その他の技術情報

プラットフォーム呼び出しのサポート