1# 使用Node-API接口进行函数创建和调用 2 3## 简介 4 5函数调用允许开发者从Node-API模块中调用ArkTS函数,并传递参数进行调用,或者直接在Node-API模块中创建一个ArkTS方法。 6 7## 基本概念 8 9函数是一种非常重要的编程概念,可以执行特定的任务或操作、提高代码的可读性、把复杂任务简化、提高代码复用性以及支持代码的组织与管理。每个函数可以负责不同的功能,提供一种将代码模块化和组织结构化的方式,使其更易于理解、维护和重用。 10 11## 场景和功能介绍 12 13| 接口 | 描述 | 14| -------- | -------- | 15| napi_get_cb_info | 当需要从给定的callback info中获取有关调用的参数信息和this指针时,可使用此接口。 | 16| napi_call_function | 当需要在Node-API模块中对ArkTS侧函数进行调用时,可使用此接口。 | 17| napi_create_function | 当需要将C/C++函数创建一个ArkTS函数时,可以使用此接口。 | 18 19## 使用示例 20 21Node-API接口开发流程参考[使用Node-API实现跨语言交互开发流程](use-napi-process.md),本文仅对接口对应C++及ArkTS相关代码进行展示。napi_create_function方法除外,具体使用见示例。 22 23## napi_get_cb_info 24 25获取有关函数调用的详细信息。 26 27cpp部分代码 28 29```cpp 30#include "napi/native_api.h" 31// 获取ArkTS侧入参的的参数信息 32static napi_value GetCbArgs(napi_env env, napi_callback_info info) 33{ 34 size_t argc = 1; 35 napi_value args[1] = {nullptr}; 36 napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); 37 return args[0]; 38} 39// 获取ArkTS侧入参的参数个数 40static napi_value GetCbArgQuantity(napi_env env, napi_callback_info info) 41{ 42 size_t argc = 0; 43 napi_value result = nullptr; 44 napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr); 45 napi_create_int32(env, argc, &result); 46 return result; 47} 48// 获取ArkTS侧this参数 49static napi_value GetCbContext(napi_env env, napi_callback_info info) 50{ 51 napi_value thisArg = nullptr; 52 napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr); 53 return thisArg; 54} 55``` 56 57接口声明 58 59```ts 60// index.d.ts 61export const getCbArgs: <T>(arg: T) => T; 62// getCbArgQuantity的入参由用户自定义,在此用例中,我们用两个入参,一个是string,一个是number 63export const getCbArgQuantity: (str: string, num: number) => number; 64export const getCbContext: () => Object; 65``` 66 67ArkTS 侧示例代码 68 69```ts 70import hilog from '@ohos.hilog' 71import testNapi from 'libentry.so' 72function summation(arr: Array<number>) { 73 let sum: number = 0; 74 for (let i = 0; i < arr.length; i++) { 75 sum += arr[i]; 76 } 77 return sum; 78} 79const str = 'message'; 80const arr = [0, 1, 2, 3, 4, 5]; 81const num = 526; 82class Student { 83 name: string; 84 age: number; 85 score: number; 86 constructor(name: string, age: number, score: number) { 87 this.name = name; 88 this.age = age; 89 this.score = score; 90 } 91} 92let student = new Student('Alice', 18, 100); 93// 获取参数 94hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get string arg:%{public}s', testNapi.getCbArgs(str)); 95hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get array arg:%{public}s ', testNapi.getCbArgs(arr).toString()); 96hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get num arg:%{public}d ', testNapi.getCbArgs(num)); 97hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get undefined arg:%{public}s ', testNapi.getCbArgs(undefined)); 98hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get object arg:%{public}s ', JSON.stringify(testNapi.getCbArgs(student))); 99hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get function arg:%{public}d ', testNapi.getCbArgs(summation(arr))); 100// 获取参数个数 101hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get arg quantity:%{public}d ', testNapi.getCbArgQuantity(str, num)); 102// 获取上下文 103hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_cb_info get thisArg:%{public}s ', testNapi.getCbContext().toString()); 104``` 105 106## napi_call_function 107 108在C/C++侧对ArkTS函数进行调用。 109注意事项:napi_call_function传入的argv的长度必须大于等于argc声明的数量,且被初始化成nullptr。 110 111cpp部分代码 112 113```cpp 114#include "napi/native_api.h" 115 116static napi_value CallFunction(napi_env env, napi_callback_info info) 117{ 118 size_t argc = 1; 119 napi_value argv[1] = {nullptr}; 120 // 获取ArkTS侧入参 121 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); 122 // 获取全局对象,这里用global是因为napi_call_function的第二个参数是JS函数的this入参。 123 napi_value global = nullptr; 124 napi_get_global(env, &global); 125 // 调用ArkTS方法 126 napi_value result = nullptr; 127 // 调用napi_call_function时传入的argv的长度必须大于等于argc声明的数量,且被初始化成nullptr 128 napi_call_function(env, global, argv[0], argc, argv, &result); 129 return result; 130} 131 132static napi_value ObjCallFunction(napi_env env, napi_callback_info info) 133{ 134 // 获取ArkTS侧传递的两个参数 135 size_t argc = 2; 136 napi_value argv[2] = {nullptr}; 137 // 获取ArkTS侧入参 138 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); 139 // 调用ArkTS方法 140 napi_value result = nullptr; 141 // 调用napi_call_function时传入的argv的长度必须大于等于argc声明的数量,且被初始化成nullptr 142 napi_call_function(env, argv[0], argv[1], argc, argv, &result); 143 return result; 144} 145``` 146 147接口声明 148 149```ts 150// index.d.ts 151export const callFunction: (func: Function) => number; 152export const objCallFunction: (obj: Object, func: Function) => number; 153``` 154 155ArkTS 侧示例代码 156 157```ts 158import hilog from '@ohos.hilog' 159import testNapi from 'libentry.so' 160 161function returnNumber() { 162 return 10; 163} 164class Person { 165 age(): number { 166 return 11; 167 } 168} 169const person = new Person(); 170hilog.info(0x0000, 'testTag', 'Test Node-API call_function:%{public}d', testNapi.callFunction(returnNumber)); 171hilog.info(0x0000, 'testTag', 'Test Node-API call_function:%{public}d', testNapi.objCallFunction(person,person.age)); 172``` 173 174## napi_create_function 175 176将一个C/C++函数包装为可在ArkTS中调用的函数,并返回一个表示该函数的napi_value。 177 178cpp部分代码 179 180```cpp 181#include "napi/native_api.h" 182 183static napi_value CalculateArea(napi_env env, napi_callback_info info) 184{ 185 // 获取ArkTS侧传递的两个参数 186 size_t argc = 2; 187 napi_value args[2] = {nullptr}; 188 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 189 double width = 0; 190 napi_get_value_double(env, args[0], &width); 191 double height = 0; 192 napi_get_value_double(env, args[1], &height); 193 napi_value area = nullptr; 194 napi_create_double(env, width * height, &area); 195 return area; 196} 197 198EXTERN_C_START 199static napi_value Init(napi_env env, napi_value exports) { 200 napi_value fn = nullptr; 201 napi_create_function(env, nullptr, 0, CalculateArea, nullptr, &fn); 202 napi_set_named_property(env, exports, "calculateArea", fn); 203 return exports; 204} 205EXTERN_C_END 206``` 207 208接口声明 209 210```ts 211// index.d.ts 212export const calculateArea: (width: number, height: number) => number; 213``` 214 215ArkTS 侧示例代码 216 217```ts 218import hilog from '@ohos.hilog' 219import testNapi from 'libentry.so' 220 221hilog.info(0x0000, 'testTag', 'Test Node-API create_function:%{public}d ', testNapi.calculateArea(1.2, 4)); 222``` 223 224以上代码如果要在native cpp中打印日志,需在CMakeLists.txt文件中添加以下配置信息(并添加头文件:#include "hilog/log.h"): 225 226```text 227// CMakeLists.txt 228add_definitions( "-DLOG_DOMAIN=0xd0d0" ) 229add_definitions( "-DLOG_TAG=\"testTag\"" ) 230target_link_libraries(entry PUBLIC libhilog_ndk.z.so) 231``` 232