2010-06-18 2 views
29

Il official examples di esporre una classe Point sembra presupporre che ci sarà un numero fisso di istanze di esso nel vostro programma. Non è chiaro in che modo vengono allocate nuove istanze nel codice C++, quando new viene chiamato in Javascript.Come si espone una classe C++ nel motore Javascript V8 in modo che possa essere creata utilizzando nuovo?

Come esporre una classe che può avere più istanze? Ad esempio, una classe Image:

var img1 = new Image(640, 480); 
var img2 = new Image(1024, 768); 

img1.clear("red"); 
img2.clear("black"); 

risposta

-11

non so come raggiungere questo obiettivo nel motore V8 Js esattamente, ma come nel mondo Python, si può semplicemente fare come segue. la classe Image:

class Image 
{ 
public: 
    Image(int w, int h); 
    int Width(void) const; 
}; 

scrivere alcune funzioni wrapper ed esporre queste funzioni per il mondo Js:

Image* Image_New(int w, int h) { return new Image(w, h); } 
void Image_Delete(Image* pImage) { delete pImage; } 
int Image_Width(const Image* pImage) { return pImage->Width(); } 

aggiungere i seguenti codici per il file js:

var Image = function (w, h) { 
    this.image = new Image(w, h); 
    this.Width = function() { 
     return Image_Width(this.image); 
    }; 
}; 

e ora puoi farti lavorare il codice. Inoltre, i codici di cui sopra non tengono conto del meccanismo di Garbage Collection, quindi prestate particolare attenzione a questo. Scusate il mio inglese Borken!

+0

Che sull'esportazione di funzioni definite? – Basilevs

+1

Sì, python ha un'ottima API per questo. Ecco perché V8 è così confuso! Perché non c'è V8 :: FunctionTemplate :: SetClassAllocator (AllocateFn, FreeFn)? –

+2

v8 è molto più veloce di Python anche se – ShrekOverflow

30

Questo è il migliore blog post I could find on exposing C++ objects to V8 Javascript. Passa a dettagli più profondi e lo suddivide in passaggi più piccoli con frammenti di codice. State attenti: i frammenti di codice hanno poche incongruenze e mi ci sono volute diverse letture per capire. Leggere il mio breve sommario può aiutare:

  1. Gli oggetti devono essere racchiusi in modelli V8. Nota: l'esempio di Google utilizza ObjectTemplates, ma l'autore spiega perché preferisce FunctionTemplates.
    1. Creazione di un modello di funzione. Le istanze di questo modello hanno un campo interno per memorizzare l'indirizzo di memoria dell'oggetto C++. Ottengono anche i metodi di accesso della classe.
    2. Crea una funzione wrapObject() che avvolgerà un oggetto C++ in uno di questi FunctionTemplates.
  2. Il costruttore deve anche essere racchiuso in un modello (diverso) V8. Un modello diverso viene utilizzato per evitare la ricorsione indesiderata. (Un metodo per combinare entrambi i modelli in uno è descritto alla fine del post del blog.)
    1. Creare un altro FunctionTemplate. Questo modello collega semplicemente l'ambito globale di JavaScript (dove new verrà chiamato da) al costruttore C++.
    2. Effettuare il metodo che verrà chiamato dal modello. Questo metodo utilizza effettivamente l'operatore C++ new e chiama il costruttore della classe C++. Quindi avvolge l'oggetto chiamando il metodo wrapObject() creato nel passaggio 1.2.

Ora, la memoria allocata al punto 2.2 deve essere delete 'D po' di tempo.Aggiornamento: Il prossimo post di blog, "Persistent Handles", illustra questo in dettaglio.

mie note sulla actual code alluded to in these blog posts:

  • Il metodo wrapPoint() nel blog è in realtà analogo al metodo unwrap() nel codice vero e proprio; nonwrap()
  • Per trovare altri punti in comune tra il codice, cercare: SetInternalFieldCount(0, constructorCall
  • Il codice vero e proprio sembra di fare la gestione della memoria utilizzando il metodo MakeWeak() per impostare un metodo di callback che fa la pulizia.
+0

il post sul blog che hai collegato in cima è morto – xaxxon

+0

@xaxxon: ho aggiornato i collegamenti con le versioni archiviate – Leftium