Native API(NDK)入門
Native API是OpenHarmony SDK上提供的一組native開發接口與工具集合(也稱為NDK),方便開發者使用C或者C++語言實現應用的關鍵功能。Native API只覆蓋了OHOS基礎的一些底層能力,如libc,圖形庫,窗口系統,多媒體,壓縮庫等,并沒有完全提供類似于JS API上的完整的OHOS 平臺能力。在應用中使用Native API會編譯成動態庫打包到應用中。
名詞概念
名詞 | 名詞解釋 |
---|---|
Native API | OHOS SDK里面native包提供的,面向三方應用開發的Native 接口以及相應編譯腳本,編譯工具鏈。包括C運行時基礎庫libc,3D圖形庫opengl,面向JS與C跨語言的接口Node-API等,具體內容詳見下表。 |
NDK | Native Develop Kit的縮寫,在OHOS上就是Native API;Native API是官方名字,NDK指代相同意思。 |
SDK CAPI | OHOS Native API中的C語言接口,以及工具鏈部分,當前OHOS的Native API里面只包含C語言接口,因此Native API與CAPI意思一樣,建議交流的時候使用CAPI,防止Native API與napi縮寫混用。 |
Node-API | 曾用名napi,是OHOS中提供JS與C跨語言調用的接口,是Native API接口中的一部分. 該接口在Node.js提供的Node-API基礎上擴展而來,但不完全與Node.js中的Node-API完全兼容。 |
napi | Node-API的曾用名,當前Node-API頭文件中的接口仍然以napi_開頭,不建議使用。 |
Native API構成介紹
Native API目錄結構
Native API在SDK包的位置為$(SDK_ROOT)/native目錄,主要有以下幾個部分組成
目錄 | 功能說明 |
---|---|
build | 應用中編譯動態庫的toolchain cmake腳本;這個目錄下ohos.toolchain.cmake文件定義了給OHOS交叉編譯選項 |
build-tools | 放置編譯構建的工具,如cmake |
docs | Native API接口參考文檔,通過doxgen從頭文件中提取出來 |
llvm | 支持OHOS ABI的llvm交叉編譯器 |
sysroot | 放置編譯鏈接的依賴文件目錄,包含頭文件,動態庫等 |
Native API接口(4.0 Release)
接口分類 | 接口功能 | 引入版本 |
---|---|---|
標準C庫 | 以musl為基礎提供的標準c庫接口,當前提供了1500+的接口 | 8 |
標準C++庫 | c運行時庫libc_shared,此庫在打包的時候需要打包或者靜態鏈接到應用中 | 8 |
日志 | 打印日志到系統的hilog接口 | 8 |
Node-API | ArkUI提供的,方便應用開發接入JS應用環境的一組類Node-API(也叫napi),是屬于Native API的一部分 | 8 |
XComponent | ArkUI XComponent組件中的surface與觸屏事件接口,方便開發者開發高性能圖形應用 | 8 |
libuv | ArkUI集成的三方的異步IO庫 | 8 |
libz | zlib庫,提供基本的壓縮,解壓接口 | 8 |
Drawing | 系統提供的2D圖形庫,可以在surface進行繪制 | 8 |
OpenGL | 系統提供的openglv3接口 | 8 |
Rawfile | 應用資源訪問接口,可以讀取應用中打包的各種資源 | 8 |
OpenSLES | 用于2D,3D音頻加速的接口庫 | 8 |
Mindspore | AI模型接口庫 | 9 |
包管理 | 包服務接口,方便查詢應用包信息 | 8 |
Native API相關資料
- Native API參考,介紹各個API參考手冊
- Native API中支持的標準庫,介紹Native API支持的開源標準庫
- Native API開發指南,結合具體的例子,場景介紹各類接口的使用
- 如何在Cmake工程中使用NDK,介紹如何使用使用NDK開發一個CMake工程
- Node-API在應用工程中的使用指導, 如何使用Node-API接口
簡單應用
如何開發應用?
- DevEco IDE創建工程選擇“Native C++”模板:
編譯運行后,點擊helloworld打印輸出有:Test NAPI 2 + 3 = 5
- ArkUI部分:
import hilog from '@ohos.hilog'; //導入hilog
import testNapi from 'libentry.so'; //導入nativeC++模塊
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() = > {
//調用nativeC++代碼
hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
})
}
.width('100%')
}
.height('100%')
}
}
- nativeC部分由 CMake 和 C代碼兩部分組成:
- CMake:
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(MyNDKApplication)
# 編譯路徑
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# 編譯頭文件路徑
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
# 編譯對象entry是對應用層可見的so,即import testNapi from 'libentry.so'
add_library(entry SHARED hello.cpp)
# 這是link命令,libace_napi 這個就是node-api需要用的so庫;
target_link_libraries(entry PUBLIC libace_napi.z.so)
- C++:
#include "napi/native_api.h"
// 對外node-api方法,對應testNapi.add(2, 3)
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
// 模塊聲明,import時候調用
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);
}
如何使用系統NDK?
上面例子運行起來后,c++部分是沒有打印信息的,若想看到對應的打印信息,則需要調用hilog進行輸出,修改如下:
- cmake修改:
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(MyNDKApplication)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
# 增加hiloglib庫引用
find_library(
# Sets the name of the path variable.
hilog-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
hilog_ndk.z
)
add_library(entry SHARED hello.cpp)
# 增加hiloglib庫連接
target_link_libraries(entry PUBLIC ${hilog-lib} libace_napi.z.so)
- c++文件修改:
// 增加hilog頭文件
#include < hilog/log.h >
#include "napi/native_api.h"
static napi_value Add(napi_env env, napi_callback_info info)
{
// 增加打印輸出
const unsigned int LOG_PRINT_DOMAIN = 0xFF00;
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Init", "Init begins");
size_t requireArgc = 2;
size_t argc = 2;
napi_value args[2] = {nullptr};
...
- 輸出:
08-07 05:40:25.079 15167-15167 A0ff00/Init com.example.myndkapplication I Init begins
08-07 05:40:25.079 15167-15167 A00000/testTag com.example.myndkapplication I Test NAPI 2 + 3 = 5
具體原理是什么?
1、PC端OHOS SDK里包括了native對應的庫文件和頭文件;
2、OHOS源碼可以編譯出帶NDK的FullSDK,也可以從CI網址下載;
# Generate NDK library from NDK description file.
#
# Variables:
# ndk_description_file:
# min_compact_version: string specifies the minimal compactible version of NDK.
# set to major_version in default.
#
template("ohos_ndk_library") {
forward_variables_from(invoker, [ "testonly" ])
assert(defined(invoker.ndk_description_file),
"ndk description file is necessary ")
...
// 在GN里用ohos_ndk_library生成ndk庫和頭文件,如
ohos_ndk_library("libhilog_ndk") {
output_name = "hilog_ndk"
ndk_description_file = "./libhilog.ndk.json"
min_compact_version = "1"
system_capability = "SystemCapability.HiviewDFX.HiLog"
}
ohos_ndk_headers("hilog_header") {
dest_dir = "$ndk_headers_out_dir/hilog"
sources = [ "./include/hilog/log.h" ]
}
// ndk_description_file 對應的 libhilog.ndk.json 文件里聲明了導出的接口函數
[
{
"name": "OH_LOG_Print"
},
{
"name": "OH_LOG_IsLoggable"
}
]
// ohos 編譯fullsdk的命令: ./build.sh --product-name ohos-sdk
使用建議
建議使用Native API的場景
主要有如下一些
不建議使用Native API的場景
- 寫一個純native的的OHOS應用
- 希望在盡可能多的OHOS設備上保持兼容的應用
維測能力
- OHOS官方提供lldb remote方式代碼調試,詳細參看[lldb參考手冊]。
- musl庫的log維測能力,請參看 libc庫維測章節。
總結
- NDK方式是應用層直接調用底層庫或者三方庫目前看最常規的方式;
- 4.0(API10)有ndk 46個,3.2(API9)有ndk 28個,實質代碼里有更多的ndk,RK的原因沒有編出更多,比如sensor部分就沒有編譯出來;
審核編輯:湯梓紅
-
接口
+關注
關注
33文章
8575瀏覽量
151021 -
SDK
+關注
關注
3文章
1035瀏覽量
45902 -
鴻蒙
+關注
關注
57文章
2339瀏覽量
42805 -
HarmonyOS
+關注
關注
79文章
1973瀏覽量
30143 -
OpenHarmony
+關注
關注
25文章
3713瀏覽量
16255
發布評論請先 登錄
相關推薦
評論