Casting a CLR type to void* and back

本小妞迷上赌 提交于 2019-12-13 14:41:19

问题


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) {
   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);
   }
   ...
}

回答1:


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.



来源:https://stackoverflow.com/questions/4695824/casting-a-clr-type-to-void-and-back

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!