2012-07-16 26 views
4

我有幾個簡單的C++類,例如:將C++方法綁定到現有JS函數原型的最簡單方法是什麼?

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-果汁和大量的博客......我找不到關於如何用C++方法「覆蓋」JS函數的單一參考。我希望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

你看過https://developers.google.com/native-client/嗎? – MadScientist 2012-07-16 07:06:22

回答

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「class」的情況下才能使用(使得可以在JS IDE中定義和記錄所有的函數)。

+0

我不喜歡接受我自己的答案。如果有人對我的原始問題有解決方案,我會接受該答案。 – 2012-07-19 14:43:58

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

我做到了,那是因爲它似乎這是通常的數據類型實現的方式。也許我稍後將原型移動到原型上,但是我會看看這是否合理。

相關問題