用Node-addon-api实现C++调用Javascript
本文介绍在使用Node-addon-api时,能够实现用C++调用Javascript的几种方式。
1. Callback
比较简单,示例:
Napi::Function cb = info[0].As<Napi::Function>();
cb.Call(env.Global(), { Napi::String::New(env, "hello world") });
Return function
String MyFunction(const CallbackInfo& info) {
Env env = info.Env();
return String::New(env, "hello world");
}
Function CreateFunction(const CallbackInfo& info) {
Env env = info.Env();
Function fn = Function::New(env, MyFunction, "funName");
return fn;
}
2. 带有ThreadSafeFunction的callback(可以在C++中另写线程重复调用JS)
Napi::Value callback(const Napi::CallbackInfo &info)
{
Napi::Env env = info.Env();
if ( info.Length() < 2 )
{
throw Napi::TypeError::New( env, "Expected two arguments" );
}
else if ( !info[0].IsFunction() )
{
throw Napi::TypeError::New( env, "Expected first arg to be function" );
}
else if ( !info[1].IsNumber() )
{
throw Napi::TypeError::New( env, "Expected second arg to be number" );
}
int count = info[1].As<Napi::Number>().Int32Value();
// Create a ThreadSafeFunction
tsfn = Napi::ThreadSafeFunction::New(
env,
info[0].As<Napi::Function>(), // JavaScript function called asynchronously
"Resource Name", // Name
0, // Unlimited queue
1, // Only one thread will use this initially
[]( Napi::Env ) { // Finalizer used to clean threads up
nativeThread.join();
} );
// Create a native thread
nativeThread = std::thread( [count] {
auto callback = []( Napi::Env env, Napi::Function jsCallback, int* value ) {
// Transform native data into JS data, passing it to the provided
// `jsCallback` -- the TSFN's JavaScript function.
jsCallback.Call( {Napi::Number::New( env, *value )} );
// We're finished with the data.
delete value;
};
for ( int i = 0; i < count; i++ )
{
// Create new data
int* value = new int( clock() );
// Perform a blocking call
napi_status status = tsfn.BlockingCall( value, callback );
if ( status != napi_ok )
{
// Handle error
break;
}
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
}
// Release the thread-safe function
tsfn.Release();
} );
return Napi::Boolean::New(env, true);
}
JS:
dlxPlugin.callback(() => {
console.log("C++ call javascript function");
}, 2)
3. Event
Napi::Value event(const Napi::CallbackInfo &info)
{
Napi::Env env = info.Env();
Napi::Function emit = info[0].As<Napi::Function>();
emit.Call({ Napi::String::New(env, "msg"), Napi::Number::New(env, 1) });
emit.Call({ Napi::String::New(env, "msg"), Napi::Number::New(env, 10) });
}
JS:
const eventListener = new EventEmitter();
eventListener.on("msg", (data) => {
console.log("Msg:", data);
}
)
event(eventListener.emit.bind(eventListener));
4. 调用JS-eval,直接运行字符串
globalThis.num = 1; console.log(nw.test()); console.log(globalThis.num); // 2
Napi::String jsStr = Napi::String::New(env, "num++"); napi_value result; napi_run_script(env, jsStr, &result); return Napi::Value::From(env, result);
可以这样运行函数
globalThis.xx = () => { return 233; } console.log(nw.test()); // 233
Napi::String jsStr = Napi::String::New(env, "xx()");
使用eval
globalThis.num = 1; console.log(nw.test()); console.log(globalThis.num); // 2
auto eval = env.Global().Get("eval").As<Napi::Function>(); return eval.Call(env.Global(), {Napi::String::New(env, "num++")});
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析