1/* 2 * Copyright (c) 2022 Huawei Device 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 */ 15 16#include <thread> 17 18#include "napi/native_api.h" 19#include "napi/native_node_api.h" 20 21#include "uv.h" 22 23struct CallbackContext { 24 napi_env env = nullptr; 25 napi_ref callbackRef = nullptr; 26 int retData = 0; 27}; 28 29void callbackTest(CallbackContext* context) 30{ 31 uv_loop_s* loop = nullptr; 32 napi_get_uv_event_loop(context->env, &loop); 33 34 uv_work_t* work = new uv_work_t; 35 context->retData = 1; 36 work->data = (void*)context; 37 38 uv_queue_work( 39 loop, work, [](uv_work_t* work) {}, 40 // using callback function back to JS thread 41 [](uv_work_t* work, int status) { 42 CallbackContext* context = (CallbackContext*)work->data; 43 napi_handle_scope scope = nullptr; 44 napi_open_handle_scope(context->env, &scope); 45 if (scope == nullptr) { 46 return; 47 } 48 49 napi_value callback = nullptr; 50 napi_get_reference_value(context->env, context->callbackRef, &callback); 51 napi_value retArg; 52 napi_create_int32(context->env, context->retData, &retArg); 53 napi_value ret; 54 napi_call_function(context->env, nullptr, callback, 1, &retArg, &ret); 55 napi_delete_reference(context->env, context->callbackRef); 56 57 napi_close_handle_scope(context->env, scope); 58 59 if (work != nullptr) { 60 delete work; 61 } 62 63 delete context; 64 } 65 ); 66} 67 68static napi_value JSTest(napi_env env, napi_callback_info info) 69{ 70 size_t argc = 1; 71 napi_value argv[1] = { 0 }; 72 napi_value thisVar = nullptr; 73 void* data = nullptr; 74 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 75 76 napi_valuetype valueType = napi_undefined; 77 napi_typeof(env, argv[0], &valueType); 78 if (valueType != napi_function) { 79 return nullptr; 80 } 81 auto asyncContext = new CallbackContext(); 82 asyncContext->env = env; 83 napi_create_reference(env, argv[0], 1, &asyncContext->callbackRef); 84 // using callback function on other thread 85 std::thread testThread(callbackTest, asyncContext); 86 testThread.detach(); 87 88 return nullptr; 89} 90 91/*********************************************** 92 * Module export and register 93 ***********************************************/ 94static napi_value CallbackExport(napi_env env, napi_value exports) 95{ 96 static napi_property_descriptor desc[] = { 97 DECLARE_NAPI_FUNCTION("test", JSTest) 98 }; 99 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); 100 return exports; 101} 102 103// callback module define 104static napi_module callbackModule = { 105 .nm_version = 1, 106 .nm_flags = 0, 107 .nm_filename = nullptr, 108 .nm_register_func = CallbackExport, 109 .nm_modname = "callback", 110 .nm_priv = ((void*)0), 111 .reserved = { 0 }, 112}; 113 114// callback module register 115extern "C" __attribute__((constructor)) void CallbackTestRegister() 116{ 117 napi_module_register(&callbackModule); 118}