Вызов функции C(++) из Node.JS с использованием N-API

Я хочу использовать C-функцию из Node.js, используя N-API с оболочкой модуля node-addon-api. Я впервые использую N-API, и я также новичок в Node и C++. У меня есть опыт программирования встроенных систем на C, но я еще не совсем понимаю эту вещь Node.jS/N-API...

Чего я не хочу делать, так это вызывать C-функцию с этим прототипом из Node.js:

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, инвертирование, ...).

Что у меня есть до сих пор, так это код С++:

#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 у меня не получилось получить рабочий код. Компиляция в порядке, но когда я выполняю ее в узле, я получаю

Ошибка: неверный аргумент в 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]);, чтобы инвертировать цвет, я получаю две ошибки:

ошибка C2675: унарный '~': 'Napi::Value' не определяет этот оператор или преобразование в тип, приемлемый для предопределенного оператора

а также

ошибка C2088: '~': недопустимо для класса

Мой вопрос

Как правильно реализовать мою c-функцию для работы с node.js?

Спасибо за любую помощь!


person groboter    schedule 17.01.2020    source источник


Ответы (1)


Команда node.js создала пример буфера массива с помощью node-addon-api (оболочка C++ для N-API). Доступ к нему можно получить по следующему URL-адресу. 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.

Этот пример охватывает следующий сценарий:

  • Получить ArrayBuffer из JavaScript
  • Создайте 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

person Satyan    schedule 17.01.2020
comment
Спасибо! Я использовал ваши чистые примеры N-API, которые мне очень помогли, теперь я думаю, что это должно скоро заработать... Также спасибо за подсказку CMake! - person groboter; 19.01.2020