V8的文档解释了how to create a Javascript object that wraps a C++ object。 Javascript对象保持指向C ++对象实例的指针。我的问题是,假设您在堆上创建C ++对象,如何在gc收集Javascript对象时获得通知,以便可以释放堆分配的C ++对象?
答案 0 :(得分:23)
诀窍是创建一个Persistent
句柄(链接到API引用的第二个项目符号点:“Persistent
句柄不会保留在堆栈上,只有在您专门删除它们时才会被删除。 ...当需要保持对一个对象的引用以进行多个函数调用时,或者当句柄生命周期与C ++范围不对应时,使用持久句柄。“),并在其上调用MakeWeak()
,传递一个回调函数将执行必要的清理(“使用Persistent::MakeWeak
可以使持久句柄变弱,以便在对对象的唯一引用来自弱持久句柄时从垃圾收集器触发回调。” - 是,当所有“常规”句柄超出范围并且垃圾收集器即将删除对象时。)
Persistent::MakeWeak
方法签名是:
void MakeWeak(void* parameters, WeakReferenceCallback callback);
其中WeakReferenceCallback
被定义为带有两个参数的函数指针:
typedef void (*WeakReferenceCallback)(Persistent<Object> object,
void* parameter);
这些可在v8.h头文件中找到,该文件随V8一起分发为公共API。
您希望传递给MakeWeak
的函数清除Persistent<Object>
对象参数,该参数在被称为回调时将传递给它。可以忽略void* parameter
参数(或void* parameter
可以指向包含需要清理的对象的C ++结构:
void CleanupV8Point(Persistent<Object> object, void*)
{
// do whatever cleanup on object that you're looking for
object.destroyCppObjects();
}
Parameter<ObjectTemplate> my_obj(ObjectTemplate::New());
// when the Javascript part of my_obj is about to be collected
// we'll have V8 call CleanupV8Point(my_obj)
my_obj.MakeWeak(NULL, &CleanupV8Point);
答案 1 :(得分:0)
通常,如果垃圾收集语言可以保存对语言引擎之外的资源的引用(文件,套接字或在您的C ++对象中),那么您应该提供一种“关闭”方法来尽快释放该资源,不等到GC认为破坏你的物体是值得的。
如果您的C ++对象占用大量内存并且垃圾收集对象只是一个引用,那么情况会变得更糟:您可能会分配数千个对象,并且GC只能看到几KB的微小对象,不足以触发收集;而C ++方面正在与数十兆的陈旧对象进行斗争。答案 2 :(得分:0)
在一些封闭的范围内(对象或功能)完成所有工作。 当你超出范围时,你可以安全地删除C ++对象。 GC不检查指针是否存在尖头对象。