2017-12-01 8 views
1

ループから定期的にコールバックを行うネイティブNodeJSモジュールを作成しようとしています。私はコールバックを作るためにメインスレッドに戻るために必要なlibuvビットの周りに頭を抱えていると思っていますが、カルバックを作る瞬間にまだsigsegvでクラッシュしています。Native to NodeJSコールバック

test_sbio.cpp:

#include <node.h> 
#include "SBIONative.h" 

namespace sbio { 

using v8::Local; 
using v8::Object; 

void InitAll(Local<Object> exports) { 
    SBIONative::Init(exports); 
} 

NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll) 

} 

SBIONative.h:

#ifndef SBIONative_H 
#define SBIONative_H 

#include <iostream> 
#include <unistd.h> 

#include <uv.h> 
#include <node.h> 
#include <node_object_wrap.h> 

namespace sbio { 
    class SBIONative : public node::ObjectWrap { 
    public: 
     static void Init(v8::Local<v8::Object> exports); 

    private: 
     explicit SBIONative(); 
     ~SBIONative(); 

     static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 
     static v8::Persistent<v8::Function> constructor; 
     static void Start(const v8::FunctionCallbackInfo<v8::Value>& args); 
     static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args); 

     static void loop(void *arg); 
     static void asyncmsg(uv_async_t* handle); 
     v8::Persistent<v8::Function> cb; 
     bool run_; 
     uv_async_t async; 
     uv_thread_t event_loop; 
    }; 
} 
#endif 

SBIONative.cpp:

#include <SBIONative.h> 

namespace sbio { 
    using v8::Context; 
    using v8::Function; 
    using v8::FunctionCallbackInfo; 
    using v8::FunctionTemplate; 
    using v8::Isolate; 
    using v8::HandleScope; 
    using v8::Local; 
    using v8::Number; 
    using v8::Object; 
    using v8::Persistent; 
    using v8::String; 
    using v8::Value; 

    Persistent<Function> SBIONative::constructor; 

    SBIONative::SBIONative() { 
    } 

    SBIONative::~SBIONative() { 
    } 

    void SBIONative::Init(Local<Object> exports) { 
     Isolate* isolate = exports->GetIsolate(); 

     // Prepare constructor template 
     Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New); 
     tpl->SetClassName(String::NewFromUtf8(isolate, "SBIONative")); 
     tpl->InstanceTemplate()->SetInternalFieldCount(2); 

     // Prototype 
     NODE_SET_PROTOTYPE_METHOD(tpl, "start", Start); 
     NODE_SET_PROTOTYPE_METHOD(tpl, "stop", Stop); 

     constructor.Reset(isolate, tpl->GetFunction()); 
     exports->Set(String::NewFromUtf8(isolate, "SBIONative"), 
        tpl->GetFunction()); 

    } 

    void SBIONative::New(const FunctionCallbackInfo<Value>& args) { 
     Isolate* isolate = args.GetIsolate(); 

     if (args.IsConstructCall()) { 
     // Invoked as constructor: `new MyObject(...)` 
     SBIONative* obj = new SBIONative(); 
     obj->Wrap(args.This()); 
     args.GetReturnValue().Set(args.This()); 

     uv_loop_t* loop = uv_default_loop(); 
     uv_async_init(loop, &obj->async, asyncmsg); 
     } else { 
     // Invoked as plain function `MyObject(...)`, turn into construct call. 
     const int argc = 1; 
     Local<Value> argv[argc] = { args[0] }; 
     Local<Context> context = isolate->GetCurrentContext(); 
     Local<Function> cons = Local<Function>::New(isolate, constructor); 
     Local<Object> result = 
      cons->NewInstance(context, argc, argv).ToLocalChecked(); 
     args.GetReturnValue().Set(result); 
     } 
    } 

    void SBIONative::Start(const FunctionCallbackInfo<Value>& args) { 
     std::cout << "Start\n"; 
     Isolate* isolate = args.GetIsolate(); 
     SBIONative* obj = ObjectWrap::Unwrap<SBIONative>(args.Holder()); 
     obj->run_ = true; 

     Local<Function> callback = Local<v8::Function>::Cast(args[0]); 
     obj->cb.Reset(isolate, callback); 

     uv_thread_create(&obj->event_loop, SBIONative::loop, (void*)obj); 
    } 

    void SBIONative::Stop(const FunctionCallbackInfo<Value>& args) { 
     std::cout << "Stop\n"; 
     SBIONative* obj = ObjectWrap::Unwrap<SBIONative>(args.Holder()); 
     obj->run_ = false; 
     uv_close((uv_handle_t*) &obj->async, NULL); 
    } 

    void SBIONative::loop(void *arg) { 
     SBIONative* obj = (SBIONative*)arg; 

     while(obj->run_) { 
      usleep(1 * 1000 * 1000); 
      std::cout << "loop\n"; 
      obj->async.data = &obj->cb; 
      uv_async_send(&obj->async); 
     } 

     std::cout << "after loop" << std::endl; 
    } 

    void SBIONative::asyncmsg(uv_async_t* handle) { 
     v8::Isolate* isolate = v8::Isolate::GetCurrent(); 
     v8::HandleScope scope(isolate); 
     Local<Value> argv[] = { v8::String::NewFromUtf8(isolate, "Hello world") }; 
     //TODO This breaks here 
     ((v8::Function*)handle->data)->Call(isolate->GetCurrentContext()->Global(), 1, argv); 
     std::cout << "callback" << std::endl; 
    } 
} 

