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