HarmonyOS NEXT系列之编译三方C/C++库
编译三方C/C++库
- 〇、前言
- 一、新建 C/C++ 项目
- 1、目录设置
- 2、更新 CMakeLists.txt
- 3、编写C/C++ 方法
- 二、编译库文件
- 三、使用预编译库
- 1、引入头文件
- 2、引入库文件
- 3、在 NAPI 中使用 simpleReturnString 方法
- 3.1、新增NAPI
- 3.2、使用 NAPI
〇、前言
熟悉主流编程语言的开发者,相比心里对 C/C++ 语言的非跨平台性,早已有所深刻体会。虽然,C/C++ 代码无法像 Python 或 Java 那样一次编写到处运行,但却允许进行制品定制:即为目标平台量身定做输出相应的制品。
而 HarmonyOS NEXT 系统,就是 C/C++ 代码编译的目标平台中的一种,而 HarmonyOS NEXT 项目中,使用 C/C++ 代码的方式,一种是直接在 NDK 模块中编写相应的 C/C++ 代码,另一种则是以 NDK 模块为桥梁将三方库集成到项目中;而在第二种方式中,必须先有一个能够在 HarmonyOS NEXT 平台上进行运行的库文件:xxxx.so。
而本篇正是要向大家普及如何将一个三方 C/C++ 库编译成 HarmonyOS NEXT 平台中能够直接使用的方法库。
一、新建 C/C++ 项目
这里推荐从零开始进行体验,也即是由自己一手创建一个新的 C/C++ 项目,为了方便源代码进行编译,需要使用 CMake 工具作为项目管理工具。
1、目录设置
使用 CMake 管理项目的 C/C++ 项目,在项目根目录中都会创建一个 CMakeLists.txt 文件,我们以该文件为参照,在同级目录中新建src目录和include目录,最终的项目目录结构如下:
project-root:- src/- include/- CMakeLists.txt
2、更新 CMakeLists.txt
对于新增的目录,默认情况下,都不会被 CMake 所识别到,需要通过 CMakeLists 文件去引入,比如,在上面的目录结构中,想要 include 目录下的所有头文件、以及src目录下的所有源文件,都能在当前项目中使用,就需要在 CMakeLists 中添加如下内容:
file(GLOB_RECURSE SOURCES "src/*.cpp")
include_directories(include)
add_library(${PROJECT_NAME} SHARED library.cpp${SOURCES}
)
另外,为了规范制品输出目录,不妨在 CMakeLists 文件末尾加上这样一段代码:
# 输出设置
set_target_properties(${PROJECT_NAME} PROPERTIESLIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/libs/${OHOS_ARCH}OUTPUT_NAME "${PROJECT_NAME}"SUFFIX ".so"
)
OHOS_ARCH 指代目标平台的芯片架构,以 HarmonyOS NEXT 来说,就是arm64-v8a
,最终,完整的 CMakeLists 文件如下:
cmake_minimum_required(VERSION 3.27)
project(HMOSThirdLib)set(CMAKE_CXX_STANDARD 17)
# 工具链和平台配置
set(CMAKE_TOOLCHAIN_FILE"/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/native/build/cmake/ohos.toolchain.cmake"CACHE STRING "" FORCE)set(CMAKE_INSTALL_PREFIX "/output/HMOSThirdLib" CACHE PATH "" FORCE)
set(OHOS_ARCH "arm64-v8a" CACHE STRING "" FORCE)
# 标准配置(需放在工具链设置之后)
enable_language(C CXX)
file(GLOB_RECURSE SOURCES "src/*.cpp")
include_directories(include)
add_library(HMOSThirdLib SHARED library.cpp${SOURCES}
)
# 输出设置
set_target_properties(HMOSThirdLib PROPERTIESLIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/libs/${OHOS_ARCH}OUTPUT_NAME "HMOSThirdLib"SUFFIX ".so"
)
3、编写C/C++ 方法
在 include 目录下,新建一个 simple.h
文件,而 src 目录下则相应地创建一个 simple.cpp
文件,记住,头文件和源文件一定要同名。在 simple.h 中声明一个方法原型:
/** Copyright (c) 2025 彭友聪* HMOSThirdLib is licensed under Mulan PSL v2.* You can use this software according to the terms and conditions of the Mulan PSL v2.* You may obtain a copy of Mulan PSL v2 at:http://license.coscl.org.cn/MulanPSL2* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.* See the Mulan PSL v2 for more details.* IDE: CLion* Project: HMOSThirdLib* File: simple.h* @author: 御承扬* @Email: 2923616405@qq.com* @Date: 2025/8/10* @Time: 13:58* * *///
// Created by pengyoucong on 2025/8/10.
//#ifndef HMOSTHIRDLIB_SIMPLE_H
#define HMOSTHIRDLIB_SIMPLE_H
const char* simpleReturnString();
#endif //HMOSTHIRDLIB_SIMPLE_H
对应的simple.cpp,对该方法进行具体实现:
/** Copyright (c) 2025 彭友聪* HMOSThirdLib is licensed under Mulan PSL v2.* You can use this software according to the terms and conditions of the Mulan PSL v2.* You may obtain a copy of Mulan PSL v2 at:http://license.coscl.org.cn/MulanPSL2* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.* See the Mulan PSL v2 for more details.* IDE: CLion* Project: HMOSThirdLib* File: simple.cpp* @author: 御承扬* @Email: 2923616405@qq.com* @Date: 2025/8/10* @Time: 14:00* * *///
// Created by pengyoucong on 2025/8/10.
//
#include "simple.h"
const char* simpleReturnString() {return "simpleReturnString:尝试将C/C++源码编译成鸿蒙平台库文件";
}
二、编译库文件
由于 CMake 进行库文件编译的时候,会生成一些配置文件和中间文件,因此,为了不污染项目目录,可以在项目根目录下新建一个专门的目录,用于存放 CMake 输出的中间文件和配置文件,比如新建一个 hmos_ouput 目录
,而后在命令行中打开该目录,并使用如下命令:
{HOMS_NDK_HOME}/native/build-tools/cmake/bin/cmake -DCMAKE_TOOLCHAIN_FILE={HOMS_NDK_HOME}/native/build/cmake/ohos.toolchain.cmake -DCMAKE_INSTALL_PREFIX=/output/HMOSThirdLib -DOHOS_ARCH=arm64-v8a .. -L
进行 cmake 编译,而编译成功之后,就会在 hmos_ouput 目录下生成 Makefile,有了这个Makefile后,同样在 hmos_ouput 目录下执行 make
命令,就可以得到最终的制品,而该制品会放在 CMakeLists 中设定的 libs/HMOSThirdLib.so
,而由于执行 CMake 操作的目录在 homs_ouput 目录,所以生成的libs也就在该目录下。
三、使用预编译库
找一个 HarmonyOS NEXT 项目,创建一个 NDK 模块,并将上述得到的 .so 文件即 C/C++ 预编译库,集成到该 NDK 模块中进行使用。
1、引入头文件
将 simple.h 文件从上面的C/C++项目中拷贝一份,并放到 NDK 模块的 src/main/cpp/include
中,为了保证 simple.h 文件能被检索到,修改 NDK 模块的 CMakeLists 文件,加上内容:
include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include)
2、引入库文件
接着,将 ibHMOSThirdLib.so 文件复制一份,并放到 NDK 模块根目录下的libs目录,相应的架构目录中,例如:
并将该库文件通过 CMakeLists 进行链接,即用 target_link_libraries(learnnapi PUBLIC libace_napi.z.so ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libHMOSThirdLib.so)
进行设置。
3、在 NAPI 中使用 simpleReturnString 方法
由于在鸿蒙APP最终以ArkTS代码编写pages作为应用交互界面,必须先将纯C/C++ 代码通过 NAPI 进行转写才行,所以,我们有必要在 NDK 模块中新增一个 NAPI,不妨就叫 testGetMessage
,具体操作如下:
3.1、新增NAPI
打开位于 /src/main/cpp 目录下的 napi_init.cpp 文件,在文件头处新增导包语句:#include "simple.h"
,并在合适位置新增如下一段代码:
static napi_value testGetMessage(napi_env env, napi_callback_info info) {const char* message = simpleReturnString();napi_value result;napi_status status = napi_create_string_utf8(env, message, strlen(message), &result);return status == napi_ok ? result : nullptr;
}
将该方法注册到 napi_property_descriptor
中:
而 src/main/cpp/types/index.d.ts 中相应增加内容:
3.2、使用 NAPI
如上所示,在 entry 模块或其他 har 包模块,只需将 NDK 模块作为依赖添加到 oh-package.json
文件中,就可以用类似如下的代码去使用 NAPI:
import nativeModule from 'liblearnnapi.so'export class NAPIAdapter {private constructor() {}static Add(x: number, y: number) {return nativeModule.add(x, y);}static NativeCallArkTs(param: number) {return nativeModule.nativeCallArkTS((x: number) => {return x + param;});}static createPerson(name: string, age: number, height: number) {return nativeModule.createPerson(name, age, height);}static parsePerson(param: object) {return nativeModule.parsePerson(param);}static testGetMessage() {return nativeModule.testGetMessage();}
}
将APP部署到真机上运行,打开日志窗口就可以看到对应的内容输出: