例如,如何正确转换 CLR 类型Foo^
, to 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
's _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);
}
...
}
需要固定。但是,您要存储此“引用”,要求该对象保持固定状态。这是非常不健康的,垃圾收集器必须不断地解决它。另一个问题是仅仅固定是不够的,必须有一个可识别的对象引用,这样 GC 就不会收集该对象。存储的 void* 还不够好。您通常可以使用 gcroot 解决此问题,但这在这里也不起作用。
更好的方法是简单地传递“句柄”。用一个Dictionary<int, Foo^>
将 void* 转换回对象。或者一个List<Foo^>
,现在索引可以是句柄。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)