From a607b5f81c8a931d0fbfd3c79937de65465ee4ee Mon Sep 17 00:00:00 2001 From: huoxiaodan Date: Wed, 10 Aug 2022 14:55:27 +0800 Subject: [PATCH] oAdd the framework generation code Signed-off-by: huoxiaodan --- out/BUILD.gn | 40 +++ out/binding.gyp | 25 ++ out/napi_gen.log | 1 + out/napitest.cpp | 56 ++++ out/napitest.h | 64 +++++ out/napitest_middle.cpp | 564 +++++++++++++++++++++++++++++++++++++ out/test.sh | 1 + out/x_napi_tool.cpp | 596 ++++++++++++++++++++++++++++++++++++++++ out/x_napi_tool.h | 157 +++++++++++ 9 files changed, 1504 insertions(+) create mode 100644 out/BUILD.gn create mode 100644 out/binding.gyp create mode 100644 out/napi_gen.log create mode 100644 out/napitest.cpp create mode 100644 out/napitest.h create mode 100644 out/napitest_middle.cpp create mode 100644 out/test.sh create mode 100644 out/x_napi_tool.cpp create mode 100644 out/x_napi_tool.h diff --git a/out/BUILD.gn b/out/BUILD.gn new file mode 100644 index 00000000..aa10aae2 --- /dev/null +++ b/out/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("napitest") +{ + sources = [ + "napitest_middle.cpp", + "napitest.cpp", + "x_napi_tool.cpp", + ] + include_dirs = [ + ".", + "//third_party/node/src", + ] + deps=[ + "//foundation/ace/napi:ace_napi", + ] + remove_configs = [ "//build/config/compiler:no_rtti" ] + cflags=[ + ] + cflags_cc=[ + "-frtti", + ] + ldflags = [ + ] + + relative_install_dir = "module" + part_name = "napitest" + subsystem_name = "napitest" +} diff --git a/out/binding.gyp b/out/binding.gyp new file mode 100644 index 00000000..2710a663 --- /dev/null +++ b/out/binding.gyp @@ -0,0 +1,25 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +{ + "targets": [ + { + "target_name": "napitest", + "sources": [ + "./napitest.cpp", + "./napitest_middle.cpp", + "./x_napi_tool.cpp"], + "include_dirs": ["."], + "cflags_cc": [ "-frtti","-std=c++17" ] + } + ] +} diff --git a/out/napi_gen.log b/out/napi_gen.log new file mode 100644 index 00000000..dbc8694b --- /dev/null +++ b/out/napi_gen.log @@ -0,0 +1 @@ +2022-8-10 14:37:14 at Object. [C:\snapshot\napi_generator-master\src\gen\cmd_gen.js(104:13)] [INF] success diff --git a/out/napitest.cpp b/out/napitest.cpp new file mode 100644 index 00000000..218b57d7 --- /dev/null +++ b/out/napitest.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "napitest.h" + +namespace napitest +{ + namespace Space3 + { + bool TestClass2::fix(std::string &v1, std::string &out) + { + return true; + } + + bool TestClass2::fun2(std::vector &numcc, Animal &animalcc, Animal &out) + { + return true; + } + + bool TestClass2::fun3(Animal &out) + { + return true; + } + + bool fun4(std::string &v3, std::string &out) + { + return true; + } + + bool fun5(uint32_t &outErrCode, std::string &out) + { + return true; + } + + bool fun6(std::string &name, NUMBER_TYPE_8 &flags, NUMBER_TYPE_10 &out) + { + return true; + } + + bool $fun8(std::map &v, std::string &out) + { + return true; + } + } +} diff --git a/out/napitest.h b/out/napitest.h new file mode 100644 index 00000000..7ce9f241 --- /dev/null +++ b/out/napitest.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef IMPL_NAPITEST_H +#define IMPL_NAPITEST_H + +#include +#include +#include +#include +#include + +using NUMBER_TYPE_1 = uint32_t; +using NUMBER_TYPE_2 = uint32_t; +using NUMBER_TYPE_3 = uint32_t; +using NUMBER_TYPE_4 = uint32_t; +using NUMBER_TYPE_5 = uint32_t; +using NUMBER_TYPE_6 = uint32_t; +using NUMBER_TYPE_7 = uint32_t; +using NUMBER_TYPE_8 = uint32_t; +using NUMBER_TYPE_9 = uint32_t; +using NUMBER_TYPE_10 = uint32_t; + + +namespace napitest {namespace Space3 { +enum Entity { + ENTITY_DEFAULT = 0, + ENTITY_HOME = 1, + ENTITY_VOICE = 2, + ENTITY_BROWSABLE = 3, + ENTITY_VIDEO = 4, +}; + +class Animal { +public: + std::string name; + NUMBER_TYPE_1 age; +}; +class TestClass2 { +public: + Animal animal; +bool fix(std::string& v1, std::string& out); +bool fun2(std::vector &numcc, Animal& animalcc, Animal& out); +bool fun3(Animal& out); +}; +bool fun4(std::string& v3, std::string& out); +bool fun5(uint32_t& outErrCode, std::string& out); +bool fun6(std::string& name, NUMBER_TYPE_8& flags, NUMBER_TYPE_10& out); +bool $fun8(std::map& v, std::string& out); +} +} + +#endif // IMPL_NAPITEST_H diff --git a/out/napitest_middle.cpp b/out/napitest_middle.cpp new file mode 100644 index 00000000..5a8e6459 --- /dev/null +++ b/out/napitest_middle.cpp @@ -0,0 +1,564 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include "x_napi_tool.h" +#include "napitest.h" + +#define NUMBER_JS_2_C(napi_v, type, dest) + if (typeid(type) == typeid(int32_t)) + { + dest = pxt->SwapJs2CInt32(napi_v); + } + else if (typeid(type) == typeid(uint32_t)) + { + dest = pxt->SwapJs2CUint32(napi_v); + } + else if (typeid(type) == typeid(int64_t)) + { + dest = pxt->SwapJs2CInt64(napi_v); + } + else if (typeid(type) == typeid(double_t)) + { + dest = pxt->SwapJs2CDouble(napi_v); + } + +#define NUMBER_JS_2_C_ENUM(napi_v, type, dest, enum_type) + if (typeid(type) == typeid(int32_t)) + { + dest = static_cast(pxt->SwapJs2CInt32(napi_v)); + } + else if (typeid(type) == typeid(uint32_t)) + { + dest = static_cast(pxt->SwapJs2CUint32(napi_v)); + } + else if (typeid(type) == typeid(int64_t)) + { + dest = static_cast(pxt->SwapJs2CInt64(napi_v)); + } + else if (typeid(type) == typeid(double_t)) + { + dest = static_cast(pxt->SwapJs2CDouble(napi_v)); + } + +#define BOOLEAN_JS_2_C(napi_v, type, dest) + { + dest = pxt->SwapC2JsBool(napi_v); + } + +#define C_DELETE(p) + if (p) + { + delete p; + } + +static napi_value number_c_to_js(XNapiTool *pxt, const std::type_info &n, void *num) +{ + if (n == typeid(int32_t)) + return pxt->SwapC2JsInt32(*(int32_t *)num); + else if (n == typeid(uint32_t)) + return pxt->SwapC2JsUint32(*(uint32_t *)num); + else if (n == typeid(int64_t)) + return pxt->SwapC2JsInt64(*(int64_t *)num); + else if (n == typeid(double_t)) + return pxt->SwapC2JsDouble(*(double_t *)num); + return nullptr; +} +#define NUMBER_C_2_JS(pxt, n) \ + number_c_to_js(pxt, typeid(n), &n) + +namespace napitest +{ + namespace Space3 + { + class Animal_middle + { + public: + static napi_value constructor(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = new XNapiTool(env, info); + + Animal *p = new Animal(); + + napi_value thisvar = pxt->WrapInstance(p, release); + + return thisvar; + } + static void release(void *p) + { + Animal *p2 = (Animal *)p; + delete p2; + } + + static napi_value getvalue_name(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + Animal *p = (Animal *)pxt->UnWarpInstance(); + napi_value result; + result = pxt->SwapC2JsUtf8(p->name.c_str()); + delete pxt; + return result; + } + static napi_value setvalue_name(napi_env env, napi_callback_info info) + { + std::shared_ptr pxt = std::make_shared(env, info); + Animal *p = (Animal *)pxt->UnWarpInstance(); + pxt->SwapJs2CUtf8(pxt->GetArgv(0), p->name); + return nullptr; + } + + static napi_value getvalue_age(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + Animal *p = (Animal *)pxt->UnWarpInstance(); + napi_value result; + result = NUMBER_C_2_JS(pxt, p->age); + delete pxt; + return result; + } + static napi_value setvalue_age(napi_env env, napi_callback_info info) + { + std::shared_ptr pxt = std::make_shared(env, info); + Animal *p = (Animal *)pxt->UnWarpInstance(); + NUMBER_JS_2_C(pxt->GetArgv(0), NUMBER_TYPE_1, p->age); + return nullptr; + } + }; + class TestClass2_middle + { + public: + static napi_value constructor(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = new XNapiTool(env, info); + + TestClass2 *p = new TestClass2(); + + napi_value thisvar = pxt->WrapInstance(p, release); + + return thisvar; + } + static void release(void *p) + { + TestClass2 *p2 = (TestClass2 *)p; + delete p2; + } + + static napi_value getvalue_animal(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + TestClass2 *p = (TestClass2 *)pxt->UnWarpInstance(); + napi_value result; + { + napi_value tnv1 = nullptr; + tnv1 = pxt->SwapC2JsUtf8(p->animal.name.c_str()); + pxt->SetValueProperty(result, "name", tnv1); + } + { + napi_value tnv1 = nullptr; + tnv1 = NUMBER_C_2_JS(pxt, p->animal.age); + pxt->SetValueProperty(result, "age", tnv1); + } + + delete pxt; + return result; + } + static napi_value setvalue_animal(napi_env env, napi_callback_info info) + { + std::shared_ptr pxt = std::make_shared(env, info); + TestClass2 *p = (TestClass2 *)pxt->UnWarpInstance(); + napi_value tnv1 = pxt->GetValueProperty(pxt->GetArgv(0), "name"); + if (tnv1 != nullptr) + { + pxt->SwapJs2CUtf8(tnv1, p->animal.name); + } + napi_value tnv2 = pxt->GetValueProperty(pxt->GetArgv(0), "age"); + if (tnv2 != nullptr) + { + NUMBER_JS_2_C(tnv2, NUMBER_TYPE_1, p->animal.age); + } + return nullptr; + } + + struct fix_value_struct + { + std::string in0; + + std::string out; + }; + + static napi_value fix_middle(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + if (pxt->IsFailed()) + { + napi_value err = pxt->GetError(); + delete pxt; + return err; + } + TestClass2 *pInstance = (TestClass2 *)pxt->UnWarpInstance(); + + struct fix_value_struct *vio = new fix_value_struct(); + + pxt->SwapJs2CUtf8(pxt->GetArgv(0), vio->in0); + + pInstance->fix(vio->in0, vio->out); + + napi_value result = nullptr; + result = pxt->SwapC2JsUtf8(vio->out.c_str()); + + delete vio; + if (pxt->IsFailed()) + { + result = pxt->GetError(); + } + + delete pxt; // release + return result; + } + struct fun2_value_struct + { + std::vector in0; + Animal in1; + + Animal out; + }; + + static napi_value fun2_middle(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + if (pxt->IsFailed()) + { + napi_value err = pxt->GetError(); + delete pxt; + return err; + } + TestClass2 *pInstance = (TestClass2 *)pxt->UnWarpInstance(); + + struct fun2_value_struct *vio = new fun2_value_struct(); + + uint32_t len3 = pxt->GetArrayLength(pxt->GetArgv(0)); + for (uint32_t i3 = 0; i3 < len3; i3++) + { + NUMBER_TYPE_7 tt3; + NUMBER_JS_2_C(pxt->GetArrayElement(pxt->GetArgv(0), i3), NUMBER_TYPE_7, tt3); + vio->in0.push_back(tt3); + } + napi_value tnv4 = pxt->GetValueProperty(pxt->GetArgv(1), "name"); + if (tnv4 != nullptr) + { + pxt->SwapJs2CUtf8(tnv4, vio->in1.name); + } + napi_value tnv5 = pxt->GetValueProperty(pxt->GetArgv(1), "age"); + if (tnv5 != nullptr) + { + NUMBER_JS_2_C(tnv5, NUMBER_TYPE_1, vio->in1.age); + } + + pInstance->fun2(vio->in0, vio->in1, vio->out); + + napi_value result = nullptr; + { + napi_value tnv1 = nullptr; + tnv1 = pxt->SwapC2JsUtf8(vio->out.name.c_str()); + pxt->SetValueProperty(result, "name", tnv1); + } + { + napi_value tnv1 = nullptr; + tnv1 = NUMBER_C_2_JS(pxt, vio->out.age); + pxt->SetValueProperty(result, "age", tnv1); + } + + delete vio; + if (pxt->IsFailed()) + { + result = pxt->GetError(); + } + + delete pxt; // release + return result; + } + struct fun3_value_struct + { + + Animal out; + }; + + static napi_value fun3_middle(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + if (pxt->IsFailed()) + { + napi_value err = pxt->GetError(); + delete pxt; + return err; + } + TestClass2 *pInstance = (TestClass2 *)pxt->UnWarpInstance(); + + struct fun3_value_struct *vio = new fun3_value_struct(); + + pInstance->fun3(vio->out); + + napi_value result = nullptr; + if (pxt->GetArgc() > 0) + { + { + napi_value tnv1 = nullptr; + tnv1 = pxt->SwapC2JsUtf8(vio->out.name.c_str()); + pxt->SetValueProperty(result, "name", tnv1); + } + { + napi_value tnv1 = nullptr; + tnv1 = NUMBER_C_2_JS(pxt, vio->out.age); + pxt->SetValueProperty(result, "age", tnv1); + } + + { + napi_value args[1] = {result}; + pxt->SyncCallBack(pxt->GetArgv(0), 1, args); + } + } + result = pxt->UndefinedValue(); + + delete vio; + if (pxt->IsFailed()) + { + result = pxt->GetError(); + } + delete pxt; // release + return result; + } + }; + struct fun4_value_struct + { + std::string in0; + + std::string out; + }; + + napi_value fun4_middle(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + if (pxt->IsFailed()) + { + napi_value err = pxt->GetError(); + delete pxt; + return err; + } + + struct fun4_value_struct *vio = new fun4_value_struct(); + + pxt->SwapJs2CUtf8(pxt->GetArgv(0), vio->in0); + + fun4(vio->in0, vio->out); + + napi_value result = nullptr; + result = pxt->SwapC2JsUtf8(vio->out.c_str()); + + delete vio; + if (pxt->IsFailed()) + { + result = pxt->GetError(); + } + + delete pxt; // release + return result; + } + struct fun5_value_struct + { + uint32_t outErrCode = 0; + std::string out; + }; + + void fun5_execute(XNapiTool *pxt, void *data) + { + fun5_value_struct *vio = (fun5_value_struct *)data; + + fun5(vio->outErrCode, vio->out); + } + + void fun5_complete(XNapiTool *pxt, void *data) + { + fun5_value_struct *vio = (fun5_value_struct *)data; + + napi_value result = nullptr; + + result = pxt->SwapC2JsUtf8(vio->out.c_str()); + + napi_value errCodeResult = nullptr; + napi_value napiErrCode = nullptr; + napiErrCode = NUMBER_C_2_JS(pxt, vio->outErrCode); + pxt->SetValueProperty(errCodeResult, "code", napiErrCode); + { + napi_value args[2] = {errCodeResult, result}; + pxt->FinishAsync(2, args); + } + + delete vio; + } + + napi_value fun5_middle(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + if (pxt->IsFailed()) + { + napi_value err = pxt->GetError(); + delete pxt; + return err; + } + + struct fun5_value_struct *vio = new fun5_value_struct(); + + napi_value result = pxt->StartAsync(fun5_execute, vio, fun5_complete, pxt->GetArgc() == 1 ? pxt->GetArgv(0) : nullptr); + + if (pxt->IsFailed()) + { + result = pxt->GetError(); + } + return result; + } + struct fun6_value_struct + { + std::string in0; + NUMBER_TYPE_8 in1; + + NUMBER_TYPE_10 out; + }; + + napi_value fun6_middle(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + if (pxt->IsFailed()) + { + napi_value err = pxt->GetError(); + delete pxt; + return err; + } + + struct fun6_value_struct *vio = new fun6_value_struct(); + + pxt->SwapJs2CUtf8(pxt->GetArgv(0), vio->in0); + NUMBER_JS_2_C(pxt->GetArgv(1), NUMBER_TYPE_8, vio->in1); + + fun6(vio->in0, vio->in1, vio->out); + + napi_value result = nullptr; + result = NUMBER_C_2_JS(pxt, vio->out); + + delete vio; + if (pxt->IsFailed()) + { + result = pxt->GetError(); + } + + delete pxt; // release + return result; + } + struct $fun8_value_struct + { + std::map in0; + + std::string out; + }; + + napi_value $fun8_middle(napi_env env, napi_callback_info info) + { + XNapiTool *pxt = std::make_unique(env, info).release(); + if (pxt->IsFailed()) + { + napi_value err = pxt->GetError(); + delete pxt; + return err; + } + + struct $fun8_value_struct *vio = new $fun8_value_struct(); + + uint32_t len6 = pxt->GetMapLength(pxt->GetArgv(0)); + for (uint32_t i6 = 0; i6 < len6; i6++) + { + std::string tt6; + NUMBER_TYPE_9 tt7; + pxt->SwapJs2CUtf8(pxt->GetMapElementName(pxt->GetArgv(0), i6), tt6); + NUMBER_JS_2_C(pxt->GetMapElementValue(pxt->GetArgv(0), tt6.c_str()), NUMBER_TYPE_9, tt7); + vio->in0.insert(std::make_pair(tt6, tt7)); + } + + $fun8(vio->in0, vio->out); + + napi_value result = nullptr; + result = pxt->SwapC2JsUtf8(vio->out.c_str()); + + delete vio; + if (pxt->IsFailed()) + { + result = pxt->GetError(); + } + + delete pxt; // release + return result; + } + } +} + +static napi_value init(napi_env env, napi_value exports) +{ + std::shared_ptr pxt = std::make_shared(env, exports); + + { + napi_value Space3 = pxt->CreateSubObject(exports, "Space3"); + { + std::map> valueList; + valueList["name"]["getvalue"] = napitest::Space3::Animal_middle::getvalue_name; + valueList["name"]["setvalue"] = napitest::Space3::Animal_middle::setvalue_name; + valueList["age"]["getvalue"] = napitest::Space3::Animal_middle::getvalue_age; + valueList["age"]["setvalue"] = napitest::Space3::Animal_middle::setvalue_age; + std::map funcList; + pxt->DefineClass("Animal", napitest::Space3::Animal_middle::constructor, valueList, funcList, Space3); + } + { + std::map> valueList; + valueList["animal"]["getvalue"] = napitest::Space3::TestClass2_middle::getvalue_animal; + valueList["animal"]["setvalue"] = napitest::Space3::TestClass2_middle::setvalue_animal; + std::map funcList; + funcList["fix"] = napitest::Space3::TestClass2_middle::fix_middle; + funcList["fun2"] = napitest::Space3::TestClass2_middle::fun2_middle; + funcList["fun3"] = napitest::Space3::TestClass2_middle::fun3_middle; + pxt->DefineClass("TestClass2", napitest::Space3::TestClass2_middle::constructor, valueList, funcList, Space3); + } + pxt->DefineFunction("fun4", napitest::Space3::fun4_middle, Space3); + pxt->DefineFunction("fun5", napitest::Space3::fun5_middle, Space3); + pxt->DefineFunction("fun6", napitest::Space3::fun6_middle, Space3); + pxt->DefineFunction("$fun8", napitest::Space3::$fun8_middle, Space3); + } + + return exports; +} + +static napi_module g_napitest_Module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = init, + .nm_modname = "napitest", + .nm_priv = ((void *)0), + .reserved = {(void *)0}, +}; + +extern "C" __attribute__((constructor)) void Register_napitest_Module(void) +{ + napi_module_register(&g_napitest_Module); +} diff --git a/out/test.sh b/out/test.sh new file mode 100644 index 00000000..0cea4b0e --- /dev/null +++ b/out/test.sh @@ -0,0 +1 @@ +node-gyp configure build && sleep 0.5 && node --expose-gc test.js \ No newline at end of file diff --git a/out/x_napi_tool.cpp b/out/x_napi_tool.cpp new file mode 100644 index 00000000..6d633793 --- /dev/null +++ b/out/x_napi_tool.cpp @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "x_napi_tool.h" +#include +#include +#include + +#define CC_ASSERT(btrue) \ + if (!(btrue)) \ + { \ + } \ + assert(btrue); + +XNapiTool::XNapiTool(napi_env env, napi_callback_info info) +{ + env_ = env; + bFailed_ = false; + executeFunction_ = nullptr; + completeFunction_ = nullptr; + valueData_ = nullptr; + asyncNeedRelease_ = false; + asyncMode_ = AsyncMode::NONE; + pInstance_ = nullptr; + releaseInstance_ = nullptr; + wrapper_ = nullptr; + + argc_size = DEFAULT_ARG_COUNT; + + napi_status result_status = napi_get_cb_info(env, info, &argc_size, argv_, &thisVar_, &data_); + CheckFailed(result_status == napi_ok, "get args fail"); +} + +XNapiTool::XNapiTool(napi_env env, napi_value exports) +{ + env_ = env; + exports_ = exports; + + asyncMode_ = AsyncMode::NONE; + wrapper_ = nullptr; +} + +XNapiTool::~XNapiTool() +{ + if (asyncMode_ == AsyncMode::PROMISE) + { + napi_status result_status = napi_delete_async_work(env_, work_); + CC_ASSERT(result_status == napi_ok); + } + if (asyncMode_ == AsyncMode::CALLBACK) + { + napi_status result_status = napi_delete_reference(env_, callbackFunc_); + CC_ASSERT(result_status == napi_ok); + result_status = napi_delete_async_work(env_, work_); + CC_ASSERT(result_status == napi_ok); + } + if (wrapper_ != nullptr) + { + napi_status result_status = napi_delete_reference(env_, wrapper_); + CC_ASSERT(result_status == napi_ok); + } +} + +bool XNapiTool::SwapJs2CBool(napi_value value) +{ + bool result; + napi_status result_status = napi_get_value_bool(env_, value, &result); + if (CheckFailed(result_status == napi_ok, "swap_js_2_c_bool fail")) + return -1; + return result; +} + +napi_value XNapiTool::GetArgv(uint32_t p) +{ + if (CheckFailed(p < argc_size, "GetArgv失败")) + return error_; + + return argv_[p]; +} + +uint32_t XNapiTool::GetArgc() +{ + return argc_size; +} + +napi_value XNapiTool::GetValueProperty(napi_value value, const char *propertyName) +{ + napi_value result; + napi_status result_status = napi_get_named_property(env_, value, propertyName, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SetValueProperty(napi_value &value, const char *propertyName, napi_value property) +{ + napi_status result_status; + if (value == nullptr) + { + result_status = napi_create_object(env_, &value); + CC_ASSERT(result_status == napi_ok); + } + result_status = napi_set_named_property(env_, value, propertyName, property); + CC_ASSERT(result_status == napi_ok); + return value; +} + +uint32_t XNapiTool::GetArrayLength(napi_value value) +{ + uint32_t ret; + napi_status result_status = napi_get_array_length(env_, value, &ret); + CC_ASSERT(result_status == napi_ok); + return ret; +} + +napi_value XNapiTool::GetArrayElement(napi_value value, uint32_t p) +{ + napi_value result; + napi_status result_status = napi_get_element(env_, value, p, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SetArrayElement(napi_value &value, uint32_t p, napi_value ele) +{ + napi_status result_status; + if (value == nullptr) + { + result_status = napi_create_array(env_, &value); + CC_ASSERT(result_status == napi_ok); + } + result_status = napi_set_element(env_, value, p, ele); + CC_ASSERT(result_status == napi_ok); + return value; +} + +uint32_t XNapiTool::GetMapLength(napi_value value) +{ + napi_value name_result; + napi_get_property_names(env_, value, &name_result); + uint32_t ret; + napi_status result_status = napi_get_array_length(env_, name_result, &ret); + CC_ASSERT(result_status == napi_ok); + return ret; +} + +napi_value XNapiTool::GetMapElementName(napi_value value, uint32_t p) +{ + napi_value name_result; + napi_get_property_names(env_, value, &name_result); + napi_value result; + napi_status result_status = napi_get_element(env_, name_result, p, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::GetMapElementValue(napi_value value, const char *utf8Name) +{ + napi_value result; + napi_status result_status = napi_get_named_property(env_, value, utf8Name, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SetMapElement(napi_value &value, const char *ele_key, napi_value ele_value) +{ + napi_status result_status; + if (value == nullptr) + { + result_status = napi_create_object(env_, &value); + CC_ASSERT(result_status == napi_ok); + } + result_status = napi_set_named_property(env_, value, ele_key, ele_value); + CC_ASSERT(result_status == napi_ok); + return value; +} + +bool XNapiTool::CheckFailed(bool b, const char *errStr) +{ + if (bFailed_) + { + return true; + } + if (b) + { + return false; + } + + napi_value errCode = nullptr; + napi_value errMessage = nullptr; + + napi_create_string_utf8(env_, "x_tool", strlen("x_tool"), &errCode); + napi_create_string_utf8(env_, errStr, strlen(errStr), &errMessage); + napi_create_error(env_, errCode, errMessage, &error_); + printf("x_napi_tool err : %s\n", errStr); + + bFailed_ = true; + return true; +} + +int32_t XNapiTool::SwapJs2CInt32(napi_value value) +{ + int32_t result; + napi_status result_status = napi_get_value_int32(env_, value, &result); + if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail")) + return -1; + return result; +} + +uint32_t XNapiTool::SwapJs2CUint32(napi_value value) +{ + uint32_t result; + napi_status result_status = napi_get_value_uint32(env_, value, &result); + if (CheckFailed(result_status == napi_ok, "swap_js_2_c_uint32 fail")) + return -1; + return result; +} + +int64_t XNapiTool::SwapJs2CInt64(napi_value value) +{ + int64_t result; + napi_status result_status = napi_get_value_int64(env_, value, &result); + if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail")) + return -1; + return result; +} + +double_t XNapiTool::SwapJs2CDouble(napi_value value) +{ + double_t result; + napi_status result_status = napi_get_value_double(env_, value, &result); + if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail")) + return -1; + return result; +} + +size_t XNapiTool::SwapJs2CUtf8(napi_value value, std::string &str) +{ + char buf[1024]; + size_t result; + napi_status result_status = napi_get_value_string_utf8(env_, value, buf, 1024, &result); + if (CheckFailed(result_status == napi_ok, "napi_get_value_string_utf8 fail")) + return -1; + str = buf; + return result; +} + +napi_value XNapiTool::SwapC2JsBool(bool value) +{ + napi_value result; + napi_status result_status = napi_create_int32(env_, value, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SwapC2JsInt32(int32_t value) +{ + napi_value result; + napi_status result_status = napi_create_int32(env_, value, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SwapC2JsUint32(uint32_t value) +{ + napi_value result; + napi_status result_status = napi_create_uint32(env_, value, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SwapC2JsInt64(int64_t value) +{ + napi_value result; + napi_status result_status = napi_create_int64(env_, value, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SwapC2JsDouble(double_t value) +{ + napi_value result; + napi_status result_status = napi_create_double(env_, value, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SwapC2JsUtf8(const char *value) +{ + napi_value result; + napi_status result_status = napi_create_string_utf8(env_, value, NAPI_AUTO_LENGTH, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +bool XNapiTool::CheckValueType(napi_value value, napi_valuetype type) +{ + napi_valuetype valueType; + napi_status result_status = napi_typeof(env_, value, &valueType); + CC_ASSERT(result_status == napi_ok); + if (CheckFailed(valueType == type, "传入参数类型不是回调函数")) + return false; + return true; +} + +napi_value XNapiTool::SyncCallBack(napi_value func, size_t argc, napi_value *args) +{ + napi_value cb_result; + napi_status result_status = napi_call_function(env_, thisVar_, func, argc, args, &cb_result); + CC_ASSERT(result_status == napi_ok); + return cb_result; +} + +void XNapiTool::AsyncExecuteFunction() +{ + if (executeFunction_ != nullptr) + { + executeFunction_(this, valueData_); + } +} +void XNapiTool::AsyncExecute(napi_env env, void *p) +{ + XNapiTool *pxt = (XNapiTool *)p; + pxt->AsyncExecuteFunction(); +} +void XNapiTool::AsyncCompleteFunction() +{ + if (completeFunction_ != nullptr) + { + completeFunction_(this, valueData_); + } +} +void XNapiTool::AsyncComplete(napi_env env, napi_status status, void *p) +{ + XNapiTool *pxt = (XNapiTool *)p; + pxt->AsyncCompleteFunction(); + delete pxt; +} + +napi_value XNapiTool::StartAsync(CallbackFunction pe, void *data, CallbackFunction pc, napi_value func) +{ + napi_value result; + napi_status result_status; + + if (func == nullptr) + { + // promise + result_status = napi_create_promise(env_, &deferred_, &result); + CC_ASSERT(result_status == napi_ok); + asyncMode_ = AsyncMode::PROMISE; + } + else + { + // callback + result_status = napi_create_reference(env_, func, 1, &callbackFunc_); + CC_ASSERT(result_status == napi_ok); + asyncMode_ = AsyncMode::CALLBACK; + result = UndefinedValue(env_); + } + + asyncNeedRelease_ = true; + executeFunction_ = pe; + completeFunction_ = pc; + valueData_ = data; + + napi_value resourceName = nullptr; + result_status = napi_create_string_utf8(env_, "x_napi_tool", NAPI_AUTO_LENGTH, &resourceName); + CC_ASSERT(result_status == napi_ok); + result_status = napi_create_async_work(env_, nullptr, resourceName, XNapiTool::AsyncExecute, + XNapiTool::AsyncComplete, this, &work_); + CC_ASSERT(result_status == napi_ok); + result_status = napi_queue_async_work(env_, work_); + CC_ASSERT(result_status == napi_ok); + + return result; +} + +void XNapiTool::FinishAsync(size_t argc, napi_value *args) +{ + if (asyncMode_ == AsyncMode::PROMISE) + { + if (argc > 1) + { + napi_resolve_deferred(env_, deferred_, args[1]); + } + else + { + napi_reject_deferred(env_, deferred_, SwapC2JsUtf8("promise fail")); + } + return; + } + napi_value result = 0; + napi_value cb = 0; + + napi_status result_status = napi_get_reference_value(env_, callbackFunc_, &cb); + CC_ASSERT(result_status == napi_ok); + result_status = napi_call_function(env_, thisVar_, cb, argc, args, &result); + CC_ASSERT(result_status == napi_ok); +} + +napi_value XNapiTool::UndefinedValue(napi_env env) +{ + napi_value result; + napi_get_undefined(env, &result); + return result; +} + +napi_value XNapiTool::UndefinedValue() +{ + napi_value result; + napi_get_undefined(env_, &result); + return result; +} + +napi_value XNapiTool::CreateSubObject(napi_value parent, const char *name) +{ + napi_value result; + napi_status result_status = napi_create_object(env_, &result); + CC_ASSERT(result_status == napi_ok); + + result_status = napi_set_named_property(env_, parent, name, result); + CC_ASSERT(result_status == napi_ok); + + return result; +} + +void XNapiTool::DefineFunction(const char *funcName, napi_callback callback, napi_value dest) +{ + if (dest == nullptr) + dest = exports_; + napi_property_descriptor descriptor[] = { + {funcName, 0, callback, 0, 0, 0, napi_default, 0}}; + + napi_status result_status = napi_define_properties(env_, dest, 1, descriptor); + CC_ASSERT(result_status == napi_ok); +} + +void XNapiTool::DefineClass(const char *className, napi_callback constructorFunc, + std::map> &valueList, + std::map &funcList, napi_value dest) +{ + if (dest == nullptr) + dest = exports_; + napi_value tmpClass = nullptr; + napi_property_descriptor funcs[funcList.size() + valueList.size()]; + + uint32_t p = 0; + for (auto it = valueList.begin(); it != valueList.end(); it++) + { + funcs[p++] = {it->first, 0, 0, it->second["getvalue"], it->second["setvalue"], 0, napi_default, 0}; // get,set + } + for (auto it = funcList.begin(); it != funcList.end(); it++) + { + funcs[p++] = {it->first, 0, it->second, 0, 0, 0, napi_default, 0}; + } + + napi_status result_status = napi_define_class(env_, className, NAPI_AUTO_LENGTH, constructorFunc, + nullptr, p, funcs, &tmpClass); + CC_ASSERT(result_status == napi_ok); + + result_status = napi_set_named_property(env_, dest, className, tmpClass); + CC_ASSERT(result_status == napi_ok); +} + +void XNapiTool::WrapFinalize(napi_env env, void *data, void *hint) +{ + XNapiTool *pxt = (XNapiTool *)data; + pxt->ReleaseInstance(); + delete pxt; +} + +void XNapiTool::ReleaseInstance() +{ + if (releaseInstance_ != nullptr) + { + releaseInstance_(pInstance_); + } +} + +napi_value XNapiTool::WrapInstance(void *instance, RELEASE_INSTANCE ri) +{ + pInstance_ = instance; + releaseInstance_ = ri; + napi_status result_status = napi_wrap(env_, thisVar_, this, WrapFinalize, nullptr, &wrapper_); + CC_ASSERT(result_status == napi_ok); + return thisVar_; +} + +void *XNapiTool::UnWarpInstance() +{ + XNapiTool *p; + napi_status result_status = napi_unwrap(env_, thisVar_, (void **)&p); + CC_ASSERT(result_status == napi_ok); + return p->pInstance_; +} + +void XNapiTool::SetAsyncInstance(void *p) +{ + asyncInstance_ = p; +} + +void *XNapiTool::GetAsyncInstance() +{ + return asyncInstance_; +} + +std::map XNapiTool::asyncFuncs_; +void XNapiTool::RegistAsyncFunc(std::string name, napi_value func) +{ + if (XNapiTool::asyncFuncs_.count(name) > 0) + { + UnregistAsyncFunc(name); + } + XNapiTool::asyncFuncs_[name].env_ = env_; + napi_status result_status = napi_create_reference(env_, func, 1, &XNapiTool::asyncFuncs_[name].funcRef_); + CC_ASSERT(result_status == napi_ok); + result_status = napi_create_reference(env_, thisVar_, 1, &XNapiTool::asyncFuncs_[name].thisVarRef_); + CC_ASSERT(result_status == napi_ok); +} + +void XNapiTool::UnregistAsyncFunc(std::string name) +{ + if (XNapiTool::asyncFuncs_.count(name) <= 0) + { + return; + } + napi_status result_status = napi_delete_reference(env_, XNapiTool::asyncFuncs_[name].funcRef_); + CC_ASSERT(result_status == napi_ok); + result_status = napi_delete_reference(env_, XNapiTool::asyncFuncs_[name].thisVarRef_); + CC_ASSERT(result_status == napi_ok); + XNapiTool::asyncFuncs_.erase(name); +} + +void XNapiTool::CallAsyncFunc(AsyncFunc *pAsyncFuncs, napi_value ret) +{ + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(pAsyncFuncs->env_, &loop); + uv_work_t *work = new uv_work_t; + + struct AsyncCallData + { + napi_ref resultRef; + AsyncFunc *p; + }; + AsyncCallData *data = (AsyncCallData *)malloc(sizeof(AsyncCallData)); + napi_create_reference(pAsyncFuncs->env_, ret, 1, &data->resultRef); + data->p = pAsyncFuncs; + work->data = data; + + uv_queue_work( + loop, + work, + [](uv_work_t *) {}, + [](uv_work_t *work, int status) + { + AsyncCallData *data = (AsyncCallData *)work->data; + AsyncFunc *paf = data->p; + napi_handle_scope scope = nullptr; + napi_open_handle_scope(paf->env_, &scope); + + napi_value cb = 0; + napi_status result_status = napi_get_reference_value(paf->env_, paf->funcRef_, &cb); + CC_ASSERT(result_status == napi_ok); + + napi_value thisvar = 0; + result_status = napi_get_reference_value(paf->env_, paf->thisVarRef_, &thisvar); + CC_ASSERT(result_status == napi_ok); + + napi_value retValue = 0; + result_status = napi_get_reference_value(paf->env_, data->resultRef, &retValue); + CC_ASSERT(result_status == napi_ok); + napi_value args[1] = {retValue}; + + napi_value cb_result; + result_status = napi_call_function(paf->env_, thisvar, cb, 1, args, &cb_result); + CC_ASSERT(result_status == napi_ok); + + result_status = napi_delete_reference(paf->env_, data->resultRef); + CC_ASSERT(result_status == napi_ok); + + napi_close_handle_scope(paf->env_, scope); + free(data); + delete work; + }); +} diff --git a/out/x_napi_tool.h b/out/x_napi_tool.h new file mode 100644 index 00000000..8689b543 --- /dev/null +++ b/out/x_napi_tool.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef CC_TOOL_H +#define CC_TOOL_H + +#include +#include +#include +#include +#include +#include + +struct AsyncFunc +{ + napi_env env_; + napi_ref funcRef_; + napi_ref thisVarRef_; +}; + +class XNapiTool +{ +public: + void RegistAsyncFunc(std::string name, napi_value func); + void UnregistAsyncFunc(std::string name); + static std::map asyncFuncs_; + static void CallAsyncFunc(AsyncFunc *pAsyncFuncs, napi_value ret); + + using CallbackFunction = void (*)(XNapiTool *pxt, void *data); + using RELEASE_INSTANCE = void (*)(void *p); + static napi_value UndefinedValue(napi_env env); + const uint32_t DEFAULT_ARG_COUNT = 8; + napi_value UndefinedValue(); + + napi_value CreateSubObject(napi_value parent, const char *name); + void DefineFunction(const char *funcName, napi_callback callback, napi_value dest = nullptr); + void DefineClass(const char *className, napi_callback constructorFunc, + std::map> &valueList, std::map &funcList, napi_value dest = nullptr); + + XNapiTool(napi_env env, napi_callback_info info); + XNapiTool(napi_env env, napi_value exports); + ~XNapiTool(); + + bool SwapJs2CBool(napi_value value); + int32_t SwapJs2CInt32(napi_value value); + uint32_t SwapJs2CUint32(napi_value value); + int64_t SwapJs2CInt64(napi_value value); + double_t SwapJs2CDouble(napi_value value); + size_t SwapJs2CUtf8(napi_value value, std::string &str); + + napi_value SwapC2JsBool(bool value); + napi_value SwapC2JsInt32(int32_t value); + napi_value SwapC2JsUint32(uint32_t value); + napi_value SwapC2JsInt64(int64_t value); + napi_value SwapC2JsDouble(double_t value); + napi_value SwapC2JsUtf8(const char *value); + + napi_value GetArgv(uint32_t p); + uint32_t GetArgc(); + + napi_value GetValueProperty(napi_value value, const char *propertyName); + napi_value SetValueProperty(napi_value &value, const char *propertyName, napi_value property); + + uint32_t GetArrayLength(napi_value value); + napi_value GetArrayElement(napi_value value, uint32_t p); + napi_value SetArrayElement(napi_value &value, uint32_t p, napi_value ele); + + uint32_t GetMapLength(napi_value value); + napi_value GetMapElementName(napi_value value, uint32_t p); + napi_value GetMapElementValue(napi_value value, const char *p); + napi_value SetMapElement(napi_value &value, const char *ele_key, napi_value ele_value); + + napi_value SyncCallBack(napi_value func, size_t argc, napi_value *args); + + napi_value StartAsync(CallbackFunction pe, void *data, CallbackFunction pc, napi_value func = nullptr); + void FinishAsync(size_t argc, napi_value *args); + + bool IsFailed() + { + return bFailed_; + } + napi_value GetError() + { + return error_; + } + napi_env GetEnv() + { + return env_; + } + + napi_value tmp_value; + + // create code related class +public: + static void WrapFinalize(napi_env env, void *data, void *hint); + void ReleaseInstance(); + napi_value WrapInstance(void *instance, RELEASE_INSTANCE ri); + void *UnWarpInstance(); + + void SetAsyncInstance(void *p); + void *GetAsyncInstance(); + +private: + napi_env env_; + napi_value exports_; + + // analyze params + napi_value argv_[8]; + size_t argc_size; + napi_value thisVar_; + void *data_; + + // error message + napi_value error_; + bool bFailed_; + bool CheckFailed(bool b, const char *errStr); + bool CheckValueType(napi_value value, napi_valuetype type); + + // asynchronous call related code + static void AsyncExecute(napi_env env, void *p); + void AsyncExecuteFunction(); + static void AsyncComplete(napi_env env, napi_status status, void *p); + void AsyncCompleteFunction(); + napi_ref callbackFunc_; + napi_async_work work_; + bool asyncNeedRelease_; + CallbackFunction executeFunction_; + CallbackFunction completeFunction_; + void *valueData_; + napi_deferred deferred_; + enum class AsyncMode + { + NONE, + CALLBACK, + PROMISE, + }; + AsyncMode asyncMode_; + +private: + napi_ref wrapper_; + void *pInstance_; + RELEASE_INSTANCE releaseInstance_; + void *asyncInstance_; +}; + +#endif -- Gitee