• 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 = -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<Value>& 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<Function> callback = Local<Function>::Cast(args[1]);
      Local<Value> argv[1] = {
        // 拼接String
        String::Concat(Local<String>::Cast(args[0]), String::NewFromUtf8(isolate, " world"))
      };
      // 调用回调, 参数: 当前上下文,参数个数,参数列表s
      callback->Call(isolate->GetCurrentContext()->Global(), 1, 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[0]);
        String::Utf8Value filePath(filepath);
        // js Number 类型转换成 v8 Number 类型s
        Local<Number> dstWidth = Local<Number>::Cast(args[1]);
        printf("%s %f
    ", *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
    ;height = %d
    ;channels = %d
    ;step = %d
    ",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<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[2]);
        const unsigned argc = 1;
        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(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<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() < 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<Function>::New(Handle<Function>::Cast(args[1]));
        baton->callback.Reset(isolate, Local<Function>::Cast(args[1]));
    
    
        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);
  • 相关阅读:
    MySQL Execution Plan--合理利用隐式的业务逻辑
    MySQL Table--MySQL外键
    MySQL倒序索引测试2
    MySQL倒序索引测试1
    CCNA-3.硬件介质
    CCNA-2.OSI 7层网络模型
    CCNA-1.认识网络
    windows本地安装Oracle数据库
    扫码登录实现原理
    phpunit 单元测试
  • 原文地址:https://www.cnblogs.com/mypsq/p/9930734.html
Copyright © 2020-2023  润新知