在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/C++  HTML/ 關于Node和C++互相調用的問題

關于Node和C++互相調用的問題

最近看了很多的相關文檔;但是有有一個地方一直很不解,關于Node調用C++傳遞回調函數(shù):
官方文檔如下:

C++部分:

// addon.cc
#include <node.h>

namespace demo {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Null;
using v8::Object;
using v8::String;
using v8::Value;

void RunCallback(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Function> cb = Local<Function>::Cast(args[0]);
  const unsigned argc = 1;
  Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };
  cb->Call(Null(isolate), argc, argv);
}

void Init(Local<Object> exports, Local<Object> module) {
  NODE_SET_METHOD(module, "exports", RunCallback);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

}  // namespace demo

js部分

// test.js
const addon = require('./build/Release/addon');

addon((msg) => {
  console.log(msg);
// Prints: 'hello world'
});

可以看得出來,這個demo中js雖然傳遞的是function,但是在C++模塊是同步的執(zhí)行的;而且同步執(zhí)行的話我也調通了,但是實際的場景肯定不是這種需求,而是在C++模塊某一個異步的事件監(jiān)聽中收到某一種消息之后才通過js模塊傳遞的回調函數(shù)回調給js;

目前已經做好的事情:
封裝一個C++的類,并且export,可用js調用此類的實例方法;

.h文件的兩個屬性:

Isolate *onPlayNoteIsolate;
Local <Function> onPlayNote;

.cpp文件

// 標記為方法1:
void MIDIDeviceHelperBridge::setOnPlayNote(const FunctionCallbackInfo<Value>& args) {
    MIDIDeviceHelperBridge *obj = ObjectWrap::Unwrap<MIDIDeviceHelperBridge>(args.Holder());
    
    Local<Function> callback = Local<Function>::Cast(args[1]);
    obj->onPlayNote = callback;
    obj->onPlayNoteIsolate = args.GetIsolate();
}

// 標記為方法2:
void MIDIDeviceHelperBridge::ReceiveMsg(DWORD Msg, DWORD TimeStamp) {
    // 此方法中的this為方法1中的obj
}

我現(xiàn)在的需求是在方法1中獲得的js模塊的回調函數(shù)存儲在obj中或者任何在C++模塊能訪問到的地方,然后在方法2中收到消息之后通過方法1獲得的js模塊的回調,將消息傳遞給js模塊;

我嘗試過在方法1中的obj里存儲callback和isolate,然后在方法2中通過this訪問callback和isolate,但是收到消息后程序崩潰了,發(fā)現(xiàn)isolate沒有問題,是callback被釋放了,后來也嘗試過Local <Function> onPlayNote;
類型換成Persistent <Function> onPlayNote;和Handle<Function> onPlayNote;也都是收到消息后崩潰;

現(xiàn)求問有沒有大神做過類似的功能?

========================================================================
經過幾個小時后修改部分問題:

1:Persistent <Function> onPlayNote;不存儲在類的成員變量中,放到全局,而且必須使用Persistent;
2:發(fā)現(xiàn)的其他問題,ReceiveMsg方法我可以在當前類對js公開的方法中調用,并且在js中調用詞方法后,js模塊的回調也是可以執(zhí)行的;
3:但實際中ReceiveMsg不是我手動調用的,而是MIDI設備(例如能通過USB連接電腦的電子琴)上的按鍵觸發(fā)后通過windows系統(tǒng)的midiapi調用ReceiveMsg方法,此時ReceiveMsg中沒有任何js的環(huán)境;

========================================================================

回答
編輯回答
莫小染

也是遇到這樣的問題,現(xiàn)在直接放棄c++了

2017年4月13日 22:15
編輯回答
舊城人

已解決
收到的消息存儲在當前對象的消息隊列,然后通過emit發(fā)送到js模塊:

C++部分

// 在類的New方法中,用類的靜態(tài)方法實例化runloop中的異步函數(shù)
void MIDIDeviceHelperBridge::New(const FunctionCallbackInfo<Value>& args) {
    MIDIDeviceHelperBridge *obj = new MIDIDeviceHelperBridge();
    obj->isolate = isolate;
    obj->message_async.data = obj;
    uv_async_init(uv_default_loop(), &obj->message_async, MIDIDeviceHelperBridge::MIDIMessageCallback);
    ……
}

void MIDIDeviceHelperBridge::ReceiveMsg(DWORD Msg, DWORD TimeStamp) {
    uv_async_send(&this->message_async);
}

void MIDIDeviceHelperBridge::MIDIMessageCallback(uv_async_t *async) {
    MIDIDeviceHelperBridge *obj = static_cast<MIDIDeviceHelperBridge*>(async->data);
    Local<v8::Function> emitFunction = obj->handle()->Get(String::NewFromUtf8(obj->isolate, "emit")).As<v8::Function>();
    const unsigned argc = 4;
    char *CustomMessageName = "CustomMessageName";
    Local <Value> argv[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部分:

const midiDeviceHelper = require(`xxx.node`);//路徑自己寫上就行
const EventEmitter = require('events').EventEmitter;
midiDeviceHelper.MIDIDeviceHelperBridge.prototype.__proto__ = EventEmitter.prototype;
const midiDeviceHelperBridge = new midiDeviceHelper.MIDIDeviceHelperBridge();
const CustomMessageName = "CustomMessageName"; //這個是上面argv里的第一個元素
midiDeviceHelperBridge.on(CustomMessageName, (a, b, c) => {
});
2017年12月29日 02:16
編輯回答
莫小染

請問MIDIDeviceHelperBridge類的handle()方法怎么實現(xiàn)的?
跪求完整的例子?@kingphone_he

2018年5月3日 06:41