如何在v8包装对象中保存
javascript提供的回调,以便将来不仅在当前函数调用中使用.本质上我想在C中创建一个javascript对象,当用新的Object()创建时,提供一个函数回调.然后在整个c对象生命中使用该回调.见下面的例子:
我遇到的问题是当我尝试在不同的静态函数中使用Handle对象时它会出错.
在节点js文件中:
var Object = require("./customModule"); var obj = new Object(function(){console.log("Callback called...")}) // Emit callback obj.emitCallback();
在c模块头中
class Object : public node::ObjectWrap { public: static void Init(v8::Handle<v8::Object> target); Object(); protected: v8::Handle<v8::Function> m_faceDetectCallback; static v8::Handle<v8::Value> New(const v8::Arguments& args); static v8::Handle<v8::Value> onEmitCallback(const v8::Arguments& args); } v8::Handle<v8::Value> Object::New(const v8::Arguments& args) { HandleScope scope; Object* obj = new Object(); obj->Wrap(args.This()); obj->m_faceDetectCallback = Handle<Function>::Cast(args[0]); //obj->m_faceDetectCallback = v8::Persistent<Function>::Cast(args[0]); // Works fine here. const unsigned argc = 1; Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) }; obj->m_faceDetectCallback->Call(Context::GetCurrent()->Global(),argc,argv); return args.This(); } static v8::Handle<v8::Value> Object::onEmitCallback(const v8::Arguments& args){ HandleScope scope; Object* obj = ObjectWrap::Unwrap<Object>(args.This()); const unsigned argc = 1; Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) }; //!! Segfaults here if(obj->m_faceDetectCallback->IsCallable()){ //obj->m_faceDetectCallback->Call(Context::GetCurrent()->Global(),argv); } return scope.Close(v8::String::New("Start called")); }
解决方法
您需要使用v8 :: Persistent而不是标准句柄. Handle是Local和Persistent的基类,所以通过执行你正在进行的转换,你抓住了一个指向v8 :: Function的指针,但没有做任何会告诉V8不要垃圾收集它的东西.
在你的课堂上这个:
v8::Persistent<v8::Function> m_faceDetectCallback;
并分配
obj->m_faceDetectCallback = v8::Persistent<v8::Function>::New(args[0]);