Hello,
I am using V8 to expose a C++ API to JavaScript, and I have a use-case where
one would need to have a JavaScript class that inherit from a C++ class. I've
seen from V8 test code how they test the inheritance thing there, but I
couldn't find anything that was specific to my case. I've exhausted all
resources that I could find on Google on this issue so I figured someone might
help here.
I've attached a simplified code snippet for my case. It contains the class that
I expose and the way I use it in JavaScript, so maybe someone can spot what I
am missing.
Thanks in advance.
--
--
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
#include "v8.h"
class CppClass {
public:
CppClass() {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
mAnotherCppClass = new AnotherCppClass();
mJsAnotherCppClass.Reset(isolate,
AnotherCppClass::Wrap(mAnotherCppClass));
}
float MyCppMethod() {
return 2.f + 2.f;
}
// V8 Stuff
static v8::Local Bind() {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
auto funcTemplate = v8::FunctionTemplate::New(isolate,
CppClass_Constructor);
funcTemplate->SetClassName(v8::String::NewFromUtf8(isolate,
"CppClass"));
funcTemplate->InstanceTemplate()->SetInternalFieldCount(1);
funcTemplate->InstanceTemplate()->SetAccessor(v8::String::NewFromUtf8(isolate,
"object"), GetObject);
funcTemplate->PrototypeTemplate()->Set(v8::String::NewFromUtf8(isolate,
"myCppMethod", v8::NewStringType::kNormal).ToLocalChecked(),
v8::FunctionTemplate::New(isolate, MyCppMethod_Callback));
functionTemplate.Reset(isolate, funcTemplate);
return functionTemplate.Get(isolate);
}
static v8::Local Wrap(CppClass* obj) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::EscapableHandleScope handleScope(isolate);
v8::Local instance =
functionTemplate->InstanceTemplate()->NewInstance();
instance->SetInternalField(0, obj);
return handleScope.Escape(instance);
}
static CppClass* Unwrap(v8::Local object) {
return (CppClass*)object->GetInternalField(0);
}
static void CppClass_Constructor(const v8::FunctionCallbackInfo&
args) {
if (!args.IsConstructCall()) {
isolate->ThrowException(v8::String::NewFromUtf8(isolate, "CppClass
cannot be call as function. Use 'new' to instantiate"));
return;
}
CppClass* newObject = new CppClass();
args.GetReturnValue().Set(CppClass::Wrap(newObject));
}
static void GetObject(v8::Local property, const
v8::PropertyCallbackInfo& info) {
CppClass* obj = CppClass::Unwrap(info.Holder());
info.GetReturnValue().Set(obj->mJsAnotherCppClass.Get(v8::Isolate::GetCurrent()));
}
static void MyCppMethod_Callback(const v8::FunctionCallbackInfo&
args) {
CppClass* obj = CppClass::Unwrap(args.This());
args.GetReturnValue().Set(obj->MyMethod());
}
static v8::Persistent functionTemplate;
private:
AnotherCppClass* mAnotherCppClass;
v8::Persistent mJsAnotherCppClass;
};
/// Somewhere in code...
globalObjectTemplate->Set(v8::String::NewFromUtf8(isolate, "CppClass",
v8::NewStringType::kNormal).ToLocalChecked(), CppClass::Bind());
/* ** JavaScript code *** */
class DerivedJsClass extends CppClass {
constructor() {
super();
this.something = 1;
}
myJsMethod() {
return this.something + 2;
}
}
// With above code unmodified:
var obj = new DerivedJsClass(); // Exception: CppClass cannot be call as
function. Use 'new' to instantiate
// When calling args.GetReturnValue().Set(args.This()) in CppClass_Constructor:
var obj = new DerivedJsClass();
console.log(obj.myCppMethod()); // prints 4
console.log(obj.myJsMethod()); // prints 3
console.log(obj.object);// prints undefined