开发者

Casting a CLR type to void* and back

How to properly convert a CLR type, say Foo^, to void* and back some time later?


The scenario is, I have some unmanaged code in a DLL that can be summarized as

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; }
};

I want to store a CLR object in the Handler's _obj field. How to implement it, taking into account that the GC may move the CLR object? (pin_ptr? gcroot?)

static void event_callback(void* obj, int detail) {
   F开发者_JS百科oo^ 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);
   }
   ...
}


Pinning would be required. However, you are storing this 'reference', requiring the object to stay pinned. That's quite unhealthy, the garbage collector would constantly have to work around it. Another problem is that just pinning isn't enough, there has to be a recognizable reference to the object so that the GC won't collect the object. The stored void* isn't good enough. You'd normally solve this with gcroot<> but that can't work here either.

A better approach is to simply pass a 'handle'. Use a Dictionary<int, Foo^> to convert the void* back to the object. Or a List<Foo^>, now the index could be the handle.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