使用N-API将流数据传输到Node.js C++插件

7
我正在为NodeJS构建一个C++插件,并且希望从C++异步地向Node传输数据。我找到了这篇文章:https://nodeaddons.com/streaming-data-into-a-node-js-c-addon/,但我想使用N-API而不是NAN。
我已经在 NodeJS 文档和示例中搜索,并寻找其他资源和示例,但还没有找到能够展示如何实现这一点的资源。这是我第一次编写 NodeJS 的 C++ 插件。
一个能够帮助我入门的示例是一个使用 N-API 的插件,它每秒向 Node 发送一个虚拟字符串,并将该字符串打印到控制台上。
1个回答

7
这里是基于事件发射器(EventEmitter)概念的代码片段,它模拟从本地层(C/C++)读取传感器数据并将其推送到 Node.js (JavaScript) 层。在这个例子中,我们使用的是 node-addon-api,一个只有头文件的 C++ 包装器。在这个例子中,我们使用了一个 for 循环(仅五次迭代),实际上它可以是一个无限循环,不断读取传感器输出,并将数据推送到 JS 层。本地层可以决定何时向 JS 层报告从传感器收集到的数据。JS 将异步接收订阅事件的数据。
#include <napi.h>
#include <thread>

Napi::Value CallEmit(const Napi::CallbackInfo &info)
{
    char buff1[128];
    char buff2[128];
    int  sensor1 = 0;
    int  sensor2 = 0;

    Napi::Env env = info.Env();

    Napi::Function emit = info[0].As<Napi::Function>();
    emit.Call(  {Napi::String::New(env, "start")}  );

    for (int i = 0; i < 5; i++)
    {
        // Let us simulate some delay for collecting data from its sensors
        std::this_thread::sleep_for(std::chrono::seconds(2));

        sprintf(buff1, "sensor1 data %d ...", ++sensor1);

        emit.Call( { Napi::String::New(env, "sensor1"),
                   Napi::String::New(env, buff1 ) } );

        // Let, sensor 2 data is reported half the rate as sensor1
        if (i % 2)
        {
            sprintf(buff2, "sensor2 data %d ...", ++sensor2);
            emit.Call({ Napi::String::New(env, "sensor2"),
                       Napi::String::New(env, buff2) });
        }
    }

    emit.Call( {Napi::String::New(env, "end")} );
    return Napi::String::New( env, "OK" );
}

模块注册片段如下:

#include <napi.h>

Napi::Object Init( Napi::Env env, Napi::Object exports )
{
  exports.Set(Napi::String::New(env, "callEmit"), Napi::Function::New(env, CallEmit));
  return exports;
}

NODE_API_MODULE( myncpp1, Init )

编译上述本地代码,一旦成功构建,则可以运行以下node.js JavaScript代码进行测试。

'use strict'

const EventEmitter = require('events').EventEmitter
const addon = require('bindings')('myncpp1')

// General theme of EventEmitter is: notify me when it is ready

function Main() {
    const emitter = new EventEmitter()

    emitter.on('start', () => {
        console.log( '### Sensor reading started ...');
    })

    emitter.on('sensor1', (evt) => {
        // This module will be called as on when the
        // sensor1 data available for consuming from JS
        console.log(evt);
    })

    emitter.on('sensor2', (evt) => {
        console.log(evt);
    })

    emitter.on('end', () => {
        console.log('### Sensor reading Ended');
    })

    addon.callEmit( emitter.emit.bind(emitter) )
}

Main();

代码段应产生以下输出。
### Sensor reading started ...
sensor1 data 1 ...
sensor1 data 2 ...
sensor2 data 1 ...
sensor1 data 3 ...
sensor1 data 4 ...
sensor2 data 2 ...
sensor1 data 5 ...
### Sensor reading Ended

2
这个很好用,谢谢!能否从另一个线程中调用发射器回调函数?我认为这值得提出一个新问题。 https://dev59.com/tLPma4cB1Zd3GeqPoEu9 - Philip Nelson
谢谢你。我会在不久的将来尝试使用它,并感谢你花时间提供代码。也许我们可以在这里得到一个活跃的node-addon-api标签! - bmacnaughton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接