Как реализовать асинхронный конструктор / Factory-Call в родном аддоне C ++ / nodejs?

Я довольно новичок в разработке C ++ и дополнения node / v8.

Я пытаюсь обернуть стороннюю C-библиотеку.
Некоторые функции инициализации выполняются довольно долго, и я хотел бы выполнять эти операции асинхронно (с помощью libuv).

Учитывая, что у меня есть следующий код:

#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
//header files of 3rd party lib to be wrapped
#include "3rdparty.h"
using namespace v8;

MyObject::MyObject(void* base) : baseobject_(base) {};
MyObject::~MyObject() {};

void MyObject::Init(Handle<Object> target) {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);

Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction());
target->Set(String::NewSymbol("MyObject"), constructor);
}

Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
if (args.IsConstructCall())
{
void* cStruct = NULL;

//
//VERY LONG TAKING OPERATION
//Want to run this async with help of libuv
createStructIn3rdPartyLib(&cStruct);

//create actual Object and pass in cStruct which becomes private field.
MyObject* obj = new MyObject(cStruct);
obj->Wrap(args.This());
return args.This();
}

return scope.Close(Undefined());
}

Я хочу бежать createStructIn3rdPartyLib(&cStruct); с помощью библиотеки libuv.

Вот то, что я придумал. К сожалению, это дает мне ошибку сегментации, и я не совсем уверен, правильный ли это подход.
Я уже изучил источник других нод-аддонов, но не нашел решения для моей проблемы. 🙁

Любые намеки приветствуются.

#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
//header files of 3rd party lib to be wrapped
#include "3rdparty.h"
using namespace v8;

// libuv allows us to pass around a pointer to an arbitrary
// object when running asynchronous functions. We create a
// data structure to hold the data we need during and after
// the async work.
typedef struct AsyncData {
Persistent<Function> callback; // callback function
void *3rdpartydata
Arguments *args;
} AsyncData;

MyObject::MyObject() {};
MyObject::~MyObject() {};

void MyObject::Init(Handle<Object> target) {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);

Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction());
target->Set(String::NewSymbol("MyObject"), constructor);
target->Set(String::NewSymbol("createObject"),
FunctionTemplate::New(New)->GetFunction(CreateObjectAsync));

}

Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
if (args.IsConstructCall())
{
void* cStruct = NULL;

//
//VERY LONG TAKING OPERATION
//Want to run this async with help of libuv
createStructIn3rdPartyLib(&cStruct);

//create actual Object and pass in cStruct which becomes private field.
MyObject* obj = new MyObject(&cStruct);
obj->Wrap(args.This());
return args.This();
}

return scope.Close(Undefined());
}

Handle<Value> MyObject::CreateObjectAsync(const Arguments& args)
{
HandleScope scope;
// create an async work token
uv_work_t *req = new uv_work_t;
// assign our data structure that will be passed around
AsyncData *asyncData = new AsyncData();
req->data = asyncData;

// expect a function as the 1st argument
// we create a Persistent reference to it so
// it won't be garbage-collected
asyncData->callback = Persistent<Function>::New(
Local<Function>::Cast(args[0]));

*(asyncData->args) = args;

// pass the work token to libuv to be run when a
// worker-thread is available to
uv_queue_work(
uv_default_loop(),
req,                          // work token
AsyncWork,                    // work function
(uv_after_work_cb)AsyncAfter  // function to run when complete
);

return scope.Close(Undefined());
}// Function to execute inside the worker-thread.
// It is not safe to access V8, or V8 data structures
// here, so everything we need for input and output
// should go on our req->data object.
void MyObject::AsyncWork(uv_work_t *req) {
// fetch our data structure
AsyncData *asyncData = (AsyncData *)req->data;
// run 3rd Party Function.
createStructIn3rdPartyLib(&asyncData->3rdpartydata);
}

// Function to execute when the async work is complete
// this function will be run inside the main event loop
// so it is safe to use V8 again
void MyObject::AsyncAfter(uv_work_t *req) {
HandleScope scope;

// fetch our data structure
AsyncData *asyncData = (AsyncData *)req->data;// create an arguments array for the callback
MyObject *cpBase = new MyObject(asyncData->3rdpartydata);
cpBase->Wrap((*asyncData->args).This());
Handle<Value> argv[] = {Null(),(*asyncData->args).This()};

// surround in a try/catch for safety
TryCatch try_catch;
// execute the callback function
asyncData->callback->Call(Context::GetCurrent()->Global(), 2, argv);
if (try_catch.HasCaught())
node::FatalException(try_catch);

// dispose the Persistent handle so the callback
// function can be garbage-collected
asyncData->callback.Dispose();
// clean up any memory we allocated
delete asyncData;
delete req;
}

Спасибо!!!

Редактировать:
Я после прочтения больше примеров, таких как привязки нод-огг Я все больше думаю о том, что нахожусь на неправильном пути с моим подходом. Возможно я должен остаться на намного более низком уровне на стороне C / C ++ и реализовать функциональность объекта на стороне javascript.

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]