方法: C++ Interop を使用して配列をマーシャリングする

このトピックでは、Visual C++ の相互運用性の一面を示します。 詳細については、「C++ Interop (暗黙の PInvoke) の使用」を参照してください。

managed、unmanaged #pragma ディレクティブを使用して、同じファイルにマネージド関数とアンマネージド関数を実装する方法を次のコード例に示します。これらの関数は、別々のファイルで定義されている場合でも同じ方法で相互運用されます。 アンマネージド関数のみを含むファイルを、/clr (共通言語ランタイムのコンパイル) を使用してコンパイルする必要はありません。

例: アンマネージド関数にマネージド配列を渡す

次の例は、アンマネージド関数にマネージド配列を渡す方法を示しています。 マネージド関数は、アンマネージド関数を呼び出す前に、pin_ptr (C++/CLI) を使用して配列のガベージ コレクションを抑制します。 アンマネージド関数に GC ヒープへの固定ポインターを指定することで、配列のコピー作成のオーバーヘッドを回避できます。 アンマネージド関数が GC ヒープ メモリにアクセスしていることを示すために、配列の内容が変更され、マネージド関数が制御を再開すると、その変更が反映されます。

// PassArray1.cpp
// compile with: /clr
#ifndef _CRT_RAND_S
#define _CRT_RAND_S
#endif

#include <iostream>
#include <stdlib.h>
using namespace std;

using namespace System;

#pragma unmanaged

void TakesAnArray(int* a, int c) {
   cout << "(unmanaged) array received:\n";
   for (int i=0; i<c; i++)
      cout << "a[" << i << "] = " << a[i] << "\n";

   unsigned int number;
   errno_t err;

   cout << "(unmanaged) modifying array contents...\n";
   for (int i=0; i<c; i++) {
      err = rand_s( &number );
      if ( err == 0 )
         a[i] = number % 100;
   }
}

#pragma managed

int main() {
   array<int>^ nums = gcnew array<int>(5);

   nums[0] = 0;
   nums[1] = 1;
   nums[2] = 2;
   nums[3] = 3;
   nums[4] = 4;

   Console::WriteLine("(managed) array created:");
   for (int i=0; i<5; i++)
      Console::WriteLine("a[{0}] = {1}", i, nums[i]);

   pin_ptr<int> pp = &nums[0];
   TakesAnArray(pp, 5);

   Console::WriteLine("(managed) contents:");
   for (int i=0; i<5; i++)
      Console::WriteLine("a[{0}] = {1}", i, nums[i]);
}

例: マネージド関数にアンマネージド配列を渡す

次の例は、マネージド関数にアンマネージド配列を渡す方法を示しています。 マネージド関数は、(マネージド配列を作成して、配列の内容をコピーするのではなく) 配列メモリに直接アクセスします。これにより、マネージド関数が行った変更を、制御を回復したときにアンマネージド関数に反映することができます。

// PassArray2.cpp
// compile with: /clr
#include <iostream>
using namespace std;

using namespace System;

#pragma managed

void ManagedTakesAnArray(int* a, int c) {
   Console::WriteLine("(managed) array received:");
   for (int i=0; i<c; i++)
      Console::WriteLine("a[{0}] = {1}", i, a[i]);

   cout << "(managed) modifying array contents...\n";
   Random^ r = gcnew Random(DateTime::Now.Second);
   for (int i=0; i<c; i++)
      a[i] = r->Next(100);
}

#pragma unmanaged

void NativeFunc() {
   int nums[5] = { 0, 1, 2, 3, 4 };

   printf_s("(unmanaged) array created:\n");
   for (int i=0; i<5; i++)
      printf_s("a[%d] = %d\n", i, nums[i]);

   ManagedTakesAnArray(nums, 5);

   printf_s("(ummanaged) contents:\n");
   for (int i=0; i<5; i++)
      printf_s("a[%d] = %d\n", i, nums[i]);
}

#pragma managed

int main() {
   NativeFunc();
}

関連項目

C++ Interop (暗黙の PInvoke) の使用