将CLR类型强制转换为void *并返回 [英] Casting a CLR type to void* and back
问题描述
如何正确转换CLR类型,例如 Foo ^
到 void *
,然后返回一段时间?
How to properly convert a CLR type, say Foo^
, to void*
and back some time later?
这种情况是,我在DLL中有一些非托管代码,可以总结为
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; }
};
我想将一个CLR对象存储在 Handler
的 _obj
字段。如何实现它,考虑到GC可能移动CLR对象? ( pin_ptr
? gcroot
?)
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);
}
...
}
推荐答案
需要固定。但是,您正在存储此引用,要求对象保持固定。这是相当不健康,垃圾收集器将不断地工作周围。另一个问题是,只是钉住是不够的,必须有一个可识别的对象引用,以便GC不会收集对象。存储的void *不够好。你通常会使用gcroot<>来解决这个问题,但这在这里也不行。
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.
一个更好的方法是简单地传递一个句柄。使用字典< int,Foo ^>
将void *转换回对象。或者 List< Foo ^>
,现在索引可以是句柄。
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.
这篇关于将CLR类型强制转换为void *并返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!