在Node.js和v8中调用一个使用包装对象作为参数的函数

我想在node.js中做如下的事情…

var a = new A(); var b = new B();

// onTick应该是一个以B的实例作为参数的函数

a.onTick = function(bInst){….}

一个循环();

这意味着A有一个属性“onTick”,这是一个在循环内被调用的函数。 请注意,A和B被定义为C ++封装函数,这里是定义

void AClass::Init(Handle<Object> target) { Local<FunctionTemplate> tpl = FunctionTemplate::New(New); tpl->SetClassName(String::NewSymbol("A")); tpl->InstanceTemplate()->SetInternalFieldCount(1); tpl->PrototypeTemplate()->Set(String::NewSymbol("tick"), FunctionTemplate::New(Tick)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("loop"), FunctionTemplate::New(Loop)->GetFunction()); constructor = Persistent<Function>::New(tpl->GetFunction()); constructor->InstanceTemplate()->SetAccessor(String::New("onTick"), GetOnTick, SetOnTick); target->Set(String::NewSymbol("A"), constructor); } Handle<Value> AClass::New(const v8::Arguments &args) { HandleScope scope; AClass* acls = new AClass(); WrappedAClass* wrappedA = new WrappedAClass(); acls->wrappedAInst_ = wrappedA; window->Wrap(args.This()); return args.This(); } Handle<Value> AClass::Loop(const Arguments &args) { HandleScope scope; AClass* acls = ObjectWrap::Unwrap<AClass>(args.This()); acls->wrappedInst_->loop(); return scope.Close(Undefined()); } 

我相信这是你如何设置属性的getter和setter

 Handle<Function> GetOnTick(Local<String> property, const AccessorInfo& info) { AClass* acls = ObjectWrap::Unwrap<AClass>(info.Holder()); return acls->onTick_; } void SetOnTick(Local<String> property, Local<Function> value, const AccessorInfo& info) { AClass* acls = ObjectWrap::Unwrap<AClass>(info.Holder()); acls->onTick_ = Persistent<Function>::New(value); //Here's where I know I'm doing it wrong void func(WrappedClassB* wcb) { const unsigned argc = 1; Local<Value> argv[argc] = { Local<Value>::New(BClass::Instantiate(wcb)) }; acls->onTick_->Call(Context::GetCurrent()->Global(), argc, argv); } acls->wrappedAInst_->setTickFunc(func); } 

我想要做的是从设置onTick(它需要一个B类的实例)的function,并包装在一个函数,instatiate一个新的BClass。

反正下面是BClass的定义

 Persistent<Function> BClass::constructor; BClass::BClass() { } BClass::~BClass() { } void BClass::Init(Handle<Object> target) { Local<FunctionTemplate> tpl = FunctionTemplate::New(New); tpl->SetClassName(String::NewSymbol("B")); tpl->InstanceTemplate()->SetInternalFieldCount(1); constructor = Persistent<Function>::New(tpl->GetFunction()); target->Set(String::NewSymbol("B"), constructor); } Handle<Value> BClass::New(const v8::Arguments &args) { HandleScope scope; BClass* bcls = new BClass(); bcls->Wrap(args.This()); WrappedBClass* wrappedB = new WrappedBClass(); bcls->wrappedBInst_ = wrappedB; return args.This(); } Handle<Value> BClass::Instantiate(const WrappedBClass &wbc) { HandleScope scope; //I know the following is wrong but it shows what I am trying to do BClass* bcls = new BClass(); bcls->wrappedBInst_ = wbc; return scope.Close(Local<v8::Value>::New(bcls)); } 

AClass和BClass都使用另一个C ++类,并将该实例保存为一个属性(wrappedBInst,wrappedAInst)我相信当我需要将WrappedBClass的实例转换为BClass时,我需要实例化函数。

WrappedBClass没有做任何特别的事情,但WrappedAClassinheritance了一个具有循环和onTick函数的类,onTick函数是我需要调用我的Javascript函数的地方,所以在WrappedAClass中我重写了onTick并添加了一个setTickFunc函数。

 class WrappedAClass : public InheritedClass{ public: void setTickFunc(void (*func)(WrappedBClass*)){ tickFunc = func; } protected: void tickFunc; virtual void onTick(WrappedBClass* wbc){ if(tickFunc){ tickFunc(wbc); } } } 

所以我认为我可以进入循环并使用JavaScript函数作为onTick函数的唯一方法是首先将javascript函数包装到c ++函数中,然后通过调用setTickFunc()来设置该函数。 我正在以正确的方式进行吗?

我是一个体面的程序员,但最近刚刚开始使用C ++,所以原谅我明显的错误,最大的错误是:

 void SetOnTick(Local<String> property, Local<Function> value, const AccessorInfo& info) { AClass* acls = ObjectWrap::Unwrap<AClass>(info.Holder()); acls->onTick_ = Persistent<Function>::New(value); //Here's where I know I'm doing it wrong void func(WrappedClassB* wcb) { const unsigned argc = 1; Local<Value> argv[argc] = { Local<Value>::New(BClass::Instantiate(wcb)) }; acls->onTick_->Call(Context::GetCurrent()->Global(), argc, argv); } acls->wrappedAInst_->setTickFunc(func); } 

我仍然试图找出如何创build一个匿名函数,从外部(acls)持有一个variables的值。 我不认为闭包在这里是有效的,关键是这个函数只有一个参数(WrappedClassB * wcb),因为它需要被设置为OnTick函数。

您不必在C ++中创build匿名函数。 也许你可以像这样定义你的WrappedAClass

 class WrappedAClass : public InheritedClass{ public: void setTickFunc(Local<Function> jsFn){ HandleScope scope; jsTickFunc = Persistent<Function>::New(jsTickFunc); } protected: Persistent<Function> jsTickFunc; virtual void onTick(WrappedBClass* wbc){ HandleScope scope; if(jsTickFunc.IsEmpty()) return; const unsigned argc = 1; Local<Value> argv[argc] = { Local<Value>::New(BClass::Instantiate(wcb)) }; jsTickFunc->Call(Context::GetCurrent()->Global(), argc, argv); } } 

注意SetOnTick函数,第二个参数的types是Local<Value> not Local<Function> 。 C ++,不像js,是静态types语言。 也许你可以定义你的SetOnTick Setter舔这个:

 void SetOnTick(Local<String> property, Local<Value> value, const AccessorInfo& info){ AClass* acls = ObjectWrap::Unwrap<AClass>(info.Holder()); if (value->IsFunction()) acls->wrappedAInst_->setTickFunc(Local<Function>::Cast(value)); }