线程队列: libuv,window 可在libuv官网下载相应版本
opencv: 编译的时候opencv的位数要和 node的bit 一致
兼容electron : node-gyp rebuild --version --Debug/--Release --archs=x64/ia32
v8文档: https://v8docs.nodesource.com/
#include
#include
#include
#include
#include <string .h>
#include <string >
#include
#include
#include
#include
using namespace v8;
// 传入了两个参数,args[0] 字符串,args[1] 回调函数s
struct SImageData {
int status = -1 ;
int width = 0 ;
int height = 0 ;
int channels = 0 ;
int size = 0 ;
int step = 0 ;
std::vector <int > data;
std:: string msg; // msg
};
void hello(const FunctionCallbackInfo& args) {
// 使用 HandleScope 来管理生命周期s
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
// 判断参数格式和格式s
if (args.Length() < 2 || !args[0 ]->IsString()) {
isolate ->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, " Wrong arguments " )));
return ;
}
// callback, 使用Cast方法来转换s
Local callback = Local::Cast(args[1 ]);
Local argv[1 ] = {
// 拼接String
String::Concat(Local::Cast(args[0 ]), String::NewFromUtf8(isolate, " world " ))
};
// 调用回调, 参数: 当前上下文,参数个数,参数列表s
callback->Call(isolate->GetCurrentContext()->Global(), 1 , argv);
}
// 三个参数 图片路径,目标图片宽度, 返回值: 图像参数,数据流s
void getImageData(const FunctionCallbackInfo& args){
Isolate * isolate = args.GetIsolate();
SImageData sData;
// 参数长度判断s
/*
if (args.Length() < 3) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Wrong params of arguments")));
return ;
}
*/
// js String 类型转换成 v8 String 类型s
Local filepath = Local::Cast(args[0 ]);
String::Utf8Value filePath(filepath);
// js Number 类型转换成 v8 Number 类型s
Local dstWidth = Local::Cast(args[1 ]);
printf( " %s %f\n " , *filePath, dstWidth->NumberValue());
cv::Mat srcImg = cv::imread(std::string (*filePath));
cv::Mat img;
int width = srcImg.cols;
int height = srcImg.rows;
// 图片压缩s
int r_width = width;
int r_height = r_width * height / width;
resize(srcImg, img, cv::Size(r_width, r_height), 0 , 0 , 3 );
// 获取图片流信息
int channels = img.channels();
uchar * buffer = img.data;
width = img.cols;
height = img.rows;
// printf("width = %d\n;height = %d\n;channels = %d\n;step = %d\n",width, height, channels, step);
int size = width * channels * height;
sData.data.clear();
/*
for (int i = 0; i < size; i += channels) {
int r = buffer[i];
int g = buffer[i + 1];
int b = buffer[i + 2];
sData.data.push_back(r);
sData.data.push_back(g);
sData.data.push_back(b);
}
*/
sData.status = 1 ;
sData.width = img.cols;
sData.height = img.rows;
sData.size = size;
sData.step = img.step;
sData.channels = channels;
// c++ -> js
Local obj = Object::New(isolate);
// Number type
Local jsStatus = Number::New(isolate, sData.status);
Local jsWidth = Number::New(isolate, sData.width);
Local jsHeight = Number::New(isolate, sData.height);
Local jsSize = Number::New(isolate, sData.size);
Local jsStep = Number::New(isolate, sData.step);
Local jsChannels = Number::New(isolate, sData.channels);
obj ->Set(String::NewFromUtf8(isolate, " status " ), jsStatus);
obj ->Set(String::NewFromUtf8(isolate, " width " ), jsWidth);
obj ->Set(String::NewFromUtf8(isolate, " height " ), jsHeight);
obj ->Set(String::NewFromUtf8(isolate, " size " ), jsSize);
obj ->Set(String::NewFromUtf8(isolate, " step " ), jsStep);
obj ->Set(String::NewFromUtf8(isolate, " channels " ), jsChannels);
// args.GetReturnValue().Set(obj);
// callback, 使用Cast方法来转换s
Local callback = Local::Cast(args[2 ]);
const unsigned argc = 1 ;
Local argv[argc] = { obj };
// cb->Call(Null(isolate), argc, argv);
// 调用回调, 参数: 当前上下文,参数个数,参数列表s
callback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
}
// async
// 在AddOn中,定义一个结构体在异步调用中传递数据s
struct LookupIpCountryBaton {
uv_work_t work; // libuv
Persistent callback; // javascript callback
int type;
};
void lookupIpCountryAsync(uv_work_t * work){
LookupIpCountryBaton * baton = (LookupIpCountryBaton*)work->data;
// block thread for 3 seconds
Sleep(3000 );
// save the result
baton->type = 100002 ;
}
void lookupIpCountryCompleted(uv_work_t * work, int ){
LookupIpCountryBaton * baton = (LookupIpCountryBaton*)work->data;
Isolate * isolate = Isolate::GetCurrent();
HandleScope handleScope(isolate);
const unsigned argc = 1 ;
Local argv[argc] = {String::NewFromUtf8(isolate, " HHEE " )};
Local ::New(isolate, baton->callback)->Call(isolate->GetCurrentContext()->Global(), argc, argv);
baton ->callback.Reset();
delete baton;
}
// 导出方法首先保存回调函数,并验证和解析传入参数s
// lookup country by ip
// 1st argument is ip address
// 2nd argument is the callback function
void lookupIpCountry(const FunctionCallbackInfo& args) {
Isolate *isolate = args.GetIsolate();
Local context = isolate->GetCurrentContext();
HandleScope scope(isolate);
if (args.Length() < 2 ) {
isolate ->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, " Wrong params of arguments " )));
return ;
}
LookupIpCountryBaton * baton = new LookupIpCountryBaton();
baton ->work.data = baton;
baton ->type = 200 ;
// baton->callback = Persistent::New(Handle::Cast(args[1]));
baton->callback.Reset(isolate, Local::Cast(args[1 ]));
uv_queue_work( uv_default_loop(), &baton->work, lookupIpCountryAsync, lookupIpCountryCompleted);
return ;
}
// 相当于在 exports 对象中添加 { hello: hello }
void init(Handle exports) {
NODE_SET_METHOD(exports, " hello " , hello);
NODE_SET_METHOD(exports, " getImageData " , getImageData);
NODE_SET_METHOD(exports, " delay " , lookupIpCountry);
}
// 将 export 对象暴露出去s
// 原型 `NODE_MODULE(module_name, Initialize)`s
NODE_MODULE(opencv_image, init);