В JS-коде биндится callback в глобальную область видимости, который потом нужно вызывать внутри C++ кода, который не связан с Node.JS и работает асинхронно через pthread, в отдельном потоке.
Упрощённо:
Persistent<Function> processCallback;
Handle<Value> bindProcess(const Arguments &args)
{
HandleScope scope;
if ( ! args[0]->IsFunction()) {
ThrowException(Exception::TypeError(String::New("Callback argument must be a function")));
return scope.Close(Undefined());
}
Local<Function> callback = Local<Function>::Cast( args[0] );
processCallback = Persistent<Function>::New( callback );
return scope.Close(Undefined());
}
int process()
{
const unsigned argc = 1;
Local<Value> argv[argc] = { Local<Value>::New( Number::New(123) ) };
processCallback->Call(Context::GetCurrent()->Global(), argc, argv);
return 0;
}
Проблема в том, что код в process, как ни крутил, — вываливается segfault-ом. Я явно что-то недопонимаю и делаю ошибку в архитектуре. Подскажите, как правильно это реализовать? Возможно нужно что-то делать через uv?
UPD: Проблема решилась после курения мануалов по libuv:
uv_work_t *baton;
void work(uv_work_t* task) {}
void after(uv_work_t* task, int status) {
HandleScope scope;
int n = *((int*)(&task->data));
const unsigned argc = 1;
Local<Value> argv[argc] = { Local<Value>::New( Number::New(n) ) };
processCallback->Call(Context::GetCurrent()->Global(), argc, argv);
scope.Close(Undefined());
delete task;
}
int process()
{
baton = new uv_work_t();
baton->data = (void*)123;
uv_queue_work(uv_default_loop(), baton, work, after);
return 0;
}
Теперь проблема в том, что код вызова в process асинхронен, мне нужно внутри process дождаться выполнения after и только после этого продолжить. Как это сделать — это уже пожалуй другой топик.
UPD2: синхронность обеспечена через семафоры:
Как синхронизировать libuv код?