犀渠玉剑良家子,白马金羁侠少年。这篇文章主要讲述#星光计划2.0# OpenHarmony 源码解析之JavaScriptAPI NAPI-C接口相关的知识,希望能为你提供帮助。
作者:赵军霞
【本文正在参与51CTO HarmonyOS技术社区创作者激励计划-星光计划2.0】
1 简介在《OpenHarmony 源码解析之JavaScript API框架(NAPI)》一文提到,NAPI就是L2设备上的 JS API实现方式。对OpenHarmony提供的NAPI的设计思想、编程原则、Sample源码等已做说明,本文不再赘述。
NAPI机制在整个OpenHarmony系统中起着承上启下的重要作用,而框架代码中C实现的比例也很大,尤其是对接驱动这方面。
本文主要呈现的是NAPI之C接口的极简方式实现范例,适合初学者了解打通NAPI流程。
1.1 UI架构相关系列
《OpenHarmony 源码解析之ACE (JavaScript运行环境初始化)》
《OpenHarmony 源码解析之JavaScript API框架(NAPI)》
《OpenHarmony 源码解析之JavaScript API框架(NAPI-C接口)》
《OpenHarmony 源码解析之JavaScript(文件管理API)》
1.2 OpenHarmony架构图
文章图片
1.3 NAPI概念回顾
NAPI在系统中位置示意图如下:
文章图片
从图中可以得出,NAPI就是JS与C/C++之间的调用方式。
1.4 NAPI 实现方式
OpenHarmony上NAPI实现方式有两种,分别是:
- NAPI之C接口
- NAPI之C++接口
文章图片
2 NAPI之C接口 2.1 实现过程解析
2.1.1 编译构建
- 增加子系统
源码/build/subsystem_config.json
中增加子系统选项,如下所示:
"sample": { "project": "hmf/sample", "path": "foundation/sample", "name": "sample", "dir": "foundation" }
- 修改产品定义
源码/productdefine/common/products/Hi3516DV300.json
中增加part选项
"sample:sample_show":{}
- 增加样例ohos.build文件
源码路径新增/foundation/sample/sample_show/ohos.build
文件,定义子系统为sample,组件为sample_show,文件内容如下:
{ "subsystem": "sample", "parts": { "sample_show": { "module_list": [ "//foundation/sample/sample_show/interfaces/kits/js/declaration:sample_show","//foundation/sample/sample_show/interfaces/kits/napi:napi_packages", ] } } }
- 增加样例BUILD.gn文件
源码路径新增/foundation/sample/sample_show/interfaces/kits/napi/sample/sample_show/BUILD.gn
文件,定义动态库名称为sample,对应的源文件为sample.cpp, 则生成的动态库名为libsample.z.so
,烧录后可以到/system/lib/
下找到对应的动态库。
```c++
ohos_shared_library(" sample" ) {
include_dirs = []
sources = [
" sample.cpp" ,
]
- 增加NAPI模块sampleModule的注册
通过Register()注册后,sampleModule对应的NAPI接口才能被编译到系统中,应用才能对接口进行调用。
```c++
extern " C" attribute((constructor)) void Register()
{
napi_module_register(& sampleModule);
}
- 新增模块的定义
sampleModule全局变量定义了当前NAPI模块对应的模块名sample,以及当前模块对外接口注册函数SampleExport。
```c++
static napi_module sampleModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = SampleExport,
.nm_modname = " sample" ,
.nm_priv = ((void*)0),
.reserved = { 0 },
};
- 新增模块的对外接口
在模块对外接口SampleExport中,增加NAPI接口定义,对于C语言的NAPI只需增加属性即可napi_define_properties,不需要定义类。
```c++
static napi_value SampleExport(napi_env env, napi_value exports)
{
static napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION(" test" , JSTest),
DECLARE_NAPI_FUNCTION(" onCallback" , JSCallback),
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports;
}
- 新增NAPI接口实现函数
样例中增加了两个接口,分别是:test
、onCallback
;
test: 接口使用场景为JS调用C相关函数;
onCallback: 接口使用场景为JS定义了一个回调函数JSFuncA,某个时机触发后,通过C语言调用JSFuncA进行回调处理。
```c++
DECLARE_NAPI_FUNCTION(" test" , JSTest),
DECLARE_NAPI_FUNCTION(" onCallback" , JSCallback),
2.2.1 JS-> C 接口解析JS调用的C接口定义:
function test(para1: number): void;
具体NAPI的实现如下:
```c++
static napi_value JSTest(napi_env env, napi_callback_info info)
{
size_t argc = 1; //参数个数定义
napi_value argv[argc];
napi_value thisVar = nullptr;
void *data = https://www.songbingjia.com/android/nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &
argc, argv, &
thisVar, &
data));
NAPI_ASSERT(env, argc >
= 1, "JSTest Wrong number of arguments");
//参数个数校验napi_value result = nullptr;
napi_create_int32(env, 0, &
result);
int cPara1;
//定义接口入参对应的C语言变量
for(size_t i= 0;
i<
argc;
i++){//参数类型校验
napi_valuetype valueType = napi_undefined;
napi_typeof(env, argv[i], &
valueType);
NAPI_ASSERT(env, valueType == napi_number, "JSTest Wrong argument type. Number expected for parameter 1.");
if(i== 0) {
//JS参数转换为C语言参数,打印其值
napi_get_value_int32(env, argv[i], &
cPara1);
SAMPLE_LOG("JSTest cPara1 value = https://www.songbingjia.com/android/%{public}d!", cPara1);
}else{
SAMPLE_LOG("JSTest napi_get_value error!");
return result;
}
}cFunction(cPara1);
//调用框架层对应的c函数,C语言参数传递到对应的C语言函数中
return result;
}
#### 2.2.2 C->
JS 接口解析C调用JS接口函数定义:`function JSCallback(callback: Function): void;
`入参即为JS的回调函数,实现如下所示:```c++
static napi_value JSCallback(napi_env env, napi_callback_info info)
{size_t argc = 1;
//参数个数定义
napi_value argv[argc];
napi_value thisVar = nullptr;
void *data = https://www.songbingjia.com/android/nullptr;
napi_ref CallbackRef;
napi_value jsObj, prop1, callback = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &
argc, argv, &
thisVar, &
data));
NAPI_ASSERT(env, argc >
= 1,"JSCallback Wrong number of arguments");
//参数个数校验napi_valuetype callbackType = napi_undefined;
napi_typeof(env, argv[0], &
callbackType);
NAPI_ASSERT(env, callbackType == napi_function, "parameter 1 type mismatch");
//参数类型校验,传进来的须是函数类型napi_create_reference(env, argv[0], 1, &
CallbackRef);
//创建引用
napi_get_reference_value(env, CallbackRef, &
callback);
//根据引用获取回调函数callbackint cPara = 1;
napi_create_object(env, &
jsObj);
//创建JS回调函数对应的参数对象
napi_create_int32(env, cPara, &
prop1);
napi_set_named_property(env, jsObj, "prop", prop1);
//设置JS参数对象属性值napi_call_function(env, nullptr, callback, 1, &
jsObj, &
undefine);
//使用生成的JS参数,调用对应的JS回调函数napi_value result = nullptr;
napi_get_undefined(env, &
result);
return result;
}
3 应用代码示例JS应用引用NAPI接口时,须先引用接口定义的对应模块,才能进行接口的调用。示例如下:
【#星光计划2.0# OpenHarmony 源码解析之JavaScriptAPI NAPI-C接口】```c++
//此处库名须与2.1.1.4 节BUILD.gn中定义的库名一致
import sample from @ohos.sample
......
onTest: function () {
console.log(" sample.test start" )
sample.test(2); //JS调用napi接口
console.log(" sample.test end" )
},
......
## 4 总结NAPI在OpenHarmony应用开发中必不可少,本文档抛砖引玉介绍了NAPI之C语言接口的极简实现方式,方便大家入门,后续随着学习的深入将不断完善对NAPI接口实现方式的解读。##更多原创内容请关注:[开鸿HarmonyOS学院](https://harmonyos.51cto.com/column/59) 入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。[想了解更多关于鸿蒙的内容,请访问:](https://harmonyos.51cto.com/#bkwz)[51CTO和华为官方战略合作共建的鸿蒙技术社区](https://harmonyos.51cto.com/#bkwz)https://harmonyos.51cto.com/#bkwz::: hljs-center![21_9.jpg](https://s2.51cto.com/images/20210924/1632469265578939.jpg?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=):::
推荐阅读
- #2021年底大盘点# --这短暂的一年,立下的flag都完成了么
- Flutter 专题27 图解 ListView/GridView 混用时滑动冲突小尝试 #yyds干货盘点#
- 新上传的WordPress主题未在网络服务器中显示
- 将Bootstrap模板转换为WordPress模板后导航Toggler崩溃不起作用
- 需要帮助将按钮链接到WordPress主题定制器中的功能
- WordPress中自定义帖子类型的”嵌套”
- 我的WordPress主题style.css覆盖管理主题
- 我的wordpress主页没有显示正确的标题
- Chrome和Safari忽略了导航栏高度