あなたは
データ配列が少なくとも同じサイズであると仮定します。これは発生するのを待っている可能性のあるバグです
malloc()の結果をチェックしない
とにかくこれを行う必要はないかもしれません。ピン留めされたバイトポインタを渡すだけで問題ありません(呼び出されたfx()関数が何らかの方法でデータを変更する場合を除きます。その場合、コピーが必要になる可能性があります)。後で解放されるメモリに基づいて、これは可能性ではない可能性があります。
それを念頭に置いて、ここに修正されたバージョンがあります
void managed_fx (byte data __gc[], size_t size)
{
if (data.Length < size)
throw gcnew System.IndexOutOfRangeException(
"the unmanaged buffer is not big enough");
// Pin the data
byte __pin *pinned_data = &data [0];
// Copy data to the unmanaged buffer.
void *unmanaged_data = malloc (size);
if (unmanaged_data == NULL)
throw gcnew OutOfMemoryException(
"could not allocate memory for the unmanaged buffer");
memcpy (unmanaged_data, (byte*) pinned_data, size);
// Forward the call
fx (unamanged_data, size);
}
さらなる質問に答えるには:
memcpyを実行するには、ピン留めが必要です。GCランタイムによるメモリの削除を防ぐことはできません(技術的にはそうですが、単にメモリへの参照を保持することもできます)。メモリ内での移動を防ぎます。memcpyはアンマネージ関数であるため、操作しているポインターをメモリ内で移動して処理することはできません。mallocは完全に管理されていません(ただし、ランタイムライブラリは管理対象ヒープの予約済み領域を自由に使用してこれを行うことができます)。
'コード'が管理されているか管理されていないかに関して、ソースC ++/CLIには明確な区別はありません。コンパイル時に、一部の部分はCIL中間コードになり、他の部分はプレーンなネイティブコードになります。重要なのは、変数が使用されるのは管理されているか、管理されていないかです。管理された参照(^が付いているもの)は、それ自体が管理されているコードによってのみ操作/使用できます。これは、ランタイムがメモリ内の管理対象オブジェクトの場所を変更した場合に、適切と思われる場合に使用される基になるポインタの値を自由に変更できることを意味します。これは、管理対象の機能に対して安全な方法で行われます(機能は、周囲の世界が変化している間は一時停止されます)。このような管理された参照を処理する方法を知らない多くの便利な関数が存在するため、それらへの単純なポインターを取得する必要が生じる可能性があります。この操作は安全ではないため(GCが参照を移動する場合)、ピン留めポインターが存在します。これは、ポインターを取得し、そのポインターの存続期間中、ランタイムがポイントされた変数を移動するのを防ぐため、これを安全かつ簡単に実行できるようにするためです。 。