5

多数の C++ 静的ライブラリに依存する C++/CLI ラッパー DLL を作成しています。一部の関数呼び出しでは、アンマネージ ポインターが渡されることを想定しています。適切に渡すにはどうすればよいですか?

また、他の関数は、「this ポインター」が void* として渡されることを想定しています。「これ」を渡す正しい方法は何ですか?

これが私のクラス定義です...

public ref class RTPClient
{
    public:
        RTPClient();
        ~RTPClient();

        bool Connect();
        void Disconnect();

    private:
        CIsmaClient* mClient;
};

問題のポインタが使用されている私の使用法は次のとおりです...

RTPClient::RTPClient():
    mClient(NULL)
{
    CIsmaClient::Create(&mClient, NULL, &AllocBuffer, &GetDataPointer, this);
}

&mClient と "this" を使用すると、次のコンパイラ エラーが発生します... 1>.\VBLoadSimulatorDll.cpp(40): エラー C2664: 'CIsmaClient::Create': パラメーター 1 を 'cli::interior_ptr' から ' に変換できませんCIsmaClient **' 1> with 1> [ 1> Type=CIsmaClient * 1> ]

1>.\VBLoadSimulatorDll.cpp(40): エラー C2664: 'CIsmaClient::Create': パラメーター 5 を 'VBLoadSimulator::RTPClient ^const' から 'VOID *' に変換できません

4

2 に答える 2

9

マネージド クラスにポインターを渡す場合、^ 参照をポインターに変換するのは簡単ですが、マネージド オブジェクトを固定して、GC がメモリ内で移動しないようにする必要があります (したがって、ポインターが無効になります)。

これはpin_ptrで簡単です

ただし、コードは機能しない2つのことを行っています

RTPClient::RTPClient():
        mClient(NULL)
{
    CIsmaClient::Create(
        &mClient,          // 1
        NULL, 
        &AllocBuffer, 
        &GetDataPointer, 
        this);            //2
}

1) マネージド ヒープ上の何かのアドレスを取得しようとしています (ポインター mClient へのポインターの場所はマネージド ヒープ上にあります

そのため、メモリ内を移動できるため、コンパイラ サプライヤーの内部ポインター (値は GC 操作で維持されます) になります。これは固定する必要があり、Create 関数がスコープの終了後にポインターを使用することを想定していない場合にのみ機能します (ポインターを別の場所に渡して保存すると、バグが発生します)。

2)ポインターではなくハンドル(変な帽子の記号)を渡しています。(ウィキペディアのセクションを読んでください。これらは概要です)これは、アンマネージ コードでは理解できません(理解できません)。

このコンテキストでこのパラメーターについて考えることができる唯一の理由は、後続の関数コールバックに渡される明示的な状態変数です (間違っている場合は修正してください)。pin_ptr が範囲外になるとメモリ内で移動する可能性があるため、このコンテキストの「this」は決して適切に機能しません。

これを念頭に置いて、修正できるものと修正できないものを明確にする (部分的に) 修正された実装を次に示します。

RTPClient::RTPClient():
        mClient(NULL)
{
    // make it clear you want the address of the instance variable
    pin_ptr<CIsmaClient*> pinnedClient = &this->mClient; 
    CIsmaClient::Create(
        pinnedClient,          // fixed
        NULL, 
        &AllocBuffer, 
        &GetDataPointer, 
        x /* pass something else in */);            //2
}

最後のパラメーターの使用目的に関する詳細情報を提供していただければ、考えられる解決策を提案できます

于 2009-02-20T14:34:41.110 に答える
2

これが、void ポインターを介してマネージド参照を渡す最も簡単な方法であることがわかると思います。

void SomeFunction(void* input)
{
  gcroot<ManagedClass^>* pointer = (gcroot<ManagedClass^>*)(input);
  (*pointer)->ManagedFunction();
}

void Example()
{
  ManagedClass^ handle = gcnew ManagedClass();
  gcroot<ManagedClass^>* pointer = new gcroot<ManagedClass^>(handle);
  SomeFunction((void*)pointer);
  delete pointer;
}
于 2010-11-12T09:50:55.813 に答える