OpenHarmony开发者论坛
标题:
OHOS 5.0 nativeC++ 应用开发
[打印本页]
作者:
深开鸿_王石
时间:
2024-12-9 19:01
标题:
OHOS 5.0 nativeC++ 应用开发
[md]#### OHOS 5.0 nativeC++ 应用开发
之前发过4.0 Native C++ 开发,但是看有些同学问如何引用三方库,所以这次提供个引用外部三方库的方法,然后也用另外一种napi的方式 AKI,来对JS层提供接口。
##### AKI简介
AKI (Alpha Kernel Interacting) 是一款边界性编程体验友好的ArkTs FFI开发框架,针对OpenHarmony Native开发提供JS与C/C++跨语言访问场景解决方案。支持极简语法糖使用方式,简洁代码逻辑完成JS与C/C++的无障碍跨语言互调。
简单讲,AKI就是对NAPI进行了一层封装,提供对典型应用场景的包装,减轻了用户开发NAPI层的开发负担,他的具体优点如下:
* 解耦FFI代码与业务代码,友好的边界性编程体验;
* 提供数据类型转换、函数绑定、对象绑定、线程安全等特性;
* 支持JS & C/C++互调
* 支持与Node-API即NAPI的嵌套使用
##### Native C/C++ 业务代码:
```c++
#include <string>
#include "aki/jsbind.h"
#include <aki/version.h>
#include "napi/native_api.h"
// AKI 方式
std::string SayHello(std::string msg) {
return msg + " too.";
}
// Step 1 注册 AKI 插件
JSBIND_ADDON(hello) // 注册 AKI 插件名: 即为编译*.so名称,规则与NAPI一致
// Step 2 注册 FFI 特性
JSBIND_GLOBAL() {
JSBIND_FUNCTION(SayHello);
}
// native 方式
static napi_value Add(napi_env env, napi_callback_info info)
{
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;
}
static const int MAX_BUFFER_SIZE = 128;
static napi_value NapiHello(napi_env env, napi_callback_info info)
{
size_t argc = 1;
napi_value result = nullptr;
std::string param;
napi_value args[1] = {nullptr};
napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
napi_valuetype valuetype0;
napi_typeof(env, args[0], &valuetype0);
size_t size = 0;
// 字符串的缓冲区
char buffer[MAX_BUFFER_SIZE];
// 字符串的缓冲区大小
size_t bufferSize = MAX_BUFFER_SIZE;
if (napi_get_value_string_utf8(env, args[0], buffer, bufferSize, &size) != napi_ok) {
return result;
}
napi_create_string_utf8(env, buffer, size, &result);
return result;
}
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 },
{ "NapiHello", nullptr, NapiHello, nullptr, nullptr, nullptr, napi_default, nullptr }
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
exports = aki::JSBind::BindSymbols(env, exports); // aki::BindSymbols 函数传入 js 对象绑定符号
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);
}
```
##### 调试
* 使用DevEco Studio NEXT Release,Build Version: 5.0.3.900, built on October 8, 2024
* 使用5.0.0 Release 镜像,在rk3568上运行测试
1. 创建NativeC++工程
2. 拷贝aki源码到 cpp 目录下 (src/main/cpp/)后面有工程
3. 修改cpp目录下的CMakeLists.txt
```cmake
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(TestNative)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# 自己手动添加的三方库位置
set(AKI_LIB_PATH ${NATIVERENDER_ROOT_PATH}/../../../libs/${OHOS_ARCH}/)
if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
# 自己手动添加的三方库,aki/include, 其他三方库头文件一样的办法加
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include
${NATIVERENDER_ROOT_PATH}/thirdparty/aki/include)
add_library(entry SHARED napi_init.cpp)
# 自己手动添加的三方库,libaki_jsbind.so, 其他三方库一样的办法加
target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so ${AKI_LIB_PATH}/libaki_jsbind.so)
```
4. 修改napi_init.cpp文件:同最前面的代码
```c++
#include <string>
#include <aki/jsbind.h>
#include <aki/version.h>
#include "napi/native_api.h"
std::string SayHello(std::string msg) {
return msg + " too.";
}
// Step 1 注册 AKI 插件
JSBIND_ADDON(hello) // 注册 AKI 插件名: 即为编译*.so名称,规则与NAPI一致
// Step 2 注册 FFI 特性
JSBIND_GLOBAL() {
JSBIND_FUNCTION(SayHello);
}
// 后面是原来napi注册的内容
......
```
5. 修改Index.d.ts
```
export const add: (a: number, b: number) => number;
export const NapiHello: (a: string) => string;
export const SayHello: (a: string) => string;
```
6. 修改Index.ets
```typescript
import { hilog } from '@kit.PerformanceAnalysisKit';
import testNapi from 'libentry.so';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
let res: number = testNapi.add(2, 3);
hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', res);
let msg: string = testNapi.SayHello("hell to cpp");
hilog.info(0x0000, 'testTag', 'Test SayHello = %{public}s', msg);
msg = testNapi.NapiHello("Napi to cpp");
hilog.info(0x0000, 'testTag', 'Test SayHello = %{public}s', msg);
this.message += `= ${res} + ${msg}`;
// hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
})
}
.width('100%')
}
.height('100%')
}
}
```
7. 编译运行
### 总结
1. 最新5.0.0 Release 的IDE也能进行开发,不过要修改工程,参考这个修改:
https://forums.openharmony.cn/fo ... &page=1#pid8694
;
2. AKI 是一个native应用开发的快速框架,提供了绑定函数,类,枚举给js层使用,以及从native侧获取js全局对象,js方法,js异步任务的方法;给应用开发者提供跨语言的互相访问能力;
3. AKI 可以和原来的 napi 开发方式并存,混合使用;
4. 如果自己要加三方库,如同aki,手动在cmake里加头文件和库文件就好
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5