使用 N-API 从 Node.JS 调用 C/C++ 函数

4

我希望使用node-addon-api模块包装器通过N-API从Node.js中使用C函数。这是我第一次使用N-API,我也是Node和C++的初学者。我在嵌入式系统的C编程方面有经验,但是对于这个Node.jS / N-API问题,我还没有完全理解...

我想要做的是从Node.js调用一个具有以下原型的C函数:

unsigned char *MyFunction(unsigned char *data, size_t size, size_t min, size_t max)

*data 是一个指向包含RGB图像数据 [R0, G0, B0, R1, G1, B1, ...] 的数组的指针,数组大小为size。这些数据应该在 MyFunction 中被处理(提取 RGB 通道、反转等)。

到目前为止,我的 C++ 代码如下:

#include <napi.h>

using namespace Napi;

Napi::Value Method(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  if (info.Length() != 3) {
    Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
    return env.Null();    
  }
  else {
    const Napi::Array inputArray = info[0].As<Napi::Array>();
    const float smin = info[1].As<Napi::Number>().FloatValue();
    const float smax = info[2].As<Napi::Number>().FloatValue();
    const unsigned int length = inputArray.Length();
    unsigned int i;
    Napi::Array outputArray = Napi::Array::New(env, length);
    Napi::Array redArray = Napi::Array::New(env, length / 3);
    Napi::Array greenArray = Napi::Array::New(env, length / 3);
    Napi::Array blueArray = Napi::Array::New(env, length / 3);

    // Extract Channels
    for (i = 0; i < (length / 3); i++) {
      redArray[i] = inputArray[i * 3];
      greenArray[i] = inputArray[i * 3 + 1];
      blueArray[i] = inputArray[i * 3 + 2];
    }

    // Apply Simple Color Balance to each channel
    for (i = 0; i < (length / 3); i++) {
      outputArray[i] = redArray[i];
    }
    return redArray;    // Test => this works
  }
}

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

NODE_API_MODULE(module, Init)

这是节点部分:

const  sharp  = require('sharp');
sharp('testPic.jpg')
  .resize(800, 600)
  .toFile('SharpOut.jpg')
  .then( data => { 
    console.log('Resize & Negate => OK')
    // Extract Channel data
    sharp('SharpOut.jpg')
    .raw()
    .toBuffer()
    .then(data => {
      var smin = 0.0;
      var smax = 0.0;
      var testArr = [];
      for (let n = 0; n < data.length; n++) {
        testArr[n] = data[n];
      }      
      const HelloWorld = require('./build/Release/module.node');
      const result =  HelloWorld.Test(testArr, smin, smax);
    })
    .catch(err => {
      console.log('ERROR during extraction of RED channel. ERR:');
      console.log(err);
    });
  })
  .catch( err => { 
    console.log('ERROR');
    console.log(err);
  });

我的问题

  1. Sharp输出的是缓冲区而不是数组,但使用 ArrayBuffer 而不是 Array 我无法得到有效代码。编译没问题,但在node中执行时出现以下错误:

Error: Invalid argument at D:\temp\testSCB\index.js:30:34

错误出现在这行代码上:const result = HelloWorld.Test(testArr, smin, smax);)

  1. 如果我将 redArray[i] = inputArray[i * 3]; 改为 redArray[i] = ~(inputArray[i * 3]); 来反转颜色,我会得到两个错误:

error C2675: unary '~': 'Napi::Value' does not define this operator or a conversion to a type acceptable to the predefined operator

error C2088: '~': illegal for class

我的问题是:如何正确实现我的C函数以使其从node.js工作起来?

谢谢任何帮助!

1个回答

3

Node.js团队使用node-addon-api(N-API的C ++包装器)创建了Array buffer示例,可以从以下网址访问。https://github.com/nodejs/node-addon-examples/tree/master/array_buffer_to_native/node-addon-api

如果您正在寻找一个纯N-API实现(不使用任何包装器),那么您可以查看以下示例,这是在我学习纯N-API时创建的。 https://github.com/msatyan/MyNodeC/blob/master/src/mync1/ArrayBuff.cpp

此示例涵盖以下场景:

  • 从JavaScript接收ArrayBuffer
  • 在本地层创建ArrayBuffer并将其返回给JavaScript
  • 在本地层创建TypedArray并将其返回给JavaScript
  • 在本地层创建具有外部分配内存的ArrayBuffer,并将其返回给JavaScript

有可用的JavaScript示例:https://github.com/msatyan/MyNodeC/blob/master/test/TestArrayBuff.js

如果您正在启动新的本地附加模块,则可以使用CMake.js而不是node-gyp(看起来node-gyp正在结束其支持)。您可以从我在进行N-API研究期间创建的示例项目中获取有关现代项目结构的更多信息。https://github.com/msatyan/MyNodeC


谢谢!我已经使用了你的纯N-API示例,这对我帮助很大,现在我认为它应该很快就能工作了...还要感谢CMake提示! - groboter

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