From ef45f27af0a6716207ceea4a19c5cb00f2511773 Mon Sep 17 00:00:00 2001 From: kuangning <2540487435@qq.com> Date: Wed, 21 May 2025 20:12:48 +0800 Subject: [PATCH] =?UTF-8?q?ndk=E6=B7=BB=E5=8A=A0=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entry/src/main/cpp/CMakeListsModule.txt | 40 ++++++++ .../src/main/cpp/HashMapValue2String.cpp | 70 +++++++++++++ .../entry/src/main/cpp/ManageNativeCPlus.cpp | 67 +++++++++++++ .../entry/src/main/cpp/RevArkTSObj.cpp | 99 +++++++++++++++++++ .../src/main/cpp/ark_ts_native_log_cpp.cpp | 93 +++++++++++++++++ .../src/main/cpp/function_passed_over_cpp.cpp | 39 ++++++++ .../cpp/get_asynchronous_computation_cpp.cpp | 81 +++++++++++++++ .../main/cpp/main_thread_communication.cpp | 58 +++++++++++ .../src/main/cpp/napi_create_arraybuffer.cpp | 35 +++++++ .../entry/src/main/cpp/napi_create_buffer.cpp | 38 +++++++ .../src/main/cpp/open_file_on_c_side_cpp.cpp | 65 ++++++++++++ .../entry/src/main/cpp/thread_limit_cpp.cpp | 48 +++++++++ .../src/main/cpp/types/libentry/Index.d.ts | 26 ++++- ...orker_calls_napi_to_implement_loop_cpp.cpp | 86 ++++++++++++++++ .../entryability/EntryAbilityNativeLog.ets | 36 +++++++ .../entry/src/main/ets/interface/Log.ts | 93 +++++++++++++++++ .../ets/pages/FunctionPassedOverArkTs.ets | 47 +++++++++ .../ets/pages/GetAsynchronousComputation.ets | 63 ++++++++++++ .../main/ets/pages/HashMapConversionArkTs.ets | 59 +++++++++++ .../src/main/ets/pages/ManageNativeCPlus.ets | 56 +++++++++++ .../main/ets/pages/NapiCreateBufferArkTs.ets | 49 +++++++++ .../src/main/ets/pages/OpenFileOnCSide.ets | 68 +++++++++++++ .../src/main/ets/pages/RevArkTSObjArkTs.ets | 68 +++++++++++++ .../src/main/ets/pages/ThreadLimitArkTs.ets | 38 +++++++ .../pages/WorkerCallsNapiToImplementLoop.ets | 78 +++++++++++++++ .../WorkerCallsNapiToImplementLoop_Two.ets | 32 ++++++ 26 files changed, 1531 insertions(+), 1 deletion(-) create mode 100644 NdkDevelopment/entry/src/main/cpp/CMakeListsModule.txt create mode 100644 NdkDevelopment/entry/src/main/cpp/HashMapValue2String.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/ManageNativeCPlus.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/RevArkTSObj.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/ark_ts_native_log_cpp.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/function_passed_over_cpp.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/get_asynchronous_computation_cpp.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/main_thread_communication.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/napi_create_arraybuffer.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/napi_create_buffer.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/open_file_on_c_side_cpp.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/thread_limit_cpp.cpp create mode 100644 NdkDevelopment/entry/src/main/cpp/worker_calls_napi_to_implement_loop_cpp.cpp create mode 100644 NdkDevelopment/entry/src/main/ets/entryability/EntryAbilityNativeLog.ets create mode 100644 NdkDevelopment/entry/src/main/ets/interface/Log.ts create mode 100644 NdkDevelopment/entry/src/main/ets/pages/FunctionPassedOverArkTs.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/GetAsynchronousComputation.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/HashMapConversionArkTs.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/ManageNativeCPlus.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/NapiCreateBufferArkTs.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/OpenFileOnCSide.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/RevArkTSObjArkTs.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/ThreadLimitArkTs.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop.ets create mode 100644 NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop_Two.ets diff --git a/NdkDevelopment/entry/src/main/cpp/CMakeListsModule.txt b/NdkDevelopment/entry/src/main/cpp/CMakeListsModule.txt new file mode 100644 index 0000000..37b86fb --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/CMakeListsModule.txt @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:在CMakeLists文件中如何获取模块版本信息 +*/ + +// [Start cmake_get_module] +cmake_minimum_required(VERSION 3.4.1) +project(CmakeModuleInfo) + +set(JSON_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../oh-package.json5) +file(READ ${JSON_FILE_PATH} JSON_STRING) +message("json string:${JSON_STRING}") +if("${JSON_STRING}" MATCHES "1.0.0") +set(SRC_LIST napi_init.cpp) +else() +set(SRC_LIST hello.cpp) +endif() +message("src_file:${SRC_LIST}") + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(entry SHARED ${SRC_LIST}) +target_link_libraries(entry PUBLIC libace_napi.z.so) +// [Start cmake_get_module] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/HashMapValue2String.cpp b/NdkDevelopment/entry/src/main/cpp/HashMapValue2String.cpp new file mode 100644 index 0000000..ec9fdd5 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/HashMapValue2String.cpp @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何实现ArkTS与C/C++的HashMap转换 +*/ + +#include +#include + +// [Start hash_map_conversion_arkTs_two] +// Convert value to string and return +std::string HashMap::value2String(napi_env env, napi_value value) { + size_t stringSize = 0; + napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize); // Get string length + std::string valueString; + valueString.resize(stringSize + 1); + napi_get_value_string_utf8(env, value, &valueString[0], stringSize + 1, &stringSize); // Convert to string based on length + return valueString; +} +napi_value HashMap::TsPutMap(napi_env env, napi_callback_info info) { + std::map myMap; + size_t argc = 3; + napi_value args[3] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + napi_value mapKey = args[0]; // key + napi_value mapVal = args[1]; // value + napi_value mapNum = args[2]; // length + + + uint32_t mapCNum = 0; + napi_get_value_uint32(env, mapNum, &mapCNum); + for (uint32_t i = 0; i < mapCNum; i++) { + napi_value keyNIndex, valNIndex; + napi_get_element(env, mapKey, i, &keyNIndex); + napi_get_element(env, mapVal, i, &valNIndex); + std::string keyIndex = value2String(env, keyNIndex); + int valIndex = 0; + napi_get_value_int32(env, valNIndex, &valIndex); + myMap[keyIndex] = valIndex; + OH_LOG_Print(LOG_APP, LOG_INFO, 0x0000, "Pure", "%{public}s %{public}d", keyIndex.c_str(), myMap[keyIndex]); + } + return nullptr; +} +// [End hash_map_conversion_arkTs_two] + +// [Start hash_map_conversion_arkTs_four] +napi_value HashMap::MapJson(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string jsonStr = value2String(env, args[0]); + std::map myMap = nlohmann::json::parse(jsonStr.c_str()); + OH_LOG_Print(LOG_APP, LOG_INFO, 0x0000, "Pure", "%{public}d %{public}d %{public}d", myMap["Abc"], myMap["Bcd"], + myMap["Cde"]); + return nullptr; +} +// [End hash_map_conversion_arkTs_four] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/ManageNativeCPlus.cpp b/NdkDevelopment/entry/src/main/cpp/ManageNativeCPlus.cpp new file mode 100644 index 0000000..dc76216 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/ManageNativeCPlus.cpp @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在ArkTS侧管理Native侧的C++对象 +*/ + +// [Start manage_native_c_plus_one] +class TestClass { +public: + int GetValue() { + return this->value; + } + void SetValue(int value) { + this->value = value; + } +private: + int value = 999; +}; +// [End manage_native_c_plus_one] + +// [Start manage_native_c_plus_two] +#include "napi/native_api.h" +#include "TestClass.h" +#include "hilog/log.h" +#define LOG_TAG "MY_TAG" + +static napi_value DefineObject(napi_env env, napi_callback_info info) { + OH_LOG_INFO(LOG_APP, "enter DefineObject"); + + napi_value result; + auto a = new TestClass(); + int64_t addrValue = (int64_t)a; + napi_create_bigint_int64(env, addrValue, &result); + OH_LOG_INFO(LOG_APP, "end DefineObject, addrValue:%{public}ld", addrValue); + return result; +} +// [End manage_native_c_plus_two] + +// [Start manage_native_c_plus_three] +static napi_value CallObject(napi_env env, napi_callback_info info) { + OH_LOG_INFO(LOG_APP, "enter CallObject"); + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + int64_t addrValue = 0; + bool flag = false; + napi_get_value_bigint_int64(env, args[0], &addrValue, &flag); + TestClass *a = (TestClass *)addrValue; + OH_LOG_INFO(LOG_APP, "CallObject, addrValue:%{public}ld", addrValue); + OH_LOG_INFO(LOG_APP, "CallObject, value:%{public}d", a->GetValue()); + a->SetValue(888); + return nullptr; +} +// [End manage_native_c_plus_three] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/RevArkTSObj.cpp b/NdkDevelopment/entry/src/main/cpp/RevArkTSObj.cpp new file mode 100644 index 0000000..8fde660 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/RevArkTSObj.cpp @@ -0,0 +1,99 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:Native侧如何对ArkTS传递的Object类型的数据、属性进行修改 +*/ + +#include + +// [Start rev_ark_ts_obj_cpp] +#include "RevArkTSObj.h" +napi_value RevArkTSObj::ModifyObject(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + + napi_value obj = args[0]; + + + napi_value obj1; + napi_value hello1; + napi_value arr1; + napi_value typedArray1; + + + napi_get_named_property(env, obj, "obj", &obj1); + char *buf = "this is modified"; + napi_value str1; + napi_create_string_utf8(env, buf, NAPI_AUTO_LENGTH, &str1); + napi_set_named_property(env, obj1, "str", str1); + napi_set_named_property(env, obj, "obj", obj1); + + + napi_create_string_utf8(env, "world0", NAPI_AUTO_LENGTH, &hello1); + napi_set_named_property(env, obj, "hello", hello1); + + + napi_get_named_property(env, obj, "arr", &arr1); + uint32_t arrLen; + napi_get_array_length(env, arr1, &arrLen); + for (int i = 0; i < arrLen; i++) { + napi_value tmp; + napi_create_uint32(env, i, &tmp); + napi_set_element(env, arr1, i, tmp); + } + napi_delete_element(env, arr1, 2, nullptr); + + + + + napi_get_named_property(env, obj, "typedArray", &typedArray1); + bool is_typedArray; + if (napi_ok != napi_is_typedarray(env, typedArray1, &is_typedArray)) { + return nullptr; + } + napi_typedarray_type type; + napi_value input_buffer; + size_t length; + size_t byte_offset; + napi_get_typedarray_info(env, typedArray1, &type, &length, nullptr, &input_buffer, &byte_offset); + // Retrieve the basic data buffer data of input_fuffer and the length byte_length of the basic data buffer. + void *data; + size_t byte_length; + napi_get_arraybuffer_info(env, input_buffer, &data, &byte_length); + // Create a new ArrayBuffer with a pointer pointing to the underlying data buffer of the ArrayBuffer, denoted as' output _ptr ' + napi_value output_buffer; + void *output_prt = nullptr; + napi_create_arraybuffer(env, byte_length, &output_prt, &output_buffer); + // Create typedarray using output buffer + napi_value output_array; + napi_create_typedarray(env, type, length, output_buffer, byte_offset, &output_array); + // Data is composed of consecutive memory locations, where reinterpret_cast(data) represents the memory address of its first element. + // Data is the old arraybuffer data pointer + uint8_t *input_bytes = reinterpret_cast(data) + byte_offset; + // Assign the 'outputting _ptr' pointer to 'outputting: bytes' + // Output_ptr is a new array buffer data pointer + uint8_t *output_bytes = reinterpret_cast(output_prt); + for (int i = 0; i < length; i++) { + // Multiply each element of the old arraybuffer data by 2 and assign it to the new arraybuffer data + output_bytes[i] = input_bytes[i] * 2; + } + // Assign the new typedArray to obj ['typedArray '] + napi_set_named_property(env, obj, "typedArray", output_array); + return obj; +} +// [End rev_ark_ts_obj_cpp] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/ark_ts_native_log_cpp.cpp b/NdkDevelopment/entry/src/main/cpp/ark_ts_native_log_cpp.cpp new file mode 100644 index 0000000..fe0a28f --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/ark_ts_native_log_cpp.cpp @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在ArkTS侧监听Native侧日志信息 +*/ + +// [Start ark_ts_native_log_cpp] +#include "napi/native_api.h" +#include +#include +#include + + +napi_ref logListenerRef = nullptr; +napi_ref onLogsFuncRef = nullptr; +static napi_value RegisterLogListener(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value globalThisAdapter = nullptr; + napi_get_cb_info(env, info, &argc, &globalThisAdapter, nullptr, nullptr); + + + napi_value getLogListenerFunc = nullptr; + napi_get_named_property(env, globalThisAdapter, "getLogsListener", &getLogListenerFunc); + + + napi_value logListener = nullptr; + napi_call_function(env, globalThisAdapter, getLogListenerFunc, 0, nullptr, &logListener); + + + napi_value onLogsFunc = nullptr; + napi_get_named_property(env, logListener, "onLogs", &onLogsFunc); + + + napi_create_reference(env, logListener, 1, &logListenerRef); + napi_create_reference(env, onLogsFunc, 1, &onLogsFuncRef); + + + return nullptr; +} +// [End ark_ts_native_log_cpp] + +// [Start ark_ts_native_log_cpp_one] +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor desc[] = { + {"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"registerLogListener", nullptr, RegisterLogListener, nullptr, nullptr, nullptr, napi_default, nullptr}}; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END +// [End ark_ts_native_log_cpp_one] + +// [Start ark_ts_native_log_cpp_two] +static void callOnLogs(napi_env env, LogLevel level, const char *message) { + + + size_t argc = 2; + napi_value argv[2] = {nullptr}; + + + int32_t tem = level; + napi_create_int32(env, tem, &argv[0]); + napi_create_string_utf8(env, message, strlen(message) + 1, &argv[1]); + napi_value logListener = nullptr; + napi_value onLogsFunc = nullptr; + napi_get_reference_value(env, logListenerRef, &logListener); + napi_get_reference_value(env, onLogsFuncRef, &onLogsFunc); + + + napi_call_function(env, logListener, onLogsFunc, argc, argv, nullptr); +} +// [End ark_ts_native_log_cpp_two] + +// [Start ark_ts_native_log_cpp_three] +static napi_value Add(napi_env env, napi_callback_info info) { + callOnLogs(env, LogLevel::LOG_INFO, "execute native Add function success"); + return nullptr; +} +// [End ark_ts_native_log_cpp_three] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/function_passed_over_cpp.cpp b/NdkDevelopment/entry/src/main/cpp/function_passed_over_cpp.cpp new file mode 100644 index 0000000..c0aaf0e --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/function_passed_over_cpp.cpp @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在C++调用从ArkTS传递过来的function +*/ + +// [Start function_passed_over_cpp] +static napi_value NativeCallArkTS(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + // Declare parameter array + napi_value args[1] = {nullptr}; + + // Retrieve the incoming parameters and sequentially place them into the parameter array + napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); + + // Create an int as a parameter for ArkTS + napi_value argv = nullptr; + napi_create_int32(env, 2, &argv ); + + // Call the incoming callback and return its result + napi_value result = nullptr; + napi_call_function(env, nullptr, args[0], 1, &argv, &result); + return result; +} +// [End function_passed_over_cpp] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/get_asynchronous_computation_cpp.cpp b/NdkDevelopment/entry/src/main/cpp/get_asynchronous_computation_cpp.cpp new file mode 100644 index 0000000..5eb8f10 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/get_asynchronous_computation_cpp.cpp @@ -0,0 +1,81 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在Native侧调用ArkTS侧异步方法,并获取异步计算结果到Native侧 +*/ + +// [Start get_asynchronous_computation_cpp] +#include "napi/native_api.h" +#include "hilog/log.h" + +// Define callback methods for the then property of Promise objects +// The callback method of the then attribute can have no return value +// In the following text, it is necessary to create an ArkTS function object through napi_make_function, so set the return value to napi_value and return nulliptr at the end of the function +napi_value ThenCallBack(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + int32_t asyncResult = 0; // ArkTS side asynchronous method calculation results + napi_get_value_int32(env, args[0], &asyncResult); + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "testTag-Native", "ArkTS Async Method Calculation Success, Result: %{public}d", + asyncResult); + return nullptr; +} +// Define callback methods for catch properties of Promise objects +// The callback method of the catch property can have no return value +// In the following text, it is necessary to create an ArkTS function object through napi_make_function, so set the return value to napi_value and return nulliptr at the end of the function +napi_value CatchCallBack(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + size_t strLen = 0; + napi_get_value_string_utf8(env, args[0], nullptr, 0, &strLen); // Get string length to strLen + char *strBuffer = new char[strLen + 1]; // Allocate a char array of appropriate size + napi_get_value_string_utf8(env, args[0], strBuffer, strLen + 1, &strLen); // Get a string representing the information about the abnormal calculation of the ArkTS side asynchronous method + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "testTag-Native", + "ArkTS Async Method Calculation Exception: %{public}s", strBuffer); + return nullptr; +} +static napi_value TestPromise(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); // Analyze the callback passed by ArkTS side + + napi_value arktsPromise = nullptr; + // Execute callback through napi_call_function to return the promise object created by ArkTS side + napi_call_function(env, nullptr, args[0], 0, nullptr, &arktsPromise); + + // Get the then property of the promise object, whose callback method is used to handle the asynchronous calculation results on the ArkTS side + napi_value thenProperty = nullptr; + napi_get_named_property(env, arktsPromise, "then", &thenProperty); + // Convert the then property callback method defined in the C++language into an ArkTS function object, which is a napi_value type value + napi_value thenCallback = nullptr; + napi_create_function(env, "thenCallback", NAPI_AUTO_LENGTH, ThenCallBack, nullptr, &thenCallback); + + // Get the catch property of the promise object, whose callback method is used to handle information about ArkTS side asynchronous computation exceptions + napi_value catchProperty = nullptr; + napi_get_named_property(env, arktsPromise, "catch", &catchProperty); + // Convert the catch property callback method defined in the C++language into an ArkTS function object, i.e. a napi_value type value + napi_value catchCallback = nullptr; + napi_create_function(env, "catchCallback", NAPI_AUTO_LENGTH, CatchCallBack, nullptr, &catchCallback); + + // Execute the callback of the then attribute through napi_call_function, similar to calling promise. then()=>{} on the ArkTS side + napi_call_function(env, arktsPromise, thenProperty, 1, &thenCallback, nullptr); + // Execute a callback for the catch property through napi_call_function, similar to calling promise. catch (()=>{}) on the ArkTS side + napi_call_function(env, arktsPromise, catchProperty, 1, &catchCallback, nullptr); + return nullptr; +} +// [End get_asynchronous_computation_cpp] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/main_thread_communication.cpp b/NdkDevelopment/entry/src/main/cpp/main_thread_communication.cpp new file mode 100644 index 0000000..050fe30 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/main_thread_communication.cpp @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:Native如何创建子线程,有什么约束,与主线程如何通信 +*/ + +// [Start main_thread_communication] +#include "napi/native_api.h" +#include "hilog/log.h" +#include "thread" + +napi_ref cbObj = nullptr; +napi_threadsafe_function tsfn; +#define NUMBER 666 +static void CallJs(napi_env env, napi_value js_cb, void *context, void *data) { + napi_get_reference_value(env, cbObj, &js_cb); + napi_value argv; + napi_create_int32(env, NUMBER, &argv); + napi_value result = nullptr; + napi_call_function(env, nullptr, js_cb, 1, &argv, &result); +} +static napi_value ThreadsTest(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value js_cb, work_name; + napi_status status; + status = napi_get_cb_info(env, info, &argc, &js_cb, nullptr, nullptr); + OH_LOG_INFO(LOG_APP, "ThreadSafeTest 0: %{public}d", status == napi_ok); + // Set initial_refcount to 0 for a weak reference, >0 for a strong reference. + status = napi_create_reference(env, js_cb, 1, &cbObj); + OH_LOG_INFO(LOG_APP, "napi_create_reference of js_cb to cbObj: %{public}d", status == napi_ok); + status = napi_create_string_utf8(env, "Work Item", NAPI_AUTO_LENGTH, &work_name); + status = napi_create_threadsafe_function(env, js_cb, NULL, work_name, 0, 1, NULL, NULL, NULL, CallJs, &tsfn); + OH_LOG_INFO(LOG_APP, "napi_create_threadsafe_function : %{public}d", status == napi_ok); + std::thread t([]() { + std::thread::id this_id = std::this_thread::get_id(); + OH_LOG_INFO(LOG_APP, "thread0 %{public}d.\n", this_id); + napi_status status; + status = napi_acquire_threadsafe_function(tsfn); + OH_LOG_INFO(LOG_APP, "thread : %{public}d", status == napi_ok); + napi_call_threadsafe_function(tsfn, NULL, napi_tsfn_blocking); + }); + t.detach(); + return NULL; +} +// [End main_thread_communication] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/napi_create_arraybuffer.cpp b/NdkDevelopment/entry/src/main/cpp/napi_create_arraybuffer.cpp new file mode 100644 index 0000000..ead0a36 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/napi_create_arraybuffer.cpp @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:Native侧如何通过char指针构造ArrayBuffer数组 +*/ + +#include + +// [Start napi_create_arraybuffer_cpp] +#include "CharToArrBuffer.h" +napi_value CharToArrBuffer::TestCharBuf(napi_env env, napi_callback_info info) { + napi_value result = nullptr; + char *buf = nullptr; + // Create an Array buffer + napi_create_arraybuffer(env, 100, reinterpret_cast(&buf), &result); + // Assign an ArrayBuffer + for (int i = 0; i < 100; i++) { + buf[i] = i + 2; + } + return result; +} +// [End napi_create_arraybuffer_cpp] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/napi_create_buffer.cpp b/NdkDevelopment/entry/src/main/cpp/napi_create_buffer.cpp new file mode 100644 index 0000000..3d185b3 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/napi_create_buffer.cpp @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:在ArkTS侧如何引用Native侧使用napi_create_buffer接口构造的对象 +*/ + +#include +// [Start napi_create_buffer_cpp] +#include "CreatBuffer.h" + +napi_value CreatBuffer::TestBuffer(napi_env env, napi_callback_info) { + size_t length = 100; + char *data = nullptr; + napi_value result = nullptr; + napi_create_buffer(env, length, reinterpret_cast(&data), &result); + + + char buf[50] = {0}; + for (int i = 0; i < 50; i++) { + buf[i] = i + 2; + } + napi_create_buffer_copy(env, 50, buf, reinterpret_cast(&data), &result); + return result; +} +// [Start napi_create_buffer_cpp] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/open_file_on_c_side_cpp.cpp b/NdkDevelopment/entry/src/main/cpp/open_file_on_c_side_cpp.cpp new file mode 100644 index 0000000..b8eba3b --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/open_file_on_c_side_cpp.cpp @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:C侧如何打开文件 +*/ + +// [Start open_file_on_c_side_cpp] +static napi_value OpenFile(unsigned int fd, unsigned int fd2) { + OH_LOG_INFO(LOG_APP, "OpenFile"); + + if (fd != -1) { + char buffer[4096]; + ssize_t bytesRead; + // Read the file content into the buffer + bytesRead = read(fd, buffer, sizeof(buffer)); + if (bytesRead == -1) { + OH_LOG_INFO(LOG_APP, "fail to read file"); + close(fd); // Close file descriptor + return nullptr; + } + while (bytesRead != 0) { + OH_LOG_INFO(LOG_APP, "Read file size %{public}lu", bytesRead); + OH_LOG_INFO(LOG_APP, "Read file cg"); + char *pData1 = buffer; + OH_LOG_INFO(LOG_APP, "file content: \n%{public}s", pData1); + ssize_t bytesWrite; + bytesWrite = write(fd2, pData1, bytesRead); + if (bytesWrite == -1) { + OH_LOG_INFO(LOG_APP, "Writing file failed"); + close(fd2); // Close file descriptor + return nullptr; + } + bytesRead = read(fd, buffer, sizeof(buffer)); + } + // Close file descriptor + close(fd); + close(fd2); // Close file descriptor + } + return nullptr; +} +static napi_value ReadFile(napi_env env, napi_callback_info info) { + size_t argc = 2; + napi_value args[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + unsigned int fd = -1; + napi_get_value_uint32(env, args[0], &fd); + unsigned int fd2 = -1; + napi_get_value_uint32(env, args[1], &fd2); + OpenFile(fd, fd2); + return nullptr; +} +// [End open_file_on_c_side_cpp] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/thread_limit_cpp.cpp b/NdkDevelopment/entry/src/main/cpp/thread_limit_cpp.cpp new file mode 100644 index 0000000..eec2406 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/thread_limit_cpp.cpp @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:Native侧获取env具有线程限制,如何在C++子线程触发ArkTS侧回调 +*/ + +// [Start thread_limit_cpp] +static napi_value AddTSFCallback(napi_env env, napi_callback_info info) { + // ... + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + auto contextData = new ContextData; + contextData->args = strBuff; + // Create thread safe function objects, register and bind callbacks and call_js_cb callbacks + napi_create_threadsafe_function(env, args[2], nullptr, asyncName, MAX_MSG_QUEUE_SIZE, INITIAL_THREAD_COUNT, nullptr,nullptr, nullptr, CallJsFunction, &tsFun); + thread t(AddFunc, static_cast(contextData)); // Create C++sub threads to handle business logic + t.detach(); + return nullptr; +} + +static void AddFunc([[maybe_unused]] napi_env env, void *data) { + ContextData *contextData = static_cast(data); // Context analysis, business processing, addition of two numbers + contextData->result = add(contextData->num1, contextData->num2); // Place the results up and down + napi_call_threadsafe_function(tsFun, data, napi_tsfn_blocking); // Call thread safe functions +} + +static void CallJsFunction(napi_env env, napi_value callBack, [[maybe_unused]] void *context, void *data) { + ContextData *contextData = static_cast(data); + // ... + napi_value callBackArgs = nullptr; + napi_create_double(env, contextData->result, &callBackArgs); + napi_value callBackResult = nullptr; + napi_call_function(env, undefined, callBack, 1, &callBackArgs, &callBackResult); // Call callback and provide feedback on the results to the ArkTS application side + DeleteContext(env, contextData); +} +// [End thread_limit_cpp] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/cpp/types/libentry/Index.d.ts b/NdkDevelopment/entry/src/main/cpp/types/libentry/Index.d.ts index 54d8504..f6b9ad8 100644 --- a/NdkDevelopment/entry/src/main/cpp/types/libentry/Index.d.ts +++ b/NdkDevelopment/entry/src/main/cpp/types/libentry/Index.d.ts @@ -5,4 +5,28 @@ export const addByLibPath: (arg0: number, arg1: number, arg2: string) => ESObjec export const callFunction: (arg0: object) => void; -export const subSobyDlOpenSo: (arg0: number, arg1: number, arg2: string) => number; \ No newline at end of file +export const subSobyDlOpenSo: (arg0: number, arg1: number, arg2: string) => number; + +export const testBuffer: () => ArrayBuffer; + +export const modifyObject: (a: object) => object; + +export const tsPutMap: (a:object, b:object, c:number) => void; + +export const mapJson: (a:string) => void; + +import { GlobalThisAdapter } from '../../../ets/interface/Log' +export const add: () => void; +export const registerLogListener: (a: GlobalThisAdapter) => void; + +export const defineObject: () => number; + +export const callObject: (a:number) => void; + +export const addTSFCallback: (a: number, b: number, c:CallableFunction) => number; + +export const nativeCallArkTS: (a:CallableFunction) => string; + +export const testPromise: (a:CallableFunction) => void; + +export const mainThread: (a:CallableFunction) => void; diff --git a/NdkDevelopment/entry/src/main/cpp/worker_calls_napi_to_implement_loop_cpp.cpp b/NdkDevelopment/entry/src/main/cpp/worker_calls_napi_to_implement_loop_cpp.cpp new file mode 100644 index 0000000..cf58b51 --- /dev/null +++ b/NdkDevelopment/entry/src/main/cpp/worker_calls_napi_to_implement_loop_cpp.cpp @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何利用worker子线程调用napi实现loop改写变量 +*/ + +// [Start worker_calls_napi_to_implement_loop_cpp_one] +struct CallbackContext { + napi_env env = nullptr; + napi_ref callbackRef = nullptr; + int retData = 0; +}; +// [End worker_calls_napi_to_implement_loop_cpp_one] + +// [Start worker_calls_napi_to_implement_loop_cpp_two] +#include "WorkerCallNapiLoop.h" +#include +#include + +void WorkerCallNapiLoop::SubThread(CallbackContext *context) { + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(context->env, &loop); + // Uvw_ork_t is the structure that associates loop and thread pool callback functions + uv_work_t *work = new uv_work_t; + work->data = (CallbackContext *)context; + uv_queue_work( + loop, work, [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + CallbackContext *context = (CallbackContext *)work->data; + napi_handle_scope scope = nullptr; + // Manage the lifecycle of napi_value to prevent memory leaks + napi_open_handle_scope(context->env, &scope); + if (scope == nullptr) { + return; + } + napi_value callback = nullptr; + napi_get_reference_value(context->env, context->callbackRef, &callback); + while (context->retData < 100) { + context->retData += 1; + napi_value retArg; + napi_create_int32(context->env, context->retData, &retArg); + napi_value ret; + napi_call_function(context->env, nullptr, callback, 1, &retArg, &ret); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + napi_close_handle_scope(context->env, scope); + if (context->retData > 99) { + napi_delete_reference(context->env, context->callbackRef); + if (work != nullptr) { + delete work; + } + } + }); +}; +napi_value WorkerCallNapiLoop::MainThread(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {0}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + auto asyncContext = new CallbackContext(); + asyncContext->env = env; + napi_create_reference(env, args[0], 1, &asyncContext->callbackRef); + auto func = [](void *asyncContext) { + delete asyncContext; + }; + napi_add_env_cleanup_hook(asyncContext->env, func, asyncContext); + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env, &loop); + // Start sub thread + std::thread testThread(SubThread, asyncContext); + testThread.detach(); + return nullptr; +} +// [End worker_calls_napi_to_implement_loop_cpp_two] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/entryability/EntryAbilityNativeLog.ets b/NdkDevelopment/entry/src/main/ets/entryability/EntryAbilityNativeLog.ets new file mode 100644 index 0000000..f76bbc4 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/entryability/EntryAbilityNativeLog.ets @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在ArkTS侧监听Native侧日志信息 +*/ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +import { GlobalThisAdapter } from '../interface/Log'; +import testNapi from 'libentry.so'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + // [Start entry_ability_native_log] + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + let globalThisAdapter: GlobalThisAdapter = GlobalThisAdapter.getInstance(); + testNapi.registerLogListener(globalThisAdapter); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + // [End entry_ability_native_log] +} \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/interface/Log.ts b/NdkDevelopment/entry/src/main/ets/interface/Log.ts new file mode 100644 index 0000000..6a22171 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/interface/Log.ts @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在ArkTS侧监听Native侧日志信息 +*/ + +// [Start ark_ts_native_log] +import { hilog } from '@kit.PerformanceAnalysisKit'; + + +export class GlobalThisAdapter { + private constructor() { + } + + + private static instance: GlobalThisAdapter; + private _logListener: LogsListener = new LogsListener(); + + + public static getInstance(): GlobalThisAdapter { + if (!GlobalThisAdapter.instance) { + GlobalThisAdapter.instance = new GlobalThisAdapter(); + } + return GlobalThisAdapter.instance; + } + + + getLogsListener(): LogsListener | undefined { + return this._logListener; + } + + + setLogsListener(value: LogsListener): void { + this._logListener = value; + } +} + + +export class LogsListener implements OnLogsListener { + public constructor() { + } + + + onLogs(level: LogLevel, message: string): void { + switch (level) { + case LogLevel.DEBUG: + hilog.debug(0x0000, 'debug', 'debug message is %{public}s', message); + break; + case LogLevel.INFO: + hilog.info(0x0000, 'info', 'info message is %{public}s', message); + break; + case LogLevel.WARN: + hilog.warn(0x0000, 'warn', 'warn message is %{public}s', message) + break; + case LogLevel.ERROR: + hilog.error(0x0000, 'error', 'error message is %{public}s', message); + break; + case LogLevel.FATAL: + hilog.fatal(0x0000, 'fatal', 'fatal message is %{public}s', message); + break; + default: + hilog.info(0x0000, 'info', 'info message is %{public}s', message); + } + } +} + + +enum LogLevel { + DEBUG = 3, + INFO, + WARN, + ERROR, + FATAL +} + + +export default interface OnLogsListener { + onLogs(level: number, message: string): void; +} +// [End ark_ts_native_log] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/FunctionPassedOverArkTs.ets b/NdkDevelopment/entry/src/main/ets/pages/FunctionPassedOverArkTs.ets new file mode 100644 index 0000000..2bb6274 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/FunctionPassedOverArkTs.ets @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在C++调用从ArkTS传递过来的function +*/ + +// [Start function_passed_over_ark_ts] +// entry/src/main/ets/pages/Index.ets +// Introduce native capabilities through import. +import nativeModule from 'libentry.so' + +@Entry +@Component +struct Index { + @State message: string = 'Test Node-API nativeCallArkTS result: '; + build() { + Row() { + Column() { + // Call the nativeCallArkTS method, corresponding to the Native NativeCallArkTS, and call the ArkTS function in Native. + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + this.message += nativeModule.nativeCallArkTS((a: number)=> { + return a * 2; + }); + }) + } + .width('100%') + } + .height('100%') + } +} +// [End function_passed_over_ark_ts] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/GetAsynchronousComputation.ets b/NdkDevelopment/entry/src/main/ets/pages/GetAsynchronousComputation.ets new file mode 100644 index 0000000..d858c6e --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/GetAsynchronousComputation.ets @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在Native侧调用ArkTS侧异步方法,并获取异步计算结果到Native侧 +*/ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +// [Start get_asynchronous_computation] +// ... +import testNapi from 'libentry.so'; + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + Text('testPromise') + // ... + .onClick(() => { + hilog.info(0x0000, 'testTag-ArkTS', 'Before calling the native interface.'); + // Call the Native interface and return the call information + testNapi.testPromise(() => { + // Callback is used to create ArkTS side Promise objects + return new Promise((resolve: Function, reject: Function) => { + // Simulate ArkTS side asynchronous method through setTimeout interface + // Scenario: After 2 seconds, trigger the setTimeout timer callback to generate a random number randomNumber. By judging the size of the random number, it is used to trigger different states of the promise object, and then perform different callback processing + setTimeout(()=>{ + const randomNumber: number = 100 * Math.random(); + if (randomNumber > 50) { + // If randomNumber is greater than 50, call the resolve method to transition the state of the Promise object to the fulfilled state, and pass the random number to the Native side as a callback parameter for the then method + resolve(randomNumber); + } else { + // If randomNumber is less than/equal to 50, call the reject method to transfer the state of the Promise object to the rejected state, and pass the exception information to the Native side as the callback parameter of the catch method + reject('The random number is less than 50, so the promise object is rejected.') + } + }, 2000); + }) + } + ) + hilog.info(0x0000, 'testTag-ArkTS', 'After the native interface is called.'); + }) + } + .width('100%') + } + .height('100%') + } +} +// [End get_asynchronous_computation] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/HashMapConversionArkTs.ets b/NdkDevelopment/entry/src/main/ets/pages/HashMapConversionArkTs.ets new file mode 100644 index 0000000..7da3ff6 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/HashMapConversionArkTs.ets @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2024 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 { HashMap } from '@kit.ArkTS'; +import testNapi from 'libentry.so'; + +/* +* FAQ:如何实现ArkTS与C/C++的HashMap转换 +*/ + +// [Start hash_map_conversion_arkTs_one] +let hashMap: HashMap = new HashMap(); +hashMap.set("Abc", 123); +hashMap.set("Bcd", 234) +hashMap.set("Cde", 345); + + +let keysArray: Array = Array.from(hashMap.keys()); +let valuesArray: Array = Array.from(hashMap.values()); +testNapi.tsPutMap(keysArray, valuesArray, hashMap.length); +// [End hash_map_conversion_arkTs_one] + +class HashMapDemo { + // [Start hash_map_conversion_arkTs_three] + map2rec(map: HashMap): Record { + // Map to Record + let Rec: Record = {}; + map.forEach((value: ESObject, key: string) => { + if (value instanceof HashMap) { + //If value is of HashMap type + let vRec: Record = this.map2rec(value); + value = vRec; + } + Rec[key] = value; + }) + return Rec; + } + // [Start hash_map_conversion_arkTs_three] + + test() { + // [Start hash_map_conversion_arkTs_four] + let myRec: Record = this.map2rec(hashMap); + let str: string = JSON.stringify(myRec); + testNapi.mapJson(str); + // [End hash_map_conversion_arkTs_four] + } +} + diff --git a/NdkDevelopment/entry/src/main/ets/pages/ManageNativeCPlus.ets b/NdkDevelopment/entry/src/main/ets/pages/ManageNativeCPlus.ets new file mode 100644 index 0000000..290edc9 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/ManageNativeCPlus.ets @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何在ArkTS侧管理Native侧的C++对象 +*/ + +// [Start manage_native_c_plus_four] +import testNapi from 'libentry.so'; + +@Entry +@Component +struct Index { + @State message: string = 'DefineObject'; + @State message2: string = 'CallObject'; + addr: number = 0; + + build() { + Column() { + Button(this.message) + .fontSize(16) + .fontWeight(FontWeight.Bold) + .onClick(() => { + this.addr = testNapi.defineObject(); + console.log('testTag:' + this.addr.toString()); + }) + Button(this.message2) + .fontSize(16) + .fontWeight(FontWeight.Bold) + .onClick(() => { + if (this.addr != 0) { + testNapi.callObject(this.addr); + this.message2 = 'CallObject'; + } else { + this.message2 = 'want define Object'; + } + }) + } + .justifyContent(FlexAlign.Center) + .height('100%') + .width('100%') + } +} +// [End manage_native_c_plus_four] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/NapiCreateBufferArkTs.ets b/NdkDevelopment/entry/src/main/ets/pages/NapiCreateBufferArkTs.ets new file mode 100644 index 0000000..09ffb71 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/NapiCreateBufferArkTs.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:在ArkTS侧如何引用Native侧使用napi_create_buffer接口构造的对象 +*/ + +// [Start napi_create_buffer_arkTs] +import testNapi from 'libentry.so'; + + +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + let arr = testNapi.testBuffer(); + let result = new Uint8Array(arr); + for (let index = 0; index < result.byteLength; index++) { + console.info(`res[${index}] = ${result[index]}`) + } + }) + } + .width('100%') + } + .height('100%') + } +} +// [End napi_create_buffer_arkTs] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/OpenFileOnCSide.ets b/NdkDevelopment/entry/src/main/ets/pages/OpenFileOnCSide.ets new file mode 100644 index 0000000..757a2bf --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/OpenFileOnCSide.ets @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:C侧如何打开文件 +*/ + +// [Start open_file_on_c_side] +import { fileIo, picker } from '@kit.CoreFileKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import testNapi from 'libentry.so'; + +@Entry +@Component +struct Index { + @State message: string = '打开文件'; + + async open() { + const photoSelectOptions = new picker.PhotoSelectOptions(); + photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // Filter and select media file type as IMAGE + photoSelectOptions.maxSelectNumber = 5; // Select the maximum number of media files + let uris: Array = []; + const photoViewPicker = new picker.PhotoViewPicker(); + await photoViewPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => { + uris = photoSelectResult.photoUris; + console.info('photoViewPicker.select to file succeed and uris are:' + uris); + }).catch((err: BusinessError) => { + console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`); + }) + let uri: string = uris[0]; + let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY); + console.info('file fd: ' + file.fd); + let fd = file.fd + let filesDir = getContext(this).filesDir; + fileIo.copyFileSync(fd, filesDir + '/test2.jpg') + let file2 = fileIo.openSync(filesDir + '/test2.jpg', fileIo.OpenMode.READ_ONLY); + let file3 = fileIo.openSync(filesDir + '/test3.jpg', fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); + testNapi.ReadFile(file2.fd, file3.fd) + } + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .onClick(() => { + this.open(); + }) + .width('100%') + } + .height('100%') + } +} +// [End open_file_on_c_side] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/RevArkTSObjArkTs.ets b/NdkDevelopment/entry/src/main/ets/pages/RevArkTSObjArkTs.ets new file mode 100644 index 0000000..a5815e4 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/RevArkTSObjArkTs.ets @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:Native侧如何对ArkTS传递的Object类型的数据、属性进行修改 +*/ + +// [Start rev_ark_ts_obj_ark_ts] +import testNapi from 'libentry.so'; + + +interface Obj1 { + obj: Obj2, + hello: String, + arr: number[], + typedArray: Uint8Array +} + + +interface Obj2 { + str: string +} + + +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + const typedArr = new Uint8Array(3); + typedArr[0] = 1; + typedArr[1] = 2; + typedArr[2] = 3; + const obj: Obj1 = { + obj: { str: 'obj in obj' }, + hello: 'world', + arr: [94, 32, 43], + typedArray: typedArr + } + console.info(`Test NAPI modifyObject result is ${JSON.stringify(testNapi.modifyObject(obj))}`) + }) + } + .width('100%') + } + .height('100%') + } +} +// [End rev_ark_ts_obj_ark_ts] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/ThreadLimitArkTs.ets b/NdkDevelopment/entry/src/main/ets/pages/ThreadLimitArkTs.ets new file mode 100644 index 0000000..2e7dae5 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/ThreadLimitArkTs.ets @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:Native侧获取env具有线程限制,如何在C++子线程触发ArkTS侧回调 +*/ + +// [Start thread_limit_ark_ts] +import testNapi from 'libentry.so'; +@Entry +@Component +struct Index { + result: number = 0; + + // ... + build() { + Button() + .onClick(() => { + testNapi.addTSFCallback(2, 3, (nativeResult: number) => { + this.result = nativeResult; + }); + }) + } +// ... +} +// [End thread_limit_ark_ts] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop.ets b/NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop.ets new file mode 100644 index 0000000..4d1f5f4 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop.ets @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何利用worker子线程调用napi实现loop改写变量 +*/ + +// [Start worker_calls_api_to_implement_loop] +import { MessageEvents, worker } from '@kit.ArkTS'; +import { Prompt } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + @State progress: number = 0; + @State message: string = '0' + state: number = 0 + + build() { + Column() { + Row() { + Button("开始") + .fontSize(40) + .fontWeight(FontWeight.Bold) + .onClick(() => { + if (this.state == 1) { + Prompt.showToast({ message: "Please do not click again" }) + return + } + this.state = 1 + let worker1: worker.ThreadWorker = + new worker.ThreadWorker('entry/ets/workers/Worker.ets', { name: "worker1" }); + worker1.postMessage('this is a msg to start worker1'); + worker1.onmessage = (e: MessageEvents) => { + this.progress = e.data.data as number + this.message = String(this.progress) + console.log('=====js main, process is:' + this.message) + + if (this.progress == 100) { + worker1.terminate() + this.state = 0 + } + } + }); + } + .margin({ + top: 10, + bottom: 10, + left: 5, + right: 5 + }) + + Row() { + Text(this.message) + .fontSize(50) + } + .margin({ + top: 10, + bottom: 5, + left: 5, + right: 5 + }) + } + } +} +// [End worker_calls_api_to_implement_loop] \ No newline at end of file diff --git a/NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop_Two.ets b/NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop_Two.ets new file mode 100644 index 0000000..b1980a0 --- /dev/null +++ b/NdkDevelopment/entry/src/main/ets/pages/WorkerCallsNapiToImplementLoop_Two.ets @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2024 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. +*/ + +/* +* FAQ:如何利用worker子线程调用napi实现loop改写变量 +*/ + +// [Start worker_calls_api_to_implement_loop_two] +import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS'; +import testNapi from 'libentry.so'; + +const workerPort: ThreadWorkerGlobalScope = worker.workerPort; + +workerPort.onmessage = (e: MessageEvents) => { + testNapi.mainThread((data:ESObject)=>{ + console.log("==worker func:data is :" + data); + workerPort.postMessage({ 'type': 1, "data": data }); + }); +} +// [End worker_calls_api_to_implement_loop_two] \ No newline at end of file -- Gitee