Ошибка сегментации обратного вызова Node.js C++ async librarary(libvlc)
Я пытаюсь создать оболочку для libvlc для node.js (большинство из них устарели). LibLVC генерирует свои события асинхронно, но если я попытаюсь вызвать js callback в таком случае, он столкнется с ошибкой сегментации. Я нашел решения для libuv и AsyncWorker Нана, но ни один не может помочь.
Ошибка сегментации происходит в функции on_media_player_end_reached
на Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(_cb), 0, 0);
,
#include <node.h>
#include <nan.h>
#include <vlc/vlc.h>
namespace libvlc {
using v8::Handle;
using v8::Persistent;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Context;
using v8::Primitive;
using node::AtExit;
int isPlaying = 1;
libvlc_instance_t *inst;
libvlc_media_player_t *mp;
libvlc_media_t *m;
libvlc_event_manager_t *evm;
void Play(const FunctionCallbackInfo <Value> &args) {
v8::String::Utf8Value str(args[0]->ToString());
char *link = (char*) *str;
m = libvlc_media_new_location(inst, link);
libvlc_media_player_set_media(mp, m);
libvlc_media_release(m);
libvlc_media_player_play (mp);
}
static Nan::CopyablePersistentTraits<v8::Function>::CopyablePersistent _cb;
void on_media_player_end_reached(const libvlc_event_t*, void *data) {
Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(_cb), 0, 0);
_cb.Reset();
}
void OnMediaPlayerEndReached(const Nan::FunctionCallbackInfo<Value> &args) {
_cb = Nan::Persistent<Function>(args[0].As<Function>());
libvlc_event_attach(evm, libvlc_MediaPlayerEndReached, on_media_player_end_reached, NULL);
}
void release_vlc(void *) {
libvlc_media_player_release(mp);
libvlc_release(inst);
}
void init(Local <Object> exports) {
char const *vlc_argv[] = {"--no-video"};
inst = libvlc_new(1, vlc_argv);
mp = libvlc_media_player_new(inst);
evm = libvlc_media_player_event_manager(mp);
NODE_SET_METHOD(exports, "play", Play);
Nan::SetMethod(exports, "onMediaPlayerEndReached", OnMediaPlayerEndReached);
AtExit(release_vlc);
}
NODE_MODULE(libvlc, init)
}
РЕДАКТИРОВАТЬ: На основе этого ответа я обнаружил, что мне нужно уведомить цикл событий, в котором работает узел. Также я изменил код и теперь я получаю
FATAL ERROR: v8::HandleScope::CreateHandle() Cannot create a handle without a HandleScope
1: node::Abort() [node]
2: 0x12b82ac [node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
4: v8::internal::HandleScope::Extend(v8::internal::Isolate*) [node]
5: v8::HandleScope::CreateHandle(v8::internal::Isolate*, v8::internal::Object*) [node]
6: libvlc::async_cb_handler(uv_async_s*) [/mnt/old/home/martin/Projects/iaeste/prehravac/build/Release/vlc.node]
7: 0x15671db [node]
8: 0x15672b3 [node]
9: 0x1577a48 [node]
10: uv_run [node]
11: node::Start(uv_loop_s*, int, char const* const*, int, char const* const*) [node]
12: node::Start(int, char**) [node]
13: __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
14: 0x8f0111 [node]
Модифицированный код:
#include <node.h>
#include <nan.h>
#include <vlc/vlc.h>
#include <uv.h>
namespace libvlc {
using v8::Handle;
using v8::Persistent;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Context;
using v8::Primitive;
using node::AtExit;
int isPlaying = 1;
libvlc_instance_t *inst;
libvlc_media_player_t *mp;
libvlc_media_t *m;
libvlc_event_manager_t *evm;
uv_async_t async;
void Play(const FunctionCallbackInfo <Value> &args) {
v8::String::Utf8Value str(args[0]->ToString());
char *link = (char*) *str;
m = libvlc_media_new_location(inst, link);
libvlc_media_player_set_media(mp, m);
libvlc_media_release(m);
libvlc_media_player_play (mp);
}
static Nan::CopyablePersistentTraits<v8::Function>::CopyablePersistent _cb;
void on_media_player_end_reached(const libvlc_event_t*, void *data) {
uv_async_send(&async);
//Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(_cb), 0, 0);
//_cb.Reset();
}
void OnMediaPlayerEndReached(const Nan::FunctionCallbackInfo<Value> &args) {
_cb = Nan::Persistent<Function>(args[0].As<Function>());
libvlc_event_attach(evm, libvlc_MediaPlayerEndReached, on_media_player_end_reached, NULL);
}
void release_vlc(void *) {
libvlc_media_player_release(mp);
libvlc_release(inst);
}
void async_cb_handler(uv_async_t *handle) {
Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(_cb), 0, 0);
_cb.Reset();
}
void init(Local <Object> exports) {
char const *vlc_argv[] = {"--no-video"};
inst = libvlc_new(1, vlc_argv);
mp = libvlc_media_player_new(inst);
evm = libvlc_media_player_event_manager(mp);
uv_async_init(uv_default_loop(), &async, async_cb_handler);
NODE_SET_METHOD(exports, "play", Play);
Nan::SetMethod(exports, "onMediaPlayerEndReached", OnMediaPlayerEndReached);
AtExit(release_vlc);
}
NODE_MODULE(libvlc, init)
}