この記事は機械翻訳されています。英語版の記事を表示するには、[英語] のチェック ボックスをオンにしてください。また、テキストにマウス ポインターを合わせると、ポップアップ ウィンドウに英語のテキストを表示することもできます。
翻訳
英語

構造体のサンプル

このサンプルでは、第 2 の構造体を指す構造体の渡し方、埋め込み構造体を含む構造体の渡し方、および埋め込み配列を含む構造体の渡し方を示します。

Structs のサンプルで使用するアンマネージ関数とその関数宣言を次に示します。

  • PinvokeLib.dll からエクスポートされる TestStructInStruct

    int TestStructInStruct(MYPERSON2* pPerson2);
    
  • PinvokeLib.dll からエクスポートされる TestStructInStruct3

    void TestStructInStruct3(MYPERSON3 person3);
    
  • PinvokeLib.dll からエクスポートされる TestArrayInStruct

    void TestArrayInStruct( MYARRAYSTRUCT* pStruct );
    

PinvokeLib.dll はカスタム アンマネージ ライブラリであり、上記の関数および構造体 MYPERSONMYPERSON2MYPERSON3、および MYARRAYSTRUCT に関する実装を含みます。 これらの構造体には次の要素が含まれます。

typedef struct _MYPERSON
{
   char* first; 
   char* last; 
} MYPERSON, *LP_MYPERSON;

typedef struct _MYPERSON2
{
   MYPERSON* person;
   int age; 
} MYPERSON2, *LP_MYPERSON2;

typedef struct _MYPERSON3
{
   MYPERSON person;
   int age; 
} MYPERSON3;

typedef struct _MYARRAYSTRUCT
{
   bool flag;
   int vals[ 3 ]; 
} MYARRAYSTRUCT;

マネージ構造体の MyPersonMyPerson2MyPerson3、および MyArrayStruct には、次に示す特性があります。

  • MyPerson には文字列メンバーだけが含まれます。 CharSet フィールドは、アンマネージ関数に渡されたときに文字列を ANSI 形式に設定します。

  • MyPerson2 には MyPerson 構造体への IntPtr が含まれます。 コードに unsafe マークが付いていない場合、.NET Framework アプリケーションはポインターを使用しないため、アンマネージ構造体を指す元のポインターは IntPtr 型に置き換えられます。

  • MyPerson3 には埋め込み構造体としての MyPerson が含まれます。 別の構造体に埋め込まれた構造体は、埋め込み構造体の要素を主構造体に直接配置して平坦化することも、このサンプルのように埋め込み構造体のままにしておくこともできます。

  • MyArrayStruct には整数の配列が含まれます。 MarshalAsAttribute 属性により、UnmanagedType 列挙値に ByValArray が設定されます。これは、配列に属する要素の数を示すために使用されます。

このサンプルでは、各メンバーが出現する順番でメモリ内に順次配列されることを保証するために、すべての構造体に StructLayoutAttribute 属性が適用されます。

LibWrap クラスには App クラスによって呼び出される TestStructInStructTestStructInStruct3、および TestArrayInStruct メソッドのマネージ プロトタイプが含まれます。 各プロトタイプは、次に示すように 1 つのパラメーターを宣言します。

  • TestStructInStructMyPerson2 型への参照を独自のパラメーターとして宣言します。

  • TestStructInStruct3MyPerson3 型を独自のパラメーターとして宣言し、そのパラメーターを値渡しします。

  • TestArrayInStructMyArrayStruct 型への参照を独自のパラメーターとして宣言します。

メソッドへの引数としての構造体は、パラメーターの中にキーワード ref (Visual Basic では ByRef) が含まれる場合を除き、値渡しされます。 たとえば、the TestStructInStruct メソッドは MyPerson2 型のオブジェクトへの参照 (アドレスの値) をアンマネージ コードに渡します。 MyPerson2 が指す構造体を操作するには、サンプルでは、指定したサイズのバッファーを作成し、Marshal.AllocCoTaskMem メソッドと Marshal.SizeOf メソッドを組み合わせることにより、そのアドレスを返します。 次に、マネージ構造体の内容をアンマネージ バッファーにコピーします。 最後に、Marshal.PtrToStructure メソッドによってアンマネージ バッファーからマネージ オブジェクトへとデータをマーシャリングし、Marshal.FreeCoTaskMem メソッドによってメモリのアンマネージ ブロックを解放します。


// Declares a managed structure for each unmanaged structure.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct MyPerson
{
    public string first;
    public string last;
}

[StructLayout(LayoutKind.Sequential)]
public struct MyPerson2
{
    public IntPtr person;
    public int age;
}

[StructLayout(LayoutKind.Sequential)]
public struct MyPerson3
{
    public MyPerson person;
    public int age;
}

[StructLayout(LayoutKind.Sequential)]
public struct MyArrayStruct
{
    public bool flag;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    public int[] vals;
}

public class LibWrap
{
    // Declares a managed prototype for unmanaged function.
    [DllImport("..\\LIB\\PinvokeLib.dll")]
    public static extern int TestStructInStruct(ref MyPerson2 person2);

    [DllImport("..\\LIB\\PinvokeLib.dll")]
    public static extern int TestStructInStruct3(MyPerson3 person3);

    [DllImport("..\\LIB\\PinvokeLib.dll")]
    public static extern int TestArrayInStruct(ref MyArrayStruct myStruct);
}



public class App
{
    public static void Main()
    {
        // Structure with a pointer to another structure.
        MyPerson personName;
        personName.first = "Mark";
        personName.last = "Lee";

        MyPerson2 personAll;
        personAll.age = 30;

        IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(personName));
        Marshal.StructureToPtr(personName, buffer, false);

        personAll.person = buffer;

        Console.WriteLine("\nPerson before call:");
        Console.WriteLine("first = {0}, last = {1}, age = {2}",
            personName.first, personName.last, personAll.age);

        int res = LibWrap.TestStructInStruct(ref personAll);

        MyPerson personRes =
            (MyPerson)Marshal.PtrToStructure(personAll.person,
            typeof(MyPerson));

        Marshal.FreeCoTaskMem(buffer);

        Console.WriteLine("Person after call:");
        Console.WriteLine("first = {0}, last = {1}, age = {2}",
            personRes.first, personRes.last, personAll.age);

        // Structure with an embedded structure.
        MyPerson3 person3 = new MyPerson3();
        person3.person.first = "John";
        person3.person.last = "Evans";
        person3.age = 27;
        LibWrap.TestStructInStruct3(person3);

        // Structure with an embedded array.
        MyArrayStruct myStruct = new MyArrayStruct();

        myStruct.flag = false;
        myStruct.vals = new int[3];
        myStruct.vals[0] = 1;
        myStruct.vals[1] = 4;
        myStruct.vals[2] = 9;

        Console.WriteLine("\nStructure with array before call:");
        Console.WriteLine(myStruct.flag);
        Console.WriteLine("{0} {1} {2}", myStruct.vals[0],
            myStruct.vals[1], myStruct.vals[2]);

        LibWrap.TestArrayInStruct(ref myStruct);
        Console.WriteLine("\nStructure with array after call:");
        Console.WriteLine(myStruct.flag);
        Console.WriteLine("{0} {1} {2}", myStruct.vals[0],
            myStruct.vals[1], myStruct.vals[2]);
    }
}


表示: