1# NAPI框架生成代码集成到OpenHarmony的方法 2 3## 场景说明 4 5为了实现工具生成的接口被其它子系统或者应用调用,需将生成的代码编译集成到OpenHarmony系统中,使其生成动态库,供OpenHarmony应用层调用。 6本文介绍如何将工具生成的源码利用OpenHarmony编译系统生成动态库供应用层调用,主要是有以下两种方式,分别为增加ohos.build文件方式和增加bundle.json文件方式。 7 8## 4.0 版本 9 10### 建立模块位置 11 12模块目录理论上可在OpenHarmony工程的任一位置,假设OpenHarmony代码库的目录为OHOS_SRC,在OHOS_SRC/foundation目录下,建测试模块目录:napitest。napitest目录结构如下: 13 14 napitest 15 |-- generatorCode // 工具代码部分 16 |-- |-- binding.gyp 17 |-- |-- BUILD.gn 18 |-- |-- bundle.json 19 |-- |-- napitest.cpp 20 |-- |-- napitest.h 21 |-- |-- napitest_middle.h 22 |-- |-- napitest_middle.cpp 23 |-- |-- test.sh 24 |-- |-- tool_utility.cpp 25 |-- |-- tool_utility.h 26 |-- |-- napi_gen.log 27 |-- serviceCode // 放置业务代码部分 28 |-- |-- NodeISayHello.h 29 |-- |-- NodeISayHello.cpp 30 31其中generatorCode为工具生成的代码,serviceCode 为用户配置的业务代码, bundle.json 为新增的编译配置文件。 32 33### 编译修改点 34 35#### 修改bundle.json文件 36 37其中destPath选项中的"//foundation/napitest/generatorCode"指的是napitest目录,":napitest"指的是上面BUILD.gn中的目标ohos_shared_library("napitest")。 38 39``` 40{ 41 "name": "@ohos/napitest", 42 "description": "napitest provides atomic capabilities", 43 "version": "4.0", 44 "license": "Apache License 2.0", 45 "publishAs": "code-segment", 46 "segment": { 47 "destPath": "foundation/napitest/generatorCode" 48 }, 49 "dirs": {}, 50 "scripts": {}, 51 "component": { 52 "name": "napitest", 53 "subsystem": "napitest", 54 "features": [], 55 "adapted_system_type": [ 56 "standard" 57 ], 58 "rom": "10000KB", 59 "ram": "10000KB", 60 "deps": { 61 "components": [ 62 "ace_napi", 63 "ipc_core", 64 "libhilog" 65 ], 66 "third_party": [ 67 "node" 68 ] 69 }, 70 "build": { 71 "sub_component": [ 72 "//foundation/napitest/generatorCode:napitest" 73 ], 74 "inner_kits": [ 75 { 76 "header": { 77 "header_base": "//foundation/napitest/generatorCode", 78 "header_files": [ 79 "tool_utility.h", 80 "napitest.h", 81 "napitest_middle.h" 82 ] 83 }, 84 "name": "//foundation/napitest/generatorCode:napitest" 85 } 86 ] 87 } 88 } 89} 90``` 91 92#### 增加子系统 93 94在源码/build/subsystem_config.json中增加子系统选项。如下所示: 95 96``` 97"napitest": { 98 "path": "foundation/napitest/generatorCode", 99 "name": "napitest" 100 } 101``` 102 103### 添加功能模块 104 105在产品配置中添加上述子系统的功能模块,编译到产品产出文件中,例如在源码vendor/hihope/rk3568/config.json中增加part选项,其中the first napitest就是BUILD.gn文件中的subsystem_name,第二个napitest就是BUILD.gn文件中的part_name。 106 107``` 108{ 109 "subsystem": "napitest", 110 "components": [ 111 { 112 "component": "napitest", 113 "features": [] 114 } 115 ] 116} 117``` 118 119### 编译验证 120 121编译成功后,就会在 /out/产品名/packages/phone/system/lib/module/ 生成libnapitest.z.so,如下所示: 122 123 /out/rk3568/packages/phone/system/lib/module 124 125### 备注 126 127若自动配置业务代码不能满足业务场景,用户可以手动配置业务代码,以下为用户手动配置业务代码并集成到OpenHarmony上的方法: 128 129[4.0版本手动配置业务代码集成方法](https://gitee.com/openharmony/napi_generator/blob/master/src/cli/dts2cpp/docs/usage/ENSEMBLE_METHOD_4.0CFGCODE.md) 130 131## 3.2 版本 132 133### 建立模块位置 134 135模块目录理论上可在OpenHarmony工程的任一位置,假设OpenHarmony代码库的目录为OHOS_SRC,在OHOS_SRC/foundation目录下,建测试模块目录:napitest。napitest目录结构如下: 136 137 napitest 138 |-- binding.gyp 139 |-- BUILD.gn 140 |-- bundle.json 141 |-- napitest.cpp 142 |-- napitest.h 143 |-- napitest_middle.h 144 |-- napitest_middle.cpp 145 |-- test.sh 146 |-- tool_utility.cpp 147 |-- tool_utility.h 148 149其中bundle.json为新建的编译配置文件,其它为工具生成的代码。 150 151### 编译修改点 152 153#### 修改bundle.json文件 154 155其中destPath选项中的"//foundation/napitest"指的是napitest目录,":napitest"指的是上面BUILD.gn中的目标ohos_shared_library("napitest")。 156 157``` 158{ 159 "name": "@ohos/napitest", 160 "description": "napitest provides atomic capabilities", 161 "version": "3.2", 162 "license": "Apache License 2.0", 163 "publishAs": "code-segment", 164 "segment": { 165 "destPath": "foundation/napitest" 166 }, 167 "dirs": {}, 168 "scripts": {}, 169 "component": { 170 "name": "napitest", 171 "subsystem": "napitest", 172 "features": [], 173 "adapted_system_type": [ 174 "standard" 175 ], 176 "rom": "10000KB", 177 "ram": "10000KB", 178 "deps": { 179 "components": [ 180 "ace_napi", 181 "ipc_core", 182 "libhilog" 183 ], 184 "third_party": [ 185 "node" 186 ] 187 }, 188 "build": { 189 "sub_component": [ 190 "//foundation/napitest:napitest" 191 ], 192 "inner_kits": [ 193 { 194 "header": { 195 "header_base": "//foundation/napitest", 196 "header_files": [ 197 "tool_utility.h", 198 "napitest.h", 199 "napitest_middle.h" 200 ] 201 }, 202 "name": "//foundation/napitest:napitest" 203 } 204 ] 205 } 206 } 207} 208``` 209 210#### 修改napitest.cpp文件 211 212为方便调试,在napitest.cpp文件中增加业务代码。以修改napitest.cpp文件为例,在以下方法中增加业务代码, 213 214在sayHello方法中增加注册的object回调方法的调用: 215 216``` 217... 218// 业务代码调用 onSayHelloStart callback 219napitest::napitest_interface::NodeISayHello::listener_.NodeISayHelloListener_onSayHelloStartCallback(info1); 220// 业务代码调用 onSayHelloEnd callback 221napitest::napitest_interface::NodeISayHello::listener_.NodeISayHelloListener_onSayHelloEndCallback(info2); 222... 223``` 224 225在sayHi方法中增加register注册的回调方法的调用: 226 227``` 228... 229napitest::napitest_interface::NodeISayHello *ptr = new napitest::napitest_interface::NodeISayHello(); 230uint32_t callbackNum = 50; 231ptr->CallbackfuncCallback(callbackNum); 232delete ptr; 233... 234``` 235 236在sayHelloWithResponse方法中增加Promise回调方法的调用: 237 238``` 239... 240out.errMsg = ""; 241out.response = "rec hello."; 242out.result = 0; 243... 244``` 245 246在funcTest方法中增加普通函数的业务逻辑: 247 248``` 249... 250if (v) { 251 out = "ret is true"; 252} else { 253 out = "ret is false"; 254} 255... 256``` 257 258增加业务代码之后的文件如下所示: 259 260``` 261#include "napitest.h" 262#include "napitest_middle.h" 263#include "hilog/log.h" 264static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0XD002E00, "NAPITESTNAPILayer"}; 265#define NAPITEST_LOGI(fmt, ...) OHOS::HiviewDFX::HiLog::Info(LABEL, \ 266 "%{public}s:%{public}d " fmt, __func__, __LINE__, ##__VA_ARGS__) 267 268namespace napitest { 269namespace napitest_interface { 270NodeISayHelloListener NodeISayHello::listener_ = {}; 271bool NodeISayHello::addSayHelloListener(NodeISayHelloListener& listener) 272{ 273 NodeISayHello::listener_ = listener; 274 return true; 275} 276 277bool NodeISayHello::removeSayHelloListener(NodeISayHelloListener& listener) 278{ 279 return true; 280} 281 282bool NodeISayHello::registerCallbackfunc() 283{ 284 return true; 285} 286 287// 供业务调用的回调接口 288void NodeISayHello::CallbackfuncCallback(NUMBER_TYPE_2& wid) 289{ 290 std::string eventName = "Callbackfunc"; 291 NodeISayHello_middle *ptr = new NodeISayHello_middle(); 292 ptr->CallbackfuncCallbackMiddle(eventName, wid); 293 delete ptr; 294} 295 296bool NodeISayHello::unRegisterCallbackfunc() 297{ 298 return true; 299} 300 301bool NodeISayHello::sayHello(std::string& from, std::string& to, NUMBER_TYPE_9& sayType) 302{ 303 NAPITEST_LOGI("NAPITEST_LOGI sayHello from = %s\r\n", from.c_str()); 304 NAPITEST_LOGI("NAPITEST_LOGI sayHello to = %s\r\n", to.c_str()); 305 NAPITEST_LOGI("NAPITEST_LOGI sayHello sayType = %d\r\n", sayType); 306 SayInfo info1; 307 info1.from = "js1"; 308 uint32_t a = 992; 309 info1.fromId.emplace(a); 310 uint32_t b = 1014; 311 info1.toId.emplace(b); 312 info1.to = "native1"; 313 info1.content = "hello1"; 314 info1.saidTime = "123456789"; 315 info1.isEnd = false; 316 SayInfo info2; 317 info2.from = "native"; 318 uint32_t c = 101; 319 info2.fromId.emplace(c); 320 uint32_t d = 99; 321 info2.toId.emplace(d); 322 info2.to = "js"; 323 info2.content = "hello"; 324 info2.saidTime = "987654321"; 325 info2.isEnd = true; 326 // 业务代码调用 onSayHelloStart callback 327 listener_.NodeISayHelloListener_onSayHelloStartCallback(info1); 328 // 业务代码调用 onSayHelloEnd callback 329 listener_.NodeISayHelloListener_onSayHelloEndCallback(info2); 330 return true; 331} 332 333bool NodeISayHello::sayHi(std::string& from, std::string& to, NUMBER_TYPE_10& sayType) 334{ 335 NAPITEST_LOGI("NAPITEST_LOGI sayHi from = %s\r\n", from.c_str()); 336 NAPITEST_LOGI("NAPITEST_LOGI sayHi to = %s\r\n", to.c_str()); 337 NAPITEST_LOGI("NAPITEST_LOGI sayHi sayType = %d\r\n", sayType); 338 NodeISayHello *ptr = new NodeISayHello(); 339 uint32_t callbackNum = 50; 340 ptr->CallbackfuncCallback(callbackNum); 341 delete ptr; 342 return true; 343} 344 345bool NodeISayHello::sayHelloWithResponse(std::string& from, std::string& to, NUMBER_TYPE_11& sayType, 346 uint32_t& outErrCode, AUTO_INTERFACE_5& out) 347{ 348 NAPITEST_LOGI("NAPITEST_LOGI sayHelloWithResponse from = %s\r\n", from.c_str()); 349 NAPITEST_LOGI("NAPITEST_LOGI sayHelloWithResponse to = %s\r\n", to.c_str()); 350 NAPITEST_LOGI("NAPITEST_LOGI sayHelloWithResponse sayType = %d\r\n", sayType); 351 out.errMsg = ""; 352 out.response = "rec hello."; 353 out.result = 0; 354 return true; 355} 356 357AUTO_INTERFACE_5 NodeISayHello::auto_interface_5OutRes = {}; 358void NodeISayHello::auto_interface_5SetCbValue(NUMBER_TYPE_6 result, std::string errMsg, std::string response) 359{ 360 NodeISayHello::auto_interface_5OutRes.result = result; 361 NodeISayHello::auto_interface_5OutRes.errMsg = errMsg; 362 NodeISayHello::auto_interface_5OutRes.response = response; 363 return; 364} 365 366bool NodeISayHelloListener::onSayHelloStart() 367{ 368 return true; 369} 370 371// 供业务调用的回调接口 372void NodeISayHelloListener::NodeISayHelloListener_onSayHelloStartCallback(SayInfo& info) 373{ 374 std::string eventName = "NodeISayHelloListener_onSayHelloStart"; 375 NodeISayHelloListener_middle *ptr = new NodeISayHelloListener_middle(); 376 ptr->NodeISayHelloListener_onSayHelloStartCallbackMiddle(eventName, info); 377 delete ptr; 378} 379 380bool NodeISayHelloListener::onSayHelloEnd() 381{ 382 return true; 383} 384 385// 供业务调用的回调接口 386void NodeISayHelloListener::NodeISayHelloListener_onSayHelloEndCallback(SayInfo& info) 387{ 388 std::string eventName = "NodeISayHelloListener_onSayHelloEnd"; 389 NodeISayHelloListener_middle *ptr = new NodeISayHelloListener_middle(); 390 ptr->NodeISayHelloListener_onSayHelloEndCallbackMiddle(eventName, info); 391 delete ptr; 392} 393 394bool funcTest(bool& v, std::string& out) 395{ 396 if (v) { 397 out = "ret is true"; 398 } else { 399 out = "ret is false"; 400 } 401 return true; 402} 403} 404} 405 406``` 407 408#### 增加子系统 409 410在源码/build/subsystem_config.json中增加子系统选项。如下所示: 411 412``` 413"napitest": { 414 "path": "foundation/napitest", 415 "name": "napitest" 416 } 417``` 418 419### 添加功能模块 420 421在产品配置中添加上述子系统的功能模块,编译到产品产出文件中,例如在源码vendor/hihope/rk3568/config.json中增加part选项,其中the first napitest就是BUILD.gn文件中的subsystem_name,第二个napitest就是BUILD.gn文件中的part_name。 422 423``` 424{ 425 "subsystem": "napitest", 426 "components": [ 427 { 428 "component": "napitest", 429 "features": [] 430 } 431 ] 432} 433``` 434 435### 编译验证 436 437编译成功后,就会在 /out/产品名/packages/phone/system/lib/module/ 生成libnapitest.z.so,如下所示: 438 439 /out/rk3568/packages/phone/system/lib/module 440 441## 3.1 版本 442 443[3.1版本集成方法](https://gitee.com/openharmony/napi_generator/blob/master/src/cli/dts2cpp/docs/usage/ENSEMBLE_METHOD_3.1VERSION.md) 444 445## 总结 446 4473.1版本两种集成方式使用场景说明: 448 449ohos.build方式集成:适合3.0前版本使用。 450 451bundle.json方式集成:兼容ohos.build方式,但3.1及以后版本建议使用此种方式集成。 452 4533.2版本适合使用bundle.json方式集成。 454 4554.0版本适合使用bundle.json方式集成。 456 457