前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >北向应用集成三方库——应用如何调用C/C++三方库

北向应用集成三方库——应用如何调用C/C++三方库

原创
作者头像
小帅聊鸿蒙
发布2024-08-24 20:58:58
880
发布2024-08-24 20:58:58
举报
文章被收录于专栏:鸿蒙开发笔记

简介

OpenHarmony上的应用一般都是js/ets语言编写的,而js/ets语言是无法直接调用C/c接口的,所以我们应用如果需要调用C/c三方库的话,需要在js/ets和C/c之间建立一个可以互通的桥梁。OpenHarmony系统中提供的napi框架正是这么一座桥梁。

应用调用C/c三方库的方式

  • so形式调用 通过OpenHarmony的SDK编译,将三方库编译成so,和系统固件一起打包到系统rom中。
  • hap形式调用 将三方库源码和应用源码放在一起,通过IDE编译最终打包到应用hap包中。

应用调用C/c三方库实战

本文通过openjpeg三方库以hap形式调用为例进行说明应用是如何调用C/c三方库的。

移植适配

openjpeg三方库的移植适配参考文档通过IDE集成C/c三方库.

Napi接口开发

三方库napi的接口一般是由需求方提供的,对于无需求或需要自己定义接口的,我们可以根据三方库对外导出的API接口进行封装或是根据原生库的测试用例对外封装测试接口。本文中我们以封装2个openjpeg测试接口为例详细说明napi接口开发的具体流程。

napi接口开发前提是需要创建一个napi的工程,具体步骤参考通过Deveco Studio创建一个Napi工程

定义napi接口

根据原生库的测试用例,我们封装2个测试用例接口

代码语言:c
复制
typedef struct {
   int comps_num;           // the number of components of the image.
    int comps_prec;         // number of bits per component per pixel
    int img_width;          // the image width
    int img_height;         // the image height
    int title_width;        // width of tile
    int title_height;       // height of title
    int irreversible;       // 1 : use the irreversible DWT 9-7
                            // 0 : use lossless compression (default)
    int cblockw_init;       // initial code block width, default to 64
    int cblockh_init;       // initial code block height, default to 64
    int numresolution;      // number of resolutions
    int offsetx;            // x component offset compared to the whole image
    int offsety;            // y component offset compared to the whole image
    int is_rand;            // Whether to generate data randomly
    char file[256];         // output filename
} J2K_Info;

int OpenjpegCompress(const char *input_file, char *output_file)   # 图片压缩成J2K格式
int openjpeg_create_j2k(J2K_Info *info)                           # 创建一张J2K格式图片
napi接口注册
代码语言:c
复制
napi_property_descriptor desc[] = {
        {"openjpeg_compress", nullptr, OpenjpegCompress, nullptr, nullptr,
          nullptr, napi_default, nullptr},
        {"openjpeg_create_j2k", nullptr, OpenjpegCreateJ2K , nullptr, nullptr,
          nullptr, napi_default, nullptr}
    };
napi接口实现

-openjpeg_compress接口的实现

代码语言:c
复制
  static napi_value OpenjpegCompressMethod(napi_env env, napi_callback_info info)
  {
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    napi_value value;
    size_t argc = 2;
    napi_value args[2];
    size_t size;
    char input_file[256] = {0};
    char output_file[256] = {0};
    
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {  // 获取参数
        return result;
    }
    
    if (napi_get_value_string_utf8(env, args[0], input_file, sizeof(input_file),
                                   &size) != napi_ok) {                           // js类型转换成C/c类型
        return result;
    }
    
    if (napi_get_value_string_utf8(env, args[1], output_file, sizeof(output_file),
                                   &size) != napi_ok) {                           // js类型转换成C/c类型
        return result;
    }

    if (OpenjpegCompress(input_file, output_file) != 0) {                       // 三方库实现调用的业务逻辑接口
        return result;
    }

    if (napi_create_int64(env, 0, &result) != napi_ok) {                        // 创建返回的js类型参数
        std::cout << "napi_create_int64" << std::endl;
    }

    return result;                                                               // 返回最终结果。
  }

-openjpeg_create_j2k接口的实现

代码语言:c
复制
  static napi_value OpenjpegCreateJ2K(napi_env env, napi_callback_info info)
  {
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    napi_value value;
    size_t argc = 1;
    J2K_Info j2kInfo;

    if (napi_get_cb_info(env, info, &argc, &value, nullptr, nullptr) != napi_ok) {  // 获取参数
        return result;
    }
    
    if (OpenjpegGetJ2kInfo(env, value, &j2kInfo) < 0) {                             // 解析参数
        return result;
    }
  
    if (OpenjpegCreateJ2K(&j2kInfo) < 0) {                                          // 三方库实现调用的业务逻辑接口
        return result;
    }
    
    if (napi_create_int64(env, 0, &result) != napi_ok) {                           // 创建返回的js类型参数
        std::cout << "napi_create_int64" << std::endl;
    }
    
    return result;                                                                 // 返回最终结果。
  }
  • 解析参数接口OpenjpegGetJ2kInfo实现:
代码语言:c
复制
  static int OpenjpegGetJ2kInfo(napi_env env, napi_value value, J2K_Info *info)
  {
    if (info == nullptr) {
        return -1;
    }
    if(GetObjectPropetry(env, value,"output_file", STRING, info->file) != napi_ok) {
        return -1;
    }
    if (GetObjectPropetry(env, value,"comps_prec", NUMBER, &info->comps_prec) !=
        napi_ok) {
        return -1;
    }
    if (GetObjectPropetry(env, value,"img_width", NUMBER, &info->img_width) !=
        napi_ok) {
        return -1;
    }
    if (GetObjectPropetry(env, value,"img_height", NUMBER, &info->img_height) !=
        napi_ok) {
        return -1;
    }
    if (GetObjectPropetry(env, value,"title_width", NUMBER, &info->title_width) !=
        napi_ok) {
        return -1;
    }
    if (GetObjectPropetry(env, value,"title_height", NUMBER, &info->title_height) !=
        napi_ok) {
        return -1;
    }
    if (GetObjectPropetry(env, value,"irreversible", NUMBER, &info->irreversible) !=
        napi_ok) {
        return -1;
    }
    GetObjectPropetry(env, value,"cblockw_init", NUMBER, &info->cblockw_init);
    GetObjectPropetry(env, value,"cblockh_init", NUMBER, &info->cblockh_init);
    GetObjectPropetry(env, value,"numresolution", NUMBER, &info->numresolution);
    GetObjectPropetry(env, value,"offsetx", NUMBER, &info->offsetx);
    GetObjectPropetry(env, value,"offsety", NUMBER, &info->offsety);
    GetObjectPropetry(env, value,"is_rand", BOOLEAN, &info->is_rand);
    
    return 0;
  }

由上代码可以看出,OpenjpegGetJ2kInfo接扣调用了一个封装的接口GetObjectPropetry,该接口实现了通过调用napi的接口获取对应的数据:

代码语言:c
复制
  static int GetObjectPropetry(napi_env env, napi_value object, std::string key, int keyType, void *retValue) {
    napi_value property = nullptr;
    napi_value result = nullptr;
    bool flag = false;
    int ret = -1;

    if (napi_create_string_utf8(env, key.c_str(), strlen(key.c_str()), &property)
        != napi_ok) {                                                               // 通过字符串获取napi_value对象
        return ret;
    }

    if (napi_has_property(env, object, property, &flag) != napi_ok && flag == true) { // 判断该字符串是否对应由属性值
        return ret;
    }

    if (napi_get_property(env, object, property, &result) != napi_ok) {             // 获取字符串对应的属性值
        return ret;
    }
    
    if (keyType == NUMBER) {
        int64_t value = 0;
        if (napi_get_value_int64(env, result, &value) != napi_ok) {               // JS数据类型转换成C/c的int数据类型
            return ret;
        }
        *(int *)retValue = value;
        ret = 0;
    } else if (keyType == BOOLEAN) {
        bool value = false;
        if (napi_get_value_bool(env, result, &value) != napi_ok) {              // JS数据类型转换成C/c 的bool数据类型
            return ret;
        }
        *(int *)retValue = (value == true ? 1 : 0);
    }else if (keyType == STRING) {
        size_t s = 0;
        char buf[256] = {0};
        if (napi_get_value_string_utf8(env, result, buf, sizeof(buf), &s) !=
            napi_ok) {                                                          // JS数据类型转换成C/c的string数据类型
            return ret;
        }
        strncpy((char *)retValue, buf, strlen(buf));
        ret = 0;
    }

    return 0;
  }

应用调用napi接口

  • 接口声明 在确定需要封装的接口后,我们需要将这些接口定义在index.d.ts文件中(路径entry/src/main/cpp/types/libentry/index.d.ts)
代码语言:js
复制
  export const openjpeg_compress: (srcName:string, desName:string) =>number;
  interface openjpegOption{
    comps_num:number                // the number of components of the image.
    comps_prec:number               // number of bits per component per pixel
    img_width:number                // the image width
    img_height:number               // the image height
    title_width:number              // width of tile
    title_height:number             // height of title
    irreversible:number             // 1 : use the irreversible DWT 9-7, 
                    // 0 : use lossless compression (default)
    output_file:string              // output filename
    cblockw_init?:number            // initial code block width, default to 64
    cblockh_init?:number            // initial code block height, default to 64
    numresolution?:number           // number of resolutions
    offsetx?:number                 // x component offset compared to the whole image
    offsety?:number                 // y component offset compared to the whole image
    is_rand?:boolean                // Whether to generate data randomly
  }
  export const openjpeg_create_j2k: (option:openjpegOption) => number
  • 导入so文件
代码语言:ts
复制
  import testNapi from "libentry.so"
  • JS应用调用接口 在ets工程中创建2个按钮,并通过按钮调用相关的接口,具体代码如下:
代码语言:ts
复制
  Button(this.buttonTxt0)
  .fontSize(50)
  .margin({top:30})
  .fontWeight(FontWeight.Normal)
  .onClick(() => {
    testNapi.openjpeg_compress(this.dir + "test_pic.bmp", this.dir + "result.j2k")
  })
  Button(this.buttonTxt1)
  .fontSize(50)
  .margin({top:30})
  .fontWeight(FontWeight.Normal)
  .onClick(() => {
    testNapi.openjpeg_create_j2k({comps_num:3,comps_prec:8,
                                  img_width:2000,img_height:2000,
                                  title_width:1000,title_height:1000,
                                  irreversible:1, output_file:this.dir +
                                  "newImage.j2k"})
  })

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 应用调用C/c三方库的方式
  • 应用调用C/c三方库实战
    • 移植适配
      • Napi接口开发
        • 定义napi接口
        • napi接口注册
        • napi接口实现
      • 应用调用napi接口
      • 写在最后
      相关产品与服务
      图片处理
      图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档