私はMac上でそれを構築する場合、これは同じ場所で失敗しますLinux上で動作します。今日までの私の推測は、オブジェクトにコールバックを格納すること、またはそれをキャストすることです。

答えて

1

今日、私はもう一度このソリューションを利用しています。そのトリックは、自分のネイティブインターフェースを試してみるのではなく、Nanを使うことでした。

addon.c:

#include <nan.h> 
#include "test.h" 

void InitAll(v8::Local<v8::Object> exports) { 
    test::Test::Init(exports); 
} 

NODE_MODULE(addon, InitAll) 

TEST.H:

#ifndef TEST_H 
#define TEST_H 

#include <nan.h> 

#include <iostream> 
#include <unistd.h> 

namespace test { 
    class Test : public Nan::ObjectWrap { 
    public: 
     static void Init(v8::Local<v8::Object> exports); 
    private: 
     explicit Test(); 
     ~Test(); 

     static void New(const Nan::FunctionCallbackInfo<v8::Value>& info); 
     static void Start(const Nan::FunctionCallbackInfo<v8::Value>& info); 
     static void Stop(const Nan::FunctionCallbackInfo<v8::Value>& info); 
     static void loop(void *arg); 
     static void asyncmsg(uv_async_t* handle); 
     static Nan::Persistent<v8::Function> constructor; 

     bool run_; 
     Nan::Callback* callback; 

     uv_async_t async; 
     uv_thread_t event_loop; 
    }; 
} 

#endif 

ます。test.cpp:

#include "test.h" 

namespace test { 

    Nan::Persistent<v8::Function> Test::constructor; 

    Test::Test(){} 

    Test::~Test(){} 

    void Test::Init(v8::Local<v8::Object> exports) { 
     Nan::HandleScope scope; 

     v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New); 
     tpl->SetClassName(Nan::New("Test").ToLocalChecked()); 
     tpl->InstanceTemplate()->SetInternalFieldCount(1); 

     Nan::SetPrototypeMethod(tpl, "start", Start); 
     Nan::SetPrototypeMethod(tpl, "stop", Stop); 

     constructor.Reset(tpl->GetFunction()); 
     exports->Set(Nan::New("Test").ToLocalChecked(), tpl->GetFunction()); 
    } 

    void Test::New(const Nan::FunctionCallbackInfo<v8::Value>& info) { 
     if (info.IsConstructCall()) { 
     // Invoked as constructor: `new Test(...)` 
     test::Test* obj = new test::Test(); 
     obj->Wrap(info.This()); 
     info.GetReturnValue().Set(info.This()); 
     uv_loop_t* loop = uv_default_loop(); 
      uv_async_init(loop, &obj->async, asyncmsg); 
     } else { 
     // Invoked as plain function `Test(...)`, turn into construct call. 
     const int argc = 1; 
     v8::Local<v8::Value> argv[argc] = { info[0] }; 
     v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor); 
     info.GetReturnValue().Set(cons->NewInstance(argc, argv)); 
     } 
    } 

    void Test::Start(const Nan::FunctionCallbackInfo<v8::Value>& info) { 
     Test* obj = ObjectWrap::Unwrap<Test>(info.Holder()); 
     obj->callback = new Nan::Callback(info[0].As<v8::Function>()); 
     obj->run_ = true; 

     uv_thread_create(&obj->event_loop, Test::loop, (void*)obj); 
    } 

    void Test::Stop(const Nan::FunctionCallbackInfo<v8::Value>& info) { 
     Test* obj = ObjectWrap::Unwrap<Test>(info.Holder()); 
     obj->run_ = false; 
    } 

    void Test::loop(void *arg) {  
     Test* obj = (Test*)arg; 

     while(obj->run_) { 
      usleep(1 * 1000 * 1000); 
      obj->async.data = obj->callback; 
      uv_async_send(&obj->async); 
     } 

     uv_close((uv_handle_t*) &obj->async, NULL); 
    } 

    void Test::asyncmsg(uv_async_t* handle) { 
     Nan::HandleScope scope; 
     v8::Isolate* isolate = v8::Isolate::GetCurrent(); 
     v8::Local<v8::Value> argv[] = { v8::String::NewFromUtf8(isolate, "Loop Callback") }; 
     ((Nan::Callback*)handle->data)->Call(1,argv); 
    } 

} 

まで書くとgithubの上の完全なプロジェクトのコードへのリンクhere

関連する問題