OpenHarmony:NDK开发
一:概述
NDK(Native Development Kit)是HarmonyOS SDK提供的Native API、相应编译脚本和编译工具链的集合,方便开发者使用C或C++语言实现应用的关键功能。NDK只覆盖了HarmonyOS一些基础的底层能力,如C运行时基础库libc、图形库、窗口系统、多媒体、压缩库、面向ArkTS/JS与C跨语言的Node-API等,没有提供ArkTS/JS API的完整能力。
运行态,开发者可以使用NDK中的Node-API接口,访问、创建、操作JS对象;也允许JS对象使用Native动态库。
本章将以led为例开发一个可供ArkTS调用的Native调用库。
其中Node-API详细可见官网:
https://developer.huawei.com/consumer/cn/doc/harmonyos-references/napihttps://developer.huawei.com/consumer/cn/doc/harmonyos-references/napi
二:工程创建
创建一个Native C++工程:该工程会创建一个NDK开发的完整框架,包含一个加法运算的demo。
Index.ets经过上一章app开发已经不陌生了,该小节重点对cpp目录下的文件进行说明:
napi_led.cpp:Native API实现的具体文件,后续会详细说明。
CMakeLists.txt:通过DevEco Studio模板工程创建的NDK工程中,包含默认生成的CMakeLists.txt脚本,如下所示:
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(UnitTestPro)# 定义一个变量,并赋值为当前模块cpp目录
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})if(DEFINED PACKAGE_FIND_FILE)include(${PACKAGE_FIND_FILE})
endif()# 添加头文件.h目录,包括cpp,cpp/include,告诉cmake去这里找到代码引入的头文件
include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include)# 声明一个产物libled.so,SHARED表示产物为动态库,napi_led.cpp为产物的源代码
add_library(led SHARED napi_led.cpp)# 声明产物led链接时需要的三方库libace_napi.z.so
# 这里直接写三方库的名称是因为它是在ndk中,已在链接寻址路径中,无需额外声明
target_link_libraries(led PUBLIC libace_napi.z.so libhilog_ndk.z.so)
oh-package.json5:Native侧配置文件
{"name": "libled.so","types": "./Index.d.ts","version": "1.0.0","description": "Please describe the basic information."
}
Index.d.ts:Native侧接口文件,用于向ArkTS暴漏接口。
export const getLedBrightness: (path: string) => number;
export const setLedBrightness: (path: string, brightness: number) => number;
三:Native接口
#include "napi/native_api.h"
#include <hilog/log.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <unistd.h>#define LOG_TAG "NapiLed"
#define LOG_DOMAIN 0x8888 // 自定义领域ID(需在应用配置中注册)static napi_value GetLedBrightness(napi_env env, napi_callback_info info)
{size_t argc = 1;napi_value args[1] = {nullptr};size_t len = 0;napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);napi_status status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &len);if (status != napi_ok) {return nullptr;}char *buff = new char[len+1];std::memset(buff, 0, len+1);napi_get_value_string_utf8(env, args[0], buff, len+1, &len);std::string color = buff;std::string brightnessPath = "/sys/class/leds/" + color + "/brightness";std::ifstream file(brightnessPath);if (!file.is_open()) {delete[] buff;return nullptr;}std::string brightness;std::getline(file, brightness);file.close();napi_value value;napi_create_int32(env, std::stoi(brightness), &value);delete[] buff;return value;
}static int GetLedMaxBrightness(std::string path)
{std::ifstream file(path);int value = 255; // 默认最大值if (!file.is_open()) {return value;}std::string buffer;if (std::getline(file, buffer)) {try {value = std::stoi(buffer);} catch (...) {std::cerr << "警告: 解析最大亮度值失败,使用默认值255" << std::endl;}} else {std::cerr << "警告: 读取最大亮度值失败,使用默认值255" << std::endl;}file.close();return value;
}static napi_value SetLedBrightness(napi_env env, napi_callback_info info)
{size_t argc = 2;napi_value args[2] = {nullptr};size_t len = 0;napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);napi_status status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &len);if (status != napi_ok) {return nullptr;}char *buff = new char[len+1];std::memset(buff, 0, len+1);napi_get_value_string_utf8(env, args[0], buff, len+1, &len);std::string color = buff;std::string brightnessPath = "/sys/class/leds/" + color + "/brightness";std::string maxBrightnessPath = "/sys/class/leds/" + color + "/max_brightness";int brightness;int maxBrightness = GetLedMaxBrightness(maxBrightnessPath);napi_get_value_int32(env, args[1], &brightness);if (brightness < 0) brightness = 0;if (brightness > maxBrightness) brightness = maxBrightness;std::ofstream file(brightnessPath);if (!file.is_open()) {OH_LOG_DEBUG(LOG_APP, "open error.");delete[] buff;return nullptr;}file << brightness;file.close();delete[] buff;napi_value value;std::string brightness_str = std::to_string(brightness);napi_create_string_utf8(env, brightness_str.c_str(), brightness_str.length(), &value);return value;}EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{napi_property_descriptor desc[] = {{ "getLedBrightness", nullptr, GetLedBrightness, nullptr, nullptr, nullptr, napi_default, nullptr },{ "setLedBrightness", nullptr, SetLedBrightness, nullptr, nullptr, nullptr, napi_default, nullptr }};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_ENDstatic napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "led",.nm_priv = ((void*)0),.reserved = { 0 },
};extern "C" __attribute__((constructor)) void RegisterLedModule(void)
{napi_module_register(&demoModule);
}
四:调试
napi_led.cpp:
# 头文件
#include <hilog/log.h># 定义LOG信息
#define LOG_TAG "NapiLed"
#define LOG_DOMAIN 0x8888 # LOG接口
OH_LOG_DEBUG(LOG_APP, "brightness:%{public}d", brightness);
OH_LOG_INFO(LOG_APP, "brightness:%{public}d", brightness);
OH_LOG_WARN(LOG_APP, "brightness:%{public}d", brightness);
OH_LOG_ERROR(LOG_APP, "brightness:%{public}d", brightness);
OH_LOG_FATAL(LOG_APP, "brightness:%{public}d", brightness);
CMakeLists.txt:链接libhilog_ndk.z.so
target_link_libraries(led PUBLIC libace_napi.z.so libhilog_ndk.z.so)
五:编译
通过构建>编译>编译Hap来生成Native so库。
生成路径:
至此以led为例的NDK开发完成。