首页 > 其他分享 >C++ addon

C++ addon

时间:2024-11-06 14:58:52浏览次数:3  
标签:info const env Env New Napi addon

node-addon-api

https://github.com/nodejs/node-addon-api

https://www.cnblogs.com/ajanuw/p/14404060.html
hello world

#include <napi.h>
 
using namespace Napi;
 
String Method(const CallbackInfo& info) {
  Env env = info.Env();
  return String::New(env, "world"); // 返回数据
}
 
Object Init(Env env, Object exports) {
  // 导出
  exports.Set(String::New(env, "hello"), Function::New(env, Method));
  return exports;
}
 

NODE_API_MODULE(hello, Init)
const addon = require("./build/Release/addon");

console.log( addon.hello() );

args

``
info.Length()

info[0].IsNumber()

double arg0 = info[0].AsNapi::Number().DoubleValue();

std::string str = info[0].ToString().Utf8Value();

// 和js一样模糊判断
Boolean b = opt.Get("b").ToBoolean();
if(b)...

env.Null();
env.Undefined();

Napi::Boolean::New(env, true);

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;

}

Wrap 获取传入的c++类

MyObject* obj1 = Napi::ObjectWrap<MyObject>::Unwrap( info[0].As<Napi::Object>() );

接收arraybuffer

#include <napi.h>

using namespace Napi;

Napi::Value a(const Napi::CallbackInfo& info) {
 Napi::ArrayBuffer buf = info[0].As<Napi::ArrayBuffer>();
 uint32_t* n = (uint32_t*)buf.Data();
 printf("%d\n", *n); // 10
 return info.Env().Undefined();
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
 exports["a"] = Napi::Function::New(env, a);
 return exports;
}


NODE_API_MODULE(hello, Init)

const array = new Uint8Array([0x0A, 0, 0, 0]);

addon.a(array.buffer)

返回array_buffer

let r = addon.test()
console.log(r); // ArrayBuffer { [Uint8Contents]: <0a 00 00 00>, byteLength: 4 }

console.log( new Uint8Array(r)[0] ); // 10

 Env env = info.Env();
 DWORD a = 10;
 auto buf = ArrayBuffer::New(env, 4);
 memcpy_s((void *)buf.Data(), 4, &a, 4);

 return buf;

接收 TypedArray

let r = addon.test(new Uint8Array([0x0A, 0]));

console.log(r); // 1

Value test(const CallbackInfo &info)
{
 auto env = info.Env();
 auto ta = info[0].As<TypedArray>();
 auto buf = ta.Get("buffer").As<ArrayBuffer>();
 return Number::From(env, *(WORD*)buf.Data());

}

接收 async function

nw.test(async function () {
 return 100;

});

Napi::Value test(const Napi::CallbackInfo &info)
{
 Napi::Env env = info.Env();

 auto promise = info[0].As<Napi::Function>().Call({}).As<Napi::Promise>();
 auto thenFunc = promise.Get("then").As<Napi::Function>();
 auto v = thenFunc.Call(promise, {Napi::Function::New(env, [](const Napi::CallbackInfo &info)
                                                      { printf("%d\n", info[0].ToNumber().Int32Value()); /* 100 */ })});
 return env.Undefined();

}

event

Napi::Value a(const Napi::CallbackInfo& info) {
 Napi::Env env = info.Env();
 Napi::Function emit = info[0].As<Napi::Function>();
 emit.Call({ Napi::String::New(env, "start") });
 emit.Call({ Napi::String::New(env, "data"), Napi::Number::New(env, 1) });
 emit.Call({ Napi::String::New(env, "end") });
 emit.Call({ Napi::String::New(env, "ok") });

}

const EventEmitter = require("events").EventEmitter;
const emitter = new EventEmitter();
emitter.on("start", () => {
 console.log("### START ...");
});
emitter.on("data", (evt) => {
 console.log(evt);
});
emitter.on("end", () => {
 console.log("### END ###");
});


addon.a(emitter.emit.bind(emitter));

保存callback函数不被垃圾回收

#include <napi.h>

class NativeAddon : public Napi::ObjectWrap<NativeAddon> {
public:
 static Napi::Object Init(Napi::Env env, Napi::Object exports)
 {
   Napi::Function func =
     DefineClass(env,
       "NativeAddon",
       { InstanceMethod("tryCallByStoredReference",
                       &NativeAddon::TryCallByStoredReference),
        InstanceMethod("tryCallByStoredFunction",
                       &NativeAddon::TryCallByStoredFunction) });

   constructor = Napi::Persistent(func);
   constructor.SuppressDestruct();

   exports.Set("NativeAddon", func);
   return exports;
 }

 NativeAddon(const Napi::CallbackInfo& info) : Napi::ObjectWrap<NativeAddon>(info) {
   jsFnRef = Napi::Persistent(info[0].As<Napi::Function>()); // use Persistent
   jsFn = info[1].As<Napi::Function>();
 }

private:
 static Napi::FunctionReference constructor;
 Napi::FunctionReference jsFnRef;
 Napi::Function jsFn;

 void TryCallByStoredReference(const Napi::CallbackInfo& info)
 {
   // Napi::Env env = info.Env();
   jsFnRef.Call({});
 }
 void TryCallByStoredFunction(const Napi::CallbackInfo& info)
 {
   // Napi::Env env = info.Env();
   jsFn.Call({});
 }
};
Napi::FunctionReference NativeAddon::constructor;
Napi::Object Init(Napi::Env env, Napi::Object exports) {
 NativeAddon::Init(env, exports);
 return exports;
}

NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

const { NativeAddon } = require("./build/Release/addon");

const addon = new NativeAddon(
 function () {
   console.log("JSFnRef");
 },
 function JSFn() {
   console.log("JSFn");
 }
);

addon.tryCallByStoredReference(); // ok

addon.tryCallByStoredFunction(); // err

继承 EventEmitter

#include <napi.h>

class NativeEmitter : public Napi::ObjectWrap<NativeEmitter> {
public:
 static Napi::Object Init(Napi::Env env, Napi::Object exports)
 {
   Napi::Function func =
     DefineClass(env,
       "NativeEmitter",
       { InstanceMethod("callAndEmit",
                       &NativeEmitter::CallAndEmit) });

   constructor = Napi::Persistent(func);
   constructor.SuppressDestruct();

   exports.Set("NativeEmitter", func);
   return exports;
 }
 NativeEmitter(const Napi::CallbackInfo& info) : Napi::ObjectWrap<NativeEmitter>(info) {}

private:
 static Napi::FunctionReference constructor;

 Napi::Value CallAndEmit(const Napi::CallbackInfo& info)
 {
   Napi::Env env = info.Env();
   Napi::Function emit =
     info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();
   emit.Call(info.This(), { Napi::String::New(env, "start") });
   for (int i = 0; i < 3; i++) {
     std::this_thread::sleep_for(std::chrono::seconds(1));
     emit.Call(
       info.This(),
       { Napi::String::New(env, "data"), Napi::String::New(env, "data ...") });
   }
   emit.Call(info.This(), { Napi::String::New(env, "end") });
   return Napi::String::New(env, "OK");
 }
};
Napi::FunctionReference NativeEmitter::constructor;

Napi::Object Init(Napi::Env env, Napi::Object exports) {
 NativeEmitter::Init(env, exports);
 return exports;
}


NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

const { NativeEmitter } = require("./build/Release/addon");
const EventEmitter = require("events").EventEmitter;

const inherits = require("util").inherits;
inherits(NativeEmitter, EventEmitter);

const emitter = new NativeEmitter();

emitter.on("start", () => {
 console.log("### START ...");
});

emitter.on("data", (evt) => {
 console.log(evt);
});

emitter.on("end", () => {
 console.log("### END ###");
});


emitter.callAndEmit();

c++ 返回 promise

Value a(const CallbackInfo& info)
{
 Env env = info.Env();
 auto re = Promise::Deferred::New(env);
 re.Resolve(String::New(env, "str"));
 return re.Promise();

}

addon.a().then((e) => {
 console.log(e); // str

});

主线程同步回调

struct TsfnContext
{
 TsfnContext(Napi::Env env, const Napi::CallbackInfo &info) : env_(env), cb(Persistent(info[0].As<Function>())){};
 FunctionReference cb;
 Napi::Env env_;
};

uintptr_t WINAPI threadEntry(void *hwnd, TsfnContext *context)
{
 return context->cb.Call({Number::New(context->env_, (uintptr_t)hwnd)}).ToNumber().Int64Value();
}

Napi::Value CreateTSFN(const Napi::CallbackInfo &info)
{
 Napi::Env env = info.Env();
 auto testData = new TsfnContext(env, info);
 BOOL r = EnumWindows((WNDENUMPROC)threadEntry, (LPARAM)testData);
 return Number::New(env, r);

}

let r = addon.createTSFN((data) => {
 return false;

});

对象包装
类属性和描述符
在子线程中调用jscallback

addon.test(() => {
 console.log("ok"); // ok 10

});

struct TsfnContext
{
 TsfnContext(const CallbackInfo &info, Napi::Env env){};
 Napi::ThreadSafeFunction tsfn;
 HANDLE hThread;
};

void mythread(TsfnContext*context)
{
 auto callback = [](Napi::Env env, Napi::Function jsCallback, void *data) {
   jsCallback.Call({Number::New(env, (int)data)});
 };
 napi_status status = context->tsfn.BlockingCall((void *)10, callback);
 if (status != napi_ok)
   Napi::Error::Fatal("ThreadEntry", "err.");
 context->tsfn.Release();
}

