简体   繁体   中英

How to expose C++ class member in V8

I want expose C++ class member in v8, and i know how to expose the class method but i don't know how to expose class member.

C++ class:

class Person{
public:
string name;
}

Javascript:

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

I want to achieve this, It's that possible. thanks!

You may use SetAccessor() for the Person prototype template, supplying pointer the the member as an external V8 Data. But you need to wrap C++ instance of Person into V8 object, and then unwrap this V8 object back to C++ object in accessor getter/setter callbacks from theirs args.This()

I use this way in my v8pp library. The library simplifies exposure of C++ classes and functions to V8. For class member variable it would look like this:

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

What pmed said is correct, but to expand a bit more, you would create an ObjectTemplate (possibly via a FunctionTemplate) with an InternalFieldCount = 1 and throw the cpp object in there as a v8::External.

Then you call SetAccessor on your ObjectTemplate with the name of the javascript property you want to have correspond to your data member (likely the same name, though you have to be careful of javascript reserved words), and a function to retrieve it. In that function, you get the cpp object from the internal field and use that to return the value of the data member, and return that to javascript in whatever format you want.

Then, when you use that ObjectTemplate to create an object ( ObjectTemplate::NewInstance() ), then you have to put the appropriate cpp object into its internal field via the v8::Object::SetInternalField() call.

The following code is not tested, but it should be pretty close:

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());

I, too, have written a library to do this: https://github.com/xaxxon/v8toolkit but pmed's is probably more stable. I have a bit of crazy stuff in mine like a plugin for the clang c++ compiler to automatically read your source code and generate the bindings for your c++ classes automatically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM