Я пытаюсь зарегистрировать функцию обратного вызова JavaScript для последующего вызова из класса C++. Я использую nbind для создания надстройки node.js. Это пример кода, который я написал для более сложного кода, который должен выполнять то же самое:
код C++ (testing.cc):
#include "nbind/api.h"
#include <string>
#include <iostream>
class Test
{
nbind::cbFunction *callback;
public:
Test() {}
//this dummy var is only here so that doCallback() will be recognized as a function
void doCallback(int dummyVar)
{
std::cout << "Calling Javascript callback" << std::endl;
//call javascript code
if (callback != nullptr)
{
(*callback)("Hi there!\n");
}
return;
}
void enrollCallback(nbind::cbFunction &cb)
{
callback = &cb;
return;
}
};
#include "nbind/nbind.h"
NBIND_CLASS(Test) {
construct<>();
method(doCallback);
method(enrollCallback);
method(unenrollCallback);
}
код JavaScript (test.js):
var nbind = require('nbind');
function printMessage(message) {
console.info(message);
}
var lib = nbind.init().lib;
var test = lib.Test();
test.enrollCallback(printMessage);
try{
test.doCallback(11);
} catch(err) {
console.info(err);
}
Когда я запускаю приведенный выше код в командной строке, я вообще не получаю никаких результатов. Когда я запускаю такой код: node inspect test.js и ввожу команду continue, я получаю следующую ошибку при вызове функции обратного вызова:
Error: read ECONNRESET
at _errnoException (util.js:992:11)
at TCP.onread (net.js:618:25)
Когда я выполняю свою программу, я получаю в консоли следующую ошибку:
TypeError: test.doCallback is not a function
at Object.<anonymous> (C:\Users\mrcole\Desktop\testy\test.js:22:10)
at Module._compile (module.js:649:14)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:191:16)
at bootstrap_node.js:612:3
В чем я ошибаюсь и почему узел действует непоследовательно?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Чтобы ответить на мой собственный вопрос, не используйте nbind для вызова функции обратного вызова JavaScript узла таким образом. Это асинхронный вызов (поправьте меня, если я ошибаюсь), и по состоянию на июнь 2018 года nbind не поддерживает асинхронные обратные вызовы.
Хорошая альтернатива - реализовать один из Классы AsyncWorker, предоставляемые NAN.
Вот пример кода:
class MyAsyncWorker : public Nan::AsyncProgressWorkerBase<T>
{
public:
MyAsyncWorker(Nan::Callback *callback_, const char *resource_name = "My Async Worker")
: AsyncProgressWorkerBase(callback_, resource_name)
{
}
~MyAsyncWorker()
{
}
//Do work, or process notifications here
void Execute(const ExecutionProgress &progress)
{
//do work. when you have something to report,
//call ExecutionProgress::Send( T * data, size_t count) to eventually call
//the HandleProgressCallback function.
}
//Call JavaScript callback from this function
void HandleProgressCallback(T *data, size_t count)
{
Nan::HandleScope scope;
v8::Local<v8::Value> argv[] = {
//initialize your data to passback to callback here
};
callback->Call(count,argv,async_resource);
}
//This is called when you are done executing
virtual void HandleOKCallback()
{
Nan::HandleScope scope;
v8::Local<v8::Value> argv[] = {
//Prepare final values to be returned
};
callback->Call(1,argv,async_resource);
}
};