为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕田峪7331174 2019-05-13 08:41:08
最近看了很多的相关文档;但是有有一个地方一直很不解,关于Node调用C++传递回调函数:官方文档如下:C++部分://addon.cc#includenamespacedemo{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)}//namespacedemojs部分//test.jsconstaddon=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的环境;========================================================================
查看完整描述

2 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

已解决收到的消息存储在当前对象的消息队列,然后通过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)=>{
});
                            
查看完整回答
反对 回复 2019-05-13
?
郎朗坤

TA贡献1921条经验 获得超9个赞

请问MIDIDeviceHelperBridge类的handle()方法怎么实现的?跪求完整的例子?@kingphone_he
                            
查看完整回答
反对 回复 2019-05-13
  • 2 回答
  • 0 关注
  • 709 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号