如何在V8中公开c++类成员

How to expose C++ class member in V8

本文关键字:c++ 成员 V8      更新时间:2023-10-16

我想在v8中暴露c++类成员,我知道如何暴露类方法,但我不知道如何暴露类成员。

c++类:

class Person{
public:
string name;
}
Javascript:

var p1 = new Person();
p1.name = "Jack";

我想做到这一点,这是可能的。谢谢!

您可以使用SetAccessor()作为Person原型模板,提供成员指针作为外部V8数据。但是你需要将Person的c++实例包装成V8对象,然后在访问器getter/setter回调中将这个V8对象解包装回c++对象。this ()

在我的v8pp库中使用这种方式。该库简化了c++类和函数对V8的暴露。对于类成员变量,它看起来像这样:

v8pp::class_<Person> Person_class(isolate);
Person_class
    // bind member variable
    .set("name", &Person::name)

pmed所说的是正确的,但是要扩展一点,您将创建一个带有InternalFieldCount = 1的ObjectTemplate(可能通过FunctionTemplate),并将cpp对象作为v8::External抛出。

然后在ObjectTemplate上调用SetAccessor,使用您希望与数据成员对应的javascript属性的名称(可能是相同的名称,尽管您必须小心javascript保留字),以及检索它的函数。在该函数中,您从内部字段获取cpp对象,并使用它返回数据成员的值,并以您想要的任何格式将其返回给javascript。

然后,当您使用该ObjectTemplate创建对象(ObjectTemplate::NewInstance())时,您必须通过v8::Object::SetInternalField()调用将适当的cpp对象放入其内部字段。

下面的代码没有经过测试,但应该非常接近:

void getter_function(Local< String > property, const PropertyCallbackInfo< Value > &info) {
    Person * person = static_cast<Person*>(info.This().GetInternalField(0));
    info.GetReturnValue().Set(v8::String::NewFromUtf8(person->name.c_str()));
}
auto obj_template = v8::ObjectTemplate::New(a_v8_isolate);
obj_template.SetAccessor(v8::String::NewFromUtf8(a_v8_isolate, "name"), getter_function /* setter is optional */);
auto js_obj = my_object_template.NewInstance(a_v8_context);
js_obj.SetInternalField(new Person());

我也写了一个库来做这件事:https://github.com/xaxxon/v8toolkit但是pmed的可能更稳定。我有一些疯狂的东西,比如clang c++编译器的一个插件,它可以自动读取你的源代码,并自动为你的c++类生成绑定。