关于Node和C++互相调用的问题

最近看了很多的相关文档;但是有有一个地方一直很不解,关于Node调用C++传递回调函数:官方文档如下:
C++部分:
//addon.cc
#include
namespacedemo{
usingv8::Function;
usingv8::FunctionCallbackInfo;
usingv8::Isolate;
usingv8::Local;
usingv8::Null;
usingv8::Object;
usingv8::String;
usingv8::Value;
voidRunCallback(constFunctionCallbackInfo&args){
Isolate*isolate=args.GetIsolate();
Localcb=Local::Cast(args[0]);
constunsignedargc=1;
Localargv[argc]={String::NewFromUtf8(isolate,"helloworld")};
cb->Call(Null(isolate),argc,argv);
}
voidInit(Localexports,Localmodule){
NODE_SET_METHOD(module,"exports",RunCallback);
}
NODE_MODULE(NODE_GYP_MODULE_NAME,Init)
}//namespacedemo
js部分
//test.js
constaddon=require('./build/Release/addon');
addon((msg)=>{
console.log(msg);
//Prints:'helloworld'
});
可以看得出来,这个demo中js虽然传递的是function,但是在C++模块是同步的执行的;而且同步执行的话我也调通了,但是实际的场景肯定不是这种需求,而是在C++模块某一个异步的事件监听中收到某一种消息之后才通过js模块传递的回调函数回调给js;
目前已经做好的事情:封装一个C++的类,并且export,可用js调用此类的实例方法;
.h文件的两个属性:
Isolate*onPlayNoteIsolate;
LocalonPlayNote;
.cpp文件
//标记为方法1:
voidMIDIDeviceHelperBridge::setOnPlayNote(constFunctionCallbackInfo&args){
MIDIDeviceHelperBridge*obj=ObjectWrap::Unwrap(args.Holder());
Localcallback=Local::Cast(args[1]);
obj->onPlayNote=callback;
obj->onPlayNoteIsolate=args.GetIsolate();
}
//标记为方法2:
voidMIDIDeviceHelperBridge::ReceiveMsg(DWORDMsg,DWORDTimeStamp){
//此方法中的this为方法1中的obj
}
我现在的需求是在方法1中获得的js模块的回调函数存储在obj中或者任何在C++模块能访问到的地方,然后在方法2中收到消息之后通过方法1获得的js模块的回调,将消息传递给js模块;
我尝试过在方法1中的obj里存储callback和isolate,然后在方法2中通过this访问callback和isolate,但是收到消息后程序崩溃了,发现isolate没有问题,是callback被释放了,后来也尝试过LocalonPlayNote;类型换成PersistentonPlayNote;和HandleonPlayNote;也都是收到消息后崩溃;
现求问有没有大神做过类似的功能?
========================================================================经过几个小时后修改部分问题:
1:PersistentonPlayNote;不存储在类的成员变量中,放到全局,而且必须使用Persistent;
2:发现的其他问题,ReceiveMsg方法我可以在当前类对js公开的方法中调用,并且在js中调用词方法后,js模块的回调也是可以执行的;
3:但实际中ReceiveMsg不是我手动调用的,而是MIDI设备(例如能通过USB连接电脑的电子琴)上的按键触发后通过windows系统的midiapi调用ReceiveMsg方法,此时ReceiveMsg中没有任何js的环境;
========================================================================

			
慕田峪7331174
浏览 710回答 2
2回答

杨魅力

已解决收到的消息存储在当前对象的消息队列,然后通过emit发送到js模块:C++部分//在类的New方法中,用类的静态方法实例化runloop中的异步函数voidMIDIDeviceHelperBridge::New(constFunctionCallbackInfo&args){MIDIDeviceHelperBridge*obj=newMIDIDeviceHelperBridge();obj->isolate=isolate;obj->message_async.data=obj;uv_async_init(uv_default_loop(),&obj->message_async,MIDIDeviceHelperBridge::MIDIMessageCallback);……}voidMIDIDeviceHelperBridge::ReceiveMsg(DWORDMsg,DWORDTimeStamp){uv_async_send(&this->message_async);}voidMIDIDeviceHelperBridge::MIDIMessageCallback(uv_async_t*async){MIDIDeviceHelperBridge*obj=static_cast(async->data);LocalemitFunction=obj->handle()->Get(String::NewFromUtf8(obj->isolate,"emit")).As();constunsignedargc=4;char*CustomMessageName="CustomMessageName";Localargv[argc]={String::NewFromUtf8(obj->isolate,CustomMessageName),Number::New(obj->isolate,1),Number::New(obj->isolate,2),Number::New(obj->isolate,3)};MakeCallback(obj->isolate,obj->handle(),emitFunction,argc,argv);}js部分:constmidiDeviceHelper=require(`xxx.node`);//路径自己写上就行constEventEmitter=require('events').EventEmitter;midiDeviceHelper.MIDIDeviceHelperBridge.prototype.__proto__=EventEmitter.prototype;constmidiDeviceHelperBridge=newmidiDeviceHelper.MIDIDeviceHelperBridge();constCustomMessageName="CustomMessageName";//这个是上面argv里的第一个元素midiDeviceHelperBridge.on(CustomMessageName,(a,b,c)=>{});

郎朗坤

请问MIDIDeviceHelperBridge类的handle()方法怎么实现的?跪求完整的例子?@kingphone_he
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript