C++ Addon Async 异步机制
线程队列: libuv,window 可在libuv官网下载相应版本
opencv: 编译的时候opencv的位数要和 node的bit 一致
兼容electron : node-gyp rebuild --version --Debug/--Release --archs=x64/ia32
v8文档: https://v8docs.nodesource.com/
#include <node.h>
#include <v8.h>
#include <uv.h>
#include <windows.h>
#include <string.h>
#include <string>
#include <iostream>
#include <thread>
#include <opencv/cv.h>
#include <opencv2/opencv.hpp> using namespace v8;
// 传入了两个参数,args[0] 字符串,args[1] 回调函数s
struct SImageData {
int status = -;
int width = ;
int height = ;
int channels = ;
int size = ;
int step = ;
std::vector<int> data;
std::string msg; //msg
}; void hello(const FunctionCallbackInfo<Value>& args) {
// 使用 HandleScope 来管理生命周期s
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate); // 判断参数格式和格式s
if (args.Length() < || !args[]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Wrong arguments")));
return;
} // callback, 使用Cast方法来转换s
Local<Function> callback = Local<Function>::Cast(args[]);
Local<Value> argv[] = {
// 拼接String
String::Concat(Local<String>::Cast(args[]), String::NewFromUtf8(isolate, " world"))
};
// 调用回调, 参数: 当前上下文,参数个数,参数列表s
callback->Call(isolate->GetCurrentContext()->Global(), , argv);
}
//三个参数 图片路径,目标图片宽度, 返回值: 图像参数,数据流s
void getImageData(const FunctionCallbackInfo<Value>& 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<String> filepath = Local<String>::Cast(args[]);
String::Utf8Value filePath(filepath);
// js Number 类型转换成 v8 Number 类型s
Local<Number> dstWidth = Local<Number>::Cast(args[]);
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), , , );
// 获取图片流信息
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 = ;
sData.width = img.cols;
sData.height = img.rows;
sData.size = size;
sData.step = img.step;
sData.channels = channels; //c++ -> js
Local<Object> obj = Object::New(isolate);
// Number type
Local<Number> jsStatus = Number::New(isolate, sData.status);
Local<Number> jsWidth = Number::New(isolate, sData.width);
Local<Number> jsHeight = Number::New(isolate, sData.height);
Local<Number> jsSize = Number::New(isolate, sData.size);
Local<Number> jsStep = Number::New(isolate, sData.step);
Local<Number> 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<Function> callback = Local<Function>::Cast(args[]);
const unsigned argc = ;
Local<Value> 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<Function> callback; //javascript callback <heap> int type;
}; void lookupIpCountryAsync(uv_work_t * work){
LookupIpCountryBaton * baton = (LookupIpCountryBaton*)work->data; // block thread for 3 seconds
Sleep();
// save the result
baton->type = ;
} void lookupIpCountryCompleted(uv_work_t * work, int){
LookupIpCountryBaton * baton = (LookupIpCountryBaton*)work->data;
Isolate * isolate = Isolate::GetCurrent();
HandleScope handleScope(isolate);
const unsigned argc = ;
Local<Value> argv[argc] = {String::NewFromUtf8(isolate, "HHEE")};
Local<Function>::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<Value>& args) {
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
HandleScope scope(isolate);
if (args.Length() < ) {
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong params of arguments")));
return ;
} LookupIpCountryBaton * baton = new LookupIpCountryBaton();
baton->work.data = baton;
baton->type = ; //baton->callback = Persistent<Function>::New(Handle<Function>::Cast(args[1]));
baton->callback.Reset(isolate, Local<Function>::Cast(args[])); uv_queue_work( uv_default_loop(), &baton->work, lookupIpCountryAsync, lookupIpCountryCompleted); return ;
} // 相当于在 exports 对象中添加 { hello: hello }
void init(Handle<Object> 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);
C++ Addon Async 异步机制的更多相关文章
- 深入理解Spring的异步机制
一.Spring中实现异步执行 在这里我先以事件的机制举例,注意默认情况下事件的发布与监听都是同步执行的.那么我们来看一看基于异步事件的例子该怎么写 首先还是定义事件: package com.bdq ...
- spring boot(17)-@Async异步
验证码的异步机制 上一篇讲过可以用邮件发验证码,通常我们在某网站发验证码时,首先会提示验证码已发送,请检查邮箱或者短信,这就是图中的1和3.然而此时查看邮箱或短信可能并没有收到验证码,往往要过几秒种才 ...
- Windows store app[Part 4]:深入WinRT的异步机制
接上篇Windows store app[Part 3]:认识WinRT的异步机制 WinRT异步机制回顾: IAsyncInfo接口:WinRT下异步功能的核心,该接口提供所有异步操作的基本功能,如 ...
- Windows store app[Part 3]:认识WinRT的异步机制
WinRT异步机制的诞生背景 当编写一个触控应用程序时,执行一个耗时函数,并通知UI更新,我们希望所有的交互过程都可以做出快速的反应.流畅的操作感变的十分重要. 在连接外部程序接口获取数据,操作本地数 ...
- 异步编程系列第01章 Async异步编程简介
p { display: block; margin: 3px 0 0 0; } --> 2016.10.11补充 三个月过去了,回头来看,我不得不承认这是一系列失败的翻译.过段时间,我将重新翻 ...
- 结合源码看nginx-1.4.0之nginx异步机制详解
目录 0. 摘要 1. nginx异步设计思想 2. nginx异步设计数据结构 3. nginx异步机制源码解析 4. 一个简单的应用异步例子 5. 小结 6. 参考源码
- JavaScript的异步机制
我们经常说JS是单线程的,比如node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何 1 先看下两 ...
- JavaScript单线程和异步机制
随着对JavaScript学习的深入和实践经验的积累,一些原理和底层的东西也开始逐渐了解.早先也看过一些关于js单线程和事件循环的文章,不过当时看的似懂非懂,只留了一个大概的印象:浏览器中的js程序时 ...
- @Async异步注解与SpringBoot结合使用
当你在service层需要启动异步线程去执行某些分支任务,又不希望显式使用Thread等线程相关类,只想专注于实现业务逻辑代码开发,可以使用@Async异步注解. 1. 使用@Async 异步注解 C ...
随机推荐
- hdu2955 Robberies(背包)
https://vjudge.net/problem/HDU-2955 概率是浮点数,只能做值(而且这里是累乘,也不能化成整数),这里注意要化成安全概率(1-p[i]),求安全概率的最大值. 钱数作二 ...
- 常见问题2:html+css效果综合整理
1.---文本框提示文字颜色--placeholder属性 <input type="text" placeholder="请输入提示文字" /> ...
- Oracle创建Database Link
一菜单方式: 打开plsql,点击[File]-[New]-[Database link],打开如下图所示窗口 填好各项信息后,点击[Apply]即可完成Database Link的创建. 二SQL方 ...
- JavaWeb中过滤器Filter的使用示例
https://github.com/YouXianMing/Java-Web-Study/tree/master/Servlet-Filter 过滤器示例基于以下流程 测试效果如下 web.xml配 ...
- 初识 Nginx
Nginx 是一个免费的,开源的,高性能的HTTP服务器和反向代理,以及IMAP / POP3代理服务器. Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名.很多高知名度的网站 ...
- quartz集群分布式(并发)部署解决方案
项目中使用分布式并发部署定时任务,多台跨JVM,按照常理逻辑每个JVM的定时任务会各自运行,这样就会存在问题,多台分布式JVM机器的应用服务同时干活,一个是加重服务负担,另外一个是存在严重的逻辑问题, ...
- Oracle 之 树查询 START WITH ... CONNECT BY ...子句
START WITH ... CONNECT BY ...子句是结构化查询中用到的,其基本语法是: select … from tablename start with 条件1 connect by ...
- 朗科32G TF卡的读写测试
卡是这样的, 下面是实际测试的结果. 容量测试 SKS的USB2外置读卡器, X240内置读卡器加上SD卡套 UNITEK的USB3.0读卡器, 经过UNITEK的USB3.0 HUB 看来读4 ...
- .NET 同步与异步 之 Mutex (十二)
本随笔续接:.NET 同步与异步 之 线程安全的集合 (十一) 本随笔 及 接下来的两篇随笔,将介绍 .NET 同步与异步系列 的最后一个大块知识点:WaitHandle家族. 抽象基类:WaitHa ...
- PHP操作二进制字节数据
在PHP开发中大都是操作字符类数据,极为方便,但操作二进制又如何呢,下面代码举例看看. 函数: pack(format,args+) pack()和unpack()函数的第一个参数表如下 Bash ...