1# Native生成工具使用说明 2 3## 准备 4 5### 依赖 6 7系统:建议Windows 10 8 9开发工具:DevEco Studio 10 11## 生成框架 12 13### 创建工程 14 151.打开 DevEco Studio: 16 17选择Create Project -> Application -> Native C++ ,然后点击Next,将Project name修改为cJsonSampleTest,点击Finish,则工程创建成功。 18 19 20 21 22 23### 导入三方库 24 25将待转换的三方库导入工程中,如将cJSON三方库导入工程: 26 271.cJSON三方库获取:[测试用三方库](https://gitee.com/openharmony/napi_generator/releases/tag/测试用资源) 选择cJSON.zip下载 28 29 30 312.将三方库导入工程:将cJSON.zip解压,解压后可以拷贝内容进 cJsonSampleTest\entry\src\main\cpp\thirdparty 和 cJsonSampleTest\entry\libs 下 32 33 34 35同时将arm64-v8a/lib下的所有.so文件拷贝一份至arm64-v8a下,将armeabi-v7a/lib下的所有.so文件拷贝一份至armeabi-v7a下。 36 373.将libcjson加入编译:在CMakeLists.txt(cJsonSampleTest/entry/src/main/cpp/CMakeLists.txt)中加入libcjson路径 38 39``` 40set(CJSON_LIB_PATH ${NATIVERENDER_ROOT_PATH}/../../../libs/${OHOS_ARCH}) 41``` 42 43在target_link_libraries中加入hilog和libcjson.so: 44 45``` 46libhilog_ndk.z.so 47``` 48 49``` 50${CJSON_LIB_PATH}/libcjson.so 51``` 52 53 54 554.修改编译选项:在cJsonSampleTest/entry/build-profile.json5文件中buildOption中增加abiFilters字段, 并将targets字段的runtimeOS改为OpenHarmony 56 57``` 58"abiFilters": [ 59 "arm64-v8a", 60 "armeabi-v7a" 61 ] 62``` 63 64``` 65"runtimeOS": "OpenHarmony" 66``` 67 68 69 70### 使用nativetool生成框架 71 72#### 准备 73 74##### 1.在本地新建文件夹nativetoolGen 75 76##### **2.下载native_gen-win.exe**, header_parser.exe 77 78下载 native_gen-win.exe 可执行程序和 header_parser.exe 可执行程序:[下载生成工具 ](https://gitee.com/openharmony/napi_generator/releases/tag/生成工具) ;选择 tool.rar下载并解压,将解压后的文件拷贝到nativetoolGen目录下 79 80 81 82#### 使用命令行生成框架 83 84##### 1.运行可执行文件 85 861.1将待转换的.h文件放到nativetoolGen目录下,例如:将cJSON.h文件放入nativetoolGen目录下(cJSON.h可从导入的三方库下的include文件夹中获取) 87 88 89 901.2在命令行使用 以下命令运行脚本 91 92``` 93native_gen-win.exe -f 接口文件路径 -o 生成路径 94``` 95 96其中,参数详情如下: 97 98-f, 必选参数,待转换的.h文件;如cJSON.h。 99 100-o, 可选参数,生成路径,默认路径为.h文件所在路径; 101 102例如: 103 104``` 105native_gen-win.exe -f cJSON.h 106``` 107 1081.3运行成功后命令行会打印出 Generate success; 109 110 111 112并在nativetoolGen/cppout目录下会生成方法的cpp文件: 分别是cjsonnapi.h(cJSON.h中接口对应的napi接口声明),cjsoninit.cpp(所有napi接口的init,用来初始化模块),cjsoncommon.h、cjsoncommon.cpp(公共方法的声明和实现,如获取错误信息方法)和cJSON.h中接口对应的cpp文件:每个cJSON.h中的接口对应一个cpp文件,该文件中为框架生成的cJSON接口的napi框架代码,如:cjsoncreateobject.cpp, cjsonparse.cpp 等等。在nativetoolGen/tsout/index.d.ts文件中会写入生成的ts接口;在nativetoolGen/testout/cJSONAbility.test.ets生成接口测试代码模板。 113 114 115 116##### 2.确认生成代码是否能正确编译 117 1182.1将cppout(nativetoolGen/cppout)拷贝至 cJsonSampleTest/entry/src/main/cpp目录下; 将cJSON.h拷贝至cppout目录下。 119 1202.2将生成的所有cpp文件加入CMakeLists.txt(cJsonSampleTest/entry/src/main/cpp/CMakeLists.txt)编译,其中cppout/cjsoninit.cpp为编译入口;即用下列add_library替换原有的add_library 121 122``` 123add_library(entry SHARED 124 cppout/cjsonparse.cpp 125 cppout/cjsoninithooks.cpp 126 cppout/cjsonaddarraytoobject.cpp 127 cppout/cjsonaddbooltoobject.cpp 128 cppout/cjsonaddfalsetoobject.cpp 129 cppout/cjsonadditemreferencetoarray.cpp 130 cppout/cjsonadditemreferencetoobject.cpp 131 cppout/cjsonadditemtoarray.cpp 132 cppout/cjsonadditemtoobject.cpp 133 cppout/cjsonadditemtoobjectcs.cpp 134 cppout/cjsonaddnulltoobject.cpp 135 cppout/cjsonaddnumbertoobject.cpp 136 cppout/cjsonaddobjecttoobject.cpp 137 cppout/cjsonaddrawtoobject.cpp 138 cppout/cjsonaddstringtoobject.cpp 139 cppout/cjsonaddtruetoobject.cpp 140 cppout/cjsoncompare.cpp 141 cppout/cjsoncreatearray.cpp 142 cppout/cjsoncreatearrayreference.cpp 143 cppout/cjsoncreatebool.cpp 144 cppout/cjsoncreatedoublearray.cpp 145 cppout/cjsoncreatefalse.cpp 146 cppout/cjsoncreatefloatarray.cpp 147 cppout/cjsoncreateintarray.cpp 148 cppout/cjsoncreatenull.cpp 149 cppout/cjsoncreatenumber.cpp 150 cppout/cjsoncreateobject.cpp 151 cppout/cjsoncreateobjectreference.cpp 152 cppout/cjsoncreateraw.cpp 153 cppout/cjsoncreatestringarray.cpp 154 cppout/cjsoncreatestringreference.cpp 155 cppout/cjsoncreatetrue.cpp 156 cppout/cjsondelete.cpp 157 cppout/cjsondeleteitemfromarray.cpp 158 cppout/cjsondeleteitemfromobject.cpp 159 cppout/cjsondeleteitemfromobjectcasesensitive.cpp 160 cppout/cjsondetachitemfromarray.cpp 161 cppout/cjsondetachitemfromobject.cpp 162 cppout/cjsondetachitemfromobjectcasesensitive.cpp 163 cppout/cjsondetachitemviapointer.cpp 164 cppout/cjsonduplicate.cpp 165 cppout/cjsonfree.cpp 166 cppout/cjsongetarrayitem.cpp 167 cppout/cjsongetarraysize.cpp 168 cppout/cjsongeterrorptr.cpp 169 cppout/cjsongetnumbervalue.cpp 170 cppout/cjsongetobjectitem.cpp 171 cppout/cjsongetobjectitemcasesensitive.cpp 172 cppout/cjsongetstringvalue.cpp 173 cppout/cjsonhasobjectitem.cpp 174 cppout/cjsoninsertiteminarray.cpp 175 cppout/cjsonisarray.cpp 176 cppout/cjsonisbool.cpp 177 cppout/cjsonisfalse.cpp 178 cppout/cjsonisinvalid.cpp 179 cppout/cjsonisnull.cpp 180 cppout/cjsonisnumber.cpp 181 cppout/cjsonisobject.cpp 182 cppout/cjsonisraw.cpp 183 cppout/cjsonisstring.cpp 184 cppout/cjsonistrue.cpp 185 cppout/cjsonmalloc.cpp 186 cppout/cjsonminify.cpp 187 cppout/cjsonparsewithlength.cpp 188 cppout/cjsonparsewithlengthopts.cpp 189 cppout/cjsonparsewithopts.cpp 190 cppout/cjsonprint.cpp 191 cppout/cjsonprintbuffered.cpp 192 cppout/cjsonprintpreallocated.cpp 193 cppout/cjsonprintunformatted.cpp 194 cppout/cjsonreplaceiteminarray.cpp 195 cppout/cjsonreplaceiteminobject.cpp 196 cppout/cjsonreplaceiteminobjectcasesensitive.cpp 197 cppout/cjsonreplaceitemviapointer.cpp 198 cppout/cjsonsetnumberhelper.cpp 199 cppout/cjsonsetvaluestring.cpp 200 cppout/cjsonversion.cpp 201 cppout/cjsoncreatestring.cpp 202 cppout/cjsoncommon.cpp 203 cppout/cjsoninit.cpp 204 ) 205``` 206 2072.4将index.d.ts(nativetoolGen/tsout/index.d.ts)中所有内容拷贝至 cJsonSampleTest/entry/src/main/cpp/types/libentry/index.d.ts中; 208 2092.5将nativetoolGen/testout/cJSONAbilitytest.test.ets拷贝到cJsonSampleTest/entry/src/ohosTest/ets/test目录下; 210 211在cJsonSampleTest/entry/src/ohosTest/ets/test/List.test.ets中导入cJSONAbilitytest.test.ets 212 213``` 214import abilityTest from './Ability.test'; 215import cJSONabilityTest from './cJSONAbility.test'; 216 217export default function testsuite() { 218 abilityTest(); 219 cJSONabilityTest(); 220} 221``` 222 223 224 2252.6对工程签名:File->Project Structure ->Project -> Signing Configs 226 227 228 229运行cJSONAbilitytest.test.ets中的测试集cJSONActsAbilityTest,用例成功运行,并打印出相关log。 230 231 232 233例如:方法KH418_cJSON_Parse打印出默认对象值(以cJSON_Parse接口为例:本例子生成的方法为KH418_cJSON_Parse,其中KH418中的数字为随机生成,用户使用时数字可能不是418, 而是其它三位随机数。) 234 235``` 236 I KH418_cJSON_Parse result: {"next":{},"prev":{},"child":{},"type":1,"valuestring":"valuestring","valueint":1,"valuedouble":1,"string":"string"} 237``` 238 239 240 241## 增加业务代码并测试 242 243### 增加业务代码 244 245以cjson_parse接口为例 246 2471.在cjsonparse.cpp(cJsonSampleTest\entry\src\main\cpp\cppout)代码中 248 249``` 250// Todo: add business logic. 在这前后代码为框架所生成 251``` 252 253处加入业务代码: 254 2551.1将字符串转换为cJSON对象,调用cJSON_Parse方法; 256 257``` 258 cJSON *json = cJSON_Parse(valueIn); 259 if (json == nullptr) { 260 return nullptr; 261 } 262 cJSON *jsonChild = nullptr; 263 if (json != nullptr) { 264 jsonChild = json->child; 265 } 266 cJSON *jsonNext = nullptr; 267 if (jsonChild != nullptr) { 268 jsonNext = jsonChild->next; 269 } 270 delete[] valueIn; 271``` 272 2731.2将native层转换成功的json对象对应转换为js层的对象:向框架生成的cJSON_ParseOut空对象中一一塞入json对象数据并返回js层。 274 275增加业务代码之后的cjsonparse.cpp如下所示:(注意:本示例的方法名字是KH418_cJSON_Parse,用户使用时需要将KH418_cJSON_Parse方法名修改为自身的KHxxx_cJSON_Parse方法名) 276 277``` 278#include "cjsonnapi.h" 279 280napi_value getCjsonChildOut2(napi_env env, napi_value childOut, cJSON *jsonChild) { 281 napi_status status; 282 const napi_extended_error_info *extended_error_info; 283 const char *tag = "[KH418_cJSON_Parse]"; 284 napi_value childTypeOut; 285 status = napi_create_int32(env, jsonChild->type, &childTypeOut); 286 if (status != napi_ok) { 287 getErrMessage(status, env, extended_error_info, "napi_create_int32 jsonChild->type", tag); 288 return nullptr; 289 } 290 status = napi_set_named_property(env, childOut, "type", childTypeOut); 291 if (status != napi_ok) { 292 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonChild->type", tag); 293 return nullptr; 294 } 295 napi_value childValueintOut; 296 status = napi_create_int32(env, jsonChild->valueint, &childValueintOut); 297 if (status != napi_ok) { 298 getErrMessage(status, env, extended_error_info, "napi_create_int32 jsonChild->valueint", tag); 299 return nullptr; 300 } 301 status = napi_set_named_property(env, childOut, "valueint", childValueintOut); 302 if (status != napi_ok) { 303 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonChild->valueint", tag); 304 return nullptr; 305 } 306 napi_value childValuedoubleOut; 307 status = napi_create_double(env, jsonChild->valuedouble, &childValuedoubleOut); 308 if (status != napi_ok) { 309 getErrMessage(status, env, extended_error_info, "napi_create_double jsonChild->valuedouble", tag); 310 return nullptr; 311 } 312 status = napi_set_named_property(env, childOut, "valuedouble", childValuedoubleOut); 313 if (status != napi_ok) { 314 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonChild->valuedouble", tag); 315 return nullptr; 316 } 317 return childOut; 318} 319 320napi_value getCjsonChildOut(napi_env env, napi_value childOut, cJSON *jsonChild) { 321 napi_status status; 322 const napi_extended_error_info *extended_error_info; 323 const char *tag = "[KH418_cJSON_Parse]"; 324 // 将数据塞入child 325 if (jsonChild != nullptr) { 326 napi_value childValuestringOut; 327 status = napi_create_string_utf8(env, jsonChild->valuestring == nullptr ? "" : jsonChild->valuestring, 328 NAPI_AUTO_LENGTH, &childValuestringOut); 329 if (status != napi_ok) { 330 getErrMessage(status, env, extended_error_info, "napi_create_string_utf8 jsonChild->valuestring", tag); 331 return nullptr; 332 } 333 status = napi_set_named_property(env, childOut, "valuestring", childValuestringOut); 334 if (status != napi_ok) { 335 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonChild->valuestring", tag); 336 return nullptr; 337 } 338 napi_value childStringOut; 339 status = napi_create_string_utf8(env, jsonChild->string == nullptr ? "" : jsonChild->string, NAPI_AUTO_LENGTH, 340 &childStringOut); 341 if (status != napi_ok) { 342 getErrMessage(status, env, extended_error_info, "napi_create_string_utf8 jsonChild->string", tag); 343 return nullptr; 344 } 345 status = napi_set_named_property(env, childOut, "string", childStringOut); 346 if (status != napi_ok) { 347 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonChild->string", tag); 348 return nullptr; 349 } 350 childOut = getCjsonChildOut2(env, childOut, jsonChild); 351 } 352 return childOut; 353} 354 355napi_value getCjsonNextOut2(napi_env env, napi_value nextOut, cJSON *jsonNext) { 356 napi_status status; 357 const napi_extended_error_info *extended_error_info; 358 const char *tag = "[KH418_cJSON_Parse]"; 359 napi_value nextTypeOut; 360 status = napi_create_int32(env, jsonNext->type, &nextTypeOut); 361 if (status != napi_ok) { 362 getErrMessage(status, env, extended_error_info, "napi_create_int32 jsonNext->type", tag); 363 return nullptr; 364 } 365 status = napi_set_named_property(env, nextOut, "type", nextTypeOut); 366 if (status != napi_ok) { 367 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonNext->type", tag); 368 return nullptr; 369 } 370 napi_value nextValueintOut; 371 status = napi_create_int32(env, jsonNext->valueint, &nextValueintOut); 372 if (status != napi_ok) { 373 getErrMessage(status, env, extended_error_info, "napi_create_int32 jsonNext->valueint", tag); 374 return nullptr; 375 } 376 status = napi_set_named_property(env, nextOut, "valueint", nextValueintOut); 377 if (status != napi_ok) { 378 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonNext->valueint", tag); 379 return nullptr; 380 } 381 napi_value nextValuedoubleOut; 382 status = napi_create_double(env, jsonNext->valuedouble, &nextValuedoubleOut); 383 if (status != napi_ok) { 384 getErrMessage(status, env, extended_error_info, "napi_create_double jsonNext->valuedouble", tag); 385 return nullptr; 386 } 387 status = napi_set_named_property(env, nextOut, "valuedouble", nextValuedoubleOut); 388 if (status != napi_ok) { 389 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonNext->valuedouble", tag); 390 return nullptr; 391 } 392 return nextOut; 393} 394 395napi_value getCjsonNextOut(napi_env env, napi_value nextOut, cJSON *jsonNext) { 396 napi_status status; 397 const napi_extended_error_info *extended_error_info; 398 const char *tag = "[KH418_cJSON_Parse]"; 399 // 将数据塞入next 400 if (jsonNext != nullptr) { 401 napi_value nextValuestringOut; 402 status = napi_create_string_utf8(env, jsonNext->valuestring == nullptr ? "" : jsonNext->valuestring, 403 NAPI_AUTO_LENGTH, &nextValuestringOut); 404 if (status != napi_ok) { 405 getErrMessage(status, env, extended_error_info, "napi_create_string_utf8 jsonNext->valuestring", tag); 406 return nullptr; 407 } 408 status = napi_set_named_property(env, nextOut, "valuestring", nextValuestringOut); 409 if (status != napi_ok) { 410 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonNext->valuestring", tag); 411 return nullptr; 412 } 413 napi_value nextStringOut; 414 status = napi_create_string_utf8(env, jsonNext->string == nullptr ? "" : jsonNext->string, NAPI_AUTO_LENGTH, 415 &nextStringOut); 416 if (status != napi_ok) { 417 getErrMessage(status, env, extended_error_info, "napi_create_string_utf8 jsonNext->string", tag); 418 return nullptr; 419 } 420 status = napi_set_named_property(env, nextOut, "string", nextStringOut); 421 if (status != napi_ok) { 422 getErrMessage(status, env, extended_error_info, "napi_set_named_property jsonNext->string", tag); 423 return nullptr; 424 } 425 nextOut = getCjsonNextOut2(env, nextOut, jsonNext); 426 } 427 return nextOut; 428} 429 430napi_value getCjsonparseOut1(napi_env env, cJSON *jsonNext, napi_value cJSON_ParseOut) { 431 napi_status status; 432 const napi_extended_error_info *extended_error_info; 433 const char *tag = "[KH418_cJSON_Parse]"; 434 napi_value nextOut; 435 /* [NAPI_GEN]: 返回值是对象时,需要使用napi_create_object创建一个js的对象与js代码交互 436 * env: 当前环境的句柄 437 * result: 一个napi_value的指针,该指针将被设置为新创建的js对象 438 */ 439 status = napi_create_object(env, &nextOut); 440 if (status != napi_ok) { 441 getErrMessage(status, env, extended_error_info, "napi_create_object", tag); 442 return nullptr; 443 } 444 nextOut = getCjsonNextOut(env, nextOut, jsonNext); 445 /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,后将该对象返回js 446 * env: 当前环境的句柄 447 * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 448 * utf8name: 属性的名称,是一个以UTF-8编码的字符串 449 * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 450 */ 451 status = napi_set_named_property(env, cJSON_ParseOut, "next", nextOut); 452 if (status != napi_ok) { 453 /* [NAPI_GEN]: 错误处理*/ 454 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 455 return nullptr; 456 } 457 napi_value prevOut; 458 /* [NAPI_GEN]: 返回值是对象时,需要使用napi_create_object创建一个js的对象与js代码交互 459 * env: 当前环境的句柄 460 * result: 一个napi_value的指针,该指针将被设置为新创建的js对象 461 */ 462 status = napi_create_object(env, &prevOut); 463 if (status != napi_ok) { 464 getErrMessage(status, env, extended_error_info, "napi_create_object", tag); 465 return nullptr; 466 } 467 /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,将该对象返回js 468 * env: 当前环境的句柄 469 * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 470 * utf8name: 属性的名称,是一个以UTF-8编码的字符串 471 * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 472 */ 473 status = napi_set_named_property(env, cJSON_ParseOut, "prev", prevOut); 474 if (status != napi_ok) { 475 /* [NAPI_GEN]: 错误处理*/ 476 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 477 return nullptr; 478 } 479 return cJSON_ParseOut; 480} 481 482napi_value getCjsonparseOut2(napi_env env, cJSON *json, cJSON *jsonChild, napi_value cJSON_ParseOut) { 483 napi_status status; 484 const napi_extended_error_info *extended_error_info; 485 const char *tag = "[KH418_cJSON_Parse]"; 486 napi_value childOut; 487 /* [NAPI_GEN]: 返回值是对象时,需要使用napi_create_object创建一个js的对象与js代码交互 488 * env: 当前环境的句柄 489 * result: 一个napi_value的指针,该指针将被设置为新创建的js对象 490 */ 491 status = napi_create_object(env, &childOut); 492 if (status != napi_ok) { 493 getErrMessage(status, env, extended_error_info, "napi_create_object", tag); 494 return nullptr; 495 } 496 childOut = getCjsonChildOut(env, childOut, jsonChild); 497 /* [NAPI_GEN]: 498 * 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,后将该对象返回js env: 499 * 当前环境的句柄 object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 utf8name: 500 * 属性的名称,是一个以UTF-8编码的字符串 value: 501 * 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 502 */ 503 status = napi_set_named_property(env, cJSON_ParseOut, "child", childOut); 504 if (status != napi_ok) { 505 /* [NAPI_GEN]: 错误处理*/ 506 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 507 return nullptr; 508 } 509 napi_value typeOut; 510 /* [NAPI_GEN]: 返回值是int32_t类型时,napi_create_int32 创建一个包含32位整数(int32_t)的js数值(Number)对象 511 * env: 当前环境的句柄 512 * value: 要准换成js数值的int32_t的值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 513 * result: 指向napi_value的指针,这个指针会被设置为新创建的js数值对象 514 */ 515 status = napi_create_int32(env, json == nullptr ? 0 : json->type, &typeOut); 516 if (status != napi_ok) { 517 getErrMessage(status, env, extended_error_info, "napi_create_int32", tag); 518 return nullptr; 519 } 520 /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,后将该对象返回js 521 * env: 当前环境的句柄 522 * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 523 * utf8name: 属性的名称,是一个以UTF-8编码的字符串 524 * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 525 */ 526 status = napi_set_named_property(env, cJSON_ParseOut, "type", typeOut); 527 if (status != napi_ok) { 528 /* [NAPI_GEN]: 错误处理*/ 529 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 530 return nullptr; 531 } 532 return cJSON_ParseOut; 533} 534 535napi_value getCjsonparseOut3(napi_env env, cJSON *json, napi_value cJSON_ParseOut) { 536 napi_status status; 537 const napi_extended_error_info *extended_error_info; 538 const char *tag = "[KH418_cJSON_Parse]"; 539 napi_value valuestringOut; 540 /* [NAPI_GEN]: 541 * 返回值是字符串时,napi_create_string_utf8用于在原生代码中创建一个新的js字符串。这个函数会根据提供的UTF-8编码的字符串创建一个等价的js字符串 542 * env: 当前环境的句柄 543 * str: 指向以null结尾的UTF-8编码的C字符串的指针,这里以valuestring举例,用户可根据需求修改 544 * length: 545 * 字符串的长度,可以是具体的字节数,或者使用特殊的值NAPI_AUTO_LENGTH来让函数自己计算长度(假定字符串以null结尾) 546 * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js字符串 547 */ 548 status = 549 napi_create_string_utf8(env, json == nullptr ? "" : (json->valuestring == nullptr ? "" : json->valuestring), 550 NAPI_AUTO_LENGTH, &valuestringOut); 551 if (status != napi_ok) { 552 /*错误处理*/ 553 getErrMessage(status, env, extended_error_info, "napi_create_string_utf8", tag); 554 return nullptr; 555 } 556 /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,后将该对象返回js 557 * env: 当前环境的句柄 558 * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 559 * utf8name: 属性的名称,是一个以UTF-8编码的字符串 560 * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 561 */ 562 status = napi_set_named_property(env, cJSON_ParseOut, "valuestring", valuestringOut); 563 if (status != napi_ok) { 564 /* [NAPI_GEN]: 错误处理*/ 565 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 566 return nullptr; 567 } 568 napi_value valueintOut; 569 /* [NAPI_GEN]: 返回值是int32_t类型时,napi_create_int32 创建一个包含32位整数(int32_t)的js数值(Number)对象 570 * env: 当前环境的句柄 571 * value: 要准换成js数值的int32_t的值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 572 * result: 指向napi_value的指针,这个指针会被设置为新创建的js数值对象 573 */ 574 status = napi_create_int32(env, json == nullptr ? 0 : json->valueint, &valueintOut); 575 if (status != napi_ok) { 576 getErrMessage(status, env, extended_error_info, "napi_create_int32", tag); 577 return nullptr; 578 } 579 /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,后将该对象返回js 580 * env: 当前环境的句柄 581 * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 582 * utf8name: 属性的名称,是一个以UTF-8编码的字符串 583 * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 584 */ 585 status = napi_set_named_property(env, cJSON_ParseOut, "valueint", valueintOut); 586 if (status != napi_ok) { 587 /* [NAPI_GEN]: 错误处理*/ 588 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 589 return nullptr; 590 } 591 return cJSON_ParseOut; 592} 593 594napi_value getCjsonparseOut4(napi_env env, cJSON *json, napi_value cJSON_ParseOut) { 595 napi_status status; 596 const napi_extended_error_info *extended_error_info; 597 const char *tag = "[KH418_cJSON_Parse]"; 598 napi_value valuedoubleOut; 599 /* [NAPI_GEN]: 返回值是double类型时,napi_create_double 创建一个包含双精度浮点数的js数值(Number)对象 600 * env: 当前环境的句柄 601 * value: 要传递给js的双精度浮点数值,这里以传入1.0为例,用例新增业务代码时可根据自身需求修改 602 * result: 指向napi_value的指针,这个指针会被设置为新创建的js数值对象 603 */ 604 status = napi_create_double(env, json == nullptr ? 0 : json->valuedouble, &valuedoubleOut); 605 if (status != napi_ok) { 606 getErrMessage(status, env, extended_error_info, "napi_create_double", tag); 607 return nullptr; 608 } 609 /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,后将该对象返回js 610 * env: 当前环境的句柄 611 * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 612 * utf8name: 属性的名称,是一个以UTF-8编码的字符串 613 * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 614 */ 615 status = napi_set_named_property(env, cJSON_ParseOut, "valuedouble", valuedoubleOut); 616 if (status != napi_ok) { 617 /* [NAPI_GEN]: 错误处理*/ 618 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 619 return nullptr; 620 } 621 napi_value stringOut; 622 /* [NAPI_GEN]: 623 * 返回值是字符串时,napi_create_string_utf8用于在原生代码中创建一个新的js字符串。这个函数会根据提供的UTF-8编码的字符串创建一个等价的js字符串 624 * env: 当前环境的句柄 625 * str: 指向以null结尾的UTF-8编码的C字符串的指针,这里以string举例,用户可根据需求修改 626 * length: 627 * 字符串的长度,可以是具体的字节数,或者使用特殊的值NAPI_AUTO_LENGTH来让函数自己计算长度(假定字符串以null结尾) 628 * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js字符串 629 */ 630 status = napi_create_string_utf8(env, json == nullptr ? "" : (json->string == nullptr ? "" : json->string), 631 NAPI_AUTO_LENGTH, &stringOut); 632 if (status != napi_ok) { 633 /*错误处理*/ 634 getErrMessage(status, env, extended_error_info, "napi_create_string_utf8", tag); 635 return nullptr; 636 } 637 /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,后将该对象返回js 638 * env: 当前环境的句柄 639 * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 640 * utf8name: 属性的名称,是一个以UTF-8编码的字符串 641 * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) 642 */ 643 status = napi_set_named_property(env, cJSON_ParseOut, "string", stringOut); 644 if (status != napi_ok) { 645 /* [NAPI_GEN]: 错误处理*/ 646 getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); 647 return nullptr; 648 } 649 return cJSON_ParseOut; 650} 651 652/* [NAPI_GEN]:对应cJSON.h中:cJSON_Parse的napi方法, 653 * 输入:value: const char *; 654 * 输出:cJSON * 655 */ 656napi_value KH418_cJSON_Parse(napi_env env, napi_callback_info info) 657{ 658 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "KH418_cJSON_Parse", "KH418_cJSON_Parse begins"); 659 napi_status status; 660 /* [NAPI_GEN]: Node.js在其N-API中用来提供错误的扩展信息的结构体,结构体包含以下字段 661 * error_message: 一个指向错误详细字符串的指针,提供了关于错误的文本描述 662 * engin_reserved: 一个保留给Js引擎使用的指针 663 * error_code: 错误码,指示了错误的种类,比如napi_pending_exception表示有一个JavaScript异常未被清理。 664 * engine_error_code:一个引擎特定的错误码,为引擎实现保留,具体含义依赖于使用的JavaScript引擎。 665 * error_message_len:错误消息字符串的长度。 666 */ 667 const napi_extended_error_info *extended_error_info; 668 /* [NAPI_GEN]: tag: 日志打印标签*/ 669 const char *tag = "[KH418_cJSON_Parse]"; 670 /* [NAPI_GEN]: get function param in*/ 671 /* [NAPI_GEN]: argc:js传入的参数个数 */ 672 size_t argc = PARAMS1; 673 /* [NAPI_GEN]: args: 一个数组,保存js传入的参数 */ 674 napi_value args[PARAMS1] = {nullptr}; 675 /* [NAPI_GEN]: napi_get_cb_info用于获取JS调用该函数时所传递的参数、接收参数的个数以及'this'的值 676 * env: 当前环境的句柄,代表当前的Node.js环境 677 * info: 回调信息句柄,代表当前回调的上下文 678 * argc: 指向size_t的指针,开始应包含可接受的max参数数量,函数返回时,它将包含实际传递的参数数量 679 * args: 一个足够大的数组,用于接收传递给回调函数的所有js参数。数组的大小应至少与argc传入的值一样大。 680 * this_arg: 如果不是NULL,则返回js回调中this的值 681 * data: 如果不是NULL,则返回与回调函数关联的任何可选数据。通常用于传递在创建函数时指定的静态数据 682 */ 683 status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 684 if(status != napi_ok) { 685 /* [NAPI_GEN]: 错误处理*/ 686 getErrMessage(status, env,extended_error_info, "napi_get_cb_info", tag); 687 return nullptr; 688 } 689 /* [NAPI_GEN]: 从args数组中获取入参 */ 690 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "KH418_cJSON_Parse", "KH418_cJSON_Parse get param info begins"); 691 napi_valuetype valuetypevalue; 692 /* [NAPI_GEN]: 获取入参类型,第PARAMS0个入参 693 * env: N-API环境的句柄,表示当前的上下文 694 * value: 要检查类型的js值 695 * result: 是一个指针,指向napi_valuetype枚举的值,函数会将结果存储在这里 696 */ 697 status = napi_typeof(env, args[PARAMS0], &valuetypevalue); 698 if (status != napi_ok) { 699 getErrMessage(status, env, extended_error_info, "napi_typeof", tag); 700 return nullptr; 701 } 702 size_t strSizePARAMS0 = 0; 703 /* [NAPI_GEN]: napi_get_value_string_utf8用于将Js字符串转换为UTF-8编码的C字符串 704 * env: N-API环境的句柄,表示当前的上下文 705 * value: 要转换的JavaScript字符串 706 * buf: 用于存储结果的字符数组的指针 707 * bufsize: 缓冲区大小,以字节为单位 708 * result: 转换后的字符串的字节长度(不包括空终止符)。若干buf是NULL,则返回所需的缓冲区大小(包括空终止符) 709 */ 710 /* [NAPI_GEN]: buf参数是NULL时,用于获取所需缓冲区大小*/ 711 status = napi_get_value_string_utf8(env, args[PARAMS0], NULL, 0, &strSizePARAMS0); 712 if (status != napi_ok) { 713 getErrMessage(status, env, extended_error_info, "get value string", tag); 714 return nullptr; 715 } 716 char *valueIn = new char[strSizePARAMS0 + 1]; 717 /* [NAPI_GEN]: 用于获取字符串*/ 718 status = napi_get_value_string_utf8(env, args[PARAMS0], valueIn, strSizePARAMS0 + 1, &strSizePARAMS0); 719 if (status != napi_ok) { 720 getErrMessage(status, env, extended_error_info, "get value string", tag); 721 delete[] valueIn; 722 return nullptr; 723 } 724 // delete[] valueIn; // remember to delete memory 725 726 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "KH418_cJSON_Parse", "KH418_cJSON_Parse get param info ends"); 727 728 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "KH418_cJSON_Parse", "KH418_cJSON_Parse get return info begins"); 729 // Todo: add business logic. 在这前后代码为框架所生成 730 cJSON *json = cJSON_Parse(valueIn); 731 if (json == nullptr) { 732 return nullptr; 733 } 734 cJSON *jsonChild = nullptr; 735 if (json != nullptr) { 736 jsonChild = json->child; 737 } 738 cJSON *jsonNext = nullptr; 739 if (jsonChild != nullptr) { 740 jsonNext = jsonChild->next; 741 } 742 delete[] valueIn; 743 744 /* [NAPI_GEN]: function return value*/ 745 napi_value cJSON_ParseOut; 746 /* [NAPI_GEN]: 返回值是对象时,需要使用napi_create_object创建一个js的对象与js代码交互 747 * env: 当前环境的句柄 748 * result: 一个napi_value的指针,该指针将被设置为新创建的js对象 749 */ 750 status = napi_create_object(env, &cJSON_ParseOut); 751 if (status != napi_ok) { 752 getErrMessage(status, env, extended_error_info, "napi_create_object", tag); 753 return nullptr; 754 } 755 cJSON_ParseOut = getCjsonparseOut1(env, jsonNext, cJSON_ParseOut); 756 cJSON_ParseOut = getCjsonparseOut2(env, json, jsonChild, cJSON_ParseOut); 757 cJSON_ParseOut = getCjsonparseOut3(env, json, cJSON_ParseOut); 758 cJSON_ParseOut = getCjsonparseOut4(env, json, cJSON_ParseOut); 759 760 cJSON_Delete(json); 761 762 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "KH418_cJSON_Parse", "KH418_cJSON_Parse get return info ends"); 763 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "KH418_cJSON_Parse", "KH418_cJSON_Parse ends"); 764 return cJSON_ParseOut; 765 766} 767 768``` 769 770### 测试调用 771 772以cjson_parse接口为例 773 7741.在cJsonSampleTest/entry/src/ohosTest/ets/test/CjsonTest/CjsonTest.test.ets测试集中修改KH418_cJSON_Parse方法的测试用例 775 776 777 778``` 779 it('KH418_cJSON_Parse', 0, () => { 780 // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. 781 hilog.info(0x0000, 'testTag', '%{public}s', 'it KH418_cJSON_Parse begin'); 782 // 测试字符串的转换 783 let value = '"helloworld"' 784 let result: testNapi.cJSON = testNapi.KH418_cJSON_Parse(value); 785 // 测试数字的转换 786 let value2 = '1.8' 787 let result2: testNapi.cJSON = testNapi.KH418_cJSON_Parse(value2); 788 // 测试数组的转换 789 let value3 = '["a","b"]' 790 let result3: testNapi.cJSON = testNapi.KH418_cJSON_Parse(value3); 791 // 测试对象的转换 792 let value4 = '{"name":"JohnDoe","age":18}' 793 let result4: testNapi.cJSON = testNapi.KH418_cJSON_Parse(value4); 794 795 // 打印结果 796 console.info("Test NAPI KH418_cJSON_Parse result1: ", JSON.stringify(result)) 797 console.info("Test NAPI KH418_cJSON_Parse result2: ", JSON.stringify(result2)) 798 console.info("Test NAPI KH418_cJSON_Parse result3: ", JSON.stringify(result3)) 799 console.info("Test NAPI KH418_cJSON_Parse result4: ", JSON.stringify(result4)) 800 }) 801``` 802 8032.运行 KH418_cJSON_Parse, 打印结果如下: 804 805``` 806I Test NAPI KH418_cJSON_Parse result1: {"next":{},"prev":{},"child":{},"type":16,"valuestring":"helloworld","valueint":0,"valuedouble":0,"string":""} 807I Test NAPI KH418_cJSON_Parse result2: {"next":{},"prev":{},"child":{},"type":8,"valuestring":"","valueint":1,"valuedouble":1.8,"string":""} 808I Test NAPI KH418_cJSON_Parse result3: {"next":{"valuestring":"b","string":"","type":16,"valueint":0,"valuedouble":0},"prev":{},"child":{"valuestring":"a","string":"","type":16,"valueint":0,"valuedouble":0},"type":32,"valuestring":"","valueint":0,"valuedouble":0,"string":""} 809I Test NAPI KH418_cJSON_Parse result4: {"next":{"valuestring":"","string":"age","type":8,"valueint":18,"valuedouble":18},"prev":{},"child":{"valuestring":"JohnDoe","string":"name","type":16,"valueint":0,"valuedouble":0},"type":64,"valuestring":"","valueint":0,"valuedouble":0,"string":""} 810``` 811 812 813 814