环境
1,node-gyp:9.0.0
2,node:16.0.0
3,python:3.10.5
4,node-addon-api:5.0.0
如果你没有配置好node-gyp的环境,需要先配一下,可以看一下:node-gyp环境配置
打包配置
由于我所有列子都写在demo.cc里,所以我的打包文件没有改动,如果你的文件命名不一致,需要在binding.gyp的sources里改一下文件名。
如果你引入了多个C文件,需要将多个文件都在sources写一下。
{
"targets": [
{
"target_name": "addon",
"sources": [ // 使用到的文件
"addon.cc",
"utils.cc",
"cpp/xxx.cpp", // 该文件在cpp文件夹里
"cpp/SPP3/xxx.cpp"
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")",
"cpp\SPP3", // 需要在这里将文件夹加一下
"cpp"
],
"dependencies": [
"<!(node -p \"require('node-addon-api').gyp\")"
],
"cflags!": ["-fno-exceptions"],
"cflags_cc!": ["-fno-exceptions"],
"defines": ["NAPI_CPP_EXCEPTIONS"],
"xcode_settings": {
"GCC_ENABLE_CPP_EXCEPTIONS": "YES"
}
}
]
}
1,数值
1,demo.cc
#include <napi.h>
#include<iostream>
#include<string>
using namespace Napi;
//直接返回c++的数值类型数据到js
Value getNumber(const CallbackInfo& info) {
Env env = info.Env();
int num = 2;
std::cout << "c++-log=>" << num << std::endl;
Number result = Number::New(env, num);
return result;
}
// 接收js传来的两个数值,转化为C++可用的数值后,相加并将结果返回。没有做参数的类型检测,传入字符串或不传,会报错
Value addNumber(const CallbackInfo& info){
Env env = info.Env();
double arg0 = info[0].As<Number>().DoubleValue();
double arg1 = info[1].As<Number>().DoubleValue();
double num = arg0+arg1;
Number result = Number::New(env, num);
return result;
}
Object Init(Env env, Object exports) {
exports.Set(String::New(env, "getNumber"), Function::New(env, getNumber));
exports.Set(String::New(env, "addNumber"), Function::New(env, addNumber));
return exports;
}
NODE_API_MODULE(addon, Init)
2,index.js
const addon = require('./build/Release/hello.node');
console.log("js--log=>",addon.getNumber());
console.log("js--log=>",addon.addNumber(3,2));
3,运行node index.js结果
2,字符串
1,demo.cc
#include <napi.h>
#include<iostream>
#include<string>
using namespace Napi;
Napi::Value getString(const CallbackInfo& info){
Env env = info.Env();
// 检测参数数量
if(info.Length()<1){
Napi::TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
// 检测参数类型
if(!info[0].IsString()){
Napi::TypeError::New(env, "Wrong arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
std::string str = info[0].As<Napi::String>();
if(str == "hello"){
str = "hello world!";
}else{
str = "Please say hello!";
}
Napi::String reslut = Napi::String::New(env,str);
return reslut;
}
Napi::Object Init(Env env, Object exports){
exports.Set(Napi::String::New(env,"getString"),Napi::Function::New(env,getString));
return exports;
}
NODE_API_MODULE(addon,Init);
2,index.js
const addon = require('./build/Release/hello.node');
try {
// 模拟没有参数的错误
console.log("js--log=>",addon.getString());
} catch (error1) {
console.log(error1);
try {
// 模拟参数类型的错误
console.log("js--log=>",addon.getString(123));
} catch (error2) {
console.log(error2);
// 正确输入
console.log("js--log=>",addon.getString('ccc'));
console.log("js--log=>",addon.getString('hello'));
}
}
3,运行结果
3,对象
demo.cc
#include <napi.h>
#include<iostream>
#include<string>
using namespace Napi;
Napi::Value getObj( const CallbackInfo& info ){
Env env = info.Env();
// 为了精简示例代码,就不对数据类型进行检测了。
// 接收并解析js传来的对象。
Napi::Object obj = info[0].As<Napi::Object>();
// Napi::Object obj = info[0].ToObject();
std::string name = obj.Get(static_cast<napi_value>(Napi::String::New(info.Env(),"name"))).As<Napi::String>();
std::cout << "c++_log=>" << name << std::endl;
// 准备返回给js,c++对象
Napi::Object result = Napi::Object::New(env);
result.Set(Napi::String::New(env,"name"),Napi::String::New(env,name));
result.Set(Napi::String::New(env,"age"),Napi::Number::New(env,36));
result.Set(Napi::String::New(env,"height"),Napi::Number::New(env,175));
result.Set(Napi::String::New(env,"weight"),Napi::Number::New(env,66.5));
return result;
}
Napi::Object Init(Env env, Object exports){
exports.Set(Napi::String::New(env,"getObj"),Napi::Function::New(env,getObj));
return exports;
}
NODE_API_MODULE(addon,Init);
2,index.js
const addon = require('./build/Release/hello.node');
console.log("js--log=>",addon.getObj({name:"zhangsan"}));
3,运行结果
4,数组
1,demo.cc
#include <napi.h>
#include<iostream>
#include<string>
using namespace Napi;
Napi::Value getArr( const CallbackInfo& info ){
Env env = info.Env();
// 为了精简示例代码,就不对数据类型进行检测了。
// 接收并解析js传来的数组。
Napi::Array arr = info[0].As<Napi::Array>();
int len = arr.Length();
std::cout << "c++_log=>" << len << std::endl;
std::string arr_1_string = arr.Get(static_cast<napi_value>(Napi::Number::New(info.Env(),0))).As<Napi::String>();
std::cout << "c++_log=>" << arr_1_string << std::endl;
int arr_2_Num = arr.Get(static_cast<napi_value>(Napi::Number::New(info.Env(),1))).As<Napi::Number>();
std::cout << "c++_log=>" << arr_2_Num << std::endl;
// 准备返回给js,c++数组
Napi::Array result = Napi::Array::New(env);
// 准备一个对象
Napi::Object obj = Napi::Object::New(env);
obj.Set(Napi::String::New(env,"name"),Napi::String::New(env,"zhangsan"));
// 给数组填充值
result.Set(Napi::Number::New(env,0),Napi::String::New(env,"balabala"));
result.Set(Napi::Number::New(env,1),Napi::Number::New(env,36));
result.Set(Napi::Number::New(env,2),Napi::Number::New(env,66.5));
result.Set(Napi::Number::New(env,3),obj);
return result;
}
Napi::Object Init(Env env, Object exports){
exports.Set(Napi::String::New(env,"getArr"),Napi::Function::New(env,getArr));
return exports;
}
NODE_API_MODULE(addon,Init);
2,index.js
const addon = require('./build/Release/hello.node');
console.log("js--log=>",addon.getArr(["laotie",666]));
3,运行结果
回调函数
1,demo.cc
#include <napi.h>
#include<iostream>
#include<string>
using namespace Napi;
void RunCallback(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::Function cb = info[0].As<Napi::Function>();
cb.Call(env.Global(), {Napi::String::New(env, "hello world")});
}
Napi::Object Init(Env env, Object exports){
exports.Set(Napi::String::New(env,"RunCallback"),Napi::Function::New(env,RunCallback));
return exports;
}
NODE_API_MODULE(addon,Init);
2,index.js
const addon = require('./build/Release/hello.node');
function callBack(params) {
console.log(params);
}
addon.RunCallback(callBack);
3,运行结果