V8 - 将 args.Data() 转换回 void 指针
V8 - Casting args.Data() back to void pointer
目前我正在使用以下方法绑定一个函数:
global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print));
具有函数:
static void js_print(const v8::FunctionCallbackInfo<v8::Value> &args);
实施:
void V8Instance::js_print(const v8::FunctionCallbackInfo<v8::Value> &args) {
for (int i = 0; i < args.Length(); i++) {
v8::HandleScope handle_scope(args.GetIsolate());
v8::String::Utf8Value str(args[i]);
std::cout << *str << std::endl;
}
std::cout << std::endl;
}
但是我希望我的 js_print 函数能够访问属于 class V8Instance 成员的变量。 V8 是否有类似能够使用 boost::bind(&Class::function, this, ...)
的东西让我绑定成员函数,或者有什么方法可以在每次调用时通过 reference/pointer 将我需要的变量传递给 js_print
吗?
更新
我发现我可以使用 FunctionTemplate::New
的数据参数传递指向我的 class 的指针:
Local<External> self = External::New(isolate, (void *) this);
global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print, self));
我可以使用 args.Data()
在我的 js_print
函数中访问它,但是这个 returns Local<Value>
对象我不确定如何转换回 void *
然后回到我的 class 指针,V8Instance *
。有人知道怎么做吗?
您可以将 C++ 对象包装到相应的 v8::ObjectTemplate
中并为其设置访问器,如 V8 Embedder's Guide 中所述。
要包装 C++ class(即要使用来自 JavaScript 的此 C++ class 的许多 C++ 实例),您需要创建 V8 FunctionTemplate
作为 JS包装 class 的构造函数,它将在 V8 Object
实例中存储指向 C++ 对象的指针,并为 class 中所需的成员函数设置 V8 函数回调。这些回调应该从 V8 对象中解包 C++ 对象,并为解包的对象调用适当的成员函数。
这种方法会导致编写大量样板代码。 Node.js 允许在本机插件中从 node::ObjectWrap
继承 C++ class。
我还创建了 v8pp 库,它以非侵入式方式绑定 C++ classes、函数和 lambda,没有继承。
存在几个类似的库。但是,据我所知,它们已经过时并且不支持新的 V8 版本。
Update. 要从外部数据中获取 V8Instance*
,您需要将 args.Data()
值转换为 v8::External
,然后从该外部数据获取指针值并将其转换为 V8Instance*
。像这样:
void V8Instance::js_print(const v8::FunctionCallbackInfo<v8::Value> &args)
{
v8::Local<v8::External> ext = args.Data().As<v8::External>();
V8Instance* self = static_cast<V8Instance*>(ext->Value());
....
}
目前我正在使用以下方法绑定一个函数:
global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print));
具有函数:
static void js_print(const v8::FunctionCallbackInfo<v8::Value> &args);
实施:
void V8Instance::js_print(const v8::FunctionCallbackInfo<v8::Value> &args) {
for (int i = 0; i < args.Length(); i++) {
v8::HandleScope handle_scope(args.GetIsolate());
v8::String::Utf8Value str(args[i]);
std::cout << *str << std::endl;
}
std::cout << std::endl;
}
但是我希望我的 js_print 函数能够访问属于 class V8Instance 成员的变量。 V8 是否有类似能够使用 boost::bind(&Class::function, this, ...)
的东西让我绑定成员函数,或者有什么方法可以在每次调用时通过 reference/pointer 将我需要的变量传递给 js_print
吗?
更新
我发现我可以使用 FunctionTemplate::New
的数据参数传递指向我的 class 的指针:
Local<External> self = External::New(isolate, (void *) this);
global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print, self));
我可以使用 args.Data()
在我的 js_print
函数中访问它,但是这个 returns Local<Value>
对象我不确定如何转换回 void *
然后回到我的 class 指针,V8Instance *
。有人知道怎么做吗?
您可以将 C++ 对象包装到相应的 v8::ObjectTemplate
中并为其设置访问器,如 V8 Embedder's Guide 中所述。
要包装 C++ class(即要使用来自 JavaScript 的此 C++ class 的许多 C++ 实例),您需要创建 V8 FunctionTemplate
作为 JS包装 class 的构造函数,它将在 V8 Object
实例中存储指向 C++ 对象的指针,并为 class 中所需的成员函数设置 V8 函数回调。这些回调应该从 V8 对象中解包 C++ 对象,并为解包的对象调用适当的成员函数。
这种方法会导致编写大量样板代码。 Node.js 允许在本机插件中从 node::ObjectWrap
继承 C++ class。
我还创建了 v8pp 库,它以非侵入式方式绑定 C++ classes、函数和 lambda,没有继承。
存在几个类似的库。但是,据我所知,它们已经过时并且不支持新的 V8 版本。
Update. 要从外部数据中获取 V8Instance*
,您需要将 args.Data()
值转换为 v8::External
,然后从该外部数据获取指针值并将其转换为 V8Instance*
。像这样:
void V8Instance::js_print(const v8::FunctionCallbackInfo<v8::Value> &args)
{
v8::Local<v8::External> ext = args.Data().As<v8::External>();
V8Instance* self = static_cast<V8Instance*>(ext->Value());
....
}