我想在node.js中执行以下操作...
var a = new A(); var b = new B();
// onTick应该是一个以B的实例作为参数的函数
a.onTick = function(bInst){ .... }
a.loop();
意味着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类的一个实例)中获取该函数并将其包装在一个实例化新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时,我需要Instantiate函数。
WrappedBClass没有做任何特别的事情,但WrappedAClass继承了一个具有循环和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);
}
我仍在试图弄清楚如何创建一个匿名函数,该函数从外部(acls)保留变量的值。我不认为闭包在这里是有效的,关键是这个函数只有一个参数(WrappedClassB * wcb),因为它需要设置为OnTick函数。
答案 0 :(得分:0)
您不必在C ++中创建匿名函数。也许您可以像这样定义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
功能,第二个参数类型为Local<Value>
而不是Local<Function>
。 C ++,与js不同,是静态类型语言。也许你可以定义你的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));
}