HarmonyOS NEXT-Native编译说明(C++)

一、介绍

本文用于说明和介绍编译底层C++代码生成动态库so,并且在harmonyOS项目中如何进行使用和集成,通过openharmony SDK在linux环境下编译动态库so,可打包其他静态库.a打包到此so,然后通过natvie项目(harmonyOS),集成此so并在项目中使用。

二、编译准备

1.1. 准备openmarmony SDK

可参考下面文档进行开发:
https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/lycium/doc/ohos_use_sdk/OHOS_SDK-Usage.md#ohos-sdk-%E4%BD%BF%E7%94%A8

1.2. 准备DevecoStudio

准备好开发工具,并配置好环境
https://developer.huawei.com/consumer/cn/deveco-studio/

1.3. 准备待编译的C++项目和代码

主要用于在linux环境下编译动态库so,并且打包一些.a第三方库静态库整合到一个so中,后续在鸿蒙项目中进行使用

三、编译步骤和说明

3.1. 使用openharmony SDK编译C++代码

可参考下面文档进行开发,这里就不细说了,后续会出单独说明文章:
https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/lycium/doc/ohos_use_sdk/OHOS_SDK-Usage.md#ohos-sdk-%E4%BD%BF%E7%94%A8

3.2. 创建native c++项目(DevecoStudio)

3.2.1.创建项目

创建项目

image.png
image.png

3.2.2 native c++项目结构

image.png
  1. so:这里使用的是3.1中编译好的so库

  2. index.d.ts: napi中定义的接口(相当于jni中定义好的接口的头文件)


    image.png

    oh-package.json5: 编译输入的接口说明文件和输出的lib.so文件
    *注:(此处的so代表通过我们之前3.1编译好的so库在native项目中二次打包编译生成的so库文件,最终需要在ets中进行应用的so库,也是最终产物)

{
  "name": "libentry.so",    // so输出产出
  "types": "./index.d.ts",   // 接口定义
  "version": "",
  "description": "Please describe the basic information."
}
  1. CMakeLists.txt:编译过android ndk的都知道这里不详细说明了,下面是截图
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(MyApplication)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(entry SHARED hello.cpp)
target_link_libraries(entry PUBLIC libace_napi.z.so)
  1. hello.cpp:关键文件,相当于android编译中的jni的cpp接口封装文件,harmonyOS中定义为napi,通过此接口的封装可调用底层c++代码的接口.
    这里定义了一个add方法并包含输入和输出的参数。
#include "napi/native_api.h"

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);

    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);
}

至此harmonyOS-native c++项目架构说明结束。

3.3.集成和使用已有的动态库so

3.3.1 准备好3.1中编译好的so库,比如HosTest.so

注意:实际编译可能需要生成多个abi架构的so库,armeabi-v7a和arm64-v8a


image.png

3.3.2 将HosTest.so放入libs文件夹(3.2中创建的项目)

这里由于测试只添加了v7a,后续可自行添加.


打开配置文件
修改abi配置文件,build-profile.json5文件
image.png

添加abi配置,根据添加的so文件架构进行配置

3.3.3 将HosTest.so放入libs文件夹(3.2中创建的项目)

① 创建thirdPart文件在cpp下(名称可自定义)


关键文件

② 创建或引入Hello.h文件,此文件为c++项目底层定义的暴露给外部的接口的头文件, 可以看到我们在Hello.h中定义了一个print的方法,并且返回值为string格式,此print方法为我们HosTest.so中的c++底层方法.

#ifndef __HELLO_H__
#define __HELLO_H__

#include <string>
class Hello
{
public:
    std::string print();
};

#endif

③ napi接口定义文件中引用Hello

// 此处引用我们上面定义的头文件,就可以使用HosTest.so中的c++接口了
#include "thirdPart/Hello.h"   
#include "napi/native_api.h"
#include <string.h>


static napi_value FN_hello_print(napi_env env, napi_callback_info info) {
    Hello ch;
    std::string string1= ch.print();
    char *str = "加油打工人";
    napi_value  result;
    napi_create_string_utf8(env,string1.c_str(),string1.length(),& result);
    return result;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {{"print", NULL, FN_hello_print, NULL, NULL, NULL, napi_default, NULL}};
    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 = NULL,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }

④ 修改CMakeLists文件


产出so修改,index.d.et文件上面的.etx描述错误

修改cpp下的oh-package.json5: 编译输入的接口说明文件和输出的lib.so文件
*注:(此处的so代表通过我们之前3.1编译好的so库在native项目中二次打包编译生成的so库文件,最终需要在ets中进行应用的so库,也是最终产物)

{
  "name": "HosSIDCard .so",    // so输出产出,这里需要修改成上面定义的名称
  "types": "./index.d.ts",   // 接口定义
  "version": "",
  "description": "Please describe the basic information."
}
修改so名称和步骤①的头文件文件夹路径

完整代码:

# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(HosNatvieProject)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(HosOutSO SHARED hello.cpp)    #此处添加 HosOutSO 代表产出的so名称  

target_link_libraries(HosSIDCard PUBLIC
libace_napi.z.so
libhilog_ndk.z.so
${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/HosTest.so #此处是引用的第三方库
)
target_include_directories(HosSIDCard PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdPart/)

⑤ 调用so文件接口

import hilog from '@ohos.hilog';
import HosTest from 'libHosTest.so';  // 引用最终产物so库

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(() => {
            console.error(HosTest.print());   // 使用接口print
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

至此,整体的第三方so库的使用已经完成。如有问题可以参考下面的问题汇总。

四、问题汇总

4.1.找不到引用的SO对象以及使用的底层方法

HosTest.print()报错


类似这类找不到引用的错误
解决方案:

① 检查cpp下的.ts文件是否定义了接口


image.png

② 检查CMakeLists文件和cpp下的oh-package-json5文件
HosOutSo是否配置和应用的so一致

# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(HosNatvieProject)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(HosOutSO SHARED hello.cpp)    #此处添加 HosOutSO 代表产出的so名称  

target_link_libraries(HosSIDCard PUBLIC
libace_napi.z.so
libhilog_ndk.z.so
${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/HosTest.so #此处是引用的第三方库
)
target_include_directories(HosSIDCard PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdPart/)

oh-package-json5文件的so配置是否一致

{
  "name": "HosSIDCard.so",    // so输出产出,这里需要修改成上面定义的名称
  "types": "./index.d.ts",   // 接口定义
  "version": "",
  "description": "Please describe the basic information."
}

③ Hello.h头文件是否包含


image.png

④ napi.cpp的文件是否正常


image.png

此问题原因基本就是某个环节配置的名称不匹配导致的,可以逐步检查解决。

4.2. cpp下的.ts文件出现error

image.png
解决方案: 目前不影响接口调用, 修改cpp下的xxxxx.ts文件修改为xxxxx.d.ts文件,之前修改自定义名称的时候没注意(dog.jpg)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容