我想将D类指针转换为void*
,并将此void*
指针与指向回调函数extern(C)
的指针一起传递给C库例程。
C库例程将调用我的回调extern(C)
函数,该函数将void*
转换回类指针并使用该类的对象。
麻烦:我听说GC对象可能会移动到其他位置(可能不是当前的D版本,而是将来的版本)。这是否意味着我的void*
指针可能变得无效(不再指向我的对象)?
如果问题确实存在,如何解决?
答案 0 :(得分:1)
您可以告诉GC以根为根握住指针,此外,还可以使用import core.memory; GC.addRoot(ptr);
函数告诉GC不要将其移到您身上。这个例子完整地展示了它:
http://dpldocs.info/experimental-docs/core.memory.GC.addRoot.html#examples
// Typical C-style callback mechanism; the passed function
// is invoked with the user-supplied context pointer at a
// later point.
extern(C) void addCallback(void function(void*), void*);
// Allocate an object on the GC heap (this would usually be
// some application-specific context data).
auto context = new Object;
// Make sure that it is not collected even if it is no
// longer referenced from D code (stack, GC heap, …).
GC.addRoot(cast(void*)context);
// Also ensure that a moving collector does not relocate
// the object.
GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE);
// Now context can be safely passed to the C library.
addCallback(&myHandler, cast(void*)context);
extern(C) void myHandler(void* ctx)
{
// Assuming that the callback is invoked only once, the
// added root can be removed again now to allow the GC
// to collect it later.
GC.removeRoot(ctx);
GC.clrAttr(ctx, GC.BlkAttr.NO_MOVE);
auto context = cast(Object)ctx;
// Use context here…
}
答案 1 :(得分:-1)
根据亚当·鲁珀(Adam D. Ruppe)的回答,但进行了重组。
更好的OO代码:
import core.memory : GC;
class UnmovableObject {
this() {
//GC.addRoot(cast(void*)this); // prevents finalization
GC.setAttr(cast(void*)this, GC.BlkAttr.NO_MOVE);
}
~this() {
//GC.removeRoot(cast(void*)this);
GC.clrAttr(cast(void*)this, GC.BlkAttr.NO_MOVE);
}
}