From f9e59d0f8d3dd29510fa9e27046bf4fd16bda602 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 21 Feb 2025 14:10:47 +0300 Subject: [PATCH 01/13] Further ANI work --- interop/src/cpp/ani/ani.h | 24 +++--- interop/src/cpp/ani/convertors-ani.h | 117 ++++++++++++++++++++++++++- interop/src/cpp/ets/convertors-ets.h | 35 ++++++-- 3 files changed, 154 insertions(+), 22 deletions(-) diff --git a/interop/src/cpp/ani/ani.h b/interop/src/cpp/ani/ani.h index 3adbe2416e..e6a175fd3b 100644 --- a/interop/src/cpp/ani/ani.h +++ b/interop/src/cpp/ani/ani.h @@ -36,7 +36,7 @@ typedef size_t ani_size; // Primitive types: typedef uint8_t ani_boolean; -typedef uint32_t ani_char; +typedef uint16_t ani_char; // NOTE: Change by uint32_t when #22672 is resolved. typedef int8_t ani_byte; typedef int16_t ani_short; typedef int32_t ani_int; @@ -128,9 +128,6 @@ typedef ani_fixedarray ani_fixedarray_double; typedef ani_fixedarray ani_fixedarray_ref; #endif // __cplusplus -struct __ani_gref; -typedef struct __ani_gref *ani_gref; - struct __ani_wref; typedef struct __ani_wref *ani_wref; @@ -204,6 +201,7 @@ typedef enum { ANI_INVALID_ARGS, ANI_INVALID_TYPE, ANI_INVALID_DESCRIPTOR, + ANI_INCORRECT_REF, ANI_PENDING_ERROR, ANI_NOT_FOUND, ANI_ALREADY_BINDED, @@ -6258,7 +6256,7 @@ struct __ani_interaction_api { * @param[out] result A pointer to store the created global reference. * @return Returns a status code of type `ani_status` indicating success or failure. */ - ani_status (*GlobalReference_Create)(ani_env *env, ani_ref ref, ani_gref *result); + ani_status (*GlobalReference_Create)(ani_env *env, ani_ref ref, ani_ref *result); /** * @brief Deletes a global reference. @@ -6269,7 +6267,7 @@ struct __ani_interaction_api { * @param[in] gref The global reference to delete. * @return Returns a status code of type `ani_status` indicating success or failure. */ - ani_status (*GlobalReference_Delete)(ani_env *env, ani_gref gref); + ani_status (*GlobalReference_Delete)(ani_env *env, ani_ref gref); /** * @brief Creates a weak reference. @@ -6301,10 +6299,12 @@ struct __ani_interaction_api { * * @param[in] env A pointer to the environment structure. * @param[in] wref The weak reference to query. - * @param[out] result A pointer to store the retrieved local reference. + * @param[out] was_released_result A pointer to boolean flag which indicates that wref is GC collected. + * @param[out] ref_result A pointer to store the retrieved local reference. * @return Returns a status code of type `ani_status` indicating success or failure. */ - ani_status (*WeakReference_GetReference)(ani_env *env, ani_wref wref, ani_ref *result); + ani_status (*WeakReference_GetReference)(ani_env *env, ani_wref wref, ani_boolean *was_released_result, + ani_ref *ref_result); /** * @brief Creates a new array buffer. @@ -8868,11 +8868,11 @@ struct __ani_env { { return c_api->TupleValue_SetItem_Ref(this, tuple_value, index, value); } - ani_status GlobalReference_Create(ani_ref ref, ani_gref *result) + ani_status GlobalReference_Create(ani_ref ref, ani_ref *result) { return c_api->GlobalReference_Create(this, ref, result); } - ani_status GlobalReference_Delete(ani_gref ref) + ani_status GlobalReference_Delete(ani_ref ref) { return c_api->GlobalReference_Delete(this, ref); } @@ -8884,9 +8884,9 @@ struct __ani_env { { return c_api->WeakReference_Delete(this, wref); } - ani_status WeakReference_GetReference(ani_wref wref, ani_ref *result) + ani_status WeakReference_GetReference(ani_wref wref, ani_boolean *was_released_result, ani_ref *ref_result) { - return c_api->WeakReference_GetReference(this, wref, result); + return c_api->WeakReference_GetReference(this, wref, was_released_result, ref_result); } ani_status CreateArrayBuffer(size_t length, void **data_result, ani_arraybuffer *arraybuffer_result) { diff --git a/interop/src/cpp/ani/convertors-ani.h b/interop/src/cpp/ani/convertors-ani.h index 05c27dcecf..e6ad2272ca 100644 --- a/interop/src/cpp/ani/convertors-ani.h +++ b/interop/src/cpp/ani/convertors-ani.h @@ -29,11 +29,124 @@ template struct InteropTypeConverter { using InteropType = T; - static T convertFrom(ani_env* env, InteropType value) { return value; } - static InteropType convertTo(ani_env* env, T value) { return value; } + static T convertFrom(ani_env* env, InteropType value) = delete; + static InteropType convertTo(ani_env* env, T value) = delete; static void release(ani_env* env, InteropType value, T converted) {} }; +template<> +struct InteropTypeConverter { + using InteropType = ani_byte; + static inline KByte convertFrom(ani_env* env, InteropType value) { + return value; + } + static inline InteropType convertTo(ani_env* env, KByte value) { + return value; + } + static inline void release(ani_env* env, InteropType value, KByte converted) {} +}; + +template<> +struct InteropTypeConverter { + using InteropType = ani_boolean; + static inline KBoolean convertFrom(ani_env* env, InteropType value) { + return value; + } + static inline InteropType convertTo(ani_env* env, KBoolean value) { + return value; + } + static inline void release(ani_env* env, InteropType value, KBoolean converted) {} +}; + +template<> +struct InteropTypeConverter { + using InteropType = ani_int; + static inline KInt convertFrom(ani_env* env, InteropType value) { + return value; + } + static inline InteropType convertTo(ani_env* env, KInt value) { + return value; + } + static inline void release(ani_env* env, InteropType value, KInt converted) {} +}; + +template<> +struct InteropTypeConverter { + using InteropType = ani_int; + static inline KUInt convertFrom(ani_env* env, InteropType value) { + return value; + } + static inline InteropType convertTo(ani_env* env, KUInt value) { + return value; + } + static inline void release(ani_env* env, InteropType value, KUInt converted) {} +}; + + +template<> +struct InteropTypeConverter { + using InteropType = ani_float; + static inline KFloat convertFrom(ani_env* env, InteropType value) { + return value; + } + static inline InteropType convertTo(ani_env* env, KFloat value) { + return value; + } + static inline void release(ani_env* env, InteropType value, KFloat converted) {} +}; + +template<> +struct InteropTypeConverter { + using InteropType = ani_object; + static inline KVMObjectHandle convertFrom(ani_env* env, InteropType value) { + return reinterpret_cast(value); + } + static inline InteropType convertTo(ani_env* env, KVMObjectHandle value) { + return reinterpret_cast(value); + } + static inline void release(ani_env* env, InteropType value, KVMObjectHandle converted) {} +}; + +template<> +struct InteropTypeConverter { + using InteropType = ani_fixedarray_byte; + static inline KInteropBuffer convertFrom(ani_env* env, InteropType value) { + if (value == nullptr) return KInteropBuffer(); + ani_size length = 0; + env->FixedArray_GetLength(value, &length); + KByte* data = new KByte[length]; + env->FixedArray_GetRegion_Byte(value, 0, length, (ani_byte*)data); + KInteropBuffer result = { 0 }; + result.data = data; + result.length = length; + return result; + } + static inline InteropType convertTo(ani_env* env, KInteropBuffer value) { + ani_fixedarray_byte result; + env->FixedArray_New_Byte(value.length, &result); + env->FixedArray_SetRegion_Byte(result, 0, value.length, reinterpret_cast(value.data)); + value.dispose(value.resourceId); + return result; + } + static inline void release(ani_env* env, InteropType value, KInteropBuffer converted) { + delete [] (KByte*)converted.data; + } +}; + +template<> +struct InteropTypeConverter { + using InteropType = ani_fixedarray_byte; + static inline KInteropReturnBuffer convertFrom(ani_env* env, InteropType value) = delete; + static inline InteropType convertTo(ani_env* env, KInteropReturnBuffer value) { + ani_fixedarray_byte result; + env->FixedArray_New_Byte(value.length, &result); + env->FixedArray_SetRegion_Byte(result, 0, value.length, reinterpret_cast(value.data)); + value.dispose(value.data, value.length); + return result; + }; + static inline void release(ani_env* env, InteropType value, KInteropReturnBuffer converted) {} +}; + template<> struct InteropTypeConverter { using InteropType = ani_string; diff --git a/interop/src/cpp/ets/convertors-ets.h b/interop/src/cpp/ets/convertors-ets.h index b8d7f5257d..139d1a340e 100644 --- a/interop/src/cpp/ets/convertors-ets.h +++ b/interop/src/cpp/ets/convertors-ets.h @@ -55,7 +55,7 @@ struct InteropTypeConverter { template<> struct InteropTypeConverter { - using InteropType = KUInt; + using InteropType = ets_int; static KUInt convertFrom(EtsEnv* env, InteropType value) { return value; } static InteropType convertTo(EtsEnv* env, KUInt value) { return value; } static void release(EtsEnv* env, InteropType value, KUInt converted) {} @@ -79,18 +79,37 @@ struct InteropTypeConverter { template<> struct InteropTypeConverter { - using InteropType = KVMObjectHandle; - static KVMObjectHandle convertFrom(EtsEnv* env, InteropType value) { return value; } - static InteropType convertTo(EtsEnv* env, KVMObjectHandle value) { return value; } + using InteropType = ets_object; + static KVMObjectHandle convertFrom(EtsEnv* env, InteropType value) { + return reinterpret_cast(value); + } + static InteropType convertTo(EtsEnv* env, KVMObjectHandle value) { + return reinterpret_cast(value); + } static void release(EtsEnv* env, InteropType value, KVMObjectHandle converted) {} }; template<> struct InteropTypeConverter { - using InteropType = KInteropBuffer; - static KInteropBuffer convertFrom(EtsEnv* env, InteropType value) { return value; } - static InteropType convertTo(EtsEnv* env, KInteropBuffer value) { return value; } - static void release(EtsEnv* env, InteropType value, KInteropBuffer converted) {} + using InteropType = ets_byteArray; + static KInteropBuffer convertFrom(EtsEnv* env, InteropType value) { + if (!value) return KInteropBuffer(); + KInteropBuffer result; + result.data = (KByte*)env->PinByteArray(value); + result.length = env->GetArrayLength(value); + return result; + } + static InteropType convertTo(EtsEnv* env, KInteropBuffer value) { + ets_byteArray array = env->NewByteArray(value.length); + KByte* data = (KByte*)env->PinByteArray(array); + memcpy(data, (KByte*)value.data, value.length); + env->UnpinByteArray(array); + value.dispose(value.resourceId); + return array; + } + static void release(EtsEnv* env, InteropType value, KInteropBuffer converted) { + env->UnpinByteArray(value); + } }; template<> -- Gitee From a2f7b3cfd02f461eef28cc70347cb924100289a4 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 21 Feb 2025 15:01:46 +0300 Subject: [PATCH 02/13] VM loader logic --- arkoala-arkts/loader/src/loader.ts | 5 +++++ interop/src/cpp/vmloader.cc | 25 ++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/arkoala-arkts/loader/src/loader.ts b/arkoala-arkts/loader/src/loader.ts index f66b0a9775..cff815aa29 100644 --- a/arkoala-arkts/loader/src/loader.ts +++ b/arkoala-arkts/loader/src/loader.ts @@ -139,6 +139,11 @@ export function checkLoader(variant: string, app: string, params: string, loopIt vmKind = 2 break } + case 'panda-ani': { + vmKind = 4 + nativePath = __dirname + "/../native" + break + } default: throw new Error(`${variant} is not known`) } diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index e7eda0d423..dd02ee6bf8 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -31,6 +31,10 @@ #include "etsapi.h" #endif +#ifdef KOALA_ANI +#include "ani.h" +#endif + #if defined(KOALA_LINUX) || defined(KOALA_MACOS) || defined(KOALA_OHOS) #include "sys/stat.h" #include "dirent.h" @@ -128,6 +132,7 @@ struct VMInitArgs { #define JAVA_VM_KIND 1 #define PANDA_VM_KIND 2 #define ES2PANDA_KIND 3 +#define PANDA_ANI_VM_KIND 4 struct ForeignVMContext { void* currentVMContext; @@ -174,8 +179,8 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP #ifdef KOALA_JNI (vmKind == JAVA_VM_KIND) ? &javaVMLib : #endif - #ifdef KOALA_ETS_NAPI - (vmKind == PANDA_VM_KIND) ? &pandaVMLib : + #if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) + (vmKind == PANDA_VM_KIND || vmKind == PANDA_ANI_VM_KIND) ? &pandaVMLib : #endif nullptr; @@ -233,8 +238,8 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP } #endif -#ifdef KOALA_ETS_NAPI - if (vmKind == PANDA_VM_KIND) { +#if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) + if (vmKind == PANDA_VM_KIND || vmKind == PANDA_ANI_VM_KIND) { EtsVMInitArgs pandaVMArgs; pandaVMArgs.version = ETS_NAPI_VERSION_1_0; std::vector etsVMOptions; @@ -273,7 +278,17 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP } else { result = createVM(&vm, &env, &pandaVMArgs); } - +#ifdef KOALA_ANI + if (vmKind == PANDA_ANI_VM_KIND) { + typedef ani_status (*ANI_GetCreatedVMs_t)(ani_vm **, ani_size, ani_size*); + ANI_GetCreatedVMs_t getVMs = (ANI_GetCreatedVMs_t)findSymbol(handle, "ANI_GetCreatedVMs"); + if (getVMs != nullptr) { + LOGI("Found ANI entry %" LOG_PUBLIC "p\n", getVMs); + } else { + LOGE("No ANI API found\n"); + } + } +#endif } #endif -- Gitee From ab48f95c65165cd9a7bda41e94bc907904f6a87c Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 21 Feb 2025 16:15:18 +0300 Subject: [PATCH 03/13] Temp ELF header hack --- interop/src/cpp/ani/convertors-ani.cc | 18 +++---- interop/src/cpp/vmloader.cc | 68 ++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/interop/src/cpp/ani/convertors-ani.cc b/interop/src/cpp/ani/convertors-ani.cc index aff874bdd5..02bb2247f5 100644 --- a/interop/src/cpp/ani/convertors-ani.cc +++ b/interop/src/cpp/ani/convertors-ani.cc @@ -73,25 +73,26 @@ bool registerAllModules(ani_env *env) { return true; } -#if 0 -extern "C" ETS_EXPORT ets_int ETS_CALL EtsNapiOnLoad(ets_env *env) { +int Koala_ANI_OnLoad(ani_env *env) { if (!registerAllModules(env)) { LOGE("Failed to register ets modules"); - return ETS_ERR; + return 1; } auto interopClasspath = AniExports::getInstance()->getClasspath("InteropNativeModule"); - auto interopClass = env->FindClass(interopClasspath.c_str()); + ani_class interopClass = nullptr; + env->FindClass(interopClasspath.c_str(), &interopClass); if (interopClass == nullptr) { LOGE("Can not find InteropNativeModule classpath to set callback dispatcher"); - return ETS_ERR; + return 1; } + #if 0 if (!setKoalaEtsNapiCallbackDispatcher(env, interopClass, callCallbackFromNative, callCallbackFromNativeSig)) { LOGE("Failed to set koala ets callback dispatcher"); - return ETS_ERR; + return 1; } - return ETS_NAPI_VERSION_1_0; + #endif + return 0; } -#endif AniExports* AniExports::getInstance() { static AniExports *instance = nullptr; @@ -141,6 +142,7 @@ static std::map g_defaultClasspaths = { {"ArkUINativeModule", "@koalaui/arkts-arkui/generated/arkts/ArkUINativeModule/ArkUINativeModule"}, {"ArkUIGeneratedNativeModule", "@koalaui/arkts-arkui/generated/arkts/ArkUIGeneratedNativeModule/ArkUIGeneratedNativeModule"}, }; + const std::string& AniExports::getClasspath(const std::string& module) { auto it = classpaths.find(module); if (it != classpaths.end()) { diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index dd02ee6bf8..934c772261 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -170,6 +170,54 @@ static int ArkMobileLog(int id, int level, const char *component, const char *fm return 0; } +#ifdef ELF_HACK +#include +#include +#include +#include +void* findWithHack(const char* lib, void* handle, const char* name) { + int fd = open(lib, O_RDONLY); + if (fd < 0 || !handle) { + return nullptr; + } + if (elf_version(EV_CURRENT) == EV_NONE) return nullptr; + Elf* elf = elf_begin(fd, ELF_C_READ, nullptr); + if (!elf) { + return nullptr; + } + Elf_Scn* scn = nullptr; + GElf_Shdr shdr; + Elf_Data* data = nullptr; + while ((scn = elf_nextscn(elf, scn)) != nullptr) { + gelf_getshdr(scn, &shdr); + if (shdr.sh_type == SHT_SYMTAB) { + data = elf_getdata(scn, nullptr); + break; + } + } + if (data) { + Dl_info info; + if (dladdr(handle, &info) == 0) { + LOGE("dladdr() fails\n"); + return nullptr; + } + char* base_address = (char*)info.dli_fbase; + size_t num_symbols = shdr.sh_size / shdr.sh_entsize; + for (size_t i = 0; i < num_symbols; i++) { + GElf_Sym sym; + gelf_getsym(data, i, &sym); + const char* func_name = elf_strptr(elf, shdr.sh_link, sym.st_name); + if (!func_name) continue; + if (GELF_ST_TYPE(sym.st_info) == STT_FUNC || GELF_ST_TYPE(sym.st_info) == STT_OBJECT) { + void* address = base_address + sym.st_value; + if (strcmp(name, func_name) == 0) return address; + } + } + } + return nullptr; +} +#endif + extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassPath, const char* appLibPath, const ForeignVMContext* foreignVMContext) { if (vmKind == ES2PANDA_KIND) { return loadES2Panda(appClassPath, appLibPath); @@ -275,6 +323,7 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP EtsEnv* pEnv = nullptr; vmInstance->GetEnv(&pEnv, ETS_NAPI_VERSION_1_0); env = static_cast(pEnv); + } else { result = createVM(&vm, &env, &pandaVMArgs); } @@ -282,10 +331,25 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP if (vmKind == PANDA_ANI_VM_KIND) { typedef ani_status (*ANI_GetCreatedVMs_t)(ani_vm **, ani_size, ani_size*); ANI_GetCreatedVMs_t getVMs = (ANI_GetCreatedVMs_t)findSymbol(handle, "ANI_GetCreatedVMs"); +#ifdef ELF_HACK + if (!getVMs) getVMs = (ANI_GetCreatedVMs_t)findWithHack(libPath.c_str(), (void*)createVM, "ANI_GetCreatedVMs"); +#endif if (getVMs != nullptr) { - LOGI("Found ANI entry %" LOG_PUBLIC "p\n", getVMs); + LOGI("Found ANI entry %" LOG_PUBLIC "p", getVMs); + ani_vm* vm; + ani_size vm_count = 0; + getVMs(&vm, 1, &vm_count); + if (vm_count > 0) { + LOGE("Found VM %p", vm); + ani_env* env = nullptr; + vm->GetEnv(1, &env); + if (env) { + LOGE("Found ENV %p", env); + g_vmEntry.env = env; + } + } } else { - LOGE("No ANI API found\n"); + LOGE("No ANI API found"); } } #endif -- Gitee From 4bf4915ea50b35685bb0d32bb4bf0c10ec4897d7 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Mon, 24 Feb 2025 04:45:13 +0300 Subject: [PATCH 04/13] WIP --- arkoala-arkts/loader/src/loader.ts | 1 + interop/src/cpp/vmloader.cc | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arkoala-arkts/loader/src/loader.ts b/arkoala-arkts/loader/src/loader.ts index cff815aa29..e4f01be1b6 100644 --- a/arkoala-arkts/loader/src/loader.ts +++ b/arkoala-arkts/loader/src/loader.ts @@ -141,6 +141,7 @@ export function checkLoader(variant: string, app: string, params: string, loopIt } case 'panda-ani': { vmKind = 4 + classPath = __dirname + "/../out/arkts-subset/abc" nativePath = __dirname + "/../native" break } diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index 934c772261..1c1c77d48c 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -304,9 +304,13 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP {EtsOptionType::ETS_BOOT_FILE, (char*)strdup((std::string(thisVM->sdkPath) + "/ets/etsstdlib.abc").c_str())}, #endif }; + std::string all_files; for (const std::string& path : files) { etsVMOptions.push_back({EtsOptionType::ETS_BOOT_FILE, (char*)strdup(path.c_str())}); + all_files.append(path); + all_files.append(":"); } + LOGE("classpath \"%s\" from %s", all_files.c_str(), appClassPath); etsVMOptions.push_back({EtsOptionType::ETS_NATIVE_LIBRARY_PATH, (char*)strdup(std::string(appLibPath).c_str())}); etsVMOptions.push_back({EtsOptionType::ETS_VERIFICATION_MODE, "on-the-fly"}); etsVMOptions.push_back({EtsOptionType::ETS_NO_JIT, nullptr}); @@ -342,7 +346,7 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP if (vm_count > 0) { LOGE("Found VM %p", vm); ani_env* env = nullptr; - vm->GetEnv(1, &env); + vm->GetEnv(/* version */ 1, &env); if (env) { LOGE("Found ENV %p", env); g_vmEntry.env = env; @@ -393,7 +397,7 @@ const AppInfo javaAppInfo = { }; #endif -#ifdef KOALA_ETS_NAPI +#ifdef KOALA_USE_PANDA_VM const AppInfo pandaAppInfo = { "@koalaui/arkts-arkui/Application/Application", "createApplication", -- Gitee From c33df6cb6b1149b6a94f4c6a99e42eb3b03b4fc5 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Mon, 24 Feb 2025 08:55:57 +0300 Subject: [PATCH 05/13] WIP --- arkoala-arkts/loader/src/loader.ts | 2 +- interop/src/cpp/vmloader.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arkoala-arkts/loader/src/loader.ts b/arkoala-arkts/loader/src/loader.ts index e4f01be1b6..9ce53bcdc4 100644 --- a/arkoala-arkts/loader/src/loader.ts +++ b/arkoala-arkts/loader/src/loader.ts @@ -141,7 +141,7 @@ export function checkLoader(variant: string, app: string, params: string, loopIt } case 'panda-ani': { vmKind = 4 - classPath = __dirname + "/../out/arkts-subset/abc" + classPath = __dirname + "/../out/arkts-peers/abc" nativePath = __dirname + "/../native" break } diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index 1c1c77d48c..feee101e3a 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -307,8 +307,8 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP std::string all_files; for (const std::string& path : files) { etsVMOptions.push_back({EtsOptionType::ETS_BOOT_FILE, (char*)strdup(path.c_str())}); + if (all_files.size() > 0) all_files.append(":"); all_files.append(path); - all_files.append(":"); } LOGE("classpath \"%s\" from %s", all_files.c_str(), appClassPath); etsVMOptions.push_back({EtsOptionType::ETS_NATIVE_LIBRARY_PATH, (char*)strdup(std::string(appLibPath).c_str())}); -- Gitee From 5774e45f867f601f6dafe5602acf68846d4e9ae0 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Mon, 24 Feb 2025 19:27:15 +0800 Subject: [PATCH 06/13] WIP --- arkoala-arkts/loader/src/loader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arkoala-arkts/loader/src/loader.ts b/arkoala-arkts/loader/src/loader.ts index 9ce53bcdc4..9ff2e118b2 100644 --- a/arkoala-arkts/loader/src/loader.ts +++ b/arkoala-arkts/loader/src/loader.ts @@ -141,7 +141,7 @@ export function checkLoader(variant: string, app: string, params: string, loopIt } case 'panda-ani': { vmKind = 4 - classPath = __dirname + "/../out/arkts-peers/abc" + classPath = __dirname + "/../out/arkts-subset/main" nativePath = __dirname + "/../native" break } -- Gitee From 3ac318e560831a01adc7400bececca38599d90d8 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 28 Feb 2025 04:44:21 +0800 Subject: [PATCH 07/13] WIP --- arkoala-arkts/arkui/src/Application.ts | 2 +- arkoala-arkts/arkui/src/ComponentBase.ts | 10 +-- arkoala-arkts/arkui/src/UserView.ts | 1 - arkoala-arkts/loader/src/loader.ts | 2 +- interop/src/cpp/ani/convertors-ani.cc | 87 ++++++++++++++++++++++++ interop/src/cpp/vmloader.cc | 71 ++++--------------- 6 files changed, 105 insertions(+), 68 deletions(-) diff --git a/arkoala-arkts/arkui/src/Application.ts b/arkoala-arkts/arkui/src/Application.ts index 0107c25bcf..1c77d66643 100644 --- a/arkoala-arkts/arkui/src/Application.ts +++ b/arkoala-arkts/arkui/src/Application.ts @@ -14,7 +14,7 @@ */ import { ComputableState, IncrementalNode, GlobalStateManager, StateManager, StateContext, memoEntry, MutableState, createAnimationTimer, callScheduledCallbacks, scheduleCallback } from "@koalaui/runtime" -import { int32, int64, scheduleCoroutine, memoryStats } from "@koalaui/common" +import { int32, int64, scheduleCoroutine } from "@koalaui/common" import { pointer, nullptr, KPointer, InteropNativeModule, registerNativeModuleLibraryName } from "@koalaui/interop" import { PeerNode } from "./PeerNode" import { ArkUINativeModule } from "#components" diff --git a/arkoala-arkts/arkui/src/ComponentBase.ts b/arkoala-arkts/arkui/src/ComponentBase.ts index eccbd97499..ee2dc37f5f 100644 --- a/arkoala-arkts/arkui/src/ComponentBase.ts +++ b/arkoala-arkts/arkui/src/ComponentBase.ts @@ -24,21 +24,17 @@ export class ComponentBase { setPeer(peer: PeerNode) { this.peer = peer } - protected checkPriority(name: string): boolean { - return true - } public applyAttributesFinish(): void { ArkUINativeModule._ApplyModifierFinish(this.peer!.peer.ptr) } public animationStart(param: AnimateParam): this { - _animationStart(param, this.isFirstBuild); + _animationStart(param, this.isFirstBuild) return this } - public animationEnd(): this { _animationEnd(this.isFirstBuild, () => { - this.isFirstBuild = false; + this.isFirstBuild = false; }) - return this; + return this } } diff --git a/arkoala-arkts/arkui/src/UserView.ts b/arkoala-arkts/arkui/src/UserView.ts index 7ccc1a4707..90c686df61 100644 --- a/arkoala-arkts/arkui/src/UserView.ts +++ b/arkoala-arkts/arkui/src/UserView.ts @@ -15,7 +15,6 @@ import { InteropNativeModule } from "@koalaui/interop" import { int32, int8Array } from "@koalaui/common" - export type UserViewBuilder = /** @memo */ (/*root: PeerNode*/) => void diff --git a/arkoala-arkts/loader/src/loader.ts b/arkoala-arkts/loader/src/loader.ts index 9ff2e118b2..e4f01be1b6 100644 --- a/arkoala-arkts/loader/src/loader.ts +++ b/arkoala-arkts/loader/src/loader.ts @@ -141,7 +141,7 @@ export function checkLoader(variant: string, app: string, params: string, loopIt } case 'panda-ani': { vmKind = 4 - classPath = __dirname + "/../out/arkts-subset/main" + classPath = __dirname + "/../out/arkts-subset/abc" nativePath = __dirname + "/../native" break } diff --git a/interop/src/cpp/ani/convertors-ani.cc b/interop/src/cpp/ani/convertors-ani.cc index 02bb2247f5..808aa052db 100644 --- a/interop/src/cpp/ani/convertors-ani.cc +++ b/interop/src/cpp/ani/convertors-ani.cc @@ -12,12 +12,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include +#include #include #include "convertors-ani.h" #include "signatures.h" #include "interop-logging.h" #include "interop-types.h" +#include "etsapi.h" static const char* callCallbackFromNative = "callCallbackFromNative"; static const char* callCallbackFromNativeSig = "I[BI:I"; @@ -73,6 +76,62 @@ bool registerAllModules(ani_env *env) { return true; } +#ifdef ELF_HACK +static int findRuntime(struct dl_phdr_info *info, size_t size, void *data) { + if (strstr(info->dlpi_name, "libarkruntime.so") != nullptr) { + *(void**)data = (void*)info; + return 1; + } + return 0; +} + +#include +#include +#include +#include +void* findWithHack(const char* lib, void* handle, const char* name) { + int fd = open(lib, O_RDONLY); + if (fd < 0 || !handle) { + return nullptr; + } + if (elf_version(EV_CURRENT) == EV_NONE) return nullptr; + Elf* elf = elf_begin(fd, ELF_C_READ, nullptr); + if (!elf) { + return nullptr; + } + Elf_Scn* scn = nullptr; + GElf_Shdr shdr; + Elf_Data* data = nullptr; + while ((scn = elf_nextscn(elf, scn)) != nullptr) { + gelf_getshdr(scn, &shdr); + if (shdr.sh_type == SHT_SYMTAB) { + data = elf_getdata(scn, nullptr); + break; + } + } + if (data) { + Dl_info info; + if (dladdr(handle, &info) == 0) { + LOGE("dladdr() fails\n"); + return nullptr; + } + char* base_address = (char*)info.dli_fbase; + size_t num_symbols = shdr.sh_size / shdr.sh_entsize; + for (size_t i = 0; i < num_symbols; i++) { + GElf_Sym sym; + gelf_getsym(data, i, &sym); + const char* func_name = elf_strptr(elf, shdr.sh_link, sym.st_name); + if (!func_name) continue; + if (GELF_ST_TYPE(sym.st_info) == STT_FUNC || GELF_ST_TYPE(sym.st_info) == STT_OBJECT) { + void* address = base_address + sym.st_value; + if (strcmp(name, func_name) == 0) return address; + } + } + } + return nullptr; +} +#endif + int Koala_ANI_OnLoad(ani_env *env) { if (!registerAllModules(env)) { LOGE("Failed to register ets modules"); @@ -94,6 +153,34 @@ int Koala_ANI_OnLoad(ani_env *env) { return 0; } +extern "C" ets_int EtsNapiOnLoad(EtsEnv *env) { + LOGE("EtsNapiOnLoad"); + dl_phdr_info* runtimeLibrary = nullptr; + dl_iterate_phdr(findRuntime, &runtimeLibrary); + if (runtimeLibrary != nullptr) { + // Aha, detected libarkruntime.so. + LOGE("Detected runtime %p\n", runtimeLibrary); + typedef ani_status (*ANI_GetCreatedVMs_t)(ani_vm **, ani_size, ani_size*); + ANI_GetCreatedVMs_t getVMs = (ANI_GetCreatedVMs_t)findWithHack(runtimeLibrary->dlpi_name, (void*)runtimeLibrary->dlpi_addr, "ANI_GetCreatedVMs"); + if (getVMs) { + LOGI("Found ANI entry %" LOG_PUBLIC "p", getVMs); + ani_vm* vm; + ani_size vm_count = 0; + getVMs(&vm, 1, &vm_count); + if (vm_count > 0) { + ani_env* aniEnv = nullptr; + LOGE("Found VM %p", vm); + vm->GetEnv(/* version */ 1, (ani_env**)&aniEnv); + if (aniEnv) { + LOGE("Found ANI ENV %p", aniEnv); + Koala_ANI_OnLoad(aniEnv); + } + } + } + } + return ETS_NAPI_VERSION_1_0; +} + AniExports* AniExports::getInstance() { static AniExports *instance = nullptr; if (instance == nullptr) { diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index feee101e3a..ecd305b8df 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -170,53 +170,6 @@ static int ArkMobileLog(int id, int level, const char *component, const char *fm return 0; } -#ifdef ELF_HACK -#include -#include -#include -#include -void* findWithHack(const char* lib, void* handle, const char* name) { - int fd = open(lib, O_RDONLY); - if (fd < 0 || !handle) { - return nullptr; - } - if (elf_version(EV_CURRENT) == EV_NONE) return nullptr; - Elf* elf = elf_begin(fd, ELF_C_READ, nullptr); - if (!elf) { - return nullptr; - } - Elf_Scn* scn = nullptr; - GElf_Shdr shdr; - Elf_Data* data = nullptr; - while ((scn = elf_nextscn(elf, scn)) != nullptr) { - gelf_getshdr(scn, &shdr); - if (shdr.sh_type == SHT_SYMTAB) { - data = elf_getdata(scn, nullptr); - break; - } - } - if (data) { - Dl_info info; - if (dladdr(handle, &info) == 0) { - LOGE("dladdr() fails\n"); - return nullptr; - } - char* base_address = (char*)info.dli_fbase; - size_t num_symbols = shdr.sh_size / shdr.sh_entsize; - for (size_t i = 0; i < num_symbols; i++) { - GElf_Sym sym; - gelf_getsym(data, i, &sym); - const char* func_name = elf_strptr(elf, shdr.sh_link, sym.st_name); - if (!func_name) continue; - if (GELF_ST_TYPE(sym.st_info) == STT_FUNC || GELF_ST_TYPE(sym.st_info) == STT_OBJECT) { - void* address = base_address + sym.st_value; - if (strcmp(name, func_name) == 0) return address; - } - } - } - return nullptr; -} -#endif extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassPath, const char* appLibPath, const ForeignVMContext* foreignVMContext) { if (vmKind == ES2PANDA_KIND) { @@ -331,7 +284,7 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP } else { result = createVM(&vm, &env, &pandaVMArgs); } -#ifdef KOALA_ANI +#if 0 if (vmKind == PANDA_ANI_VM_KIND) { typedef ani_status (*ANI_GetCreatedVMs_t)(ani_vm **, ani_size, ani_size*); ANI_GetCreatedVMs_t getVMs = (ANI_GetCreatedVMs_t)findSymbol(handle, "ANI_GetCreatedVMs"); @@ -345,11 +298,9 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP getVMs(&vm, 1, &vm_count); if (vm_count > 0) { LOGE("Found VM %p", vm); - ani_env* env = nullptr; - vm->GetEnv(/* version */ 1, &env); + vm->GetEnv(/* version */ 1, (ani_env**)&env); if (env) { - LOGE("Found ENV %p", env); - g_vmEntry.env = env; + LOGE("Found ANI ENV %p", env); } } } else { @@ -430,9 +381,12 @@ extern "C" DLL_EXPORT KNativePointer StartApplication(const char* appUrl, const #ifdef KOALA_JNI (g_vmEntry.vmKind == JAVA_VM_KIND) ? &javaAppInfo : #endif - #ifdef KOALA_ETS_NAPI + #if defined(KOALA_ETS_NAPI) (g_vmEntry.vmKind == PANDA_VM_KIND) ? isTestEnv ? &harnessAppInfo : &pandaAppInfo : #endif + #if defined(KOALA_ANI) + (g_vmEntry.vmKind == PANDA_ANI_VM_KIND) ? isTestEnv ? &harnessAppInfo : &pandaAppInfo : + #endif nullptr; if (!appInfo) { @@ -476,8 +430,9 @@ extern "C" DLL_EXPORT KNativePointer StartApplication(const char* appUrl, const app, start)); } #endif -#ifdef KOALA_ETS_NAPI - if (g_vmEntry.vmKind == PANDA_VM_KIND) { +#if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) + if (g_vmEntry.vmKind == PANDA_VM_KIND || g_vmEntry.vmKind == PANDA_ANI_VM_KIND) { + LOGE("OJJ1"); EtsEnv* etsEnv = (EtsEnv*)g_vmEntry.env; ets_class appClass = etsEnv->FindClass(appInfo->className); if (!appClass) { @@ -588,7 +543,7 @@ extern "C" DLL_EXPORT KBoolean RunApplication(const KInt arg0, const KInt arg1) } return result; } - #endif +#endif return 1; } @@ -639,7 +594,7 @@ extern "C" DLL_EXPORT const char* EmitEvent(const KInt type, const KInt target, const char *result = etsEnv->GetStringUTFChars(rv, 0); return result; } - #endif +#endif return "-1"; } @@ -680,7 +635,7 @@ extern "C" DLL_EXPORT void RestartWith(const char* page) { etsEnv->ErrorClear(); } } - #endif +#endif } void traverseDir(std::string root, std::vector& paths, int depth) { -- Gitee From 550206e18a5ef03a9344944499fb232d3cacbeb4 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 28 Feb 2025 11:20:54 +0800 Subject: [PATCH 08/13] WIP --- interop/src/cpp/ani/convertors-ani.cc | 15 +++++++++------ interop/src/cpp/vmloader.cc | 1 - 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/interop/src/cpp/ani/convertors-ani.cc b/interop/src/cpp/ani/convertors-ani.cc index 808aa052db..3520da943e 100644 --- a/interop/src/cpp/ani/convertors-ani.cc +++ b/interop/src/cpp/ani/convertors-ani.cc @@ -57,15 +57,18 @@ static bool registerNatives(ani_env *env, const ani_class clazz, const std::vect return registerByOne ? true : result; } -bool registerAllModules(ani_env *env) { +bool registerAllModules(ani_env *aniEnv, ets_env* etsEnv) { auto moduleNames = AniExports::getInstance()->getModules(); for (auto it = moduleNames.begin(); it != moduleNames.end(); ++it) { std::string classpath = AniExports::getInstance()->getClasspath(*it); ani_class nativeModule = nullptr; - env->FindClass(classpath.c_str(), &nativeModule); + // ani_module nativeModule = nullptr; + aniEnv->FindClass(classpath.c_str(), &nativeModule); if (nativeModule == nullptr) { LOGE("Cannot find managed class %s", classpath.c_str()); + ets_class c2 = etsEnv->FindClass(classpath.c_str()); + LOGE("ETS %p", c2); continue; } if (!registerNatives(env, nativeModule, AniExports::getInstance()->getMethods(*it))) { @@ -132,14 +135,14 @@ void* findWithHack(const char* lib, void* handle, const char* name) { } #endif -int Koala_ANI_OnLoad(ani_env *env) { - if (!registerAllModules(env)) { +int Koala_ANI_OnLoad(ani_env *aniEnv, ets_env* etsEnv) { + if (!registerAllModules(aniEnv, etsEnv)) { LOGE("Failed to register ets modules"); return 1; } auto interopClasspath = AniExports::getInstance()->getClasspath("InteropNativeModule"); ani_class interopClass = nullptr; - env->FindClass(interopClasspath.c_str(), &interopClass); + aniEnv->FindClass(interopClasspath.c_str(), &interopClass); if (interopClass == nullptr) { LOGE("Can not find InteropNativeModule classpath to set callback dispatcher"); return 1; @@ -173,7 +176,7 @@ extern "C" ets_int EtsNapiOnLoad(EtsEnv *env) { vm->GetEnv(/* version */ 1, (ani_env**)&aniEnv); if (aniEnv) { LOGE("Found ANI ENV %p", aniEnv); - Koala_ANI_OnLoad(aniEnv); + Koala_ANI_OnLoad(aniEnv, env); } } } diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index ecd305b8df..5576ddd98e 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -432,7 +432,6 @@ extern "C" DLL_EXPORT KNativePointer StartApplication(const char* appUrl, const #endif #if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) if (g_vmEntry.vmKind == PANDA_VM_KIND || g_vmEntry.vmKind == PANDA_ANI_VM_KIND) { - LOGE("OJJ1"); EtsEnv* etsEnv = (EtsEnv*)g_vmEntry.env; ets_class appClass = etsEnv->FindClass(appInfo->className); if (!appClass) { -- Gitee From b5811e527fc3bdb4b89d348bfd4f48c9e8c82823 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 28 Feb 2025 16:14:33 +0800 Subject: [PATCH 09/13] Works --- interop/src/cpp/ani/convertors-ani.cc | 66 +++++++-------------------- interop/src/cpp/ani/convertors-ani.h | 7 +-- interop/src/cpp/vmloader.cc | 9 ++-- 3 files changed, 26 insertions(+), 56 deletions(-) diff --git a/interop/src/cpp/ani/convertors-ani.cc b/interop/src/cpp/ani/convertors-ani.cc index 3520da943e..4063cf9bb3 100644 --- a/interop/src/cpp/ani/convertors-ani.cc +++ b/interop/src/cpp/ani/convertors-ani.cc @@ -20,13 +20,10 @@ #include "signatures.h" #include "interop-logging.h" #include "interop-types.h" -#include "etsapi.h" static const char* callCallbackFromNative = "callCallbackFromNative"; static const char* callCallbackFromNativeSig = "I[BI:I"; -static const char* FAST_NATIVE_PREFIX = "#F$"; - const bool registerByOne = true; static bool registerNatives(ani_env *env, const ani_class clazz, const std::vector> impls) { @@ -37,7 +34,7 @@ static bool registerNatives(ani_env *env, const ani_class clazz, const std::vect ani_native_function method; method.name = name.c_str(); method.pointer = func; - method.signature = (flag & ANI_SLOW_NATIVE_FLAG) == 0 ? FAST_NATIVE_PREFIX : nullptr; + method.signature = nullptr; if (registerByOne) { result &= env->Class_BindNativeMethods(clazz, &method, 1) == ANI_OK; ani_boolean isError = false; @@ -57,9 +54,8 @@ static bool registerNatives(ani_env *env, const ani_class clazz, const std::vect return registerByOne ? true : result; } -bool registerAllModules(ani_env *aniEnv, ets_env* etsEnv) { +bool registerAllModules(ani_env *aniEnv) { auto moduleNames = AniExports::getInstance()->getModules(); - for (auto it = moduleNames.begin(); it != moduleNames.end(); ++it) { std::string classpath = AniExports::getInstance()->getClasspath(*it); ani_class nativeModule = nullptr; @@ -67,15 +63,12 @@ bool registerAllModules(ani_env *aniEnv, ets_env* etsEnv) { aniEnv->FindClass(classpath.c_str(), &nativeModule); if (nativeModule == nullptr) { LOGE("Cannot find managed class %s", classpath.c_str()); - ets_class c2 = etsEnv->FindClass(classpath.c_str()); - LOGE("ETS %p", c2); continue; } - if (!registerNatives(env, nativeModule, AniExports::getInstance()->getMethods(*it))) { + if (!registerNatives(aniEnv, nativeModule, AniExports::getInstance()->getMethods(*it))) { return false; } } - return true; } @@ -135,53 +128,28 @@ void* findWithHack(const char* lib, void* handle, const char* name) { } #endif -int Koala_ANI_OnLoad(ani_env *aniEnv, ets_env* etsEnv) { - if (!registerAllModules(aniEnv, etsEnv)) { - LOGE("Failed to register ets modules"); - return 1; +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { + ani_env* aniEnv = nullptr; + *result = 1; + vm->GetEnv(/* version */ 1, (ani_env**)&aniEnv); + if (!registerAllModules(aniEnv)) { + LOGE("Failed to register ANI modules"); + return ANI_ERROR; } auto interopClasspath = AniExports::getInstance()->getClasspath("InteropNativeModule"); ani_class interopClass = nullptr; aniEnv->FindClass(interopClasspath.c_str(), &interopClass); if (interopClass == nullptr) { LOGE("Can not find InteropNativeModule classpath to set callback dispatcher"); - return 1; + return ANI_ERROR; } #if 0 if (!setKoalaEtsNapiCallbackDispatcher(env, interopClass, callCallbackFromNative, callCallbackFromNativeSig)) { LOGE("Failed to set koala ets callback dispatcher"); - return 1; + return ANI_ERROR; } #endif - return 0; -} - -extern "C" ets_int EtsNapiOnLoad(EtsEnv *env) { - LOGE("EtsNapiOnLoad"); - dl_phdr_info* runtimeLibrary = nullptr; - dl_iterate_phdr(findRuntime, &runtimeLibrary); - if (runtimeLibrary != nullptr) { - // Aha, detected libarkruntime.so. - LOGE("Detected runtime %p\n", runtimeLibrary); - typedef ani_status (*ANI_GetCreatedVMs_t)(ani_vm **, ani_size, ani_size*); - ANI_GetCreatedVMs_t getVMs = (ANI_GetCreatedVMs_t)findWithHack(runtimeLibrary->dlpi_name, (void*)runtimeLibrary->dlpi_addr, "ANI_GetCreatedVMs"); - if (getVMs) { - LOGI("Found ANI entry %" LOG_PUBLIC "p", getVMs); - ani_vm* vm; - ani_size vm_count = 0; - getVMs(&vm, 1, &vm_count); - if (vm_count > 0) { - ani_env* aniEnv = nullptr; - LOGE("Found VM %p", vm); - vm->GetEnv(/* version */ 1, (ani_env**)&aniEnv); - if (aniEnv) { - LOGE("Found ANI ENV %p", aniEnv); - Koala_ANI_OnLoad(aniEnv, env); - } - } - } - } - return ETS_NAPI_VERSION_1_0; + return ANI_OK; } AniExports* AniExports::getInstance() { @@ -226,11 +194,11 @@ void AniExports::setClasspath(const char* module, const char *classpath) { } static std::map g_defaultClasspaths = { - {"InteropNativeModule", "@koalaui/interop/InteropNativeModule/InteropNativeModule"}, + {"InteropNativeModule", "L@koalaui/interop/InteropNativeModule/InteropNativeModule;"}, // todo leave just InteropNativeModule, define others via KOALA_ETS_INTEROP_MODULE_CLASSPATH - {"TestNativeModule", "@koalaui/arkts-arkui/generated/arkts/TestNativeModule/TestNativeModule"}, - {"ArkUINativeModule", "@koalaui/arkts-arkui/generated/arkts/ArkUINativeModule/ArkUINativeModule"}, - {"ArkUIGeneratedNativeModule", "@koalaui/arkts-arkui/generated/arkts/ArkUIGeneratedNativeModule/ArkUIGeneratedNativeModule"}, + {"TestNativeModule", "L@koalaui/arkts-arkui/generated/arkts/TestNativeModule/TestNativeModule;"}, + {"ArkUINativeModule", "L@koalaui/arkts-arkui/generated/arkts/ArkUINativeModule/ArkUINativeModule;"}, + {"ArkUIGeneratedNativeModule", "L@koalaui/arkts-arkui/generated/arkts/ArkUIGeneratedNativeModule/ArkUIGeneratedNativeModule;"}, }; const std::string& AniExports::getClasspath(const std::string& module) { diff --git a/interop/src/cpp/ani/convertors-ani.h b/interop/src/cpp/ani/convertors-ani.h index e6ad2272ca..ae51c25cf8 100644 --- a/interop/src/cpp/ani/convertors-ani.h +++ b/interop/src/cpp/ani/convertors-ani.h @@ -159,12 +159,13 @@ struct InteropTypeConverter { result.resize(lengthUtf8); ani_size lengthUtf16 = 0; env->String_GetUTF16Size(value, &lengthUtf16); - ani_size count; - env->String_GetUTF8SubString(value, 0, lengthUtf16, result.data(), result.length(), &count); + ani_size count = 0; + env->String_GetUTF8SubString(value, 0, lengthUtf16, result.data(), lengthUtf8 + 1, &count); + result.data()[lengthUtf8] = 0; return result; } static InteropType convertTo(ani_env* env, const KStringPtr& value) { - ani_string result; + ani_string result = nullptr; env->String_NewUTF8(value.c_str(), value.length(), &result); return result; } diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index 5576ddd98e..8505fb64bf 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -521,8 +521,8 @@ extern "C" DLL_EXPORT KBoolean RunApplication(const KInt arg0, const KInt arg1) return result; } #endif -#ifdef KOALA_ETS_NAPI - if (g_vmEntry.vmKind == PANDA_VM_KIND) { +#if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) + if (g_vmEntry.vmKind == PANDA_VM_KIND || g_vmEntry.vmKind == PANDA_ANI_VM_KIND) { EtsEnv* etsEnv = (EtsEnv*)(g_vmEntry.env); if (!g_vmEntry.enter) { LOGE("Cannot find enter method"); @@ -543,6 +543,7 @@ extern "C" DLL_EXPORT KBoolean RunApplication(const KInt arg0, const KInt arg1) return result; } #endif + return 1; } @@ -570,7 +571,7 @@ extern "C" DLL_EXPORT const char* EmitEvent(const KInt type, const KInt target, return result; } #endif -#ifdef KOALA_ETS_NAPI +#if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) if (g_vmEntry.vmKind == PANDA_VM_KIND) { EtsEnv* etsEnv = (EtsEnv*)(g_vmEntry.env); if (!g_vmEntry.emitEvent) { @@ -616,7 +617,7 @@ extern "C" DLL_EXPORT void RestartWith(const char* page) { } } #endif -#ifdef KOALA_ETS_NAPI +#if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) if (g_vmEntry.vmKind == PANDA_VM_KIND) { EtsEnv* etsEnv = (EtsEnv*)(g_vmEntry.env); if (!g_vmEntry.restartWith) { -- Gitee From 5d8a0adeaaa1886ad2541df6759a5beaa1d5e39a Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 28 Feb 2025 16:17:33 +0800 Subject: [PATCH 10/13] Update --- arkoala-arkts/arkui/src/ComponentBase.ts | 3 +++ interop/src/cpp/vmloader.cc | 25 +----------------------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/arkoala-arkts/arkui/src/ComponentBase.ts b/arkoala-arkts/arkui/src/ComponentBase.ts index ee2dc37f5f..14b878f911 100644 --- a/arkoala-arkts/arkui/src/ComponentBase.ts +++ b/arkoala-arkts/arkui/src/ComponentBase.ts @@ -24,6 +24,9 @@ export class ComponentBase { setPeer(peer: PeerNode) { this.peer = peer } + protected checkPriority(name: string): boolean { + return true + } public applyAttributesFinish(): void { ArkUINativeModule._ApplyModifierFinish(this.peer!.peer.ptr) } diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index 8505fb64bf..407d73fd47 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -239,6 +239,7 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP } #endif +// For now we use ETS API for VM startup and entry. #if defined(KOALA_ETS_NAPI) || defined(KOALA_ANI) if (vmKind == PANDA_VM_KIND || vmKind == PANDA_ANI_VM_KIND) { EtsVMInitArgs pandaVMArgs; @@ -284,30 +285,6 @@ extern "C" DLL_EXPORT KInt LoadVirtualMachine(KInt vmKind, const char* appClassP } else { result = createVM(&vm, &env, &pandaVMArgs); } -#if 0 - if (vmKind == PANDA_ANI_VM_KIND) { - typedef ani_status (*ANI_GetCreatedVMs_t)(ani_vm **, ani_size, ani_size*); - ANI_GetCreatedVMs_t getVMs = (ANI_GetCreatedVMs_t)findSymbol(handle, "ANI_GetCreatedVMs"); -#ifdef ELF_HACK - if (!getVMs) getVMs = (ANI_GetCreatedVMs_t)findWithHack(libPath.c_str(), (void*)createVM, "ANI_GetCreatedVMs"); -#endif - if (getVMs != nullptr) { - LOGI("Found ANI entry %" LOG_PUBLIC "p", getVMs); - ani_vm* vm; - ani_size vm_count = 0; - getVMs(&vm, 1, &vm_count); - if (vm_count > 0) { - LOGE("Found VM %p", vm); - vm->GetEnv(/* version */ 1, (ani_env**)&env); - if (env) { - LOGE("Found ANI ENV %p", env); - } - } - } else { - LOGE("No ANI API found"); - } - } -#endif } #endif -- Gitee From 7cb5e6820ccb88e9aca41c10706567736f561c0e Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 28 Feb 2025 16:19:32 +0800 Subject: [PATCH 11/13] Remove legacy --- interop/src/cpp/ani/convertors-ani.cc | 61 +-------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/interop/src/cpp/ani/convertors-ani.cc b/interop/src/cpp/ani/convertors-ani.cc index 4063cf9bb3..4b3d398b8d 100644 --- a/interop/src/cpp/ani/convertors-ani.cc +++ b/interop/src/cpp/ani/convertors-ani.cc @@ -59,7 +59,6 @@ bool registerAllModules(ani_env *aniEnv) { for (auto it = moduleNames.begin(); it != moduleNames.end(); ++it) { std::string classpath = AniExports::getInstance()->getClasspath(*it); ani_class nativeModule = nullptr; - // ani_module nativeModule = nullptr; aniEnv->FindClass(classpath.c_str(), &nativeModule); if (nativeModule == nullptr) { LOGE("Cannot find managed class %s", classpath.c_str()); @@ -72,62 +71,6 @@ bool registerAllModules(ani_env *aniEnv) { return true; } -#ifdef ELF_HACK -static int findRuntime(struct dl_phdr_info *info, size_t size, void *data) { - if (strstr(info->dlpi_name, "libarkruntime.so") != nullptr) { - *(void**)data = (void*)info; - return 1; - } - return 0; -} - -#include -#include -#include -#include -void* findWithHack(const char* lib, void* handle, const char* name) { - int fd = open(lib, O_RDONLY); - if (fd < 0 || !handle) { - return nullptr; - } - if (elf_version(EV_CURRENT) == EV_NONE) return nullptr; - Elf* elf = elf_begin(fd, ELF_C_READ, nullptr); - if (!elf) { - return nullptr; - } - Elf_Scn* scn = nullptr; - GElf_Shdr shdr; - Elf_Data* data = nullptr; - while ((scn = elf_nextscn(elf, scn)) != nullptr) { - gelf_getshdr(scn, &shdr); - if (shdr.sh_type == SHT_SYMTAB) { - data = elf_getdata(scn, nullptr); - break; - } - } - if (data) { - Dl_info info; - if (dladdr(handle, &info) == 0) { - LOGE("dladdr() fails\n"); - return nullptr; - } - char* base_address = (char*)info.dli_fbase; - size_t num_symbols = shdr.sh_size / shdr.sh_entsize; - for (size_t i = 0; i < num_symbols; i++) { - GElf_Sym sym; - gelf_getsym(data, i, &sym); - const char* func_name = elf_strptr(elf, shdr.sh_link, sym.st_name); - if (!func_name) continue; - if (GELF_ST_TYPE(sym.st_info) == STT_FUNC || GELF_ST_TYPE(sym.st_info) == STT_OBJECT) { - void* address = base_address + sym.st_value; - if (strcmp(name, func_name) == 0) return address; - } - } - } - return nullptr; -} -#endif - ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { ani_env* aniEnv = nullptr; *result = 1; @@ -143,12 +86,12 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { LOGE("Can not find InteropNativeModule classpath to set callback dispatcher"); return ANI_ERROR; } - #if 0 +#if 0 if (!setKoalaEtsNapiCallbackDispatcher(env, interopClass, callCallbackFromNative, callCallbackFromNativeSig)) { LOGE("Failed to set koala ets callback dispatcher"); return ANI_ERROR; } - #endif +#endif return ANI_OK; } -- Gitee From b8c911c5fce6f35d09838dc8cac08c3d291f0fbc Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 28 Feb 2025 16:22:16 +0800 Subject: [PATCH 12/13] Update --- interop/src/cpp/ani/convertors-ani.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interop/src/cpp/ani/convertors-ani.cc b/interop/src/cpp/ani/convertors-ani.cc index 4b3d398b8d..e9c7520b3f 100644 --- a/interop/src/cpp/ani/convertors-ani.cc +++ b/interop/src/cpp/ani/convertors-ani.cc @@ -40,7 +40,7 @@ static bool registerNatives(ani_env *env, const ani_class clazz, const std::vect ani_boolean isError = false; env->ExistUnhandledError(&isError); if (isError) { - //env->ErrorDescribe(); + env->ErrorDescribe(); env->ResetError(); } } -- Gitee From c2cedbbf8e4407cba9fbdb4f8849a42c7fabe82b Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 28 Feb 2025 16:23:14 +0800 Subject: [PATCH 13/13] WIP --- interop/src/cpp/ani/convertors-ani.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interop/src/cpp/ani/convertors-ani.cc b/interop/src/cpp/ani/convertors-ani.cc index e9c7520b3f..71f9491512 100644 --- a/interop/src/cpp/ani/convertors-ani.cc +++ b/interop/src/cpp/ani/convertors-ani.cc @@ -40,7 +40,7 @@ static bool registerNatives(ani_env *env, const ani_class clazz, const std::vect ani_boolean isError = false; env->ExistUnhandledError(&isError); if (isError) { - env->ErrorDescribe(); + env->DescribeError(); env->ResetError(); } } -- Gitee