I'm currently sending data from C++ to NodeJS passing a NodeJS readableStream.push.bind(readableStream)
to the C++ binding code and writing onto the stream from C++ using
Napi::Function push = info[0].As<Napi::Function>();
Napi::ThreadSafeFunction push_safe = Napi::ThreadSafeFunction::New(env, push, "push", 0, 1);
push_safe.BlockingCall(data, custom_callback);
Now I want to be able to send data to the C++ binding, using a NodeJS Stream, but I can't figure out if C++ can accept a Stream, and calling a C++ version of .on('data', (data) => {})
on it, something like:
example NodeJS:
const read_stream = fs.createReadStream("./random.bin");
mybinding.myfunc(read_stream);
example C++:
Value myfunc(const CallbackInfo& info) {
Env env = info.Env();
auto on_data_lambda = [](data)
{
std::cout << "new data arrived from nodejs stream: " << data << std::endl;
}
/*some magic*/
}
Implementing this with all the bells and whistles is not trivial. As always, the most complex part is handling all the errors.
I suggest you go check in Node.js sources src/js_stream.cc
which contains something similar and you will understand why a good/fast implementation is difficult.
If you want to keep it simple, you can start by creating a JS reference to your C++ on_data
function.
Then you can register this function as an event receiver.
Napi::Value ondata(const Napi::CallbackInfo &info) {
if (!info[0].IsObject()) printf("Something strange received");
else printf("received %s\n", info[0].ToString().Utf8Value().c_str());
return info.Env().Undefined();
}
Napi::Value stream(const Napi::CallbackInfo &info) {
Napi::Object stream = info[0].ToObject();
Napi::Function on_data_ref = Napi::Function::New(info.Env(), ondata, "on_data");
Napi::Value onValue = stream.Get("on");
if (!onValue.IsFunction()) throw Napi::Error::New(info.Env(), "This is not an event emitter");
Napi::Function on = onValue.As<Napi::Function>();
on.Call(stream, {Napi::String::New(info.Env(), "data"), on_data_ref});
return info.Env().Undefined();
}
If you do this, data will start flowing. But you still have to do correctly the error handling and everything else.