1/* 2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15const { writeFile } = require("../tools/FileRW"); 16const re = require("../tools/re"); 17 18let xNapiToolH = `\ 19#ifndef CC_TOOL_H 20#define CC_TOOL_H 21 22#include <node_api.h> 23#include <string> 24#include <memory> 25#include <map> 26#include <any> 27#include <vector> 28#include <cmath> 29 30struct AsyncFunc 31{ 32 napi_env env_; 33 napi_ref funcRef_; 34 napi_ref thisVarRef_; 35}; 36 37class XNapiTool 38{ 39public: 40 void RegistAsyncFunc(std::string name, napi_value func); 41 void UnregistAsyncFunc(std::string name); 42 static std::map<std::string, AsyncFunc> asyncFuncs_; 43 static void CallAsyncFunc(AsyncFunc * pAsyncFuncs, napi_value ret); 44 45 using CallbackFunction = void (*)(XNapiTool *pxt, void *data); 46 using RELEASE_INSTANCE = void (*)(void *p); 47 static napi_value UndefinedValue(napi_env env); 48 const uint32_t DEFAULT_ARG_COUNT = 8; 49 napi_value UndefinedValue(); 50 51 napi_value CreateSubObject(napi_value parent, const char *name); 52 void DefineFunction(const char *funcName, napi_callback callback, napi_value dest = nullptr); 53 void DefineClass(const char *className, napi_callback constructorFunc, 54 std::map<const char *, std::map<const char *, napi_callback>> &valueList, std::map<const char *, 55 napi_callback> &funcList, napi_value dest = nullptr); 56 57 58 void SetEnumProperty(napi_value dstObj, const char *propName, const std::any objValue); 59 void CreateEnumObject(const char *enumName, std::map<const char *, std::any> enumMap); 60 61 XNapiTool(napi_env env, napi_callback_info info); 62 XNapiTool(napi_env env, napi_value exports); 63 ~XNapiTool(); 64 65 bool SwapJs2CBool(napi_value value); 66 int32_t SwapJs2CInt32(napi_value value); 67 uint32_t SwapJs2CUint32(napi_value value); 68 int64_t SwapJs2CInt64(napi_value value); 69 double_t SwapJs2CDouble(napi_value value); 70 size_t SwapJs2CUtf8(napi_value value, std::string &str); 71 72 napi_value SwapC2JsBool(bool value); 73 napi_value SwapC2JsInt32(int32_t value); 74 napi_value SwapC2JsUint32(uint32_t value); 75 napi_value SwapC2JsInt64(int64_t value); 76 napi_value SwapC2JsDouble(double_t value); 77 napi_value SwapC2JsUtf8(const char *value); 78 79 napi_value GetArgv(uint32_t p); 80 uint32_t GetArgc(); 81 82 napi_value GetValueProperty(napi_value value, const char *propertyName); 83 napi_value SetValueProperty(napi_value &value, const char *propertyName, napi_value property); 84 85 napi_value CreateArray(napi_value &value); 86 uint32_t GetArrayLength(napi_value value); 87 napi_value GetArrayElement(napi_value value, uint32_t p); 88 napi_value SetArrayElement(napi_value &value, uint32_t p, napi_value ele); 89 90 uint32_t GetMapLength(napi_value value); 91 napi_value GetMapElementName(napi_value value, uint32_t p); 92 napi_value GetMapElementValue(napi_value value, const char * p); 93 napi_value SetMapElement(napi_value &value, const char * ele_key, napi_value ele_value); 94 95 std::string GetUnionType(napi_value object); 96 97 std::string GetAnyType(napi_value object); 98 std::string GetAnyArrayType(napi_value object); 99 void SetAnyValue(std::string &any_type, napi_value argv, std::any &any); 100 void GetAnyValue (std::string any_type, napi_value &result, std::any any); 101 void GetObjectValue(napi_value &result, std::map<std::string, std::any> valueIn); 102 103 napi_value SyncCallBack(napi_value func, size_t argc, napi_value *args); 104 105 napi_value StartAsync(CallbackFunction pe, void *data, CallbackFunction pc, napi_value func = nullptr); 106 void FinishAsync(size_t argc, napi_value *args); 107 108 bool IsFailed() 109 { 110 return bFailed_; 111 } 112 napi_value GetError() 113 { 114 return error_; 115 } 116 napi_env GetEnv() 117 { 118 return env_; 119 } 120 121 napi_value tmp_value; 122 123 // create code related class 124public: 125 static void WrapFinalize(napi_env env, void *data, void *hint); 126 void ReleaseInstance(); 127 napi_value WrapInstance(void *instance, RELEASE_INSTANCE ri); 128 void *UnWarpInstance(); 129 130 void SetAsyncInstance(void *p); 131 void *GetAsyncInstance(); 132 133private: 134 napi_env env_; 135 napi_value exports_; 136 137 // analyze params 138 napi_value argv_[8]; 139 size_t argc_size; 140 napi_value thisVar_; 141 void *data_; 142 143 // error message 144 napi_value error_; 145 bool bFailed_; 146 bool CheckFailed(bool b, const char *errStr); 147 bool CheckValueType(napi_value value, napi_valuetype type); 148 149 // asynchronous call related code 150 static void AsyncExecute(napi_env env, void *p); 151 void AsyncExecuteFunction(); 152 static void AsyncComplete(napi_env env, napi_status status, void *p); 153 void AsyncCompleteFunction(); 154 napi_ref callbackFunc_; 155 napi_async_work work_; 156 bool asyncNeedRelease_; 157 CallbackFunction executeFunction_; 158 CallbackFunction completeFunction_; 159 void *valueData_; 160 napi_deferred deferred_; 161 enum class AsyncMode 162 { 163 NONE, 164 CALLBACK, 165 PROMISE, 166 }; 167 AsyncMode asyncMode_; 168 169private: 170 napi_ref wrapper_; 171 void *pInstance_; 172 RELEASE_INSTANCE releaseInstance_; 173 void *asyncInstance_; 174}; 175 176#endif 177` 178 179let xNapiToolCpp = ` 180 181#include "tool_utility.h" 182#include <cassert> 183#include <cstring> 184#include <uv.h> 185 186#define CC_ASSERT(btrue) \\ 187 if (!(btrue)) { \\ 188 \\ 189 } \\ 190 assert(btrue); 191 192XNapiTool::XNapiTool(napi_env env, napi_callback_info info) 193{ 194 env_ = env; 195 bFailed_ = false; 196 executeFunction_ = nullptr; 197 completeFunction_ = nullptr; 198 valueData_ = nullptr; 199 asyncNeedRelease_ = false; 200 asyncMode_ = AsyncMode::NONE; 201 pInstance_ = nullptr; 202 releaseInstance_ = nullptr; 203 wrapper_ = nullptr; 204 205 argc_size = DEFAULT_ARG_COUNT; 206 207 napi_status result_status = napi_get_cb_info(env, info, &argc_size, argv_, &thisVar_, &data_); 208 CheckFailed(result_status == napi_ok, "get args fail"); 209} 210 211XNapiTool::XNapiTool(napi_env env, napi_value exports) 212{ 213 env_ = env; 214 exports_ = exports; 215 216 asyncMode_ = AsyncMode::NONE; 217 wrapper_ = nullptr; 218} 219 220XNapiTool::~XNapiTool() 221{ 222 if (asyncMode_ == AsyncMode::PROMISE) { 223 napi_status result_status = napi_delete_async_work(env_, work_); 224 CC_ASSERT(result_status == napi_ok); 225 } 226 if (asyncMode_ == AsyncMode::CALLBACK) { 227 napi_status result_status = napi_delete_reference(env_, callbackFunc_); 228 CC_ASSERT(result_status == napi_ok); 229 result_status = napi_delete_async_work(env_, work_); 230 CC_ASSERT(result_status == napi_ok); 231 } 232 if (wrapper_ != nullptr) { 233 napi_status result_status = napi_delete_reference(env_, wrapper_); 234 CC_ASSERT(result_status == napi_ok); 235 } 236} 237 238bool XNapiTool::SwapJs2CBool(napi_value value) 239{ 240 bool result; 241 napi_status result_status = napi_get_value_bool(env_, value, &result); 242 if (CheckFailed(result_status == napi_ok, "swap_js_2_c_bool fail")) 243 return -1; 244 return result; 245} 246 247napi_value XNapiTool::GetArgv(uint32_t p) 248{ 249 if (CheckFailed(p < argc_size, "GetArgv失败")) 250 return error_; 251 252 return argv_[p]; 253} 254 255uint32_t XNapiTool::GetArgc() 256{ 257 return argc_size; 258} 259 260napi_value XNapiTool::GetValueProperty(napi_value value, const char *propertyName) 261{ 262 napi_value result; 263 napi_status result_status = napi_get_named_property(env_, value, propertyName, &result); 264 CC_ASSERT(result_status == napi_ok); 265 return result; 266} 267 268napi_value XNapiTool::SetValueProperty(napi_value &value, const char *propertyName, napi_value property) 269{ 270 napi_status result_status; 271 if (value == nullptr) { 272 result_status = napi_create_object(env_, &value); 273 CC_ASSERT(result_status == napi_ok); 274 } 275 result_status = napi_set_named_property(env_, value, propertyName, property); 276 CC_ASSERT(result_status == napi_ok); 277 return value; 278} 279 280napi_value XNapiTool::CreateArray(napi_value &value) 281{ 282 if (value == nullptr) { 283 napi_status result_status = napi_create_array(env_, &value); 284 CC_ASSERT(result_status == napi_ok); 285 } 286 return value; 287} 288 289uint32_t XNapiTool::GetArrayLength(napi_value value) 290{ 291 uint32_t ret; 292 napi_status result_status = napi_get_array_length(env_, value, &ret); 293 CC_ASSERT(result_status == napi_ok); 294 return ret; 295} 296 297napi_value XNapiTool::GetArrayElement(napi_value value, uint32_t p) 298{ 299 napi_value result; 300 napi_status result_status = napi_get_element(env_, value, p, &result); 301 CC_ASSERT(result_status == napi_ok); 302 return result; 303} 304 305napi_value XNapiTool::SetArrayElement(napi_value &value, uint32_t p, napi_value ele) 306{ 307 napi_status result_status; 308 if (value == nullptr) { 309 result_status = napi_create_array(env_, &value); 310 CC_ASSERT(result_status == napi_ok); 311 } 312 result_status = napi_set_element(env_, value, p, ele); 313 CC_ASSERT(result_status == napi_ok); 314 return value; 315} 316 317uint32_t XNapiTool::GetMapLength(napi_value value) 318{ 319 napi_value name_result; 320 napi_get_property_names(env_, value, &name_result); 321 uint32_t ret; 322 napi_status result_status = napi_get_array_length(env_, name_result, &ret); 323 CC_ASSERT(result_status == napi_ok); 324 return ret; 325} 326 327napi_value XNapiTool::GetMapElementName(napi_value value, uint32_t p) 328{ 329 napi_value name_result; 330 napi_get_property_names(env_, value, &name_result); 331 napi_value result; 332 napi_status result_status = napi_get_element(env_, name_result, p, &result); 333 CC_ASSERT(result_status == napi_ok); 334 return result; 335} 336 337napi_value XNapiTool::GetMapElementValue(napi_value value, const char * utf8Name) 338{ 339 napi_value result; 340 napi_status result_status = napi_get_named_property(env_, value, utf8Name, &result); 341 CC_ASSERT(result_status == napi_ok); 342 return result; 343} 344 345napi_value XNapiTool::SetMapElement(napi_value &value, const char * ele_key, napi_value ele_value) 346{ 347 napi_status result_status; 348 if (value == nullptr) { 349 result_status = napi_create_object(env_, &value); 350 CC_ASSERT(result_status == napi_ok); 351 } 352 result_status = napi_set_named_property(env_, value, ele_key, ele_value); 353 CC_ASSERT(result_status == napi_ok); 354 return value; 355} 356 357std::string XNapiTool::GetAnyType(napi_value object){ 358 napi_valuetype result; 359 napi_typeof(env_, object, &result); 360 if (result == napi_string) { 361 return "string"; 362 } else if (result == napi_number) { 363 return "number"; 364 } else if (result == napi_boolean) { 365 return "boolean"; 366 } else if (result == napi_object) { 367 bool is_array; 368 napi_is_array(env_, object, &is_array); 369 if (is_array) { 370 napi_value arr_value_result; 371 napi_valuetype arr_type_result; 372 napi_get_element (env_, object, 0, &arr_value_result); 373 napi_typeof(env_, arr_value_result, &arr_type_result); 374 if (arr_type_result == napi_string) { 375 return "arr_string"; 376 } else if (arr_type_result == napi_number) { 377 return "arr_number"; 378 } else if (arr_type_result == napi_boolean) { 379 return "arr_boolean"; 380 } else { 381 return nullptr; 382 } 383 } 384 napi_value obj_name_value; 385 napi_value obj_name_result; 386 napi_valuetype obj_name_type; 387 std::string obj_name_string; 388 napi_get_property_names (env_, object, &obj_name_value); 389 napi_get_element (env_, obj_name_value, 0, &obj_name_result); 390 napi_typeof(env_, obj_name_result, &obj_name_type); 391 if (obj_name_type == napi_string) { 392 napi_value obj_value; 393 napi_valuetype obj_value_type; 394 SwapJs2CUtf8(obj_name_result, obj_name_string); 395 napi_get_named_property (env_, object, obj_name_string.c_str(), &obj_value); 396 napi_typeof(env_, obj_value, &obj_value_type); 397 if (obj_value_type == napi_string) { 398 return "map_string"; 399 } else if (obj_value_type == napi_number) { 400 return "map_number"; 401 } else if (obj_value_type == napi_boolean) { 402 return "map_boolean"; 403 } else { 404 return nullptr; 405 } 406 } 407 return nullptr; 408 } else { 409 return nullptr; 410 } 411} 412 413std::string XNapiTool::GetAnyArrayType(napi_value object){ 414 napi_valuetype result; 415 napi_typeof(env_, object, &result); 416 if (result == napi_object) { 417 bool is_array; 418 napi_is_array(env_, object, &is_array); 419 if (is_array) { 420 napi_value arr_value_result; 421 napi_valuetype arr_type_result; 422 napi_get_element (env_, object, 0, &arr_value_result); 423 napi_typeof(env_, arr_value_result, &arr_type_result); 424 if (arr_type_result == napi_string) { 425 return "arr_string"; 426 } else if (arr_type_result == napi_number) { 427 return "arr_number"; 428 } else if (arr_type_result == napi_boolean) { 429 return "arr_boolean"; 430 } else { 431 return nullptr; 432 } 433 } 434 return nullptr; 435 } 436 return nullptr; 437} 438 439void XNapiTool::SetAnyValue(std::string &any_type, napi_value argv, std::any &any) 440{ 441 if (any_type == "string") { 442 std::string any_string; 443 SwapJs2CUtf8(argv, any_string); 444 any = any_string; 445 return; 446 } else if (any_type == "boolean") { 447 bool any_bool; 448 any_bool = SwapJs2CBool(argv); 449 any = any_bool; 450 return; 451 } else if (any_type == "number") { 452 std::uint32_t any_number; 453 any_number = SwapJs2CInt32(argv); 454 any = any_number; 455 return; 456 } else if (any_type.substr(0,3) == "arr") { 457 uint32_t len=GetArrayLength(argv); 458 if (any_type == "arr_string") { 459 std::vector<std::string> any_arr_string; 460 for(uint32_t i=0;i<len;i++) { 461 std::string tt; 462 SwapJs2CUtf8(GetArrayElement(argv, i), tt); 463 any_arr_string.push_back(tt); 464 } 465 any = any_arr_string; 466 return; 467 } else if (any_type == "arr_number") { 468 std::vector<std::uint32_t> any_arr_number; 469 for(uint32_t i=0;i<len;i++) { 470 uint32_t tt; 471 tt = SwapJs2CInt32(GetArrayElement(argv, i)); 472 any_arr_number.push_back(tt); 473 } 474 any = any_arr_number; 475 return; 476 } else if (any_type == "arr_boolean") { 477 std::vector<bool> any_arr_boolean; 478 for(uint32_t i=0;i<len;i++) { 479 bool tt; 480 tt = SwapJs2CBool(GetArrayElement(argv,i)); 481 any_arr_boolean.push_back(tt); 482 } 483 any = any_arr_boolean; 484 return; 485 } 486 return; 487 } else if (any_type.substr(0,3) == "map") { 488 uint32_t len = GetMapLength(argv); 489 if (any_type == "map_string") { 490 std::map<std::string,std::string> any_map_string; 491 for(uint32_t i=0;i<len;i++) { 492 std::string tt1; 493 std::string tt2; 494 SwapJs2CUtf8(GetMapElementName(argv,i), tt1); 495 SwapJs2CUtf8(GetMapElementValue(argv,tt1.c_str()), tt2); 496 any_map_string.insert(std::make_pair(tt1, tt2)); 497 } 498 any = any_map_string; 499 return; 500 } else if (any_type == "map_number") { 501 std::map<std::string,std::uint32_t> any_map_number; 502 for(uint32_t i=0;i<len;i++) { 503 std::string tt1; 504 uint32_t tt2; 505 SwapJs2CUtf8(GetMapElementName(argv,i), tt1); 506 tt2 = SwapJs2CInt32(GetMapElementValue(argv,tt1.c_str())); 507 any_map_number.insert(std::make_pair(tt1, tt2)); 508 } 509 any = any_map_number; 510 return; 511 } else if (any_type == "map_boolean") { 512 std::map<std::string,bool> any_map_boolean; 513 for(uint32_t i=0;i<len;i++) { 514 std::string tt1; 515 bool tt2; 516 SwapJs2CUtf8(GetMapElementName(argv,i), tt1); 517 tt2 = SwapJs2CBool(GetMapElementValue(argv,tt1.c_str())); 518 any_map_boolean.insert(std::make_pair(tt1, tt2)); 519 } 520 any = any_map_boolean; 521 return; 522 } 523 return; 524 } 525 return; 526} 527 528void XNapiTool::GetAnyValue (std::string any_type, napi_value &result, std::any any) 529{ 530 result = nullptr; 531 if (any_type == "string") { 532 std::string any_string = std::any_cast<std::string>(any); 533 result = SwapC2JsUtf8(any_string.c_str()); 534 return; 535 } else if (any_type == "boolean") { 536 bool any_bool = std::any_cast<bool>(any); 537 result = SwapC2JsBool(any_bool); 538 return; 539 } else if (any_type == "number") { 540 std::uint32_t any_number = std::any_cast<std::uint32_t>(any); 541 if (typeid(any_number) == typeid(int32_t)) 542 result = SwapC2JsInt32(any_number); 543 else if (typeid(any_number) == typeid(uint32_t)) 544 result = SwapC2JsUint32(any_number); 545 else if (typeid(any_number) == typeid(int64_t)) 546 result = SwapC2JsInt64(any_number); 547 else if (typeid(any_number) == typeid(double_t)) 548 result = SwapC2JsDouble(any_number); 549 return; 550 } else if (any_type.substr(0,3) == "arr") { 551 result = nullptr; 552 if (any_type == "arr_string") { 553 std::vector<std::string> any_arr_string = std::any_cast<std::vector<std::string>>(any); 554 uint32_t len=any_arr_string.size(); 555 for(uint32_t i=0;i<len;i++) { 556 napi_value tnv = nullptr; 557 tnv = SwapC2JsUtf8(any_arr_string[i].c_str()); 558 SetArrayElement(result, i, tnv); 559 } 560 return; 561 } else if (any_type == "arr_number") { 562 std::vector<std::uint32_t> any_arr_number = std::any_cast<std::vector<std::uint32_t>>(any); 563 uint32_t len=any_arr_number.size(); 564 for(uint32_t i=0;i<len;i++) { 565 napi_value tnv = nullptr; 566 if (typeid(any_arr_number[i]) == typeid(int32_t)){ 567 tnv = SwapC2JsInt32(any_arr_number[i]); 568 } 569 else if (typeid(any_arr_number[i]) == typeid(uint32_t)){ 570 tnv = SwapC2JsUint32(any_arr_number[i]); 571 } 572 else if (typeid(any_arr_number[i]) == typeid(int64_t)){ 573 tnv = SwapC2JsInt64(any_arr_number[i]); 574 } 575 else if (typeid(any_arr_number[i]) == typeid(double_t)){ 576 tnv = SwapC2JsDouble(any_arr_number[i]); 577 } 578 SetArrayElement(result, i, tnv); 579 } 580 return; 581 } else if (any_type == "arr_boolean") { 582 std::vector<bool> any_arr_boolean = std::any_cast<std::vector<bool>>(any); 583 uint32_t len=any_arr_boolean.size(); 584 for(uint32_t i=0;i<len;i++) { 585 napi_value tnv = nullptr; 586 tnv = SwapC2JsBool(any_arr_boolean[i]); 587 SetArrayElement(result, i, tnv); 588 } 589 return; 590 } 591 return; 592 } else if (any_type.substr(0,3) == "map") { 593 if (any_type == "map_string") { 594 std::map<std::string,std::string> any_map_string = std::any_cast<std::map<std::string,std::string>>(any); 595 for (auto i = any_map_string.begin(); i != any_map_string.end(); i++) 596 { 597 const char * tnv1; 598 napi_value tnv2 = nullptr; 599 tnv1 = (i -> first).c_str(); 600 tnv2 = SwapC2JsUtf8(i->second.c_str()); 601 SetMapElement(result, tnv1, tnv2); 602 } 603 return; 604 } else if (any_type == "map_number") { 605 std::map<std::string,std::uint32_t> any_map_number = 606 std::any_cast<std::map<std::string,std::uint32_t>>(any); 607 for (auto i = any_map_number.begin(); i != any_map_number.end(); i++) 608 { 609 const char * tnv1; 610 napi_value tnv2 = nullptr; 611 tnv1 = (i -> first).c_str(); 612 if (typeid(i->second) == typeid(int32_t)){ 613 tnv2 = SwapC2JsInt32(i->second); 614 } 615 else if (typeid(i->second) == typeid(uint32_t)){ 616 tnv2 = SwapC2JsUint32(i->second); 617 } 618 else if (typeid(i->second) == typeid(int64_t)){ 619 tnv2 = SwapC2JsInt64(i->second); 620 } 621 else if (typeid(i->second) == typeid(double_t)){ 622 tnv2 = SwapC2JsDouble(i->second); 623 } 624 SetMapElement(result, tnv1, tnv2); 625 } 626 return; 627 } else if (any_type == "map_boolean") { 628 std::map<std::string,bool> any_map_boolean = std::any_cast<std::map<std::string,bool>>(any); 629 for (auto i = any_map_boolean.begin(); i != any_map_boolean.end(); i++) 630 { 631 const char * tnv1; 632 napi_value tnv2 = nullptr; 633 tnv1 = (i -> first).c_str(); 634 tnv2 = SwapC2JsBool(i->second); 635 SetMapElement(result, tnv1, tnv2); 636 } 637 return; 638 } 639 return; 640 } 641 return; 642} 643 644std::string XNapiTool::GetUnionType(napi_value object){ 645 napi_valuetype result; 646 napi_typeof(env_, object, &result); 647 if (result == napi_string) { 648 return "string"; 649 } else if (result == napi_number) { 650 return "number"; 651 } else if (result == napi_boolean) { 652 return "boolean"; 653 } else { 654 return nullptr; 655 } 656} 657 658void XNapiTool::GetObjectValue(napi_value &result, std::map<std::string, std::any> valueIn) 659{ 660 //napi_value result = nullptr; 661 napi_create_object(env_, &result); 662 663 /*std::map<std::string,std::uint32_t> any_map_number = 664 std::any_cast<std::map<std::string, std::uint32_t>>(valueIn); 665 */ 666 667 for (auto i = valueIn.begin(); i != valueIn.end(); i++) 668 { 669 const char * tnv1; 670 std::any anyValue; 671 napi_value tnv2 = nullptr; 672 tnv1 = (i -> first).c_str(); 673 674 if (typeid(i->second) == typeid(int32_t)){ 675 tnv2 = SwapC2JsInt32(std::any_cast<int32_t>(i->second)); 676 } 677 else if (typeid(i->second) == typeid(uint32_t)){ 678 tnv2 = SwapC2JsUint32(std::any_cast<uint32_t>(i->second)); 679 } 680 else if (typeid(i->second) == typeid(int64_t)){ 681 tnv2 = SwapC2JsInt64(std::any_cast<int64_t>(i->second)); 682 } 683 else if (typeid(i->second) == typeid(double_t)){ 684 tnv2 = SwapC2JsDouble(std::any_cast<double_t>(i->second)); 685 } 686 else if (typeid(i->second) == typeid(char *)){ 687 tnv2 = SwapC2JsUtf8(std::any_cast<char *>(i->second)); 688 } 689 else if (typeid(i->second) == typeid(bool)){ 690 tnv2 = SwapC2JsBool(std::any_cast<bool>(i->second)); 691 } 692 693 SetMapElement(result, tnv1, tnv2); 694 } 695 return; 696} 697 698bool XNapiTool::CheckFailed(bool b, const char *errStr) 699{ 700 if (bFailed_) { 701 return true; 702 } 703 if (b) { 704 return false; 705 } 706 707 napi_value errCode = nullptr; 708 napi_value errMessage = nullptr; 709 710 napi_create_string_utf8(env_, "x_tool", strlen("x_tool"), &errCode); 711 napi_create_string_utf8(env_, errStr, strlen(errStr), &errMessage); 712 napi_create_error(env_, errCode, errMessage, &error_); 713 printf("tool_utility err : %s\\n", errStr); 714 715 bFailed_ = true; 716 return true; 717} 718 719int32_t XNapiTool::SwapJs2CInt32(napi_value value) 720{ 721 int32_t result; 722 napi_status result_status = napi_get_value_int32(env_, value, &result); 723 if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail")) 724 return -1; 725 return result; 726} 727 728uint32_t XNapiTool::SwapJs2CUint32(napi_value value) 729{ 730 uint32_t result; 731 napi_status result_status = napi_get_value_uint32(env_, value, &result); 732 if (CheckFailed(result_status == napi_ok, "swap_js_2_c_uint32 fail")) 733 return -1; 734 return result; 735} 736 737int64_t XNapiTool::SwapJs2CInt64(napi_value value) 738{ 739 int64_t result; 740 napi_status result_status = napi_get_value_int64(env_, value, &result); 741 if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail")) 742 return -1; 743 return result; 744} 745 746double_t XNapiTool::SwapJs2CDouble(napi_value value) 747{ 748 double_t result; 749 napi_status result_status = napi_get_value_double(env_, value, &result); 750 if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail")) 751 return -1; 752 return result; 753} 754 755size_t XNapiTool::SwapJs2CUtf8(napi_value value, std::string &str) 756{ 757 char buf[1024]; 758 size_t result; 759 napi_status result_status = napi_get_value_string_utf8(env_, value, buf, 1024, &result); 760 if (CheckFailed(result_status == napi_ok, "napi_get_value_string_utf8 fail")) 761 return -1; 762 str = buf; 763 return result; 764} 765 766napi_value XNapiTool::SwapC2JsBool(bool value) 767{ 768 napi_value result; 769 napi_status result_status = napi_get_boolean(env_, value, &result); 770 CC_ASSERT(result_status == napi_ok); 771 return result; 772} 773 774napi_value XNapiTool::SwapC2JsInt32(int32_t value) 775{ 776 napi_value result; 777 napi_status result_status = napi_create_int32(env_, value, &result); 778 CC_ASSERT(result_status == napi_ok); 779 return result; 780} 781 782napi_value XNapiTool::SwapC2JsUint32(uint32_t value) 783{ 784 napi_value result; 785 napi_status result_status = napi_create_uint32(env_, value, &result); 786 CC_ASSERT(result_status == napi_ok); 787 return result; 788} 789 790napi_value XNapiTool::SwapC2JsInt64(int64_t value) 791{ 792 napi_value result; 793 napi_status result_status = napi_create_int64(env_, value, &result); 794 CC_ASSERT(result_status == napi_ok); 795 return result; 796} 797 798napi_value XNapiTool::SwapC2JsDouble(double_t value) 799{ 800 napi_value result; 801 napi_status result_status = napi_create_double(env_, value, &result); 802 CC_ASSERT(result_status == napi_ok); 803 return result; 804} 805 806napi_value XNapiTool::SwapC2JsUtf8(const char *value) 807{ 808 napi_value result; 809 napi_status result_status = napi_create_string_utf8(env_, value, NAPI_AUTO_LENGTH, &result); 810 CC_ASSERT(result_status == napi_ok); 811 return result; 812} 813 814bool XNapiTool::CheckValueType(napi_value value, napi_valuetype type) 815{ 816 napi_valuetype valueType; 817 napi_status result_status = napi_typeof(env_, value, &valueType); 818 CC_ASSERT(result_status == napi_ok); 819 if (CheckFailed(valueType == type, "传入参数类型不是回调函数")) 820 return false; 821 return true; 822} 823 824napi_value XNapiTool::SyncCallBack(napi_value func, size_t argc, napi_value *args) 825{ 826 napi_value cb_result; 827 napi_status result_status = napi_call_function(env_, thisVar_, func, argc, args, &cb_result); 828 CC_ASSERT(result_status == napi_ok); 829 return cb_result; 830} 831 832void XNapiTool::AsyncExecuteFunction() 833{ 834 if (executeFunction_ != nullptr) { 835 executeFunction_(this, valueData_); 836 } 837} 838void XNapiTool::AsyncExecute(napi_env env, void *p) 839{ 840 XNapiTool *pxt = (XNapiTool *)p; 841 pxt->AsyncExecuteFunction(); 842} 843void XNapiTool::AsyncCompleteFunction() 844{ 845 if (completeFunction_ != nullptr) { 846 completeFunction_(this, valueData_); 847 } 848} 849void XNapiTool::AsyncComplete(napi_env env, napi_status status, void *p) 850{ 851 XNapiTool *pxt = (XNapiTool *)p; 852 pxt->AsyncCompleteFunction(); 853 delete pxt; 854} 855 856napi_value XNapiTool::StartAsync(CallbackFunction pe, void *data, CallbackFunction pc, napi_value func) 857{ 858 napi_value result; 859 napi_status result_status; 860 861 if (func == nullptr) { 862 // promise 863 result_status = napi_create_promise(env_, &deferred_, &result); 864 CC_ASSERT(result_status == napi_ok); 865 asyncMode_ = AsyncMode::PROMISE; 866 } else { 867 // callback 868 result_status = napi_create_reference(env_, func, 1, &callbackFunc_); 869 CC_ASSERT(result_status == napi_ok); 870 asyncMode_ = AsyncMode::CALLBACK; 871 result = UndefinedValue(env_); 872 } 873 874 asyncNeedRelease_ = true; 875 executeFunction_ = pe; 876 completeFunction_ = pc; 877 valueData_ = data; 878 879 napi_value resourceName = nullptr; 880 result_status = napi_create_string_utf8(env_, "tool_utility", NAPI_AUTO_LENGTH, &resourceName); 881 CC_ASSERT(result_status == napi_ok); 882 result_status = napi_create_async_work(env_, nullptr, resourceName, XNapiTool::AsyncExecute, 883 XNapiTool::AsyncComplete, this, &work_); 884 CC_ASSERT(result_status == napi_ok); 885 result_status = napi_queue_async_work(env_, work_); 886 CC_ASSERT(result_status == napi_ok); 887 888 return result; 889} 890 891void XNapiTool::FinishAsync(size_t argc, napi_value *args) 892{ 893 if (asyncMode_ == AsyncMode::PROMISE) { 894 if (argc > 1) { 895 napi_resolve_deferred(env_, deferred_, args[1]); 896 } else { 897 napi_reject_deferred(env_, deferred_, SwapC2JsUtf8("promise fail")); 898 } 899 return; 900 } 901 napi_value result = 0; 902 napi_value cb = 0; 903 904 napi_status result_status = napi_get_reference_value(env_, callbackFunc_, &cb); 905 CC_ASSERT(result_status == napi_ok); 906 result_status = napi_call_function(env_, thisVar_, cb, argc, args, &result); 907 CC_ASSERT(result_status == napi_ok); 908} 909 910napi_value XNapiTool::UndefinedValue(napi_env env) 911{ 912 napi_value result; 913 napi_get_undefined(env, &result); 914 return result; 915} 916 917napi_value XNapiTool::UndefinedValue() 918{ 919 napi_value result; 920 napi_get_undefined(env_, &result); 921 return result; 922} 923 924napi_value XNapiTool::CreateSubObject(napi_value parent, const char *name) 925{ 926 napi_value result; 927 napi_status result_status = napi_create_object(env_, &result); 928 CC_ASSERT(result_status == napi_ok); 929 930 result_status = napi_set_named_property(env_, parent, name, result); 931 CC_ASSERT(result_status == napi_ok); 932 933 return result; 934} 935 936void XNapiTool::DefineFunction(const char *funcName, napi_callback callback, napi_value dest) 937{ 938 if (dest == nullptr) 939 dest = exports_; 940 napi_property_descriptor descriptor[] = { 941 {funcName, 0, callback, 0, 0, 0, napi_default, 0}}; 942 943 napi_status result_status = napi_define_properties(env_, dest, 1, descriptor); 944 CC_ASSERT(result_status == napi_ok); 945} 946 947void XNapiTool::SetEnumProperty(napi_value dstObj, const char *propName, std::any objValue) 948{ 949 napi_value prop = nullptr; 950 napi_status result_status = napi_invalid_arg; 951 952 if (objValue.type() == typeid(int32_t)) { 953 result_status = napi_create_int32(env_, std::any_cast<int32_t>(objValue), &prop); 954 } else if (objValue.type() == typeid(uint32_t)) { 955 result_status = napi_create_uint32(env_, std::any_cast<uint32_t>(objValue), &prop); 956 } else if (objValue.type() == typeid(int64_t)) { 957 result_status = napi_create_int64(env_, std::any_cast<int64_t>(objValue), &prop); 958 } else if (objValue.type() == typeid(double_t)) { 959 result_status = napi_create_double(env_, std::any_cast<double_t>(objValue), &prop); 960 } else if (objValue.type() == typeid(const char *)){ 961 result_status = napi_create_string_utf8(env_, std::any_cast<const char *>(objValue), NAPI_AUTO_LENGTH, &prop); 962 } 963 964 CC_ASSERT(result_status == napi_ok); 965 result_status = napi_set_named_property(env_, dstObj, propName, prop); 966 CC_ASSERT(result_status == napi_ok); 967} 968 969void XNapiTool::CreateEnumObject(const char *enumName, std::map<const char *, std::any> enumMap) 970{ 971 napi_value enumObj = nullptr; 972 napi_create_object(env_, &enumObj); 973 974 for (auto it = enumMap.begin(); it != enumMap.end(); it++) { 975 SetEnumProperty(enumObj, it->first, it->second); 976 } 977 978 napi_property_descriptor exportEnum[] = { 979 {enumName, 0, 0, 0, 0, enumObj, napi_enumerable, 0} 980 }; 981 napi_status result_status = napi_define_properties(env_, exports_, 1, exportEnum); 982 CC_ASSERT(result_status == napi_ok); 983} 984 985void XNapiTool::DefineClass(const char *className, napi_callback constructorFunc, 986 std::map<const char *, std::map<const char *, napi_callback>> &valueList, 987 std::map<const char *, napi_callback> &funcList, napi_value dest) 988{ 989 if (dest == nullptr) 990 dest = exports_; 991 napi_value tmpClass = nullptr; 992 napi_property_descriptor funcs[funcList.size() + valueList.size()]; 993 994 uint32_t p = 0; 995 for (auto it = valueList.begin(); it != valueList.end(); it++) { 996 funcs[p++] = {it->first, 0, 0, it->second["getvalue"], it->second["setvalue"], 0, napi_default, 0}; // get,set 997 } 998 for (auto it = funcList.begin(); it != funcList.end(); it++) { 999 funcs[p++] = {it->first, 0, it->second, 0, 0, 0, napi_default, 0}; 1000 } 1001 1002 napi_status result_status = napi_define_class(env_, className, NAPI_AUTO_LENGTH, constructorFunc, 1003 nullptr, p, funcs, &tmpClass); 1004 CC_ASSERT(result_status == napi_ok); 1005 1006 result_status = napi_set_named_property(env_, dest, className, tmpClass); 1007 CC_ASSERT(result_status == napi_ok); 1008} 1009 1010void XNapiTool::WrapFinalize(napi_env env, void *data, void *hint) 1011{ 1012 XNapiTool *pxt = (XNapiTool *)data; 1013 pxt->ReleaseInstance(); 1014 delete pxt; 1015} 1016 1017void XNapiTool::ReleaseInstance() 1018{ 1019 if (releaseInstance_ != nullptr) { 1020 releaseInstance_(pInstance_); 1021 } 1022} 1023 1024napi_value XNapiTool::WrapInstance(void *instance, RELEASE_INSTANCE ri) 1025{ 1026 pInstance_ = instance; 1027 releaseInstance_ = ri; 1028 napi_status result_status = napi_wrap(env_, thisVar_, this, WrapFinalize, nullptr, &wrapper_); 1029 CC_ASSERT(result_status == napi_ok); 1030 return thisVar_; 1031} 1032 1033void *XNapiTool::UnWarpInstance() 1034{ 1035 XNapiTool *p; 1036 napi_status result_status = napi_unwrap(env_, thisVar_, (void **)&p); 1037 CC_ASSERT(result_status == napi_ok); 1038 return p->pInstance_; 1039} 1040 1041void XNapiTool::SetAsyncInstance(void *p) 1042{ 1043 asyncInstance_ = p; 1044} 1045 1046void *XNapiTool::GetAsyncInstance() 1047{ 1048 return asyncInstance_; 1049} 1050 1051std::map<std::string, AsyncFunc> XNapiTool::asyncFuncs_; 1052void XNapiTool::RegistAsyncFunc(std::string name, napi_value func) 1053{ 1054 if (XNapiTool::asyncFuncs_.count(name) > 0) { 1055 UnregistAsyncFunc(name); 1056 } 1057 XNapiTool::asyncFuncs_[name].env_ = env_; 1058 napi_status result_status = napi_create_reference(env_, func, 1, &XNapiTool::asyncFuncs_[name].funcRef_); 1059 CC_ASSERT(result_status == napi_ok); 1060 result_status = napi_create_reference(env_, thisVar_, 1, &XNapiTool::asyncFuncs_[name].thisVarRef_); 1061 CC_ASSERT(result_status == napi_ok); 1062} 1063 1064void XNapiTool::UnregistAsyncFunc(std::string name) 1065{ 1066 if (XNapiTool::asyncFuncs_.count(name) <= 0) { 1067 return; 1068 } 1069 napi_status result_status = napi_delete_reference(env_, XNapiTool::asyncFuncs_[name].funcRef_); 1070 CC_ASSERT(result_status == napi_ok); 1071 result_status = napi_delete_reference(env_, XNapiTool::asyncFuncs_[name].thisVarRef_); 1072 CC_ASSERT(result_status == napi_ok); 1073 XNapiTool::asyncFuncs_.erase(name); 1074} 1075 1076void XNapiTool::CallAsyncFunc(AsyncFunc * pAsyncFuncs, napi_value ret) 1077{ 1078 uv_loop_s *loop = nullptr; 1079 napi_get_uv_event_loop(pAsyncFuncs->env_, &loop); 1080 uv_work_t *work = new uv_work_t; 1081 1082 struct AsyncCallData 1083 { 1084 napi_ref resultRef; 1085 AsyncFunc *p; 1086 }; 1087 AsyncCallData *data = (AsyncCallData *)malloc(sizeof(AsyncCallData)); 1088 napi_create_reference(pAsyncFuncs->env_, ret, 1, &data->resultRef); 1089 data->p = pAsyncFuncs; 1090 work->data = data; 1091 1092 uv_queue_work( 1093 loop, 1094 work, 1095 [](uv_work_t *) {}, 1096 [](uv_work_t *work, int status) 1097 { 1098 AsyncCallData *data = (AsyncCallData *)work->data; 1099 AsyncFunc *paf = data->p; 1100 napi_handle_scope scope = nullptr; 1101 napi_open_handle_scope(paf->env_, &scope); 1102 1103 napi_value cb = 0; 1104 napi_status result_status = napi_get_reference_value(paf->env_, paf->funcRef_, &cb); 1105 CC_ASSERT(result_status == napi_ok); 1106 1107 napi_value thisvar = 0; 1108 result_status = napi_get_reference_value(paf->env_, paf->thisVarRef_, &thisvar); 1109 CC_ASSERT(result_status == napi_ok); 1110 1111 napi_value retValue = 0; 1112 result_status = napi_get_reference_value(paf->env_, data->resultRef, &retValue); 1113 CC_ASSERT(result_status == napi_ok); 1114 napi_value args[1] = {retValue}; 1115 1116 napi_value cb_result; 1117 result_status = napi_call_function(paf->env_, thisvar, cb, 1, args, &cb_result); 1118 CC_ASSERT(result_status == napi_ok); 1119 1120 result_status = napi_delete_reference(paf->env_, data->resultRef); 1121 CC_ASSERT(result_status == napi_ok); 1122 1123 napi_close_handle_scope(paf->env_, scope); 1124 free(data); 1125 delete work; 1126 }); 1127} 1128` 1129 1130function generateBase(destDir, license) { 1131 writeFile(re.pathJoin(destDir, "tool_utility.h"), null != license ? (license + "\n" + xNapiToolH) : xNapiToolH) 1132 writeFile(re.pathJoin(destDir, "tool_utility.cpp"), null != license ? (license + "\n" + xNapiToolCpp):xNapiToolCpp) 1133} 1134 1135module.exports = { 1136 generateBase 1137}