2016-04-16 9 views
1

Ich möchte einen Nodejs Callback aus meiner asynchronen Addon-Funktion aufrufen. Ich habe das synchrone Beispiel (here) gesehen und verwende ein wunderbares asynchrones Beispiel (here) als Ausgangsbasis.NodeJS Addon Aufruf von Javascript Callback von innen NAN AsyncWorker :: Führen Sie

Wenn ich jedoch versuche, einen Rückruf auszuführen, der an die C++ AsyncWorker-Kindklasse übergeben wurde, erhalte ich einen Segmentierungsfehler.

Hier ist mein Code:

#include <nan.h> 
#include <functional> 
#include <iostream> 
#include <exception> 
using namespace Nan; 
using namespace v8; 
using namespace std; 

class ScriptWorker : public AsyncWorker { 
    public: 
    ScriptWorker(Callback *callback, const std::map<std::string, Callback*>) 
    : AsyncWorker(callback), script(script), cbs(cbs) {} 

    ~ScriptWorker() {} 

    void Execute() { 

     // ------------------------ 
     // Segmentation fault after 
     // ------------------------ 

     Local<Value> argv[] = { 
     New<v8::Number>(id) 
     }; 

     // ------------------------- 
     // Segmentation fault before 
     // ------------------------- 

     cbs["getUser"]->Call(1, argv); 
    } 

    private: 
    std::string script; 
    std::map<std::string, Callback*> cbs; 
}; 

NAN_METHOD(Method) { 
    Local<Object> array = info[0]->ToObject(); 
    Callback *callback = new Callback(info[1].As<Function>()); 

    // Build up callbacks passed in from javascript. 
    // Will be a dynamic loop, but for now, hard code the one getUser example. 
    std::map<std::string, Callback*> cbs; 
    cbs.insert(std::pair<std::string, Callback*>("getUser", 
    new Callback(
     array->Get(
     v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "getUser") 
    ).As<Function>() 
    ) 
)); 
    AsyncQueueWorker(new ScriptWorker(callback, cbs)); 
} 

NAN_MODULE_INIT(Init) { 
    Nan::Set(target, Nan::New<String>("hello").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(Method)).ToLocalChecked()); 
} 

NODE_MODULE(hello, Init) 

Meine Fragen:

  1. Sollte ich Nan AsyncWorker nicht und stattdessen meine eigene Rolle?
  2. Wie konfiguriere ich die Funktion Ausführen, um Javascript aufzurufen?

Antwort

4

EDIT:

dieses Repo Siehe:

https://github.com/xavero/node_addon_sample

es eine Probe darauf hat, wie mit Callback-Funktionen und Emissions Ereignissen aus C Land zu arbeiten.

Sie sollten nicht v8/Nan-Funktionen in Ihrer Execute-Methode von ScriptWorker aufrufen, oder Sie erhalten Segmentfehler. Überschreiben Sie die HandleOKCallback-Funktion, um den JavaScript-Rückruf zu verwenden.

vom Javascript aufzurufen, in der C++ Add-on:

NAN_MODULE_INIT(Init) { 
    Nan::Set(target, Nan::New("myJsFunctionName").ToLocalChecked(), 
    Nan::GetFunction(Nan::New<FunctionTemplate>(Method)).ToLocalChecked()); 
} 

NODE_MODULE(anyNameHere, Init) 

Und in Ihrem javascript:

// run "npm install bindings --save" in console first 
var addon = require('bindings')('NativeExtension'); 

addon.myJsFunctionName({ foo: "bar"}, (arg1,arg2) => console.log(`${arg1} - ${arg2}`)) 
+1

Sorry, ich habe im Urlaub gewesen, aber jetzt bin ich wieder da und bereit zu Lass das gelöst werden. @Xavero, ich habe vergessen, die Aufrufe NAN_MODULE_INIT und NODE_MODULE in mein Beispiel aufzunehmen. Sie sind jetzt da. Ich sehe, was Sie über das Erstellen von V8-Objekten und Aufrufen außerhalb des Hauptthreads sagen. Ich denke, ich muss Old-School gehen und verwenden Sie uv_thread_create() und ein uv_async_t gekoppelt mit einem uv_mutex_t, um "custom" (außerhalb dessen, was NAN AsyncWorker erwartet) Anrufe zu machen. Irgendwelche Gedanken? – EToreo

+0

Wenn Sie einen Rückruf wünschen (führen Sie eine C-Async-Funktion und dann ein Javascript mit der Antwort), ist der richtige Weg mit AsyncQueueWorker + ScriptWorker. Vertrau mir. Jetzt, wenn Sie ein Ereignis aus C Land emittieren möchten, dann müssen Sie Uv Lib – Xavero

+0

Ich tat dies in einem Projekt letzte Woche ... lassen Sie mich eine wichtige oder etwas mit einem einfachen Beispiel einrichten. Gib mir ein paar Stunden. – Xavero