2011-01-14 3 views
3

CLRタイプをFoo^と正しく変換して、後でvoid*に変換するにはどうしたらいいですか?シナリオがあるCLRタイプをvoid *にキャストして戻す


、私はHandler_objフィールドでCLRオブジェクトを保存したい

class Handler { 
    void* _obj; 
    void (*_call)(void* obj, int detail); 

    void handle_event() { _call(_obj, 1234); } 
public: 
    void set_object(void* obj) { _obj = obj; } 
    void set_callback(void(*callback)(void*,int)) { _call = callback; } 
}; 

ように要約することができるDLL内のいくつかのアンマネージコードを持っています。 GCがCLRオブジェクトを移動する可能性があることを考慮して、実装する方法は? ( pin_ptrgcroot?)

static void event_callback(void* obj, int detail) { 
    Foo^ clr_obj = undo_magic(obj); 
//    ^^^^^^^^^^ how? 
    clr_obj->DoStuff(detail); 
} 

public ref class Foo { 
    Handle* h; 
public: 
    void Start() { 
    h = new Handler; 
    void* obj = do_magic(this); 
//    ^^^^^^^^ how? 
    h->set_object(obj); 
    h->set_callback(event_callback); 
    } 
    ... 
} 

答えて

2

ピン留めが必要とされるであろう。しかし、この '参照'を保存していて、オブジェクトを固定したままにする必要があります。それはかなり不健全で、ガベージコレクタは常にそれを回避する必要があります。もう一つの問題は、ピニングだけでは不十分で、GCがオブジェクトを収集しないように、オブジェクトへの認識可能な参照がなければならないということです。格納されたvoid *は十分ではありません。通常はgcroot <>でこれを解決しますが、ここでもうまくいきません。

より良いアプローチは、単に「ハンドル」を渡すことです。 void *をオブジェクトに戻すには、Dictionary<int, Foo^>を使用します。またはList<Foo^>の場合、インデックスがハンドルになる可能性があります。

関連する問題