IT科技

OpenHarmony 源码解析之 JavaScriptAPI NAPI-C 接口

时间:2010-12-5 17:23:32  作者:系统运维   来源:IT科技类资讯  查看:  评论:0
内容摘要:想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com1 简介在《OpenHarmony 源码解析之JavaScript API框架(NAPI)

想了解更多内容,码解请访问:

和华为官方合作共建的接口鸿蒙技术社区

https://harmonyos.51cto.com

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/下找到对应的动态库。

ohos_shared_library("sample") {      include_dirs = []     sources = [         "sample.cpp",     ] 

2.1.2 源码编写

增加NAPI模块sampleModule的注册

通过Register()注册后,sampleModule对应的NAPI接口才能被编译到系统中,应用才能对接口进行调用。

extern "C" __attribute__((constructor)) void Register()      {             napi_module_register(&sampleModule);         }  新增模块的定义

sampleModule全局变量定义了当前NAPI模块对应的模块名sample,以及当前模块对外接口注册函数SampleExport。

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,不需要定义类。

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进行回调处理。

DECLARE_NAPI_FUNCTION("test", JSTest),   DECLARE_NAPI_FUNCTION("onCallback", JSCallback), 

2.2 接口解析

2.2.1 JS->C 接口解析

JS调用的C接口定义:function test(para1: number): void;

具体NAPI的云服务器实现如下:

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 = 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 = %{ 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的回调函数,实现如下所示:

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 = 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); //根据引用获取回调函数callback int 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.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接口实现方式的解读。

文章相关附件可以点击下面的原文链接前往下载

https://harmonyos.51cto.com/resource/1550

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap