c++ in nodejs (V8)
2023-09-14 08:58:44 时间
$ npm i -g node-gyp
$ mkdir node-addons
$ cd node-addons
$ npm i nan
$ touch hello.cpp binding.gyp test.js
hello.cpp
#include <node.h>
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Object;
using v8::String;
using v8::Value;
#define V8_STR(str) String::NewFromUtf8(isolate, str, NewStringType::kNormal).ToLocalChecked()
void a(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set( V8_STR("world") );
}
void Initialize(Local<Object> exports) {
NODE_SET_METHOD(exports, "a", a);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
binding.gyp
{
"targets": [
{
"target_name": "addon",
"sources": ["main.cpp"],
"include_dirs": [
"<!(node -e \"require('nan')\")"
]
}
]
}
test.js
const addon = require('./build/Release/addon');
console.log(addon.a());
λ node-gyp configure
λ node-gyp build
λ node test.js
打包成功后,可以使用vs打开"build/binding.sln"
v8::String to string
#include <ostream>
#include <node.h>
#include <nan.h>
using namespace std;
using v8::String;
using Nan::Utf8String;
auto k = String::NewFromUtf8(isolate, "msg", NewStringType::kNormal).ToLocalChecked();
string str{ *Utf8String{k} };
printf("%s\n", str.c_str()); // msg
// or
// string str{ *String::Utf8Value{isolate, k} };
函数传参
#include <ostream>
#include <node.h>
using namespace std;
using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Number;
#define V8_STR(str) String::NewFromUtf8(isolate, str, NewStringType::kNormal).ToLocalChecked()
void a(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
printf("%d\n", args.Length()); // 2
if (args.Length() < 2) {
isolate->ThrowException(Exception::TypeError(V8_STR("Wrong number of arguments")));
return;
}
if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
isolate->ThrowException(Exception::TypeError( V8_STR("Wrong arguments") ));
return;
}
double a1 = args[0].As<Number>()->Value();
double a2 = args[1].As<Number>()->Value();
double value = a1 + a2;
printf("%f + %f = %f\n", a1, a2, value); // 1.000000 + 2.000000 = 3.0000003
Local<Number> num = Number::New(isolate, value);
args.GetReturnValue().Set(num);
}
void Initialize(Local<Object> exports) {
NODE_SET_METHOD(exports, "a", a);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
let r = addon.a(1, 2);
console.log(r); // 3
回调函数
#include <ostream>
#include <node.h>
using namespace std;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Null;
using v8::Object;
using v8::String;
using v8::Value;
#define V8_STR(str) String::NewFromUtf8(isolate, str, NewStringType::kNormal).ToLocalChecked()
void a(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> ctx = isolate->GetCurrentContext();
Local<Function> cb = Local<Function>::Cast(args[0]);
const size_t argc = 2;
Local<Value> argv[argc] = {
V8_STR("hello"),
V8_STR("world"),
};
cb->Call(ctx, Null(isolate), argc, argv).ToLocalChecked();
}
void Initialize(Local<Object> exports, Local<Object> module) {
// module.exports = ...
NODE_SET_METHOD(module, "exports", a);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
addon((a, b) => {
console.log(a, b); // hello world
});
返回object
#include <ostream>
#include <node.h>
using namespace std;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Null;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Number;
#define V8_STR(str) String::NewFromUtf8(isolate, str, NewStringType::kNormal).ToLocalChecked()
void a(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> ctx = isolate->GetCurrentContext();
Local<Object> obj = Object::New(isolate);
auto k = V8_STR("msg");
auto v = args[0]->ToString(ctx).ToLocalChecked();
obj->Set(ctx, k, v).FromJust();
args.GetReturnValue().Set(obj);
}
void Initialize(Local<Object> exports, Local<Object> module) {
NODE_SET_METHOD(module, "exports", a);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
let r = addon('xxx');
console.log(r); // { msg: 'xxx' }
返回函数
#include <ostream>
#include <node.h>
#include <nan.h>
using namespace std;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Null;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Number;
using Nan::Utf8String;
using v8::FunctionTemplate;
#define V8_STR(str) String::NewFromUtf8(isolate, str, NewStringType::kNormal).ToLocalChecked()
void MyFunction(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set( V8_STR("hello world") );
}
void a(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, MyFunction);
Local<Function> fn = tpl->GetFunction(context).ToLocalChecked();
fn->SetName( V8_STR("theFunction") );
args.GetReturnValue().Set(fn);
}
void Initialize(Local<Object> exports, Local<Object> module) {
NODE_SET_METHOD(module, "exports", a);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
let r = addon();
console.log(r()); // hello world
返回Promise
#include <node.h>
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Promise;
#define V8_STR(str) String::NewFromUtf8(isolate, str, NewStringType::kNormal).ToLocalChecked()
void a(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
auto context = isolate->GetCurrentContext();
Local<Promise::Resolver> resolver = Promise::Resolver::New(context).ToLocalChecked();
Local<Promise> promise = resolver->GetPromise();
args.GetReturnValue().Set( promise );
resolver->Resolve( context, V8_STR("hello world.") );
}
void Initialize(Local<Object> exports) {
NODE_SET_METHOD(exports, "a", a);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
addon.a().then((r) => {
console.log(r); // hello world.
});
返回promise,你可以随时返回结果
#include <Windows.h>
int r = MessageBoxA(0, "body", "title", 0);
resolver->Resolve( context, Number::New(isolate, r) );
// int r = MessageBoxA(0, "body", "title", 0);
// args.GetReturnValue().Set( Number::New(isolate, r) );
See also:
相关文章
- C++:关键字explicit的用法
- C++学习2——基础知识
- 深度探索C++对象模型--------默认构造函数
- c++保存数据到TXT
- electron 调用nodejs native c++ addon
- 创建可重用代码(C++)
- C/C++每日一练(20230418)
- C/C++每日一练(20230219)
- C语言/C++常见习题问答集锦(五十七) 之小C的随机数选择
- Open3D (C++) 点云投影到平面
- 2034. 股票价格波动-c++,无序字典+有序集合
- C++学习心得与c语言到c++衔接技巧
- 解答私信@被c++折磨头秃的花季美少女 //C++ 利用指针数组输入10个单词,编写函数对10个单词进行排序并输出,要求判断是否有相同的单词,如果有相同的单词在输出时该单词只输出一次。
- 解答私信@被c++折磨头秃的花季美少女 //C++ 编写一个进阶版的进制转换程序,运行功能如下:请选择要输入的数字的进制(2、8、10、16):请输入该数字:请选择要转换成的进制(2、8。。。
- C++每日面试之字符串自定义解压算法
- C++每日面试之算法训练 寻找数组中最大值
- C++文件流fstream相关操作
- eclipse c++ 开发工具 Linux Ubuntu
- AI模型C++部署:ubuntu安装Cython并使用C/C++调用python动态库【附加c++与python互相调用算法demo程序接口的源码】
- VS2019中C++20的协程实现
- C/C++语言中常见问题1
- C++Primer学习笔记4-基本函数