积分1636 / 贡献20

提问18答案被采纳66文章40

[经验分享] OpenHarmony应用开发引入开源C/C++库---之Lycium使用经验总结 原创

深开鸿_王石 显示全部楼层 发表于 2024-6-27 10:17:17

论坛里好多人在问,我有c,c++库,怎么在so里调用,这边介绍个可行方案,供大家参考

lycium 交叉编译框架

lycium是一款协助开发者通过shell语言实现C/C++三方库快速交叉编译,并在OpenHarmony 系统上快速验证的编译框架工具。开发者只需要设置对应C/C++三方库的编译方式以及编译参数,通过lycium就能快速的构建出能在OpenHarmony 系统运行的二进制文件。

  • 原则 移植过程,不可以改源码(即不patchc/cpp文件,不patch构建脚本)。如移植必须patch,patch必须评审,给出充分理由。(不接受业务patch)
  • 目录结构
    .
    ├── docs                            #说明使用文档
    ├── LICENSE
    ├── lycium                          #编译工具
    │   ├── build.sh                    #编译的入口脚本
    │   ├── Buildtools
    │   ├── CItools
    │   ├── community
    │   ├── doc
    │   ├── lycium_build_intl.log
    │   ├── ohos-sdk                    #我解压的sdk,然后export配置了路径,后面会说
    │   ├── OpenHarmony_4.0.8.tar.gz    #我自己下载的sdk
    │   ├── README.md
    │   ├── script
    │   ├── template
    │   ├── test.sh
    │   └── usr                         #编译后的头文件和lib库会安装在此目录下
    ├── README_zh.md
    └── thirdparty                      #改过编译配置文件的三方库

通过Lycium工具构建C/C++三方库

  1. 编译环境准备
    1. 安装缺少的库:lycium框架支持多种构建方式的三方库,为了保障三方库能正常编译,我们需要保证编译环境中包含以下几个基本编译命令: gcc, cmake, make, pkg-config, autoconf, autoreconf, automake, 如若缺少相关命令,可通过官网下载对应版本的工具包,也可以在编译机上通过命令安装,如若 Ubuntu系统上缺少 cmake可以通过以下命令安装:
    sudo apt install cmake

    其他都一样,比如我编译ffmpeg的时候出现了以下报错,这个其实就是要不缺少nasm,要不缺少yasm,确认下

      nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.
    
      xx@XX_ZLL:~/xx/tpc_c_cplusplus/lycium$ nasm
      Command 'nasm' not found, but can be installed with:
      sudo apt install nasm
      xx@XX_ZLL:~/xx/tpc_c_cplusplus/lycium$ yasm
      Command 'yasm' not found, but can be installed with:
      sudo apt install yasm
    
    1. 下载OHOS_SDK,官方下载路径 。 SDK分Full SDK 和 Public SDK,对交叉编译一样,所以随便下,这里给两个我下的链接。
    sdk(windows+linux): http://download.ci.openharmony.cn/version/Master_Version/OpenHarmony_4.0.10.5/20230824_120941/version-Master_Version-OpenHarmony_4.0.10.5-20230824_120941-ohos-sdk-full_monthly.tar.gz
    ohos-sdk-public: http://download.ci.openharmony.cn/version/Master_Version/OpenHarmony_4.0.10.5/20230824_120921/version-Master_Version-OpenHarmony_4.0.10.5-20230824_120921-ohos-sdk-public_monthly.tar.gz

    下载完毕后需要部署好,我是在~/xx/tpc_c_cplusplus/lycium这个里面下的,所以就原地解压了,命令如下:

      # 解压sdk
      tar -zxvf version-Master_Version-OpenHarmony_4.0.8.1-20230608_091016-ohos-sdk-full.tar.gz
    
      # 进入sdk里的linux目录
      cd ohos-sdk/linux/
    
      # 解压目录里的zip文件,解完后可以进到native目录里去看有没有arm工具链,你会失望的发现,没有
      for i in *.zip;do unzip ${i};done
    
      # 进入到工具包目录
      cd lycium/Buildtools     
    
      # 可校验工具包是否正常, 若输出"toolchain.tar.gz: OK"则说明工具包正常,否则说明工具包异常,需重新下载
      sha512sum -c SHA512SUM               
    
      # 解压拷贝编译工具,这个里面其实就是arm工具链
      tar -zxvf toolchain.tar.gz           
    
      # 将命令拷贝到工具链的native/llvm/bin目录下
      cp toolchain/* ${OHOS_SDK}/native/llvm/bin  

    如上全做完,你的工具链就在ohos-sdk/linux/native下装好了

    lycium/ohos-sdk/linux/native
    ├── build
    │   └── cmake
    │       ├── ohos.toolchain.cmake
    │       └── sdk_native_platforms.cmake
    ├── build-tools
    │   └── cmake
    │       ├── bin
    │       ├── doc
    │       ├── man
    │       └── share
    ├── docs
    ├── llvm
    │   ├── bin
    │   │   ├── aarch64-linux-ohos-clang
    │   │   ├── aarch64-linux-ohos-clang++
    │   │   ├── arm-linux-ohos-clang                      #拷贝来的工具
    │   │   ├── arm-linux-ohos-clang++
    │   │   ├── ......
    │   │   ├── sanstats
    │   │   ├── scan-build
    │   │   ├── scan-view
    │   │   └── yaml2obj
    │   ├── include
    │   ├── lib
    │   │   ├── aarch64-linux-ohos
    │   │   ├── arm-linux-ohos
    │   │   ├── arm-liteos-ohos
    │   │   ├── clang
    │   │   ├── ......
    │   │   ├── mipsel-linux-ohos
    │   │   ├── riscv64-linux-ohos
    │   │   ├── x86_64-linux-ohos
    │   │   └── x86_64-unknown-linux-gnu
    │   ├── libexec
    │   │   ├── analyze-c++
    │   │   ├── analyze-cc
    │   │   ├── c++-analyzer
    │   │   ├── ccc-analyzer
    │   │   ├── intercept-c++
    │   │   └── intercept-cc
    │   ├── NOTICE
    │   └── share
    ├── nativeapi_syscap_config.json
    ├── ndk_system_capability.json
    ├── NOTICE.txt
    ├── oh-uni-package.json
    └── sysroot
        └── usr
            ├── include
            └── lib
    1. native 目录介绍
      build 目录存放的是 构建时 cmake 依赖的配置文件
    
      build-tools 目录存放的是 构建工具包含 cmake 和 ninja,我们后面采用 make 进行构建。
    
      docs 目录存放 使用说明
    
      llvm 目录存放 clang 编译器
    
      sysroot 目录为编译器的 sysroot 目录,存放 SDK 内部的已经包含的库和对应的头文件
    
      oh-uni-package.json 为 SDK 信息描述,如版本
    
      NOTICE.txt 为注意事项,内容多为 SDK 的详细描述
    
      ndk_system_capability.json 记录 SDK 提供的能力
    
      nativeapi_syscap_config.json 记录 SDK 提供的能力对应的头文件

    **build和build-tools目录提供构建时的 cmake,ninja,以及 toolchain 依赖。llvm 提供编译工具链。sysroot 提供 usr 系统资源**

  2. 编译现成三方库

    装完SDK后就可以编译了,在lycium目录执行./build.sh 【pkgname】,进行自动编译三方库,并打包安装到当前目录的 usr/【pkgname】/ARCH 目录

    所以我们就去thirdparty目录下挑选了个比较熟悉的库:DLib

    xx@XX_ZLL:~/xx/tpc_c_cplusplus/lycium$ ./build.sh DLib
    Build OS linux
    OHOS_SDK=/home/xx/wshikh/tpc_c_cplusplus/lycium/ohos-sdk/linux
    CLANG_VERSION=15.0.4
    DLib not ready. wait boost opencv_3.4.1
    Build boost 1.81.0 start!
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                Dload  Upload   Total   Spent    Left  Speed
    0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
    100  133M  100  133M    0     0  3419k      0  0:00:40  0:00:40 --:--:-- 4113k
    boost_1_81_0.tar.gz: OK
    
    
    Compile OpenHarmony armeabi-v7a boost 1.81.0 libs...
  3. 测试现成三方库
    1. 准备CI环境

    业界内C/C++三方库测试框架多种多样,我们无法将其统一,因此为了保证原生库功能完整,我们基于原生库的测试用例进行测试验证。为此,我们需要集成了一套可以在OH环境上进行cmake, ctest等操作的环境,具体请阅读 lycium CItools,在此验证下具体步骤:

    1. 直接用编译好的二进制,请点击下载链接 ,解压:

      # 下载库
      git clone https://gitee.com/han_jin_fei/lycium-citools.git
      
      # 进入lycium-citools解压库
      for i in *.tar.gz;do tar zxvf ${i};done
      
      $ hdc_std file send lyciumCI-armeabi-v7a-perl.tar.gz /data/local/tmp
      FileTransfer finish, Size:21347830, File count = 1, time:5833ms rate:3659.84kB/s
      $ hdc_std file send lyciumCI-armeabi-v7a-busybox.tar.gz /data/local/tmp
      FileTransfer finish, Size:972992, File count = 1, time:275ms rate:3538.15kB/s
      $ hdc_std file send lyciumCI-armeabi-v7a-shell_cmd.tar.gz /data/local/tmp
      FileTransfer finish, Size:6389194, File count = 1, time:1760ms rate:3630.22kB/s
      $ hdc_std file send lyciumCI-armeabi-v7a-cmake_make.tar.gz /data/local/tmp
      FileTransfer finish, Size:44749407, File count = 1, time:11773ms rate:3801.02kB/s
      $ hdc_std file send lyciumCI-armeabi-v7a-gdb.tar.gz /data/local/tmp
      FileTransfer finish, Size:11666656, File count = 1, time:3231ms rate:3610.85kB/s
      
      $ hdc_std shell
      # mount -o remount,rw /
      
      # mkdir /usr
      
      # cd /data/local/tmp
      
      # tar zxvf lyciumCI-armeabi-v7a-cmake_make.tar.gz 
      
      # tar zxvf lyciumCI-armeabi-v7a-gdb.tar.gz 
      
      # tar zxvf lyciumCI-armeabi-v7a-shell_cmd.tar.gz 
      
      # tar zxvf lyciumCI-armeabi-v7a-busybox.tar.gz
      
      # cp -rf armeabi-v7a-cmake_make/* /usr/ 
      
      # cp -rf perl/* /usr/ 
      
      # cp -rf armeabi-v7a-shell_cmd/* /usr/ 
      
      # tar zxvf lyciumCI-armeabi-v7a-perl.tar.gz 
      
      # cp -rf perl/* /usr/                                             
      
      # cmake -version                                                               
      cmake version 3.26.0-rc5
      
      CMake suite maintained and supported by Kitware (kitware.com/cmake).
     # make -v
     GNU Make 4.4
     Built for arm-unknown-linux-gnueabihf
     Copyright (C) 1988-2022 Free Software Foundation, Inc.
     License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
     This is free software: you are free to change and redistribute it.
     There is NO WARRANTY, to the extent permitted by law.
    
     # perl -v
     This is perl 5, version 34, subversion 1 (v5.34.1) built for arm-linux
    
     Copyright 1987-2022, Larry Wall
    
     Perl may be copied only under the terms of either the Artistic License or the
     GNU General Public License, which may be found in the Perl 5 source kit.
    
     Complete documentation for Perl, including FAQ lists, should be found on
     this system using "man perl" or "perldoc perl".  If you have access to the
     Internet, point your browser at http://www.perl.org/, the Perl Home Page.
    
     # cp -rf armeabi-v7a-busybox/bin/busybox /bin/                                 
     # cd /bin
    
     # mv toybox toybox_bak                                           
    
     # toybox_bak mv busybox toybox                                                
     # diff -v
     diff: invalid option -- 'v'
     BusyBox v1.36.0 (2023-03-10 02:22:28 UTC) multi-call binary.
    
     Usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2
    
     Compare files line by line and output the differences between them.
     This implementation supports unified diffs only.
    
        -a  Treat all files as text
        -b  Ignore changes in the amount of whitespace
        -B  Ignore changes whose lines are all blank
        -d  Try hard to find a smaller set of changes
        -i  Ignore case differences
        -L  Use LABEL instead of the filename in the unified header
        -N  Treat absent files as empty
        -q  Output only whether files differ
        -r  Recurse
        -S  Start with FILE when comparing directories
        -T  Make tabs line up by prefixing a tab when necessary
        -s  Report when two files are the same
        -t  Expand tabs to spaces in output
        -U  Output LINES lines of context
        -w  Ignore all whitespace
    
    
    
    2. **测试脚本确认**
    
    **  lycium框架提供了**[HPKCHECK](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/lycium/template/HPKCHECK)文件供开发者对相应的C/C++三方库的自动化测试,如果现成三方库里有这个脚本就可以测试。
    
    
    3. **测试运行:**
    
    **  因为是交叉编译的结果,所以需要将所有东西打包放到设备上进行验证。因此我们需要将原生库的源码及生成文件都作为测试资源打包到开发板进行测试(直接将tpc\_c\_cplusplus直接打包成一个测试资源,并且保证测试资源在开发板的测试路径与编译路径保持一致,避免部分原生库因编译时对测试文件配置了路径而导致测试不过),然后在**[lycium](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/lycium)目录下执行脚本./test.sh,自动运行thridparty目录下已编译的三方库,并在终端显示已测试三方库总数以及通过和未通过的三方库。
    
    
    4. **之前找的DLib没有测试项目,所以找了个简单的,比如cJSON,所以测试下:**
    

     # 编译cJSON xx@NJKH_ZLL:~/xx/tpc_c_cplusplus/lycium$ ./build.sh cJSON Build OS linux  OHOS_SDK=/home/xx/xx/tpc_c_cplusplus/lycium/ohos-sdk/linux  CLANG_VERSION=15.0.4 Build cJSON v1.7.15 start!   % Total   % Received % Xferd Average Speed   Time   Time     Time Current                                   Dload Upload   Total   Spent   Left Speed    0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0  100 344k    0 344k    0     0   229k      0 --:--:--  0:00:01 --:--:-- 463k cJSON-1.7.15.tar.gz: OK Compile OpenHarmony armeabi-v7a cJSON v1.7.15 libs... The test must be on an OpenHarmony device! Compile OpenHarmony arm64-v8a cJSON v1.7.15 libs... The test must be on an OpenHarmony device! Build cJSON v1.7.15 end! ALL JOBS DONE!!!

     # 确认编译目录,注意是编译目录,不是输出目录 xx@NJKH_ZLL:~/xx/tpc_c_cplusplus/lycium$ ls ../thirdparty/cJSON/cJSON-1.7.15/armeabi-v7a-build/ -lh total 336K  -rw-rw-r-- 1 xx xx 125K Mar 26 14:55 build.log  -rw-rw-r-- 1 xx xx  777 Mar 26 14:55 cJSONConfig.cmake  -rw-rw-r-- 1 xx xx  368 Mar 26 14:55 cJSONConfigVersion.cmake  -rwxrwxr-x 1 xx xx 47K Mar 26 14:55 cJSON_test # 测试程序  -rw-rw-r-- 1 xx xx 20K Mar 26 14:55 CMakeCache.txt drwxrwxr-x 9 xx xx 4.0K Mar 26 14:55 CMakeFiles  -rw-rw-r-- 1 xx xx 11K Mar 26 14:55 cmake_install.cmake  -rw-rw-r-- 1 xx xx  764 Mar 26 14:55 CTestTestfile.cmake drwxrwxr-x 3 xx xx 4.0K Mar 26 14:55 fuzzing  -rw-rw-r-- 1 xx xx  837 Mar 26 14:55 install_manifest.txt  -rw-rw-r-- 1 xx xx  377 Mar 26 14:55 libcjson.pc lrwxrwxrwx 1 xx xx   13 Mar 26 14:55 libcjson.so -> libcjson.so.1 # 库文件 lrwxrwxrwx 1 xx xx   18 Mar 26 14:55 libcjson.so.1 -> libcjson.so.1.7.15  -rwxrwxr-x 1 xx xx 76K Mar 26 14:55 libcjson.so.1.7.15  -rw-rw-r-- 1 xx xx 19K Mar 26 14:55 Makefile drwxrwxr-x 4 xx xx 4.0K Mar 26 14:55 tests

     # 设定库路径,运行测试用例

     # LD_LIBRARY_PATH=./ ./cJSON_test                                               Version: 1.7.15 { "name": "Jack (\"Bee\") Nimble", "format": { "type": "rect", "width": 1920, "height": 1080, "interlace": false, "frame rate": 24 } } ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] [[0, -1, 0], [1, 0, 0], [0, 0, 1]] { "Image": { "Width": 800, "Height": 600, "Title": "View from 15th Floor", "Thumbnail": { "Url": "http:/*www.example.com/image/481989943", "Height": 125, "Width": "100" }, "IDs": [116, 943, 234, 38793] } } [{ "precision": "zip", "Latitude": 37.7668, "Longitude": -122.3959, "Address": "", "City": "SAN FRANCISCO", "State": "CA", "Zip": "94107", "Country": "US" }, { "precision": "zip", "Latitude": 37.371991, "Longitude": -122.026, "Address": "", "City": "SUNNYVALE", "State": "CA", "Zip": "94085", "Country": "US" }] { "number": null }

    
    
    

解析Lycium运行规则

解析编译构建脚本build.sh
  • 原则:**移植过程,不可以改源码(即不patchc/cpp文件,不patch构建脚本)。如移植必须patch,patch必须评审,给出充分理由。(不接受业务patch)**

  • 工作原理:

    • 输入 build.sh pkgname

    • 根据 pkgname 从 ../thirdparty/cJSON/HPKBUILD 里执行编译命令

      #!/bin/bash
      
      ......
      
      main() {
          # 检查编译环境
          checkbuildenv
      
          # 编译过的库都放到这个csv里,下次可以不编译
          readdonelibs "$LYCIUM_ROOT/usr/hpk_build.csv"
      
          # 创建lib库,从HPKBUILD里读需要编译的库,并加入hpkPaths队列
          if [ $# -ne 0 ]
          then
              makelibsdir $*
          else
              findmainhpkdir $LYCIUM_ROOT/$hpksdir
              # exit 2
          fi
      
          # 进入前面构造的hpkPaths对应的编译目录,然后把build_hpk.sh链接进编译目录
          prepareshell ${hpkPaths[@]}
          
          # 开始编译,一般会编译两个 armeabi 和 arm64
          buildhpk
      
          # 把 prepareshell 做的build链接删掉
          cleanhpkdir
          
          unset LYCIUM_BUILD_OS LYCIUM_ROOT LYCIUM_BUILD_CHECK CLANG_VERSION
      }
      
      main $*
      
      # 编译任务不成功, 返回-1
      if [ ${#buildfalselist[*]} -ne 0 -o ${#nextroundlist[*]} -ne 0 ]
      then
          exit -1
      fi
    • HPKBUILD解析,

      • CMAKE 例子,用cJSON做例子

        # Contributor: Jeff Han <hanjinfei@foxmail.com>
        # Maintainer: Jeff Han <hanjinfei@foxmail.com>
        
        # 库名称
        pkgname=cJSON
        
        # 编译版本
        pkgver=v1.7.15
        pkgrel=0
        pkgdesc=""
        url=""
        
        # 编译架构
        archs=("armeabi-v7a" "arm64-v8a")
        license=("MIT")
        depends=()
        makedepends=()
        
        # 对应的下载路径,
        source="https://github.com/DaveGamble/$pkgname/archive/refs/tags/$pkgver.tar.gz"
        
        autounpack=true
        downloadpackage=true
        
        builddir=$pkgname-${pkgver:1}
        packagename=$builddir.tar.gz
        
        # 对应的shell脚本动作 prepare
        prepare() {
            mkdir -p $builddir/$ARCH-build
        }
        
        # 对应的shell脚本动作 build
        build() {
            cd $builddir
            ${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" -DOHOS_ARCH=$ARCH -B$ARCH-build -S./ -L > `pwd`/$ARCH-build/build.log 2>&1
            make -j4 -C $ARCH-build >> `pwd`/$ARCH-build/build.log 2>&1
            ret=$?
            cd $OLDPWD
            return $ret
        }
        
        # 对应的shell脚本动作 package
        package() {
            cd $builddir
            make -C $ARCH-build install >> `pwd`/$ARCH-build/build.log 2>&1
            cd $OLDPWD
        }
        
        check() {
            echo "The test must be on an OpenHarmony device!"
        }
        
        # 清理环境
        cleanbuild(){
            rm -rf ${PWD}/$builddir #${PWD}/$packagename
        }
      • Make 例子,用CUnit做例子

        # Contributor: Jeff Han <hanjinfei@foxmail.com>
        # Maintainer: Jeff Han <hanjinfei@foxmail.com>
        pkgname=CUnit
        pkgver=2.1-3
        pkgrel=0
        pkgdesc=""
        url=""
        archs=("armeabi-v7a" "arm64-v8a")
        license=()
        depends=()
        makedepends=()
        install=
        source="https://sourceforge.net/projects/cunit/files/$pkgname/$pkgver/$pkgname-$pkgver.tar.bz2"
        
        autounpack=false
        downloadpackage=true
        buildtools="configure"
        
        builddir=$pkgname-${pkgver}
        packagename=$builddir.tar.bz2
        
        source envset.sh
        host=
        prepare() {
            mkdir $pkgname-$ARCH-build
            tar -jxf $packagename -C $pkgname-$ARCH-build
            if [ $ARCH == "armeabi-v7a" ]
            then
                setarm32ENV
                host=arm-linux
            fi
            if [ $ARCH == "arm64-v8a" ]
            then
                setarm64ENV
                host=aarch64-linux
            fi
            cd $pkgname-$ARCH-build/$builddir
            ./bootstrap > `pwd`/build.log 2>&1
            cd $OLDPWD
        }
        
        build() {
            cd $pkgname-$ARCH-build/$builddir
            ./configure "$@" --host=$host --enable-debug --enable-automated --enable-basic --enable-console --enable-examples --enable-test >> `pwd`/build.log 2>&1
            make -j4 >> `pwd`/build.log 2>&1
            ret=$?
            cd $OLDPWD
            return $ret
        }
        
        package() {
            cd $pkgname-$ARCH-build/$builddir
            make install >> `pwd`/build.log 2>&1
            cd $OLDPWD
            if [ $ARCH == "armeabi-v7a" ]
            then
                unsetarm32ENV
            fi
            if [ $ARCH == "arm64-v8a" ]
            then
                unsetarm64ENV
            fi
        
            unset host
        }
        
        check() {
            echo "The test must be on an OpenHarmony device!"
            # 在OpenHarmony开发板中执行用例
            # ./test_cunit
        }
        
        # 清理环境
        cleanbuild(){
            rm -rf ${PWD}/$pkgname-armeabi-v7a-build ${PWD}/$pkgname-arm64-v8a-build #${PWD}/$packagename
        }
      • Make 例子,用CUnit做例子

        #!/bin/bash
        
        # 执行HPKBUILD里对应的方法,如:prepare,build,package,check,cleanbuild
        sure() {
            eval $*
            err=$?
            if [ "$err" != "0" ]
            then
                echo "ERROR during : $*"
                echo "ERROR during : $*: $err" > last_error
                exit 1
            fi
        }
        
        PKGBUILD_ROOT=$(cd $(dirname ${BASH_SOURCE[0]}); pwd)
        
        # 下载库压缩包
        # 参数1 链接地址
        # 参数2 压缩包名
        download() {
            if [ -s ${PWD}/$2 ]
            then
                echo ${PWD}/$2",存在"
            else
                curl -f -L -k -- "$1" > ${PWD}/$2
                return $?
            fi
        }
        
        # 解压库
        # 参数1 压缩包名
        unpack() {
            ......
        }
        
        # 加载库的编译信息
        source ${PWD}/HPKBUILD
        
        # 库的完整性校验
        checksum() {
            ......
        }
        
        ......
        
        main() {
            # 清理上次的环境
            sure cleanhpk
            # 编译 PKG
            sure builpackage $*
        }
        
        main $*

解析编译结果应用到HAP

  1. 创建native C++工程项目,这个教程太多,不讲了;

  2. 拷贝编译结果到libs,tpc_c_cplusplus/lycium/usr/cJSON里的 armeabi-v7a(32位),arm64-v8a(64位),将里面的so库拷贝到工程路径下(\entry\libs)

    cjsontes\entry\libs> tree 
    ├─arm64-v8a
    │  ├─libcjson.so
    │  ├─libcjson.so.1
    │  └─libcjson.so.1.7.15
    └─armeabi-v7a
       ├─libcjson.so
       ├─libcjson.so.1
       └─libcjson.so.1.7.15
    
  3. 拷贝对应的头文件到cpp/thirdparty目录下

    cjsontes\entry\src\main\cpp\thirdparty> tree 
    ├─arm64-v8a
    │  ├─include
    │    ├─cjson
    └─armeabi-v7a
    │  ├─include
    │    ├─cjson
    
  4. 改对应的 CMakeLists.txt

    # the minimum version of CMake.
    cmake_minimum_required(VERSION 3.4.1)
    project(cjsontes)
    
    set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
    set(CJSON_LIB_PATH ${NATIVERENDER_ROOT_PATH}/../../../libs/${OHOS_ARCH})
    
    include_directories(${NATIVERENDER_ROOT_PATH}
                        ${NATIVERENDER_ROOT_PATH}/include
                        ${NATIVERENDER_ROOT_PATH}/thirdparty/cJSON/${OHOS_ARCH}/include)
    
    add_library(entry SHARED hello.cpp)
    target_link_libraries(entry PUBLIC
        libace_napi.z.so
        libace_ndk.z.so
        librawfile.z.so
        libhilog_ndk.z.so
        ${CJSON_LIB_PATH}/libcjson.so)
  5. 改 build-profile.json5 文件

    {
      "apiType": "stageMode",
      "buildOption": {
        "externalNativeOptions": {
          "path": "./src/main/cpp/CMakeLists.txt",
          "arguments": "",
          "cppFlags": "",
          # 增加适配的平台
          "abiFilters": [
            "arm64-v8a"
          ]
        }
      },
      "targets": [
        {
          "name": "default",
          "runtimeOS": "HarmonyOS"
        },
        {
          "name": "ohosTest",
        }
      ]
    }
  6. 改 hello.cpp

    #include "napi/native_api.h"
    #include "hilog/log.h"
    #include "cjson/cJSON.h"
    
    #define GLOBAL_RESMGR (0xFFEE)
    
    static const char *TAG = "[cjsontest]";
    
    static napi_value Add(napi_env env, napi_callback_info info)
    {
        size_t requireArgc = 2;
        size_t argc = 2;
        napi_value args[2] = {nullptr};
    
        napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
    
        napi_valuetype valuetype0;
        napi_typeof(env, args[0], &valuetype0);
    
        napi_valuetype valuetype1;
        napi_typeof(env, args[1], &valuetype1);
    
        double value0;
        napi_get_value_double(env, args[0], &value0);
    
        double value1;
        napi_get_value_double(env, args[1], &value1);
    
        // 增加cjson测试代码
        cJSON *parsed = NULL;
        char *content = "[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]";
        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "content %{public}s.", content);
        
        parsed = cJSON_Parse(content);
    
        char *jsonmsg = cJSON_Print(parsed);
        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "jsonprint %{public}s.", jsonmsg);
    
        napi_value sum;
        napi_create_double(env, value0 + value1, &sum);
    
        return sum;
    
    }
    
    EXTERN_C_START
    static napi_value Init(napi_env env, napi_value exports)
    {
        napi_property_descriptor desc[] = {
            { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
        };
        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
        return exports;
    }
    EXTERN_C_END
    
    static napi_module demoModule = {
        .nm_version = 1,
        .nm_flags = 0,
        .nm_filename = nullptr,
        .nm_register_func = Init,
        .nm_modname = "entry",
        .nm_priv = ((void*)0),
        .reserved = { 0 },
    };
    
    extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
    {
        napi_module_register(&demoModule);
    }
    
  7. 测试输出

    com.example.cjsontest  E  content ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"].
    com.example.cjsontest  E  jsonprint ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"].

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部