V8 对象包装器未正确添加属性
V8 object wrapper is not adding properties correctly
我有一个名为 TransformComponent
的 C++ class,它具有三个 glm::vec3*
类型的属性。我正在尝试将此 class 的实例公开给我的 JS 代码,但我很难包装它。
这是我的包装代码:
v8::Local<v8::Object> TransformComponent::WrapObject(TransformComponent* object)
{
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Context::Scope context_scope(context);
v8::Local<v8::ObjectTemplate> class_template = v8::ObjectTemplate::New(isolate);
class_template->SetInternalFieldCount(1);
// class_template->SetAccessor(v8::String::NewFromUtf8(isolate, "position"), V8_GetPosition);
// class_template->SetAccessor(v8::String::NewFromUtf8(isolate, "rotation"), V8_GetRotation);
class_template->SetAccessor(v8::String::NewFromUtf8(isolate, "scale"), V8_GetScale);
v8::Local<v8::Object> obj = class_template->NewInstance(context).ToLocalChecked();
obj->SetInternalField(0, v8::External::New(isolate, object));
return obj;
}
这是我的getter方法:
void TransformComponent::V8_GetScale(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info)
{
printf("S: Getter called!\n");
TransformComponent* component = V8Helper::UnwrapObject<TransformComponent>(info);
info.GetReturnValue().Set(Vec3Wrapper::WrapObject(component->scale));
}
最后这就是我在全局 js 对象中注入包装对象的方式:
v8::Local<v8::Object> transform_obj = TransformComponent::WrapObject(actor->GetComponent<TransformComponent>());
global->Set(V8_STR("transform"), transform_obj);
使用这段代码,一个名为 transform
的全局对象在 JS 代码中变得可用,但由于某种原因,它的属性未定义 (console.log(transform.scale); prints 'undefined'
),即使我正在调用 SetAccessor
并传递正确的函数。 getter 函数甚至没有被调用,因为 printf 没有向控制台打印任何内容。
我是不是漏掉了什么?我已经尝试将嵌套对象包装在一个单独的项目中(我通常在主项目中实现它们之前测试 V8 的东西),并且它在那里工作。 Here 你可以看看我用 Point*
属性.
包装 Line
对象的工作测试程序
这里是 V8 开发人员。我要尝试的第一件事是从 WrapObject
函数中删除 HandleScope
。当 HandleScope 超出范围时,它会使在其中创建的所有句柄都无效——在这种情况下,特别是 obj
。所以我真的很惊讶这段代码不会崩溃 ;-)
如果您确实需要本地 HandleScope,可以使用 EscapableHandleScope,它内部有一个特殊插槽,可以让一个句柄比它长寿。
我有一个名为 TransformComponent
的 C++ class,它具有三个 glm::vec3*
类型的属性。我正在尝试将此 class 的实例公开给我的 JS 代码,但我很难包装它。
这是我的包装代码:
v8::Local<v8::Object> TransformComponent::WrapObject(TransformComponent* object)
{
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Context::Scope context_scope(context);
v8::Local<v8::ObjectTemplate> class_template = v8::ObjectTemplate::New(isolate);
class_template->SetInternalFieldCount(1);
// class_template->SetAccessor(v8::String::NewFromUtf8(isolate, "position"), V8_GetPosition);
// class_template->SetAccessor(v8::String::NewFromUtf8(isolate, "rotation"), V8_GetRotation);
class_template->SetAccessor(v8::String::NewFromUtf8(isolate, "scale"), V8_GetScale);
v8::Local<v8::Object> obj = class_template->NewInstance(context).ToLocalChecked();
obj->SetInternalField(0, v8::External::New(isolate, object));
return obj;
}
这是我的getter方法:
void TransformComponent::V8_GetScale(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info)
{
printf("S: Getter called!\n");
TransformComponent* component = V8Helper::UnwrapObject<TransformComponent>(info);
info.GetReturnValue().Set(Vec3Wrapper::WrapObject(component->scale));
}
最后这就是我在全局 js 对象中注入包装对象的方式:
v8::Local<v8::Object> transform_obj = TransformComponent::WrapObject(actor->GetComponent<TransformComponent>());
global->Set(V8_STR("transform"), transform_obj);
使用这段代码,一个名为 transform
的全局对象在 JS 代码中变得可用,但由于某种原因,它的属性未定义 (console.log(transform.scale); prints 'undefined'
),即使我正在调用 SetAccessor
并传递正确的函数。 getter 函数甚至没有被调用,因为 printf 没有向控制台打印任何内容。
我是不是漏掉了什么?我已经尝试将嵌套对象包装在一个单独的项目中(我通常在主项目中实现它们之前测试 V8 的东西),并且它在那里工作。 Here 你可以看看我用 Point*
属性.
Line
对象的工作测试程序
这里是 V8 开发人员。我要尝试的第一件事是从 WrapObject
函数中删除 HandleScope
。当 HandleScope 超出范围时,它会使在其中创建的所有句柄都无效——在这种情况下,特别是 obj
。所以我真的很惊讶这段代码不会崩溃 ;-)
如果您确实需要本地 HandleScope,可以使用 EscapableHandleScope,它内部有一个特殊插槽,可以让一个句柄比它长寿。