我想通过将 N-API 与 node-addon-api 模块包装器结合使用来使用 Node.js 中的 C 函数。这是我第一次使用 N-API,而且我也是 Node 和 C++ 的初学者。我有嵌入式系统 C 编程经验,但是 Node.jS/N-API 的东西我还没有完全理解......
我不想做的是从 Node.js 调用具有此原型(prototype)的 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 channel 、反转……)。
到目前为止我所拥有的是这个 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)
这是 Node 部分:
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);
});
我的问题
- Sharp 输出一个缓冲区而不是一个数组,但使用
ArrayBuffer
而不是Array
我无法获得工作代码。编译没问题,但是当我在 Node 中执行它时,我得到了
Error: Invalid argument at D:\temp\testSCB\index.js:30:34
这行代码是const result = HelloWorld.Test(testArr, smin, smax);)
- 如果我将
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
我的问题
从 Node.js 实现 c-Function 的正确方法是什么?
感谢您的帮助!
最佳答案
node.js 团队使用node-addon-api(N-API 的 C++ 包装器)创建了数组缓冲区示例,可以从以下 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 。
此示例涵盖以下场景:
- 从 JavaScript 接收 ArrayBuffer
- 在原生层创建一个ArrayBuffer并将其返回给JavaScript
- 在原生层创建一个 TypedArray 并将其返回给 JavaScript
- 使用外部分配的内存在 native 层创建 ArrayBuffer 并将其返回给 JavaScript
它的 JavaScript 用法示例可用:https://github.com/msatyan/MyNodeC/blob/master/test/TestArrayBuff.js
如果您正在启动一个新的 native 附加模块,我可能会鼓励使用CMake.js而不是node-gyp(看起来node-gyp正在结束)它的支持)。您可以从我在 N-API 研究期间创建的示例项目中获取有关现代项目结构的更多信息。 https://github.com/msatyan/MyNodeC
关于node.js - 使用 N-API 从 Node.JS 调用 C(++) 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59788339/