Приведение типа CLR к void * и обратно - PullRequest
3 голосов
/ 14 января 2011

Как правильно преобразовать тип CLR, скажем Foo^, в void* и обратно через некоторое время?


Сценарий таков: у меня есть неуправляемый код в DLL, которыйСуммируется как

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

Я хочу сохранить объект CLR в поле Handler _obj.Как это реализовать, учитывая, что GC может перемещать объект CLR?(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 Ответ

2 голосов
/ 15 января 2011

Закрепление будет необходимо.Однако вы сохраняете эту «ссылку», требуя, чтобы объект оставался закрепленным.Это довольно вредно, сборщику мусора придется постоянно обходить его.Другая проблема состоит в том, что простого закрепления недостаточно, должна быть распознаваемая ссылка на объект, чтобы GC не собирал объект.Сохраненная пустота * недостаточно хороша.Обычно вы решаете это с помощью gcroot <>, но и здесь это не сработает.

Лучше всего просто передать «дескриптор».Используйте Dictionary<int, Foo^>, чтобы преобразовать пустоту * обратно в объект.Или List<Foo^>, теперь индекс может быть дескриптором.

...