当前位置: 首页 > news >正文

GMSSL2.x编译鸿蒙静态库和动态库及使用

一、编译环境准备

1.1 开发工具

DevEco-Studio下载。

1.2 SDK下载

​ 下载编译第三方库的SDK有两种方式,第一种方式从官方渠道根据电脑系统选择对应的SDK版本,第二种方式通过DevEco-Studio下载SDK。本文只介绍通过DevEco-Studio下载SDK的方式。

  • 安装SDK到本地

Xnip2024-07-22_09-55-12

Xnip2024-07-22_10-13-51 Xnip2024-07-22_10-25-15
  • 根据SDK安装位置获取SDK

Xnip2024-07-22_10-38-51

  • 将SDK复制到GMSSL的同级目录并更名为ohos-sdk

Xnip2024-07-22_16-36-50

二、编译鸿蒙架构

​ 第三方库编译鸿蒙架构有两种方式。一种是使用C/C++原生构建工具configure、makefile编译,一种是使用lycium框架快速交叉编译。本文只详细介绍通过configure、makefile编译的方式。

2.1 原生工具构建

  • 编写编译脚本

    #!/bin/bash# Define paths and environment variables
    # 获取脚本当前所在路径
    CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    # 获取GmSSL源码路径
    GMSSL_DIR=$CURRENT_PATH/GmSSL2.5.4
    # 取脚本执行的第一个参数
    OHOS_TARGET_ABI=$1
    # 获取鸿蒙SDK路径
    export OHOS_SDK=$CURRENT_PATH/ohos-sdk# 编译64位架构
    if [ "$OHOS_TARGET_ABI" == "arm64-v8a" ]
    thenexport AS=${OHOS_SDK}/native/llvm/bin/llvm-asexport CC=${OHOS_SDK}/native/llvm/bin/aarch64-unknown-linux-ohos-clangexport CXX=${OHOS_SDK}/native/llvm/bin/aarch64-unknown-linux-ohos-clang++export LD=${OHOS_SDK}/native/llvm/bin/ld.lldexport STRIP=${OHOS_SDK}/native/llvm/bin/llvm-stripexport RANLIB=${OHOS_SDK}/native/llvm/bin/llvm-ranlibexport OBJDUMP=${OHOS_SDK}/native/llvm/bin/llvm-objdumpexport OBJCOPY=${OHOS_SDK}/native/llvm/bin/llvm-objcopyexport NM=${OHOS_SDK}/native/llvm/bin/llvm-nmexport AR=${OHOS_SDK}/native/llvm/bin/llvm-arexport CFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1"export CXXFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1"outdir=arm64-v8acd ${GMSSL_DIR}./Configure linux-aarch64elif [ "$OHOS_TARGET_ABI" == "armeabi-v7a" ]
    then
    #编译32位架构export AS=${OHOS_SDK}/native/llvm/bin/llvm-asexport CC=${OHOS_SDK}/native/llvm/bin/armv7-unknown-linux-ohos-clangexport CXX=${OHOS_SDK}/native/llvm/bin/armv7-unknown-linux-ohos-clang++export LD=${OHOS_SDK}/native/llvm/bin/ld.lldexport STRIP=${OHOS_SDK}/native/llvm/bin/llvm-stripexport RANLIB=${OHOS_SDK}/native/llvm/bin/llvm-ranlibexport OBJDUMP=${OHOS_SDK}/native/llvm/bin/llvm-objdumpexport OBJCOPY=${OHOS_SDK}/native/llvm/bin/llvm-objcopyexport NM=${OHOS_SDK}/native/llvm/bin/llvm-nmexport AR=${OHOS_SDK}/native/llvm/bin/llvm-arexport CFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1"export CXXFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1"outdir=armeabi-v7acd ${GMSSL_DIR}./Configure linux-generic32elif [ "$OHOS_TARGET_ABI" == "x86_64" ]
    then
    #编译32位架构export AS=${OHOS_SDK}/native/llvm/bin/llvm-asexport CC=${OHOS_SDK}/native/llvm/bin/x86_64-unknown-linux-ohos-clangexport CXX=${OHOS_SDK}/native/llvm/bin/x86_64-unknown-linux-ohos-clang++export LD=${OHOS_SDK}/native/llvm/bin/ld.lldexport STRIP=${OHOS_SDK}/native/llvm/bin/llvm-stripexport RANLIB=${OHOS_SDK}/native/llvm/bin/llvm-ranlibexport OBJDUMP=${OHOS_SDK}/native/llvm/bin/llvm-objdumpexport OBJCOPY=${OHOS_SDK}/native/llvm/bin/llvm-objcopyexport NM=${OHOS_SDK}/native/llvm/bin/llvm-nmexport AR=${OHOS_SDK}/native/llvm/bin/llvm-arexport CFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1"export CXXFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1"outdir=x86_64# Navigate to OpenSSL directory./Configure linux-x86_64elseecho "Unsupported target ABI: $ANDROID_TARGET_ABI"exit 1
    fimake# Copy the outputs
    OUTPUT_INCLUDE=$CURRENT_PATH/ohos_libs/include
    OUTPUT_LIB=$CURRENT_PATH/ohos_libs/lib/${outdir}
    mkdir -p $OUTPUT_INCLUDE
    mkdir -p $OUTPUT_LIB
    cp -RL include/openssl $OUTPUT_INCLUDE
    cp libcrypto.so.1.1 $OUTPUT_LIB
    cp libcrypto.a $OUTPUT_LIB
    cp libssl.so.1.1 $OUTPUT_LIB
    cp libssl.a $OUTPUT_LIB

    将编写好的脚本文件命名为ohos.sh。文件之间的目录结构如下:

    Xnip2024-07-22_11-23-56

  • 执行脚本

    cd到HarmonyOS-SDK目录下,依次执行如下命令,分别编译64位、32位、x86_64的鸿蒙架构。

    ohos.sh  arm64-v8a
    ohos.sh  armeabi-v7a
    ohos.sh  x86_64
  • 编译问题

    截屏2024-07-19 11.11.09

    解决方案:删除GMSSL2.5.4源码中对getcontext、makecontext、setcontext等函数的引用。

2.2 使用lycium框架编译

  • 环境配置

    查看环境配置文档

  • 编译步骤

    查看lycium编译步骤

三、使用库文件

​ 鸿蒙工程可以使用.a的静态库和.so的动态库,两种类型的库引用一种即可。

3.1 创建NAPI工程

​ NAPI是OpenHarmony系统中的原生模块扩展开发框架,提供JavaScript与C/C++模块之间相互调用的交互能力。

Xnip2024-07-22_14-43-42

  • 添加二进制文件到工程

Xnip2024-07-22_15-03-28

如果该三方库二进制文件为so文件,还需要将so文件拷贝到工程目录的entry/libs/${OHOS_ARCH}/目录下,如下图:

so_location

3.2 配置链接

​ 添加二进制文件后需要在cpp目录的CMakeLists.txt文件中添加对应target_link_libraries才能被工程引用。

  • 配置静态库链接

    target_link_libraries(product PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gmssl/${OHOS_ARCH}/lib/libcrypto.a)
    target_link_libraries(product PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gmssl/${OHOS_ARCH}/lib/libssl.a)
  • 配置动态库链接

    target_link_libraries(product PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gmssl/${OHOS_ARCH}/lib/libcrypto.so)
    target_link_libraries(product PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gmssl/${OHOS_ARCH}/lib/libssl.so)
  • 配置头文件

    target_include_directories(product PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gmssl/${OHOS_ARCH}/include)

Xnip2024-07-22_15-16-13

四、编写NAPI接口

​ 配置完三方库的链接和头文件路径后,可以根据各自的业务逻辑调用三方库对应的接口完成NAPI接口的编写,NAPI接口开发可以参照以下文档学习。

  1. 使用Node-API实现跨语言交互开发流程

  2. C/C++三方库使用

4.1 NAPI编写示例

​ NAPI接口编写的基本思路是将从JavaScript层传入的参数转成C/C++数据类型,然后调用第三方库接口执行业务逻辑,最后将执行的结果转成JavaScript数据类型返回给JavaScript层。

Xnip2024-07-22_15-43-46

  • 编写接口

    napi_init.cpp文件中编写NAPI接口。

第一步:获取JS层传入的参数转成C/C++数据类型并将转换的结果作为参数传入第三方库函数中。

static napi_value gm_post(napi_env env, napi_callback_info info){size_t argc = 4;napi_value args[4];// 获取JS参数napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);char url[512] = {0},parameter[MAX_BUF] = {0}, filePath[1024] = {0};size_t url_len,parameter_len,filePath_len;double timeOut;// 获取请求地址 napi(JS)数据类型转c/c++数据类型napi_get_value_string_utf8(env, args[0], url, sizeof(url), &url_len);// 获取请求参数 napi(JS)数据类型转c/c++数据类型napi_get_value_string_utf8(env, args[1], parameter, sizeof(parameter), &parameter_len);// 获取超时时间napi_get_value_double(env, args[2], &timeOut);// 获取证书路径napi_get_value_string_utf8(env, args[3], filePath, sizeof(filePath), &filePath_len);// 调用gmssl库的post请求方法resp_t *resp = infosecPost(url, parameter, timeOut, NULL, filePath);// 格式转换后返回响应数据return transformRespToNapi(env, resp);
}

第二步:将第三方库返回的结果转成JavaScript数据类型

static napi_value transformRespToNapi(napi_env env,resp_t *resp){napi_value res_obj;// 1.创建对象napi_status status = napi_create_object(env, &res_obj);if (status != napi_ok) {napi_throw_error(env,"-1","创建响应数据对象异常");return nullptr;}// 2.创建data属性值napi_value res_data;status = napi_create_string_utf8(env, resp->data, NAPI_AUTO_LENGTH, &res_data);if (status != napi_ok) {napi_throw_error(env,"-2","创建属性值异常");return nullptr;}status = napi_set_named_property(env, res_obj, "data", res_data);if (status != napi_ok) {napi_throw_error(env,"-3","设置对象的属性异常");return nullptr;}// 3.创建code属性napi_value res_code;status = napi_create_double(env, resp->code, &res_code);if (status != napi_ok) {napi_throw_error(env,"-2","创建属性值异常");return nullptr;}status = napi_set_named_property(env, res_obj, "code", res_code);if (status != napi_ok) {napi_throw_error(env,"-3","设置对象的属性异常");return nullptr;}resp_free(resp);return res_obj;
}

第三步:ArkTS接口与C/C++接口绑定和映射

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{napi_property_descriptor desc[] = {{ "send_gm_post", nullptr, gm_post, nullptr, nullptr, nullptr, napi_default, nullptr }};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_END

​ 说明:send_gm_post是ArkTS的函数名,gm_post是C/C++函数名。

  • 声明ArkTS侧的方法

Index.d.ts文件中声明ArkTS侧的方法。

export const send_gm_post: (url: string,parameters:string,timeOut:number,caPath:string) => object;

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【ELK】window下ELK的安装与部署
  • 【算法专题】双指针算法之LCR 179. 查找总价格为目标值的两个商品(力扣)
  • 【已解决】服务器无法联网与更换镜像源
  • JavaScript之WebAPIs-BOM
  • TCP重传机制详解
  • 【BUG】已解决:requests.exceptions.ProxyError: HTTPSConnectionPool
  • Python自动化DevOps任务入门
  • go语言Gin框架的学习路线(七)
  • python调用chrome浏览器自动化如何选择元素
  • 函数(递归)
  • 【JAVA】数据类型及变量
  • Android Navigation 组件原理和使用教程
  • 面试问题:React基本概念,和所遇到的CPU和IO问题
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • Java面试题--JVM大厂篇之深入解析JVM中的Serial GC:工作原理与代际区别
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 78. Subsets
  • C++11: atomic 头文件
  • create-react-app做的留言板
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • egg(89)--egg之redis的发布和订阅
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • HashMap ConcurrentHashMap
  • JavaScript学习总结——原型
  • JWT究竟是什么呢?
  • Meteor的表单提交:Form
  • Netty源码解析1-Buffer
  • SpringBoot 实战 (三) | 配置文件详解
  • SQLServer之创建显式事务
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • Swoft 源码剖析 - 代码自动更新机制
  • Vue 重置组件到初始状态
  • vue脚手架vue-cli
  • Webpack 4x 之路 ( 四 )
  • yii2权限控制rbac之rule详细讲解
  • 工作手记之html2canvas使用概述
  • 如何进阶一名有竞争力的程序员?
  • 新书推荐|Windows黑客编程技术详解
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • C# - 为值类型重定义相等性
  • PostgreSQL之连接数修改
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 整理一些计算机基础知识!
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • # Maven错误Error executing Maven
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (3)nginx 配置(nginx.conf)
  • (二)hibernate配置管理
  • (二十六)Java 数据结构
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (十) 初识 Docker file
  • (四)进入MySQL 【事务】
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战