1# NAPI框架生成工具使用说明 2## 简介 3 4NAPI框架生成工具支持三种入口,分别是可执行程序、VS Code插件、DevEco Studio上使用的IntelliJ插件,使用者可以根据自己的需要选择合适的工具。 5 61.可执行文件下载路径如下(由于网络原因,可能会导致有的下载链接失效,因此提供了以下三个下载链接): 7 8[可执行文件下载链接1](http://ftpkaihongdigi.i234.me:5000/sharing/yaRiKSjBI) 9 10[可执行文件下载链接2](http://ftp.kaihong.com:5000/fsdownload/yaRiKSjBI/) 11 12[可执行文件下载链接3](http://ftp.kaihongdigi.com:5000/fsdownload/yaRiKSjBI/) 13 14访问密码:kaihong 15 16压缩包解压密码:kaihong20231121 17 18DevEco Studio上使用的IntelliJ插件下载路径如下: 19 20[DevEco Studio上使用的IntelliJ插件下载链接](https://plugins.jetbrains.com/plugin/19593-napi-generator/versions) 21 22## 工具介绍 23 24通过NAPI框架生成工具,使用者可输入一个接口定义的ts文件,一键生成NAPI框架代码、业务代码框架、GN脚本等文件,并使用生成的NAPI接口及功能。使用者也可以输入一个定义方法的.h头文件,反向生成ts文件。 25 26 27 28## 预检查 29 30napi_generator的可执行程序方式和插件方式都具有预检查的功能,如果.d.ts文件中存在语法错误,那么执行的时候命令行会打印出错误信息,指出代码中存在错误的行号。使用效果如下: 31 32 joey@joey-virtual-machine:~/code/napi_test$ ./napi_generator-linux -f @ohos.napitest.d.ts 33 @ohos.napitest.d.ts (33,12): Identifier expected. 34 @ohos.napitest.d.ts (33,13): ';' expected. 35 @ohos.napitest.d.ts (33,13): An identifier or keyword cannot immediately follow a numeric literal. 36 @ohos.napitest.d.ts (33,13): Cannot find name 'shutdownDevice'. 37 @ohos.napitest.d.ts (33,28): Cannot find name 'reason'. 38 @ohos.napitest.d.ts (33,34): ',' expected. 39 @ohos.napitest.d.ts (33,36): 'string' only refers to a type, but is being used as a value here. 40 @ohos.napitest.d.ts (33,43): ';' expected. 41 @ohos.napitest.d.ts (33,49): Expression expected. 42 43 joey@joey-virtual-machine:~/code/napi_test$ 44 45@ohos.napitest.d.ts (33,49),其中括号中the first 参数含义为行号,第二个参数含义为列号。 46 47预检查的触发方式与生成框架的入口一致,使用方法参见生成框架描述。 48 49## 生成框架 50 51### 自动配置业务代码用例 52 531.ts文件用例 54 55 [@ohos.napitest.d.ts](https://gitee.com/openharmony/napi_generator/blob/master/test/dts2cpp/ts/@ohos.napitest.d.ts) 56 57注册关键字说明 58 59(1) registerXXX/unRegisterXXX 60 61register与unRegister成对使用, registerXXX用于注册回调,其参数即为注册的回调函数,注册之后在其它普通方法中即可在C++层调用registerXXX注册的回调函数;unRegisterXXX用于注销回调,其参数即为需要注销的回调函数,注销之后将无法再在C++层调用注销的回调函数。如: 62 63``` 64export class NodeISayHello 65{ 66 ... 67 // register注册回调 68 registerCallbackfunc(cb : (wid: number) => string); 69 // unRegister注销回调 70 unRegisterCallbackfunc(cb : (wid: number) => string); 71 ... 72} 73``` 74 75其中注册/注销的回调方法为箭头函数 (wid: number) => string。注册回调之后,工具会生成回调方法CallbackfuncCallback,业务代码中用户自行定义回调时机进而通过回调接口调用回调,若回调被注销,则业务代码无法触发该回调。 76 77(2) addXXX/removeXXX onXXX 78 79addXXX与removeXXX成对使用,addXXX用于注册回调,其参数为class对象, 将需要注册的回调函数放于class中,其写法为onXXX,class中可以有多个onXXX回调函数;removeXXX用于注销回调,其参数为class对象,用于注销addXXX注册的回调。如: 80 81``` 82export class NodeISayHello 83{ 84 ... 85 // 注册object回调 86 addSayHelloListener(listener: NodeISayHelloListener); 87 // 注销object回调 88 removeSayHelloListener(listener: NodeISayHelloListener); 89 ... 90} 91... 92export class NodeISayHelloListener 93{ // 定义回调 94 onSayHelloStart(info: SayInfo); 95 onSayHelloEnd(info: SayInfo); 96} 97``` 98 99其中注册/注销的回调方法为onSayHelloStart(info: SayInfo); onSayHelloEnd(info: SayInfo); 注册回调之后,工具会生成两个回调接口供用户调用,业务代码中用户自行定义回调时机进而通过回调接口调用回调,若回调被注销,则业务代码无法触发回调。 100 1012.自动配置业务代码用例使用的cfg.json 102 103``` 104[ 105 { 106 "genPath": "E:\\napi_aboutTest\\testcase_napi_intellijPlugin\\generatorCode", 107 "includeName": "../serviceCode/NodeISayHello.h", 108 "cppName": "../serviceCode/NodeISayHello.cpp", 109 "interfaceName": "NodeISayHello::sayHello", 110 "serviceCode": "napitest::NodeISayHello *p = new napitest::NodeISayHello();\n p->sayHello(from, to, sayType);\n delete p;" 111 }, 112 { 113 "genPath": "E:\\napi_aboutTest\\testcase_napi_intellijPlugin\\generatorCode", 114 "includeName": "../serviceCode/NodeISayHello.h", 115 "cppName": "../serviceCode/NodeISayHello.cpp", 116 "interfaceName": "NodeISayHello::sayHi", 117 "serviceCode": "napitest::NodeISayHello *p = new napitest::NodeISayHello();\n p->sayHi(from, to, sayType);\n delete p;" 118 }, 119 { 120 "genPath": "E:\\napi_aboutTest\\testcase_napi_intellijPlugin\\generatorCode", 121 "includeName": "../serviceCode/NodeISayHello.h", 122 "cppName": "../serviceCode/NodeISayHello.cpp", 123 "interfaceName": "funcTest", 124 "serviceCode": "out = napitest::funcTest(v);" 125 }, 126 { 127 "genPath": "E:\\napi_aboutTest\\testcase_napi_intellijPlugin\\generatorCode", 128 "includeName": "../serviceCode/NodeISayHello.h", 129 "cppName": "../serviceCode/NodeISayHello.cpp", 130 "interfaceName": "NodeISayHello::sayHelloWithResponse", 131 "serviceCode": "napitest::NodeISayHello *p = new napitest::NodeISayHello();\n p->sayHelloWithResponse(from, to, sayType);\n delete p;" 132 } 133] 134``` 135 1363.自动配置业务代码使用的业务代码用例 137 138业务代码用例如下: 139 140serviceCode/NodeISayHello.h 141 142``` 143#ifndef IMPL_NODEISAYHELLO_H 144#define IMPL_NODEISAYHELLO_H 145 146#include <string> 147#include <memory> 148 149namespace napitest { 150class NodeISayHello; 151class NodeISayHello { 152public: 153 void sayHello(std::string& from, std::string& to, uint32_t& sayType); 154 void sayHi(std::string& from, std::string& to, uint32_t& sayType); 155 void sayHelloWithResponse(std::string& from, std::string& to, uint32_t& sayType); 156}; 157std::string funcTest(bool& v); 158} 159#endif // IMPL_NODEISAYHELLO_H 160``` 161 162serviceCode/NodeISayHello.cpp 163 164``` 165#include "NodeISayHello.h" 166#include "../generatorCode/napitest.h" 167#include "hilog/log.h" 168static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0XD002E00, "NAPITESTNAPILayer"}; 169#define NAPITEST_LOGI(fmt, ...) OHOS::HiviewDFX::HiLog::Info(LABEL, \ 170 "%{public}s:%{public}d " fmt, __func__, __LINE__, ##__VA_ARGS__) 171 172namespace napitest { 173 // 1. 打印from, to, enum sayType的值 174 // 2. 调用注册的NodeISayHelloListenerSayHelloStart(info: SayInfo)方法 175 // 工具提供的业务接口(回调) void NodeISayHello::SayHelloListenerSayHelloStartCallback(SayInfo& info) 176 // 3. 调用注册的NodeISayHelloListenerSayHelloEnd(info: SayInfo)方法 177 // 工具提供的业务接口(回调) void NodeISayHello::SayHelloListenerSayHelloEndCallback(SayInfo& info) 178void NodeISayHello::sayHello(std::string& from, std::string& to, uint32_t& sayType) 179{ 180 // 1.打印 181 NAPITEST_LOGI("NAPITEST_LOGI sayHello from = %s\r\n", from.c_str()); 182 NAPITEST_LOGI("NAPITEST_LOGI sayHello to = %s\r\n", to.c_str()); 183 NAPITEST_LOGI("NAPITEST_LOGI sayHello sayType = %d\r\n", sayType); 184 185 // 2.调用回调 186 napitest::napitest_interface::SayInfo info1; 187 info1.from = "js1"; 188 uint32_t a = 992; 189 info1.fromId.emplace(a); 190 uint32_t b = 1014; 191 info1.toId.emplace(b); 192 info1.to = "native1"; 193 info1.content = "hello1"; 194 info1.saidTime = "123456789"; 195 info1.isEnd = false; 196 197 napitest::napitest_interface::SayInfo info2; 198 info2.from = "native"; 199 uint32_t c = 101; 200 info2.fromId.emplace(c); 201 uint32_t d = 99; 202 info2.toId.emplace(d); 203 info2.to = "js"; 204 info2.content = "hello"; 205 info2.saidTime = "987654321"; 206 info2.isEnd = true; 207 // 业务代码调用 onSayHelloStart callback 208 NAPITEST_LOGI("NAPITEST_LOGI NodeISayHelloListener_onSayHelloStartCallback begin\r\n"); 209 napitest::napitest_interface::NodeISayHello::listener_.NodeISayHelloListener_onSayHelloStartCallback(info1); 210 NAPITEST_LOGI("NAPITEST_LOGI NodeISayHelloListener_onSayHelloStartCallback end\r\n"); 211 // 业务代码调用 onSayHelloEnd callback 212 NAPITEST_LOGI("NAPITEST_LOGI NodeISayHelloListener_onSayHelloEndCallback begin\r\n"); 213 napitest::napitest_interface::NodeISayHello::listener_.NodeISayHelloListener_onSayHelloEndCallback(info2); 214 NAPITEST_LOGI("NAPITEST_LOGI NodeISayHelloListener_onSayHelloEndCallback end\r\n"); 215 return; 216} 217 218// 调用register注册的回调 219void NodeISayHello::sayHi(std::string& from, std::string& to, uint32_t& sayType) 220{ 221 // 1.打印 222 NAPITEST_LOGI("NAPITEST_LOGI sayHi from = %s\r\n", from.c_str()); 223 NAPITEST_LOGI("NAPITEST_LOGI sayHi to = %s\r\n", to.c_str()); 224 NAPITEST_LOGI("NAPITEST_LOGI sayHi sayType = %d\r\n", sayType); 225 // 2.调用回调 226 napitest::napitest_interface::NodeISayHello *ptr = new napitest::napitest_interface::NodeISayHello(); 227 uint32_t callbackNum = 50; 228 ptr->CallbackfuncCallback(callbackNum); 229 delete ptr; 230 return; 231} 232 233// 普通函数调用,返回str 234std::string funcTest(bool& v) 235{ 236 if (v) { 237 return "ret is true"; 238 } else { 239 return "ret is false"; 240 } 241} 242 243// 1.打印值:from, to 以及枚举enum SayType的值 244// 2. 将回调值(0, "", "recv hello.")的值传回Js层 245void NodeISayHello::sayHelloWithResponse(std::string& from, std::string& to, uint32_t& sayType) 246{ 247 // 1.打印 248 NAPITEST_LOGI("NAPITEST_LOGI sayHelloWithResponse from = %s\r\n", from.c_str()); 249 NAPITEST_LOGI("NAPITEST_LOGI sayHelloWithResponse to = %s\r\n", to.c_str()); 250 NAPITEST_LOGI("NAPITEST_LOGI sayHelloWithResponse sayType = %d\r\n", sayType); 251 // 2.调用promise回调 (0, "", "recv hello.") 252 napitest::napitest_interface::NodeISayHello *p = new napitest::napitest_interface::NodeISayHello(); 253 // 调用工具接口将回调传回工具 254 p->auto_interface_5SetCbValue(0, "", "recv hello."); 255 delete p; 256 return; 257} 258} 259 260``` 261 262### 可执行程序使用方法 263 264#### Linux 265 2661.将待转换的.d.ts文件、napi_generator-linux、依赖文件basic.d.ts、 配置文件cfg.json、业务代码文件夹serviceCode(其中serviceCode目录下放置业务代码的.h文件和.cpp文件)放在同级目录下。此处新建generatorCode文件夹,用于存放生成框架代码。整体目录文件如下: 267 268 OpenHarmony@Ubuntu-64:~/service$ ls 269 napi_generator-linux @ohos.napitest.d.ts basic.d.ts generatorCode cfg.json serviceCode 270 2712.在终端中进入到之前可执行程序napi_generator-linux所在的目录,并运行napi_generator-linux,命令如下: 272 273 OpenHarmony@Ubuntu-64:~/service$ ./napi_generator-linux -f @ohos.napitest.d.ts -o generatorCode -i false -n int -s cfg.json 274 275其中,参数详情如下: 276 277 -f, 待转换的.d.ts文件,若同时转换多个文件,文件之间用“,”隔开; 278 279 -d, 根据指定路径转换该文件夹中所有.d.ts文件; 280 281 -i, 可选参数,默认false,待转换.d.ts文件中引用非basic.d.ts的ts文件时打开开关; 282 283 -o, 可选参数,默认为当前目录,指定生成框架代码输出路径; 284 285 -n, 可选参数,默认为uint32_t,指定生成框架代码中number类型全部为指定类型; 286 287 -s, 可选参数,默认为不配置业务代码,指定生成框架代码的业务配置文件,用于粘合工具代码和业务代码的配置。 288 289 备注1:-f与-d两个参数只选其中一个参数即可。 290 291 备注2:若.d.ts文件中声明了basic.d.ts文件,将basic.d.ts文件放置在待转换.d.ts文件同一级目录;若除此之外还声明其它.d.ts文件,将此类文件放置在待转换.d.ts文件同级目录。 292 293其中,cfg.json内容如下: 294 295``` 296[ 297 { 298 "genPath": "/home/kaihong1/napi/myCommitNapiTest/generatorCode", 299 "includeName": "../serviceCode/NodeISayHello.h", 300 "cppName": "../serviceCode/NodeISayHello.cpp", 301 "interfaceName": "funcTest", 302 "serviceCode": "out = napitest::funcTest(v);" 303 "description": "includeName: 引入的业务代码.h文件相对路径, cppName: 引入的业务代码.cpp文件相对路径, interfaceName: ts文件中的使用接口名,业务代码就在该接口中调用;格式为:类名::方法名(如: TestClass::funcTest1),若无类名,则格式为:方法名(如: funcTest), serviceCode: 在接口中调用业务代码的调用语句。(该属性只做注释使用)" 304 } 305] 306``` 307 308cfg.json是一个数组,每一项配置对应一个方法的调用,需要对多少方法进行调用就配置多少项;其中 309 310"genPath": 生成框架代码路径,用户的业务代码相对于该路径配置,如:"/home/kaihong1/napi/myCommitNapiTest/generatorCode" 311 312"includeName": 引入的业务代码.h文件相对路径, 如:"../serviceCode/NodeISayHello.h", 313 314"cppName": 引入的业务代码.cpp文件相对路径, 如:"../serviceCode/NodeISayHello.cpp", 315 316"interfaceName": ts文件中的使用接口名,业务代码就在该接口中调用;格式为:类名::方法名(如: TestClass::funcTest1),若无类名,则格式为:方法名(如: funcTest), 317 318"serviceCode": 在接口中调用业务代码的调用语句。此处调用的是实现该接口的业务代码, 如:"out = napitest::funcTest(v);", 319 320"description": 仅作为cfg.json文件中描述其它字段含义的属性,用户配置时,可以不用填写这个字段 321 3223.运行成功后会在generatorCode目录下生成框架代码文件,如下所示: 323 324 OpenHarmony@Ubuntu-64:~/linshi/napi_generator_8/examples/ts/generatorCode$ ls 325 binding.gyp BUILD.gn napi_gen.log napitest.cpp napitest.h napitest_middle.h napitest_middle.cpp test.sh tool_utility.cpp tool_utility.h 326 327#### Windows 328 3291.将待转换的.d.ts文件、napi_generator-win.exe、 配置文件cfg.json、依赖文件basic.d.ts、业务代码文件夹serviceCode(其中serviceCode目录下放置业务代码的.h文件和.cpp文件)放在同级目录下。此处新建generatorCode文件夹,用于存放生成框架代码。整体目录文件如下: 330 331 E:\demo\napi>dir /B 332 @ohos.napitest.d.ts 333 basic.d.ts 334 napi_generator-win.exe 335 generatorCode 336 cfg.json 337 serviceCode 338 3392.在终端中进入到之前可执行程序napi_generator-win.exe所在的目录,并运行napi_generator-win.exe,命令如下: 340 341 E:\demo\napi>napi_generator-win.exe -f @ohos.napitest.d.ts -o generatorCode -i false -n double -s cfg.json 342 343其中,参数详情如下: 344 345 -f, 待转换的.d.ts文件,若同时转换多个文件,文件之间用“,”隔开; 346 347 -d, 根据指定路径转换该文件夹中所有.d.ts文件; 348 349 -i, 可选参数,默认false,待转换.d.ts文件中引用非basic.d.ts的ts文件时打开开关; 350 351 -o, 可选参数,默认为当前目录,指定生成框架代码输出路径; 352 353 -n, 可选参数,默认为uint32_t,指定生成框架代码中number类型全部为指定类型; 354 355 -s, 可选参数,默认为不配置业务代码,指定生成框架代码的业务配置文件,用于粘合工具代码和业务代码的配置。 356 357 备注1:-f与-d两个参数只选其中一个参数即可。 358 359 备注2:若.d.ts文件中声明了basic.d.ts文件,将basic.d.ts文件放置在待转换.d.ts文件同一级目录;若除此之外还声明其它.d.ts文件,将此类文件放置在待转换.d.ts文件同级目录。 360 361其中,cfg.json内容如下: 362 363``` 364[ 365 { 366 "genPath": "E:\\napi_aboutTest\\testcase_napi_intellijPlugin\\generatorCode", 367 "includeName": "../serviceCode/NodeISayHello.h", 368 "cppName": "../serviceCode/NodeISayHello.cpp", 369 "interfaceName": "funcTest", 370 "serviceCode": "out = napitest::funcTest(v);" 371 "description": "includeName: 引入的业务代码.h文件相对路径, cppName: 引入的业务代码.cpp文件相对路径, interfaceName: ts文件中的使用接口名,业务代码就在该接口中调用;格式为:类名::方法名(如: TestClass::funcTest1),若无类名,则格式为:方法名(如: funcTest), serviceCode: 在接口中调用业务代码的调用语句。(该属性只做注释使用)" 372 } 373] 374``` 375 376cfg.json是一个数组,每一项配置对应一个方法的调用,需要对多少方法进行调用就配置多少项;其中 377 378"genPath": 生成框架代码路径,用户的业务代码相对于该路径配置,如:"E:\\napi_aboutTest\\testcase_napi_intellijPlugin\\generatorCode" 379 380"includeName": 引入的业务代码.h文件相对路径, 如:"../serviceCode/NodeISayHello.h", 381 382"cppName": 引入的业务代码.cpp文件相对路径, 如:"../serviceCode/NodeISayHello.cpp", 383 384"interfaceName": ts文件中的使用接口名,业务代码就在该接口中调用;格式为:类名::方法名(如: TestClass::funcTest1),若无类名,则格式为:方法名(如: funcTest), 385 386"serviceCode": 在接口中调用业务代码的调用语句。此处调用的是实现该接口的业务代码, 如:"out = napitest::funcTest(v);", 387 388"description": 仅作为cfg.json文件中描述其它字段含义的属性,用户配置时,可以不用填写这个字段 389 3903.运行成功后会在generatorCode目录下生成框架代码文件,如下所示: 391 392 E:\demo\napi\generatorCode>dir /B 393 binding.gyp 394 BUILD.gn 395 napitest.cpp 396 napitest.h 397 napitest_middle.h 398 napitest_middle.cpp 399 napi_gen.log 400 test.sh 401 tool_utility.cpp 402 tool_utility.h 403 404#### Mac 405 406方法步骤参考windows、Linux的使用方法。 407 408### 不配置cfg.json文件生成框架代码 409 410若用户想手动配置业务代码,可不配置cfg.json文件生成框架代码之后手动增加业务代码,不配置cfg.json文件生成框架代码说明如下: 411 412[不配置cfg.json生成框架代码说明](https://gitee.com/openharmony/napi_generator/blob/master/src/cli/dts2cpp/docs/usage/ADD_SERVICECODE_INSTRUCTION.md) 413 414### VS Code插件使用方法 415 416具体的插件使用步骤,可以左键单击以下链接了解: 417 418[VS插件使用说明](https://gitee.com/openharmony/napi_generator/blob/master/src/vscode_plugin/dts2cpp/napi_vs_plugin/docs/usage/INSTRUCTION_ZH.md) 419 420### DevEco Studio上使用的IntelliJ插件使用方法 421 422具体的插件使用步骤,可以左键单击以下链接了解: 423 424[DevEco Studio上使用的IntelliJ插件使用说明](https://gitee.com/openharmony/napi_generator/blob/master/src/intellij_plugin/dts2cpp/napi_IntelliJ_plugin/docs/usage/INSTRUCTION_ZH.md) 425 426## 集成测试 427NAPI框架代码生成后,系统框架开发者进行二次开发后,即可集成到OpenHarmony编译系统,生成对应的库文件,供应用开发者调用接口。工具集成测试的具体操作步骤可以左键单击以下链接了解: 428 429 [工具集成测试](https://gitee.com/openharmony/napi_generator/blob/master/src/cli/dts2cpp/docs/usage/INTEGRATION_TESTING_ZH.md) 430 431