void FinalizerCallback(Napi::Env env, void *finalizeData, TsfnContext*context)
{
 CloseHandle(context->hThread);
 delete context;
}

void test(const CallbackInfo &info)
{
 Napi::Env env = info.Env();
 auto testData = new TsfnContext(info, env);
 testData->tsfn = Napi::ThreadSafeFunction::New(
     env,                          // Environment
     info[0].As<Napi::Function>(), // JS function from caller
     "name",                       // Resource name
     0,                            // Max queue size (0 = unlimited).
     1,                            // Initial thread count
     testData,                     // Context,
     FinalizerCallback,            // Finalizer
     (void *)nullptr               // Finalizer data
 );
 testData->hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)mythread, testData, 0, 0);

}

获取global对象

 napi_value g;
 napi_get_global(env, &g);
 auto global = Object(env, g);
 auto str = global.Get("name").ToString().Utf8Value();

 printf("str: %s\n", str.c_str()); // str: ajanuw

name = "ajanuw";

addon.test();

运行js字符串

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++")});

标签:info,const,env,Env,New,Napi,addon
From: https://www.cnblogs.com/runtimeerror/p/18530229

相关文章

  • gameobject_template | gameobject_template_addon
    目录gameobject_templateentrytypedisplayIdIconNameContentTuningIdAINamegameobject_template_addon factionflagsgameobject_templateentry gameobject模板的IDtype gameobject模板类型,取值参考源码GameObjectData.h的structGameObjectTemplat......
  • CentOS6.3安装xtables-addons,实现流量复制&镜像克隆
    一、版本要求CentOS6.3,64位(内核版本2.6.32-279),iptables版本是自带的v1.4.7CentOS6.9--6.10也可以,其它版本没有测试。ubuntu22.04上没有安装成功。二、依赖安装yuminstallgccyuminstallgcc-c++yuminstalliptables-devel三、下载安装包下载地址:https://inai.d......
  • 用Napi编写nodejs Addon并调用dll
    用Napi编写nodejsAddon并调用dllnpdejs调用C++addon并没有先前那篇随笔那么复杂,这是一篇补充说明:说明如何使用c++项目的include头文件以及lib,dll引入到addon内使用一、使用VS编写DLL导出项目步骤1:通过VisualStudio(推荐2019及其以上)新建一个“具有导出项的(DLL)动态链接库......
  • vue搭建脚手架 出现问题Command vue init requires a global addon to be installed.
    使用vue-cli脚手架命令vueinitwebpackmy-App创建项目回车时显示Commandvueinitrequiresa global addontobeinstalled.Pleaserun yarn globaladd@vue/cli-initandtryagain. 解决方法:npminstall-g@vue/cli-init 然后创建项目,正常。 ......
  • nodejs集成C++代码:手写简单的addon
    文章目录nodejs与node-gyp手写一个简单的addon编写一个简单的binding.gyp文件编写C++源文件V8版本:addon.ccnapi_api版本:addon_api.cc编译命令JS调用在这个专栏里,已经提到过web系统中c++的两大应用场景了:assembly和cef框架的应用,这两个可以说都是客户......
  • doxygen/addon/doxywizard/wizard.cpp
    Step2::Step2(Wizard*wizard,constQHash<QString,Input*>&modelData) :m_wizard(wizard),m_modelData(modelData){ QRadioButton*r; QVBoxLayout*layout=newQVBoxLayout(this); //--------------------------------------------------- m_extractMo......
  • KubeBlocks 研发轶事之 addon 抽象
    作者介绍张云杨,前阿里云数据库产品负责人,2016-2019年任阿里云数据库产品总监,负责RDS、PolarDB、Redis、MongoDB等核心产品。目前作者就职于云猿生数据,主要负责云原生数据控制面KubeBlocks和ServerlessMySQL产品。欢迎云计算或数据库行业从业者加微信交流。作者微信:realzyy......
  • 使用cmake-js 构建node addon
    cmake-js是nodejs包装的cmake,可以用来方便的进行nodejsnative项目的构建,以下是一个试用简单项目项目结构├──CMakeLists.txt├──hello_world.cc├──index.d.ts├──lib│├──binding.d.ts│└──binding.js├──pack......
  • OpenFunction 1.2.0 发布:集成 KEDA http-addon 作为同步函数运行时
    OpenFunction是一个开源的云原生FaaS(FunctionasaService,函数即服务)平台,旨在帮助开发者专注于业务逻辑的研发。我们非常高兴地宣布OpenFunction又迎来了一次重要的更新,即v1.2.0版本的发布!本次更新中,我们继续致力于为开发者们提供更加灵活和强大的工具,并在此基础上加入了......
  • 一些改动 \odoo\addons\web\static\src\webclient\user_menu\user_menu_items
      一些改动\odoo\addons\web\static\src\webclient\user_menu\user_menu_items.jsregistry.category("user_menuitems")//.add("documentation",documentationItem)//.add("support",supportItem).add("sho......