From af30be1cda8b5a2c26db634f164520a647b74d1b Mon Sep 17 00:00:00 2001 From: Pavel Mironchik Date: Wed, 18 Jun 2025 18:27:33 +0300 Subject: [PATCH] draft example how to assign proper component destroy callback to capi --- arkoala-arkts/arkui/src/CallbacksChecker.ts | 13 +++++++++++++ .../framework/native/src/generated/library.cc | 6 ++++++ arkoala/arkui/src/peer_events_checker.ts | 13 +++++++++++++ interop/src/cpp/callback-resource.cc | 18 ++++++++++++++++++ interop/src/cpp/callback-resource.h | 3 +++ 5 files changed, 53 insertions(+) diff --git a/arkoala-arkts/arkui/src/CallbacksChecker.ts b/arkoala-arkts/arkui/src/CallbacksChecker.ts index 31d5cead0..be9e489d6 100644 --- a/arkoala-arkts/arkui/src/CallbacksChecker.ts +++ b/arkoala-arkts/arkui/src/CallbacksChecker.ts @@ -17,11 +17,14 @@ import { KBuffer } from "@koalaui/interop" import { Deserializer } from "./generated/peers/Deserializer"; import { deserializeAndCallCallback } from "./generated/peers/CallbackDeserializeCall" import { ResourceHolder, InteropNativeModule } from "@koalaui/interop" +import { destroyUiDetachedRoot } from "./Application" +import { PeerNode } from "./PeerNode"; enum CallbackEventKind { Event_CallCallback = 0, Event_HoldManagedResource = 1, Event_ReleaseManagedResource = 2, + Event_ReleaseComponent = 3, } const bufferSize = 4096 @@ -49,6 +52,16 @@ export function checkArkoalaCallbacks() { ResourceHolder.instance().release(resourceId) break; } + case CallbackEventKind.Event_ReleaseComponent: { + const nodeId = deserializer.readPointer(); + const peer = PeerNode.findPeerByNativeId(nodeId) + if (peer !== undefined) { + destroyUiDetachedRoot(peer) + } else { + InteropNativeModule._NativeLog("ERROR: can not find PeerNode for native id " + nodeId) + } + break; + } default: throw new Error(`Unknown callback event kind ${eventKind}`) } } diff --git a/arkoala-arkts/framework/native/src/generated/library.cc b/arkoala-arkts/framework/native/src/generated/library.cc index 8bb21b945..31380962b 100644 --- a/arkoala-arkts/framework/native/src/generated/library.cc +++ b/arkoala-arkts/framework/native/src/generated/library.cc @@ -18,6 +18,8 @@ #include "interop-types.h" #include "dynamic-loader.h" #include "interop-logging.h" +#include "arkoala_api_generated.h" +#include "callback-resource.h" #ifndef GENERATED_FOUNDATION_ACE_FRAMEWORKS_CORE_INTERFACES_ANY_API_H #define GENERATED_FOUNDATION_ACE_FRAMEWORKS_CORE_INTERFACES_ANY_API_H @@ -133,6 +135,10 @@ const OH_AnyAPI* GetAnyImpl(int kind, int version, std::string* result) { if (service) { if (logger) service->setLogger(reinterpret_cast(logger)); } + auto extended = (const GENERATED_ArkUIExtendedNodeAPI*)(*getAPI)(GENERATED_EXTENDED, GENERATED_ARKUI_EXTENDED_NODE_API_VERSION); + if (extended) { + extended->setCustomNodeDestroyCallback((void(*)(Ark_NodeHandle))releaseComponent); + } impl = (*getAPI)(kind, version); if (!impl) { diff --git a/arkoala/arkui/src/peer_events_checker.ts b/arkoala/arkui/src/peer_events_checker.ts index ff4c37a20..5f24147be 100644 --- a/arkoala/arkui/src/peer_events_checker.ts +++ b/arkoala/arkui/src/peer_events_checker.ts @@ -2,11 +2,14 @@ import { InteropNativeModule, ResourceHolder } from "@koalaui/interop" import { setCustomEventsChecker } from "@koalaui/arkoala" import { Deserializer } from "./generated/peers/Deserializer" import { deserializeAndCallCallback } from "./generated/peers/CallbackDeserializeCall" +import { PeerNode } from "@koalaui/arkoala" +import { destroyUiDetachedRoot } from "@koalaui/arkoala" enum CallbackEventKind { Event_CallCallback = 0, Event_HoldManagedResource = 1, Event_ReleaseManagedResource = 2, + Event_ReleaseComponent = 3, } const bufferSize = 4096 @@ -34,6 +37,16 @@ export function checkArkoalaCallbacks() { ResourceHolder.instance().release(resourceId) break; } + case CallbackEventKind.Event_ReleaseComponent: { + const nodeId = deserializer.readPointer(); + const peer = PeerNode.findPeerByNativeId(nodeId as number) + if (peer !== undefined) { + destroyUiDetachedRoot(peer) + } else { + InteropNativeModule._NativeLog("ERROR: can not find PeerNode for native id " + nodeId) + } + break; + } default: throw new Error(`Unknown callback event kind ${eventKind}`) } } diff --git a/interop/src/cpp/callback-resource.cc b/interop/src/cpp/callback-resource.cc index acbe9cd23..197b87a94 100644 --- a/interop/src/cpp/callback-resource.cc +++ b/interop/src/cpp/callback-resource.cc @@ -26,6 +26,7 @@ static bool needReleaseFront = false; static std::deque callbackEventsQueue; static std::deque callbackCallSubqueue; static std::deque callbackResourceSubqueue; +static std::deque componentSubqueue; void enqueueCallback(const CallbackBuffer* event) { callbackEventsQueue.push_back(Event_CallCallback); @@ -42,6 +43,11 @@ void releaseManagedCallbackResource(InteropInt32 resourceId) { callbackResourceSubqueue.push_back(resourceId); } +void releaseComponent(InteropNativePointer nodeId) { + callbackEventsQueue.push_back(Event_ReleaseComponent); + componentSubqueue.push_back(nodeId); +} + KInt impl_CheckCallbackEvent(KSerializerBuffer buffer, KInt size) { KByte* result = (KByte*)buffer; if (needReleaseFront) @@ -56,6 +62,9 @@ KInt impl_CheckCallbackEvent(KSerializerBuffer buffer, KInt size) { case Event_ReleaseManagedResource: callbackResourceSubqueue.pop_front(); break; + case Event_ReleaseComponent: + componentSubqueue.pop_front(); + break; default: INTEROP_FATAL("Unknown event kind"); } @@ -91,6 +100,15 @@ KInt impl_CheckCallbackEvent(KSerializerBuffer buffer, KInt size) { #endif break; } + case Event_ReleaseComponent: { + const InteropNativePointer nodeId = componentSubqueue.front(); + #ifdef __STDC_LIB_EXT1__ + memcpy_s(result + 4, size, &frontEventKind, 4); + #else + memcpy(result + 4, &nodeId, 8); + #endif + break; + } default: INTEROP_FATAL("Unknown event kind"); } diff --git a/interop/src/cpp/callback-resource.h b/interop/src/cpp/callback-resource.h index c7a742a05..478c53499 100644 --- a/interop/src/cpp/callback-resource.h +++ b/interop/src/cpp/callback-resource.h @@ -51,10 +51,13 @@ enum CallbackEventKind { Event_CallCallback = 0, Event_HoldManagedResource = 1, Event_ReleaseManagedResource = 2, + Event_ReleaseComponent = 3, }; extern "C" DLL_EXPORT void enqueueCallback(const CallbackBuffer* event); extern "C" DLL_EXPORT void holdManagedCallbackResource(InteropInt32 resourceId); extern "C" DLL_EXPORT void releaseManagedCallbackResource(InteropInt32 resourceId); +// TODO must be removed later. CustomBuilder must return not pointer to component but pointer + CallbackResource, that allows to control component lifecycle +extern "C" DLL_EXPORT void releaseComponent(InteropNativePointer nodeId); #endif -- Gitee