虽然现在大部分情况都是使用n-api来编写插件,但是底层毕竟是v8(和libuv),使用v8编写简单的插件,同时熟悉v8的使用。
本文介绍在写c++插件时,简单又常用的写法,其实本质上,写插件的难处在于底层的能力和对libuv、v8的了解。话不多说,直接看代码。
#include<node.h> namespacedemo{ usingv8::FunctionCallbackInfo; usingv8::Isolate; usingv8::Local; usingv8::Object; usingv8::String; usingv8::Value; usingv8::FunctionTemplate; usingv8::Function; usingv8::Number; usingv8::MaybeLocal; usingv8::Context; usingv8::Int32; staticintseq; //定义一个工具函数,生成seq voidGenSeq(constFunctionCallbackInfo<Value>&args){ Isolate*isolate=args.GetIsolate(); args.GetReturnValue().Set(Number::New(isolate,++seq)); } //定义一个加法函数 voidAdd(constFunctionCallbackInfo<Value>&args){ Isolate*isolate=args.GetIsolate(); inta=args[0].As<Int32>()->Value(); intb=args[1].As<Int32>()->Value(); args.GetReturnValue().Set(Number::New(isolate,a+b)); } voidInitialize( Local<Object>exports, Local<Value>module, Local<Context>context ){ Isolate*isolate=context->GetIsolate(); //新建一个函数模版 Local<FunctionTemplate>func=FunctionTemplate::New(isolate); //新建一个字符串表示函数名 Local<String>zaylee=String::NewFromUtf8(isolate,"zaylee",v8::NewStringType::kNormal).ToLocalChecked(); //设置函数名 func->SetClassName(zaylee); //设置原型属性 func->PrototypeTemplate()->Set(isolate,"protoField",Number::New(isolate,1)); //设置对象属性 func->InstanceTemplate()->Set(isolate,"instanceField",Number::New(isolate,2)); func->InstanceTemplate()->Set(isolate,"add",FunctionTemplate::New(isolate,Add)); //设置函数对象本身的属性 func->Set(isolate,"funcField",Number::New(isolate,3)); //根据函数模版创建一个函数 Local<Function>ret=func->GetFunction(context).ToLocalChecked(); Local<String>Demo=String::NewFromUtf8(isolate,"Demo",v8::NewStringType::kNormal).ToLocalChecked(); //导出函数 exports->Set(context,Demo,ret).Check(); //导出工具函数 NODE_SET_METHOD(exports,"genSeq",GenSeq); } NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME,Initialize) }//namespacedemo 写个测试例子
const{Demo,genSeq}=require('./build/Release/test.node'); constdemo=newDemo(); console.log('demo对象:',demo,'\n'); console.log('原型属性:',demo.protoField,'\n'); console.log('执行add方法:',demo.add(1,2),'\n'); console.log('执行seq方法:',genSeq(),genSeq(),'\n'); 最后编写编译配置
{ "targets":[ { "target_name":"test", "sources":["./test.cc"] } ] } 看起来非常简单,大概的流程如下
npminstall-gnode-gyp node-gypconfigure node-gypbuild nodetest.js 拓展nodejs的方式很多,插件是一种,直接修改内核也是一种,之前有介绍过如何修改内核,有兴趣的同学也可以看一下。
原文地址:https://mp.weixin.qq.com/s/oJDHYoPuCR7iy7XGp6eHTw