2016-08-01 10 views
0
Zeiger auf void

Zeit eine Funktion mit der folgenden Ich Bindung:V8 - Casting args.Data() zurück

global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print)); 

Mit der Funktion:

static void js_print(const v8::FunctionCallbackInfo<v8::Value> &args); 

Umsetzung:

void V8Instance::js_print(const v8::FunctionCallbackInfo<v8::Value> &args) { 
    for (int i = 0; i < args.Length(); i++) { 
     v8::HandleScope handle_scope(args.GetIsolate()); 
     v8::String::Utf8Value str(args[i]); 
     std::cout << *str << std::endl; 
    } 
    std::cout << std::endl; 
} 

Allerdings möchte ich meine js_print-Funktion Zugriff auf eine Variable, die ein Mitglied der Klasse V8Instance ist. Hat V8 etwas, das in der Lage ist, boost::bind(&Class::function, this, ...) zu verwenden, das mich Elementfunktionen binden kann, oder gibt es eine Möglichkeit, die Variable, die ich benötige, durch Verweis/Zeiger an js_print jedes Mal zu übergeben, wenn es aufgerufen wird?

aktualisieren

ich herausgefunden haben, dass ich die Datenparameter von FunctionTemplate::New einen Zeiger auf meiner Klasse passieren kann mit:

Local<External> self = External::New(isolate, (void *) this); 
global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print, self)); 

Das kann ich Zugriff auf meine js_print Funktion args.Data() aber kehrt Local<Value> Objekt, das ich nicht sicher bin, wie zu void * zurückgeworfen werden und dann zurück zu meinem Klassenzeiger, V8Instance *. Weiß jemand, wie man das macht?

Antwort

1

Sie können ein C++ - Objekt in eine entsprechende v8::ObjectTemplate umbrechen und Accessoren dafür einrichten, wie in V8 Embedder's Guide beschrieben. Um eine C++ - Klasse zu umschließen (dh viele C++ - Instanzen dieser C++ - Klasse aus JavaScript zu verwenden), müssen Sie V8 FunctionTemplate als JS-Konstruktorfunktion für die umhüllte Klasse erstellen, die den Zeiger auf ein C++ - Objekt in einem V8 speichert Object und Callbacks für V8-Funktionen für die gewünschten Elementfunktionen in der Klasse. Diese Rückrufe sollten das C++ - Objekt aus dem V8-Objekt auspacken und die entsprechende Elementfunktion für das unverpackte Objekt aufrufen.

Diese Herangehensweise führt dazu, dass viel Code geschrieben wird. Node.js erlaubt es, die C++ Klasse von node::ObjectWrap in einem nativen Addon zu erben.

Ich habe auch erstellt v8pp Bibliothek, die C++ - Klassen, Funktionen und Lambdas in nicht-intrusive Weise, ohne Vererbung bindet.

Es sind mehrere ähnliche Bibliotheken vorhanden. Aber wie ich weiß, sind sie veraltet und unterstützen keine neuen V8-Versionen.

Aktualisierung. Um V8Instance* von externen Daten zu bekommen, müssen Sie args.Data() Wert zu v8::External umwandeln und dann Zeiger von diesem externen Wert holen und es auf V8Instance* werfen. Etwas wie folgt aus:

void V8Instance::js_print(const v8::FunctionCallbackInfo<v8::Value> &args) 
{ 
    v8::Local<v8::External> ext = args.Data().As<v8::External>(); 
    V8Instance* self = static_cast<V8Instance*>(ext->Value()); 
    .... 
} 
+0

Ich fragte an der Gruppe v8 Google und anscheinend kann ich nur einen Zeiger auf meiner Klasse als Daten in der 'FunctionTemplate' passieren Ich habe herausgefunden, wie dies zu tun mit (3. Argument.) Folgendes: 'Local self = External :: New (isolieren, (void *) this);' und dann übergeben 'selbst' als das dritte Argument, aber ich kann nicht herausfinden, wie zu konvertieren 'args.Data() '(in' js_print') zurück zu 'V8Instance *' – Jack

+0

Hinzugefügt Update in meiner Antwort. – pmed

+0

Danke, ja, genau das habe ich gesucht. Marked correct – Jack