1

マネージ C++ を使用して、統計言語 R を .NET から直接インターフェイスしています。私は Managed C++ に少し慣れていないので、少しトリッキーなことをする必要があります。void*関数に渡すために使用される構造体には、後のコールバックで使用可能なペイロード データを渡すために使用される汎用データ ポインターがあります。私が説明したことを願っていますが、これは C/C++ でかなりよく使用されるパターンです。しかし、私の使用のために、それを使用して管理対象オブジェクトを渡す必要がありvoid *ます。どうすればよいですか?

私は試しています:

BinaryWriter^ bs=gcnew......;
stream->data=(void*)(%bs);

しかし、それは機能しません。何か助けはありますか?

更新 これはうまくいくようですが、それが最善の方法であるかどうかはわかりません:

pin_ptr<BinaryWriter^> p = &bs;
stream->data=(void*)p;
4

3 に答える 3

1

私の C++/CLI は少しさびています (そのため、これを行うためのより良い方法があるかもしれません。pin_ptr は次の省略形である可能性があります) が、C# ではGCHandleを使用するのが標準です。

// getting a fixed pointer
BinaryWriter^ bs=gcnew......;
GCHandle handle = GCHandle.Alloc(bs, GCHandleType.Pinned);
IntPtr ptr = GCHandle.ToIntPtr(handle);

// in callback
GCHandle handle = GCHandle.FromIntPtr(ptr);
BinaryWriter^ bs = (BinaryWriter^)handle.Target;
handle.Free();

もちろん、 a にキャストしたり、再びIntPtrキャストしたりすることもできます。void*

于 2013-09-25T11:02:44.633 に答える
1

C++/CLI コンパイラは、これを行うことを妨げます。これは、実行時にひどく誤動作します。「追跡ハンドル」のポイントは、ヒープを圧縮するときにオブジェクトを移動するときに、ガベージ コレクターがポインターを見つけてその値を更新できることです。void* にキャストしてそのポインターをネイティブ コードに渡すと、これを行うことはできません。そのネイティブ コードは、ガベージ コレクションの後もオブジェクトを元の場所にあるかのように使用し続けます。それは悲惨です。

はい、 pin_ptr<> を使用することは回避策であり、オブジェクトを固定して移動できないようにします。pin_ptr<> が宣言されているスコープ ブロックが実行されている間だけ固定されたままになるため、ネイティブ コードが後でそのポインターを逆参照できないようにしてください。GCHandle::Alloc() でより永続的なピンを取得し、GCHandleType::Pinned を渡します。GCHandle::AddrOfPinnedObject() はポインター値を返します。

一歩下がって、マネージ コードからのみ呼び出すことができるマネージ オブジェクトへのポインターを渡したいとします。つまり、ネイティブ コードがその void* に対して実際にできることは何もありません。

于 2013-09-25T12:43:45.063 に答える