我有几个简单的C ++类,例如:
class Audio {
public:
Audio(const char *filename, bool async = true);
~Audio();
Audio *play(int fade = 0);
Audio *pause();
Audio *loop(int loops = -1);
Audio *volume(float volume);
我在JavaScript中复制了如下结构:
var Audio = function(filename, async) {};
Audio.prototype.Play = function(fade) {};
Audio.prototype.Pause = function() {};
Audio.prototype.Loop = function(loops) {};
Audio.prototype.Volume = function(volume) {};
在阅读了v8,v8-juice和大量博客的文档和来源之后......我找不到关于如何用C ++方法“覆盖”JS函数的单一参考。 / p>
理想情况下,我希望JS能够控制类创建/销毁(这可能吗?),并且这些对象总是指向我的原生函数(PrototypeTemplate?)。
今天我认真地花了一整天阅读与此相关的文章/博客/代码,找不到,我希望的是一个简单的答案。
为了你的缘故,对我来说一个“简单”的回答就是这样的东西(包装对我来说很好;如果我必须为创作/破坏写包装,那就没关系):
v8::Local<v8::Function> jsAudioFunction = v8::Local<v8::Function>::Cast(v8::Context::GetCurrent()->Global()->Get(v8::String::New("Audio")));
jsAudioFunction->Setup(/* setup constructor/destructor */);
jsAudioFunction->SetPrototype(/* map native methods to js functions */);
答案 0 :(得分:2)
虽然这没有回答将本机代码绑定到JS对象的问题,但这是我的劳动成果:
static void jsAudioGC(v8::Persistent<v8::Value> object, void *data) {
v8::Persistent<v8::Object> obj = v8::Persistent<v8::Object>::Cast(object);
Audio *audio = static_cast<Audio*>(obj->GetPointerFromInternalField(0));
if (audio != NULL) {
obj->SetPointerInInternalField(0, NULL);
v8::V8::AdjustAmountOfExternalAllocatedMemory(-sizeof(audio));
delete audio;
}
object.Dispose();
}
v8::Handle<v8::Value> jsAudio(const v8::Arguments &args) {
v8::Persistent<v8::Object>::New(args.This()).MakeWeak(NULL, jsAudioGC);
Audio *audio = new Audio(get(args[0], ""), get(args[1], true));
v8::V8::AdjustAmountOfExternalAllocatedMemory(sizeof(audio));
args.This()->SetPointerInInternalField(0, audio);
return args.This();
}
v8::Handle<v8::Value> jsAudioPlay(const v8::Arguments &args) {
Audio *audio = static_cast<Audio*>(args.This()->GetPointerFromInternalField(0));
if (audio != NULL) audio->play(get(args[0], 0));
return args.This();
}
我的init()函数内部:
v8::Handle<v8::FunctionTemplate> audio = v8::FunctionTemplate::New(&jsAudio);
audio->PrototypeTemplate()->Set("Play", v8::FunctionTemplate::New(&jsAudioPlay));
audio->InstanceTemplate()->SetInternalFieldCount(1);
globals->Set("Audio", audio);
这完全符合我的要求;包括适当的实例化和垃圾收集。
我对这种方法的唯一遗憾是我希望能够“只使用已定义的内容”。这样,这些函数仅在包含JS“类”时才可用(使得可以在JS IDE中定义和记录所有函数)。
答案 1 :(得分:0)
好吧,我遇到了同样的问题......但还没有找到GC集成的东西。对我来说,它主要是有两个不同的模板。一个FunctionTemplate用于构造函数(和实例生成器),一个ObjectTemplate用于生成带回调的数据。
这是C ++ API类的一个示例:
https://github.com/martensms/lycheeJS-adk/blob/master/v8gl/api/script.cpp
这就是JavaScript方面的样子:
https://github.com/martensms/lycheeJS-adk/blob/master/v8gl/test/04-script.js
我是这样做的,因为这似乎是通常的数据类型的实现方式。也许我稍后会在原型上移动方法,但我会看看那是否有意义。