2016-04-16 1 views
1

Я хотел бы вызвать обратный вызов nodejs из моей асинхронной функции аддона. Я видел синхронный пример (here) , и я использую замечательный асинхронный пример (here) в качестве начальной базы.NodeJS Аддон, вызывающий обратный вызов Javascript изнутри NAN AsyncWorker :: Execute

Однако, когда я пытаюсь выполнить обратный вызов, который был передан дочернему классу C++ AsyncWorker, я получаю ошибку сегментации.

Вот мой код:

#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) 

Мои вопросы:

  1. Должен ли я не использовать AsyncWorker Нэн и вместо того, чтобы катиться самостоятельно?
  2. Как настроить функцию Execute для вызова в Javascript?

ответ

4

EDIT:

Смотрите этот репозиторий:

https://github.com/xavero/node_addon_sample

он имеет образец, как работать с функциями обратного вызова и испускающих событий из C земли.

Вы не должны вызывать функции v8/Nan в методе Execute ScriptWorker, иначе вы получите ошибки сегмента. Переопределите функцию HandleOKCallback, чтобы использовать обратный вызов javascript.

Чтобы позвонить из JavaScript в вашем C++ аддон:

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

NODE_MODULE(anyNameHere, Init) 

А в вашем 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

К сожалению, я был в отпуске, но теперь я вернулся и готов к решить эту проблему. @ Xavero, я забыл включить вызовы NAN_MODULE_INIT и NODE_MODULE в свой пример. Они там сейчас. Я вижу, что вы говорите о создании объектов V8 и вызовов за пределами основного потока. Я думаю, мне нужно пойти в старую школу и использовать uv_thread_create() и uv_async_t в сочетании с uv_mutex_t, чтобы сделать «обычай» (за пределами ожидаемых NAN AsyncWorker) звонков. Есть предположения? – EToreo

+0

Если вы хотите получить обратный вызов (выполнить функцию асинхронизации C, а затем javascript с ответом), правильный путь - с помощью AsyncQueueWorker + ScriptWorker. Доверьтесь мне. Теперь, если вы хотите выпустить событие из земли C, вам понадобится использовать uv lib – Xavero

+0

Я сделал это в проекте на прошлой неделе ... позвольте мне настроить сущность или что-то с простым образцом. Дайте мне несколько часов. – Xavero

Смежные вопросы