本篇主要写一些基本函数使用示例
同系列参考文章
本地环境
macOS
函数示例
无参函数
Napi::Value HelloWorld(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::String::New(env, "Hello, World!");
}
有参函数
Napi::Value Add(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber()) {
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
return env.Null();
}
double a = info[0].As<Napi::Number>().DoubleValue();
double b = info[1].As<Napi::Number>().DoubleValue();
double result = a + b;
return Napi::Number::New(env, result);
}
自定义结构参数
struct Point {
double x;
double y;
};
Napi::Value TranslatePoint(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// Parse input
Napi::Object pointObj = info[0].As<Napi::Object>();
Point point;
point.x = pointObj.Get("x").ToNumber();
point.y = pointObj.Get("y").ToNumber();
// Modify point
point.x += 1.0;
point.y += 1.0;
// Create output object
Napi::Object result = Napi::Object::New(env);
result.Set("x", point.x);
result.Set("y", point.y);
return result;
}
回调函数
class IntAsyncWorker : public Napi::AsyncWorker {
public:
IntAsyncWorker(const Napi::Function& callback)
: Napi::AsyncWorker(callback), result(0) {}
// 执行异步任务的代码
void Execute() override {
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟异步工作
result = 42; // 假设处理结果是 42
}
// 异步任务完成后回调 JavaScript 函数
void OnOK() override {
Napi::HandleScope scope(Env());
Callback().Call({ Napi::Number::New(Env(), result) });
}
private:
int result;
};
// 启动异步任务
Napi::Value StartAsyncWork(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::Function callback = info[0].As<Napi::Function>();
IntAsyncWorker* worker = new IntAsyncWorker(callback);
worker->Queue();
return env.Undefined();
}
整体代码
native_module.cc
#include <napi.h>
#include <thread>
// Example 1: Function to add two numbers
Napi::Value Add(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber()) {
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
return env.Null();
}
double a = info[0].As<Napi::Number>().DoubleValue();
double b = info[1].As<Napi::Number>().DoubleValue();
double result = a + b;
return Napi::Number::New(env, result);
}
// Example 2: Struct and function to manipulate a Point struct
struct Point {
double x;
double y;
};
Napi::Value TranslatePoint(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// Parse input
Napi::Object pointObj = info[0].As<Napi::Object>();
Point point;
point.x = pointObj.Get("x").ToNumber();
point.y = pointObj.Get("y").ToNumber();
// Modify point
point.x += 1.0;
point.y += 1.0;
// Create output object
Napi::Object result = Napi::Object::New(env);
result.Set("x", point.x);
result.Set("y", point.y);
return result;
}
// Example 3: Asynchronous data processing with callback
class IntAsyncWorker : public Napi::AsyncWorker {
public:
IntAsyncWorker(const Napi::Function& callback)
: Napi::AsyncWorker(callback), result(0) {}
// 执行异步任务的代码
void Execute() override {
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟异步工作
result = 42; // 假设处理结果是 42
}
// 异步任务完成后回调 JavaScript 函数
void OnOK() override {
Napi::HandleScope scope(Env());
Callback().Call({ Napi::Number::New(Env(), result) });
}
private:
int result;
};
// 启动异步任务
Napi::Value StartAsyncWork(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::Function callback = info[0].As<Napi::Function>();
IntAsyncWorker* worker = new IntAsyncWorker(callback);
worker->Queue();
return env.Undefined();
}
// Example 4: Simple function with no parameters
Napi::Value HelloWorld(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::String::New(env, "Hello, World!");
}
// Initialize the addon
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set("add", Napi::Function::New(env, Add));
exports.Set("translatePoint", Napi::Function::New(env, TranslatePoint));
exports.Set("startAsyncWork", Napi::Function::New(env, StartAsyncWork));
exports.Set("helloWorld", Napi::Function::New(env, HelloWorld));
return exports;
}
NODE_API_MODULE(native_module, Init)
binding.gyp
{
"targets": [
{
"target_name": "native_module",
"sources": [
"C++/native_module.cc"
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
"cflags_cc": ["-fexceptions" ],
"defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ]
}
]
}
index.js
const { app, BrowserWindow } = require('electron');
const path = require('node:path');
const nativeModule = require('../build/Release/native_module.node');
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) {
app.quit();
}
// 加载原生模块
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Example 1: Call the add function
const result = nativeModule.add(5, 3);
console.log(`Result of add(5, 3): ${result}`); // Output: 8
// Example 2: Call the translatePoint function
const point = { x: 10, y: 20 };
const newPoint = nativeModule.translatePoint(point);
console.log(`Translated point: (${newPoint.x}, ${newPoint.y})`); // Output: (11, 21)
// Example 3: Call the startProcessing function with a callback
nativeModule.startAsyncWork((result) => {
console.log(`Callback result: ${result}`); // Output after 2 seconds: 42
});
// Example 4: Call the helloWorld function
const greeting = nativeModule.helloWorld();
console.log(`Greeting from helloWorld: ${greeting}`); // Output: Hello, World!
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow();
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.