diff --git a/.vscode/launch.json b/.vscode/launch.json index 25d01c0b4a..02662a8dea 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -440,9 +440,9 @@ "name": "app (C/C++) (lldb, launch)", "type": "lldb", "request": "launch", - "program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/cpp/check_start_graph/check_start_graph_app/bin/check_start_graph_source", + "program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/cpp/standalone_test_cpp/default_extension_cpp/out/linux/x64/tests/default_extension_cpp_test", "args": [], - "cwd": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/cpp/check_start_graph/check_start_graph_app", + "cwd": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/cpp/standalone_test_cpp/default_extension_cpp/out/linux/x64/tests/", "env": { "ASAN_OPTIONS": "use_sigaltstack=0", }, diff --git a/core/include/ten_runtime/binding/cpp/internal/app.h b/core/include/ten_runtime/binding/cpp/internal/app.h index 67ef6efb6b..431b8efc4b 100644 --- a/core/include/ten_runtime/binding/cpp/internal/app.h +++ b/core/include/ten_runtime/binding/cpp/internal/app.h @@ -12,7 +12,7 @@ #include "ten_runtime/app/app.h" #include "ten_runtime/binding/common.h" #include "ten_runtime/binding/cpp/internal/common.h" -#include "ten_runtime/binding/cpp/internal/extension_group.h" +#include "ten_runtime/binding/cpp/internal/ten_env.h" #include "ten_runtime/ten.h" #include "ten_utils/macro/check.h" diff --git a/core/include/ten_runtime/binding/cpp/internal/extension_group.h b/core/include/ten_runtime/binding/cpp/internal/extension_group.h deleted file mode 100644 index fbf6b33b78..0000000000 --- a/core/include/ten_runtime/binding/cpp/internal/extension_group.h +++ /dev/null @@ -1,212 +0,0 @@ -// -// Copyright © 2024 Agora -// This file is part of TEN Framework, an open source project. -// Licensed under the Apache License, Version 2.0, with certain conditions. -// Refer to the "LICENSE" file in the root directory for more information. -// -#pragma once - -#include - -#include "ten_runtime/binding/common.h" -#include "ten_runtime/binding/cpp/internal/ten_env.h" -#include "ten_runtime/extension_group/extension_group.h" -#include "ten_utils/container/list.h" -#include "ten_utils/macro/check.h" - -// NOLINTNEXTLINE(bugprone-forward-declaration-namespace) -using ten_extension_group_t = struct ten_extension_group_t; -using ten_env_t = struct ten_env_t; - -namespace ten { - -class ten_env_t; -class app_t; - -class extension_group_t { - public: - virtual ~extension_group_t() { - TEN_ASSERT(c_extension_group, "Should not happen."); - ten_extension_group_destroy(c_extension_group); - - TEN_ASSERT(cpp_ten_env, "Should not happen."); - delete cpp_ten_env; - } - - // @{ - extension_group_t(const extension_group_t &) = delete; - extension_group_t(extension_group_t &&) = delete; - extension_group_t &operator=(const extension_group_t &) = delete; - extension_group_t &operator=(extension_group_t &&) = delete; - // @} - - // @{ - // Internal use only. - ::ten_extension_group_t *get_c_extension_group() const { - return c_extension_group; - } - // @} - - protected: - explicit extension_group_t(const std::string &name) - : c_extension_group(ten_extension_group_create( - name.c_str(), proxy_on_configure, proxy_on_init, proxy_on_deinit, - proxy_on_create_extensions, proxy_on_destroy_extensions)), - cpp_ten_env( - new ten_env_t(ten_extension_group_get_ten_env(c_extension_group))) { - ten_binding_handle_set_me_in_target_lang( - reinterpret_cast(c_extension_group), this); - - TEN_ASSERT(cpp_ten_env, "Should not happen."); - } - - virtual void on_configure(ten_env_t &ten_env) { ten_env.on_configure_done(); } - - virtual void on_init(ten_env_t &ten_env) { ten_env.on_init_done(); } - - virtual void on_deinit(ten_env_t &ten_env) { ten_env.on_deinit_done(); } - - virtual void on_create_extensions(ten_env_t &ten_env) { - std::vector const extensions; - ten_env.on_create_extensions_done(extensions); - } - - virtual void on_destroy_extensions( - TEN_UNUSED ten_env_t &ten_env, - const std::vector & /* extensions */) { - TEN_ASSERT(0 && "should be overriden by the child class.", - "Should not happen."); - } - - private: - friend class ten_env_t; - friend class app_t; - - static void proxy_on_configure(ten_extension_group_t *extension_group, - ::ten_env_t *ten_env) { - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Invalid argument."); - TEN_ASSERT(ten_extension_group_get_ten_env(extension_group) && - ten_env_check_integrity( - ten_extension_group_get_ten_env(extension_group), true), - "Should not happen."); - - auto *cpp_extension_group = static_cast( - ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(extension_group))); - - auto *cpp_ten_env = - static_cast(ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(ten_env))); - - cpp_extension_group->on_configure(*cpp_ten_env); - } - - static void proxy_on_init(ten_extension_group_t *extension_group, - ::ten_env_t *ten_env) { - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Invalid argument."); - TEN_ASSERT(ten_extension_group_get_ten_env(extension_group) && - ten_env_check_integrity( - ten_extension_group_get_ten_env(extension_group), true), - "Should not happen."); - - auto *cpp_extension_group = static_cast( - ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(extension_group))); - - auto *cpp_ten_env = - static_cast(ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(ten_env))); - - cpp_extension_group->on_init(*cpp_ten_env); - } - - static void proxy_on_deinit(ten_extension_group_t *extension_group, - ::ten_env_t *ten_env) { - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Invalid argument."); - TEN_ASSERT(ten_extension_group_get_ten_env(extension_group) && - ten_env_check_integrity( - ten_extension_group_get_ten_env(extension_group), true), - "Should not happen."); - - auto *cpp_extension_group = static_cast( - ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(extension_group))); - - auto *cpp_ten_env = - static_cast(ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(ten_env))); - - cpp_extension_group->on_deinit(*cpp_ten_env); - } - - static void proxy_on_create_extensions(ten_extension_group_t *extension_group, - ::ten_env_t *ten_env) { - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Invalid argument."); - TEN_ASSERT(ten_extension_group_get_ten_env(extension_group) && - ten_env_check_integrity( - ten_extension_group_get_ten_env(extension_group), true), - "Should not happen."); - - auto *cpp_extension_group = static_cast( - ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(extension_group))); - TEN_ASSERT(cpp_extension_group, "Should not happen."); - - auto *cpp_ten_env = - static_cast(ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(ten_env))); - - cpp_extension_group->on_create_extensions(*cpp_ten_env); - } - - static void proxy_on_destroy_extensions( - ten_extension_group_t *extension_group, ::ten_env_t *ten_env, - ::ten_list_t extensions) { - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Invalid argument."); - TEN_ASSERT(ten_extension_group_get_ten_env(extension_group) && - ten_env_check_integrity( - ten_extension_group_get_ten_env(extension_group), true), - "Should not happen."); - - auto *cpp_extension_group = static_cast( - ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(extension_group))); - TEN_ASSERT(cpp_extension_group, "Should not happen."); - - std::vector extensions_vector; - ten_list_foreach (&extensions, iter) { - auto *c_extension = - static_cast<::ten_extension_t *>(ten_ptr_listnode_get(iter.node)); - TEN_ASSERT( - c_extension && ten_extension_check_integrity(c_extension, true), - "Should not happen."); - - extensions_vector.push_back( - static_cast(ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(c_extension)))); - } - - auto *cpp_ten_env = - static_cast(ten_binding_handle_get_me_in_target_lang( - reinterpret_cast(ten_env))); - - // The extension group should be responsible for deleting the C++ - // ten_extension_t object. - cpp_extension_group->on_destroy_extensions(*cpp_ten_env, extensions_vector); - } - - ::ten_extension_group_t *c_extension_group; - ten_env_t *cpp_ten_env; -}; - -} // namespace ten diff --git a/core/include/ten_runtime/binding/cpp/internal/ten_env_impl.h b/core/include/ten_runtime/binding/cpp/internal/ten_env_impl.h index 787b5d8c6a..de52c713e4 100644 --- a/core/include/ten_runtime/binding/cpp/internal/ten_env_impl.h +++ b/core/include/ten_runtime/binding/cpp/internal/ten_env_impl.h @@ -10,7 +10,6 @@ #include "ten_runtime/binding/cpp/internal/addon.h" #include "ten_runtime/binding/cpp/internal/extension.h" -#include "ten_runtime/binding/cpp/internal/extension_group.h" #include "ten_runtime/binding/cpp/internal/ten_env.h" #include "ten_utils/lang/cpp/lib/error.h" @@ -30,10 +29,6 @@ inline bool ten_env_t::on_create_instance_done(void *instance, void *context, case ADDON_TASK_CREATE_EXTENSION: c_instance = static_cast(instance)->get_c_extension(); break; - case ADDON_TASK_CREATE_EXTENSION_GROUP: - c_instance = - static_cast(instance)->get_c_extension_group(); - break; default: TEN_ASSERT(0, "Should not happen."); break; diff --git a/core/include/ten_runtime/binding/cpp/ten.h b/core/include/ten_runtime/binding/cpp/ten.h index 73a8e843f5..f5ad62d2ff 100644 --- a/core/include/ten_runtime/binding/cpp/ten.h +++ b/core/include/ten_runtime/binding/cpp/ten.h @@ -32,6 +32,5 @@ #include "ten_runtime/addon/extension_group/extension_group.h" // IWYU pragma: export #include "ten_runtime/binding/cpp/internal/addon.h" // IWYU pragma: export #include "ten_runtime/binding/cpp/internal/app.h" // IWYU pragma: export -#include "ten_runtime/binding/cpp/internal/extension_group.h" // IWYU pragma: export #include "ten_runtime/binding/cpp/internal/extension_impl.h" // IWYU pragma: export #include "ten_runtime/binding/cpp/internal/ten_env_impl.h" // IWYU pragma: export diff --git a/core/include/ten_utils/lib/file.h b/core/include/ten_utils/lib/file.h index 0c4b5545bd..c4c688ff1e 100644 --- a/core/include/ten_utils/lib/file.h +++ b/core/include/ten_utils/lib/file.h @@ -22,8 +22,6 @@ TEN_UTILS_API int ten_file_size(const char *filename); TEN_UTILS_API char *ten_file_read(const char *filename); -TEN_UTILS_API char *ten_file_read_from_open_file(FILE *fp); - TEN_UTILS_API char *ten_symlink_file_read(const char *path); TEN_UTILS_API int ten_file_write(const char *filename, ten_buf_t buf); diff --git a/core/include/ten_utils/lib/module.h b/core/include/ten_utils/lib/module.h index 14de58613f..3b7ffeaf4f 100644 --- a/core/include/ten_utils/lib/module.h +++ b/core/include/ten_utils/lib/module.h @@ -26,4 +26,7 @@ TEN_UTILS_API void *ten_module_load(const ten_string_t *name, int as_local); * @param handle The handle of the module to unload. * @return 0 on success, or -1 on failure. */ -TEN_UTILS_API int ten_module_close(void *handle); \ No newline at end of file +TEN_UTILS_API int ten_module_close(void *handle); + +TEN_UTILS_API void *ten_module_get_symbol(void *handle, + const char *symbol_name); diff --git a/core/include_internal/ten_runtime/addon/addon.h b/core/include_internal/ten_runtime/addon/addon.h index 6c5935f90d..845d863853 100644 --- a/core/include_internal/ten_runtime/addon/addon.h +++ b/core/include_internal/ten_runtime/addon/addon.h @@ -73,6 +73,8 @@ typedef struct ten_addon_host_t { ten_env_t *ten_env; TEN_ADDON_TYPE type; + + void *user_data; } ten_addon_host_t; typedef struct ten_addon_on_create_instance_info_t { @@ -102,6 +104,9 @@ TEN_RUNTIME_PRIVATE_API ten_addon_host_t *ten_addon_host_create( TEN_RUNTIME_API void ten_addon_host_destroy(ten_addon_host_t *self); +TEN_RUNTIME_PRIVATE_API TEN_ADDON_TYPE +ten_addon_type_from_string(const char *addon_type_str); + TEN_RUNTIME_PRIVATE_API void ten_addon_register(ten_addon_store_t *addon_store, ten_addon_host_t *addon_host, const char *name, diff --git a/core/include_internal/ten_runtime/addon/addon_autoload.h b/core/include_internal/ten_runtime/addon/addon_autoload.h index 5fc8a2bb39..68354c5ebb 100644 --- a/core/include_internal/ten_runtime/addon/addon_autoload.h +++ b/core/include_internal/ten_runtime/addon/addon_autoload.h @@ -14,6 +14,8 @@ typedef struct ten_app_t ten_app_t; +typedef void (*ten_addon_register_func_t)(void *register_ctx); + TEN_RUNTIME_PRIVATE_API bool ten_addon_load_all_from_app_base_dir( ten_app_t *app, ten_list_t *extension_dependencies, ten_list_t *extension_group_dependencies, ten_list_t *protocol_dependencies, diff --git a/core/include_internal/ten_runtime/addon/extension/extension.h b/core/include_internal/ten_runtime/addon/extension/extension.h index 3104723d79..b1e5532f53 100644 --- a/core/include_internal/ten_runtime/addon/extension/extension.h +++ b/core/include_internal/ten_runtime/addon/extension/extension.h @@ -9,5 +9,11 @@ #include "ten_runtime/ten_config.h" typedef struct ten_addon_store_t ten_addon_store_t; +typedef struct ten_addon_t ten_addon_t; -TEN_RUNTIME_PRIVATE_API ten_addon_store_t *ten_extension_get_store(void); +TEN_RUNTIME_PRIVATE_API ten_addon_store_t *ten_extension_get_global_store(void); + +TEN_RUNTIME_API void ten_addon_register_extension_v2(const char *name, + const char *base_dir, + void *register_ctx, + ten_addon_t *addon); diff --git a/core/include_internal/ten_runtime/addon/extension_group/extension_group.h b/core/include_internal/ten_runtime/addon/extension_group/extension_group.h index e806356e28..8e0c1eebf3 100644 --- a/core/include_internal/ten_runtime/addon/extension_group/extension_group.h +++ b/core/include_internal/ten_runtime/addon/extension_group/extension_group.h @@ -15,7 +15,8 @@ typedef struct ten_env_t ten_env_t; typedef struct ten_addon_store_t ten_addon_store_t; -TEN_RUNTIME_PRIVATE_API ten_addon_store_t *ten_extension_group_get_store(void); +TEN_RUNTIME_PRIVATE_API ten_addon_store_t *ten_extension_group_get_global_store( + void); TEN_RUNTIME_API bool ten_addon_create_extension_group( ten_env_t *ten_env, const char *addon_name, const char *instance_name, diff --git a/core/include_internal/ten_runtime/addon/protocol/protocol.h b/core/include_internal/ten_runtime/addon/protocol/protocol.h index c377b00ca2..ee44f327ca 100644 --- a/core/include_internal/ten_runtime/addon/protocol/protocol.h +++ b/core/include_internal/ten_runtime/addon/protocol/protocol.h @@ -37,7 +37,7 @@ TEN_RUNTIME_PRIVATE_API bool ten_addon_create_protocol( TEN_PROTOCOL_ROLE role, ten_env_addon_on_create_protocol_async_cb_t cb, void *user_data, ten_error_t *err); -TEN_RUNTIME_PRIVATE_API ten_addon_store_t *ten_protocol_get_store(void); +TEN_RUNTIME_PRIVATE_API ten_addon_store_t *ten_protocol_get_global_store(void); TEN_RUNTIME_PRIVATE_API ten_addon_host_t *ten_addon_protocol_find( const char *protocol); diff --git a/core/include_internal/ten_runtime/app/metadata.h b/core/include_internal/ten_runtime/app/metadata.h index 103cb9bbd5..67d8e63838 100644 --- a/core/include_internal/ten_runtime/app/metadata.h +++ b/core/include_internal/ten_runtime/app/metadata.h @@ -11,7 +11,6 @@ #include #include -#include "include_internal/ten_runtime/common/constant_str.h" #include "ten_utils/lib/error.h" typedef struct ten_app_t ten_app_t; @@ -29,6 +28,9 @@ typedef struct ten_app_ten_namespace_prop_info_t { TEN_RUNTIME_PRIVATE_API void ten_app_handle_metadata(ten_app_t *self); +TEN_RUNTIME_API void ten_app_get_extension_dependencies_for_extension( + ten_app_t *self, ten_list_t *extension_dependencies); + TEN_RUNTIME_PRIVATE_API bool ten_app_handle_ten_namespace_properties( ten_app_t *self); @@ -54,30 +56,3 @@ TEN_RUNTIME_PRIVATE_API bool ten_app_init_log_level(ten_app_t *self, TEN_RUNTIME_PRIVATE_API bool ten_app_init_log_file(ten_app_t *self, ten_value_t *value); - -static const ten_app_ten_namespace_prop_info_t - ten_app_ten_namespace_prop_info_list[] = { - { - .name = TEN_STR_ONE_EVENT_LOOP_PER_ENGINE, - .init_from_value = ten_app_init_one_event_loop_per_engine, - }, - { - .name = TEN_STR_LONG_RUNNING_MODE, - .init_from_value = ten_app_init_long_running_mode, - }, - { - .name = TEN_STR_URI, - .init_from_value = ten_app_init_uri, - }, - { - .name = TEN_STR_LOG_LEVEL, - .init_from_value = ten_app_init_log_level, - }, - { - .name = TEN_STR_LOG_FILE, - .init_from_value = ten_app_init_log_file, - }}; - -static const size_t ten_app_ten_namespace_prop_info_list_size = - sizeof(ten_app_ten_namespace_prop_info_list) / - sizeof(ten_app_ten_namespace_prop_info_list[0]); diff --git a/core/include_internal/ten_runtime/app/ten_property.h b/core/include_internal/ten_runtime/app/ten_property.h new file mode 100644 index 0000000000..3ad873db1e --- /dev/null +++ b/core/include_internal/ten_runtime/app/ten_property.h @@ -0,0 +1,39 @@ +// +// Copyright © 2024 Agora +// This file is part of TEN Framework, an open source project. +// Licensed under the Apache License, Version 2.0, with certain conditions. +// Refer to the "LICENSE" file in the root directory for more information. +// +#pragma once + +#include "ten_runtime/ten_config.h" + +#include "include_internal/ten_runtime/app/metadata.h" +#include "include_internal/ten_runtime/common/constant_str.h" + +static const ten_app_ten_namespace_prop_info_t + ten_app_ten_namespace_prop_info_list[] = { + { + .name = TEN_STR_ONE_EVENT_LOOP_PER_ENGINE, + .init_from_value = ten_app_init_one_event_loop_per_engine, + }, + { + .name = TEN_STR_LONG_RUNNING_MODE, + .init_from_value = ten_app_init_long_running_mode, + }, + { + .name = TEN_STR_URI, + .init_from_value = ten_app_init_uri, + }, + { + .name = TEN_STR_LOG_LEVEL, + .init_from_value = ten_app_init_log_level, + }, + { + .name = TEN_STR_LOG_FILE, + .init_from_value = ten_app_init_log_file, + }}; + +static const size_t ten_app_ten_namespace_prop_info_list_size = + sizeof(ten_app_ten_namespace_prop_info_list) / + sizeof(ten_app_ten_namespace_prop_info_list[0]); diff --git a/core/include_internal/ten_runtime/binding/cpp/internal/ten_env_internal_accessor.h b/core/include_internal/ten_runtime/binding/cpp/internal/ten_env_internal_accessor.h index f56ce1ea2e..e2e4eb4d07 100644 --- a/core/include_internal/ten_runtime/binding/cpp/internal/ten_env_internal_accessor.h +++ b/core/include_internal/ten_runtime/binding/cpp/internal/ten_env_internal_accessor.h @@ -32,6 +32,8 @@ class ten_env_internal_accessor_t { return ten_env->init_manifest_from_json(json_str, nullptr); } + ::ten_env_t *get_c_ten_env() const { return ten_env->get_c_ten_env(); } + private: ten_env_t *ten_env; }; diff --git a/core/include_internal/ten_runtime/binding/cpp/ten.h b/core/include_internal/ten_runtime/binding/cpp/ten.h index 73cc016be8..35ec443513 100644 --- a/core/include_internal/ten_runtime/binding/cpp/ten.h +++ b/core/include_internal/ten_runtime/binding/cpp/ten.h @@ -28,7 +28,6 @@ // 'extension.h' must be in front of 'addon.h' #include "ten_runtime/binding/cpp/internal/extension.h" // IWYU pragma: export // clang-format on - #include "include_internal/ten_runtime/binding/cpp/internal/extension_impl.h" // IWYU pragma: export #include "include_internal/ten_runtime/binding/cpp/internal/ten_env_impl.h" // IWYU pragma: export #include "include_internal/ten_runtime/binding/cpp/internal/ten_env_internal_accessor.h" // IWYU pragma: export @@ -36,5 +35,4 @@ #include "ten_runtime/addon/extension_group/extension_group.h" // IWYU pragma: export #include "ten_runtime/binding/cpp/internal/addon.h" // IWYU pragma: export #include "ten_runtime/binding/cpp/internal/app.h" // IWYU pragma: export -#include "ten_runtime/binding/cpp/internal/extension_group.h" // IWYU pragma: export #include "ten_runtime/binding/cpp/internal/ten_env_impl.h" // IWYU pragma: export diff --git a/core/include_internal/ten_runtime/binding/go/extension_group/extension_group.h b/core/include_internal/ten_runtime/binding/go/extension_group/extension_group.h deleted file mode 100644 index 249496e9fd..0000000000 --- a/core/include_internal/ten_runtime/binding/go/extension_group/extension_group.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright © 2024 Agora -// This file is part of TEN Framework, an open source project. -// Licensed under the Apache License, Version 2.0, with certain conditions. -// Refer to the "LICENSE" file in the root directory for more information. -// -#include "ten_runtime/ten_config.h" - -#include "include_internal/ten_runtime/extension/extension.h" -#include "src/ten_runtime/binding/go/interface/ten/common.h" -#include "ten_utils/lib/signature.h" - -#define TEN_GO_EXTENSION_GROUP_SIGNATURE 0xCD7EC4A88C000EC0U - -typedef struct ten_go_extension_group_t { - ten_signature_t signature; - - ten_go_bridge_t bridge; - - ten_extension_group_t *c_extension_group; - const char *name; -} ten_go_extension_group_t; - -TEN_RUNTIME_PRIVATE_API bool ten_go_extension_group_check_integrity( - ten_go_extension_group_t *self); - -TEN_RUNTIME_PRIVATE_API ten_go_extension_group_t * -ten_go_extension_group_reinterpret(uintptr_t extension_group_bridge); - -TEN_RUNTIME_PRIVATE_API ten_go_handle_t -ten_go_extension_group_go_handle(ten_go_extension_group_t *self); - -TEN_RUNTIME_PRIVATE_API ten_go_extension_group_t * -ten_go_extension_group_create_internal(ten_go_handle_t go_extension_group, - const char *name); - -TEN_RUNTIME_PRIVATE_API ten_extension_group_t * -ten_go_extension_group_c_extension_group(ten_go_extension_group_t *self); - -TEN_RUNTIME_PRIVATE_API void ten_go_extension_group_set_go_handle( - ten_go_extension_group_t *self, ten_go_handle_t go_handle); diff --git a/core/include_internal/ten_runtime/binding/python/addon/decorator.h b/core/include_internal/ten_runtime/binding/python/addon/decorator.h index 9df6c3a1c0..a8c1c8d092 100644 --- a/core/include_internal/ten_runtime/binding/python/addon/decorator.h +++ b/core/include_internal/ten_runtime/binding/python/addon/decorator.h @@ -21,7 +21,3 @@ typedef struct ten_py_decorator_register_addon_t { TEN_RUNTIME_PRIVATE_API bool ten_py_decorator_register_addon_as_extension_init_for_module(PyObject *module); - -TEN_RUNTIME_PRIVATE_API bool -ten_py_decorator_register_addon_as_extension_group_init_for_module( - PyObject *module); diff --git a/core/include_internal/ten_runtime/common/constant_str.h b/core/include_internal/ten_runtime/common/constant_str.h index 83eaa1f8ad..13df2557b7 100644 --- a/core/include_internal/ten_runtime/common/constant_str.h +++ b/core/include_internal/ten_runtime/common/constant_str.h @@ -161,3 +161,8 @@ #define TEN_STR_DEFAULT_EXTENSION_GROUP "default_extension_group" #define TEN_STR_TEN_TEST_EXTENSION "ten:test_extension" + +#define TEN_STR_ADDON_REGISTER_FUNCTION_PREFIX "____ten_addon_" +#define TEN_STR_ADDON_REGISTER_FUNCTION_POSTFIX "_register____" + +#define TEN_STR_MANIFEST_JSON "manifest.json" diff --git a/core/include_internal/ten_runtime/metadata/manifest.h b/core/include_internal/ten_runtime/metadata/manifest.h index 52d2ea867b..0003f88446 100644 --- a/core/include_internal/ten_runtime/metadata/manifest.h +++ b/core/include_internal/ten_runtime/metadata/manifest.h @@ -6,14 +6,14 @@ // #include "ten_runtime/ten_config.h" +#include "include_internal/ten_runtime/addon/addon.h" #include "ten_utils/lib/string.h" #include "ten_utils/value/value.h" -TEN_RUNTIME_PRIVATE_API void -ten_manifest_dependencies_get_dependencies_type_and_name( - ten_value_t *manifest_dependencies, ten_list_t *extension_list, - ten_list_t *extension_group_list, ten_list_t *protocol_list); - TEN_RUNTIME_PRIVATE_API void ten_manifest_get_dependencies_type_and_name( ten_value_t *manifest, ten_list_t *extension_list, ten_list_t *extension_group_list, ten_list_t *protocol_list); + +TEN_RUNTIME_PRIVATE_API bool ten_manifest_get_type_and_name( + const char *filename, TEN_ADDON_TYPE *type, ten_string_t *name, + ten_error_t *err); diff --git a/core/include_internal/ten_runtime/ten_env/ten_env.h b/core/include_internal/ten_runtime/ten_env/ten_env.h index 89a5220f49..637d7ca227 100644 --- a/core/include_internal/ten_runtime/ten_env/ten_env.h +++ b/core/include_internal/ten_runtime/ten_env/ten_env.h @@ -73,6 +73,9 @@ TEN_RUNTIME_PRIVATE_API ten_runloop_t *ten_env_get_attached_runloop( TEN_RUNTIME_PRIVATE_API ten_env_t *ten_env_create_for_extension_group( ten_extension_group_t *extension_group); +TEN_RUNTIME_PRIVATE_API ten_env_t *ten_env_create_for_addon( + ten_addon_host_t *addon_host); + TEN_RUNTIME_PRIVATE_API ten_env_t *ten_env_create_for_extension( ten_extension_t *extension); diff --git a/core/src/ten_runtime/addon/addon.c b/core/src/ten_runtime/addon/addon.c index 8d6453200a..f0fdce4705 100644 --- a/core/src/ten_runtime/addon/addon.c +++ b/core/src/ten_runtime/addon/addon.c @@ -11,14 +11,12 @@ #include "include_internal/ten_runtime/addon/extension/extension.h" #include "include_internal/ten_runtime/addon/extension_group/extension_group.h" #include "include_internal/ten_runtime/addon/protocol/protocol.h" -#include "include_internal/ten_runtime/app/app.h" #include "include_internal/ten_runtime/app/base_dir.h" #include "include_internal/ten_runtime/common/base_dir.h" #include "include_internal/ten_runtime/common/constant_str.h" #include "include_internal/ten_runtime/extension/extension.h" #include "include_internal/ten_runtime/extension_group/extension_group.h" #include "include_internal/ten_runtime/metadata/metadata_info.h" -#include "include_internal/ten_runtime/protocol/protocol.h" #include "include_internal/ten_runtime/ten_env/ten_env.h" #include "ten_runtime/app/app.h" #include "ten_runtime/binding/common.h" @@ -116,6 +114,8 @@ void ten_addon_host_init(ten_addon_host_t *self) { self->manifest_info = NULL; self->property_info = NULL; + + self->user_data = NULL; } void ten_addon_host_destroy(ten_addon_host_t *self) { @@ -162,6 +162,20 @@ static void ten_addon_load_metadata(ten_addon_host_t *self, ten_env_t *ten_env, } } +TEN_ADDON_TYPE ten_addon_type_from_string(const char *addon_type_str) { + TEN_ASSERT(addon_type_str, "Invalid argument."); + + if (ten_c_string_is_equal(addon_type_str, TEN_STR_EXTENSION)) { + return TEN_ADDON_TYPE_EXTENSION; + } else if (ten_c_string_is_equal(addon_type_str, TEN_STR_EXTENSION_GROUP)) { + return TEN_ADDON_TYPE_EXTENSION_GROUP; + } else if (ten_c_string_is_equal(addon_type_str, TEN_STR_PROTOCOL)) { + return TEN_ADDON_TYPE_PROTOCOL; + } else { + return TEN_ADDON_TYPE_INVALID; + } +} + static const char *ten_addon_type_to_string(TEN_ADDON_TYPE type) { switch (type) { case TEN_ADDON_TYPE_EXTENSION: @@ -189,14 +203,13 @@ void ten_addon_register(ten_addon_store_t *addon_store, const char *base_dir, ten_addon_t *addon) { TEN_ASSERT(addon_host && ten_addon_host_check_integrity(addon_host), "Should not happen."); - TEN_ASSERT(!addon_host->ten_env, "Invalid argument."); TEN_ASSERT(name, "Should not happen."); addon_host->addon = addon; addon_host->store = addon_store; - addon_host->ten_env = ten_env_create(); - ten_env_set_attach_to(addon_host->ten_env, TEN_ENV_ATTACH_TO_ADDON, - addon_host); + if (!addon_host->ten_env) { + addon_host->ten_env = ten_env_create_for_addon(addon_host); + } ten_string_set_formatted(&addon_host->name, "%s", name); @@ -308,13 +321,14 @@ ten_addon_host_t *ten_addon_host_find(const char *addon_name, switch (type) { case TEN_ADDON_TYPE_EXTENSION: - return ten_addon_store_find(ten_extension_get_store(), addon_name); + return ten_addon_store_find(ten_extension_get_global_store(), addon_name); case TEN_ADDON_TYPE_EXTENSION_GROUP: - return ten_addon_store_find(ten_extension_group_get_store(), addon_name); + return ten_addon_store_find(ten_extension_group_get_global_store(), + addon_name); case TEN_ADDON_TYPE_PROTOCOL: - return ten_addon_store_find(ten_protocol_get_store(), addon_name); + return ten_addon_store_find(ten_protocol_get_global_store(), addon_name); default: TEN_ASSERT(0, "Should not happen."); diff --git a/core/src/ten_runtime/addon/addon_autoload.c b/core/src/ten_runtime/addon/addon_autoload.c index cbf92ec5d2..29457ce688 100644 --- a/core/src/ten_runtime/addon/addon_autoload.c +++ b/core/src/ten_runtime/addon/addon_autoload.c @@ -6,11 +6,6 @@ // #include "include_internal/ten_runtime/addon/addon_autoload.h" -#include "ten_runtime/app/app.h" -#include "ten_utils/container/list.h" -#include "ten_utils/container/list_node_str.h" -#include "ten_utils/lib/error.h" - #if defined(OS_LINUX) #define _GNU_SOURCE #endif @@ -22,13 +17,23 @@ #include #endif +#include "include_internal/ten_runtime/addon/addon.h" +#include "include_internal/ten_runtime/addon/extension/extension.h" #include "include_internal/ten_runtime/app/app.h" +#include "include_internal/ten_runtime/common/constant_str.h" #include "include_internal/ten_runtime/global/global.h" #include "include_internal/ten_runtime/global/signal.h" +#include "include_internal/ten_runtime/metadata/manifest.h" +#include "include_internal/ten_runtime/ten_env/ten_env.h" #include "include_internal/ten_utils/log/log.h" +#include "ten_runtime/app/app.h" +#include "ten_utils/container/list.h" +#include "ten_utils/container/list_node_str.h" +#include "ten_utils/lib/error.h" #include "ten_utils/lib/module.h" #include "ten_utils/lib/path.h" #include "ten_utils/lib/string.h" +#include "ten_utils/log/log.h" /** * @brief @@ -45,7 +50,13 @@ * Neither Android nor iOS support unload library. */ #if defined(OS_MACOS) || defined(OS_LINUX) || defined(OS_WINDOWS) -static void load_all_dynamic_libraries_under_path(const char *path) { +static void load_all_dynamic_libraries_under_path(ten_app_t *app, + TEN_ADDON_TYPE addon_type, + const char *addon_name, + const char *path) { + TEN_ASSERT(app && ten_app_check_integrity(app, true), "Invalid argument."); + TEN_ASSERT(path, "Invalid argument."); + ten_dir_fd_t *dir = NULL; ten_path_itor_t *itor = NULL; ten_string_t *file_path = NULL; @@ -83,18 +94,56 @@ static void load_all_dynamic_libraries_under_path(const char *path) { goto continue_loop; } + ten_addon_host_t *addon_host = ten_addon_store_find( + ten_extension_get_global_store(), ten_string_get_raw_str(short_name)); + if (addon_host) { + // Do _not_ register again. + goto continue_loop; + } + if (ten_path_to_system_flavor(file_path) != 0) { TEN_LOGE("Failed to convert path to system flavor: %s", ten_string_get_raw_str(file_path)); goto continue_loop; } - if (ten_module_load(file_path, 1) == 0) { + void *module_handle = ten_module_load(file_path, 1); + if (!module_handle) { TEN_LOGE("Failed to load module: %s", ten_string_get_raw_str(file_path)); goto continue_loop; } - TEN_LOGI("Loaded module: %s", ten_string_get_raw_str(file_path)); + ten_string_t register_func_name; + ten_string_init(®ister_func_name); + ten_string_append_formatted( + ®ister_func_name, "%s%s%s", TEN_STR_ADDON_REGISTER_FUNCTION_PREFIX, + addon_name, TEN_STR_ADDON_REGISTER_FUNCTION_POSTFIX); + + void *symbol = ten_module_get_symbol( + module_handle, ten_string_get_raw_str(®ister_func_name)); + if (symbol) { + ten_addon_register_func_t register_func = + (ten_addon_register_func_t)symbol; + + addon_host = ten_addon_host_create(addon_type); + TEN_ASSERT(addon_host, "Should not happen."); + + addon_host->user_data = app; + addon_host->ten_env = ten_env_create_for_addon(addon_host); + TEN_ASSERT(addon_host->ten_env, "Should not happen."); + + register_func((void *)addon_host); + + TEN_LOGI("Register addon using function: %s", + ten_string_get_raw_str(®ister_func_name)); + } else { + TEN_LOGD("Registration function not found for module: %s", + ten_string_get_raw_str(file_path)); + } + + TEN_LOGD("Loaded module: %s", ten_string_get_raw_str(file_path)); + + ten_string_deinit(®ister_func_name); continue_loop: if (file_path) { @@ -116,36 +165,41 @@ static void load_all_dynamic_libraries_under_path(const char *path) { } } -static void ten_addon_load_from_base_dir(const char *path) { - ten_string_t self; - ten_string_init_formatted(&self, "%s", path); +static void ten_addon_load_from_base_dir(ten_app_t *app, + TEN_ADDON_TYPE addon_type, + const char *addon_name, + const char *path) { + ten_string_t lib_dir; + ten_string_init_formatted(&lib_dir, "%s", path); - if (!ten_path_is_dir(&self)) { + if (!ten_path_is_dir(&lib_dir)) { goto done; } - ten_string_append_formatted(&self, "/lib"); - if (ten_path_to_system_flavor(&self) != 0) { + ten_string_append_formatted(&lib_dir, "/lib"); + if (ten_path_to_system_flavor(&lib_dir) != 0) { TEN_LOGE("Failed to convert path to system flavor: %s", - ten_string_get_raw_str(&self)); + ten_string_get_raw_str(&lib_dir)); goto done; } - if (!ten_path_exists(ten_string_get_raw_str(&self)) || - !ten_path_is_dir(&self)) { + if (!ten_path_exists(ten_string_get_raw_str(&lib_dir)) || + !ten_path_is_dir(&lib_dir)) { TEN_LOGD("The dynamic library path(%s) does not exist.", - ten_string_get_raw_str(&self)); + ten_string_get_raw_str(&lib_dir)); goto done; } // Load self first. - load_all_dynamic_libraries_under_path(ten_string_get_raw_str(&self)); + load_all_dynamic_libraries_under_path(app, addon_type, addon_name, + ten_string_get_raw_str(&lib_dir)); done: - ten_string_deinit(&self); + ten_string_deinit(&lib_dir); } -static void load_all_dynamic_libraries(const char *path, +static void load_all_dynamic_libraries(ten_app_t *app, const char *path, + TEN_ADDON_TYPE addon_type, ten_list_t *dependencies) { ten_string_t *cur = NULL; ten_string_t *short_name = NULL; @@ -204,7 +258,9 @@ static void load_all_dynamic_libraries(const char *path, goto continue_loop; } - ten_addon_load_from_base_dir(ten_string_get_raw_str(cur)); + ten_addon_load_from_base_dir(app, addon_type, + ten_string_get_raw_str(short_name), + ten_string_get_raw_str(cur)); ten_string_destroy(cur); cur = NULL; @@ -274,11 +330,24 @@ bool ten_addon_load_all_from_app_base_dir( struct { const char *path; + TEN_ADDON_TYPE addon_type; ten_list_t *dependencies; } folders[] = { - {"/ten_packages/extension", extension_dependencies}, - {"/ten_packages/extension_group", extension_group_dependencies}, - {"/ten_packages/protocol", protocol_dependencies}, + { + "/ten_packages/extension", + TEN_ADDON_TYPE_EXTENSION, + extension_dependencies, + }, + { + "/ten_packages/extension_group", + TEN_ADDON_TYPE_EXTENSION_GROUP, + extension_group_dependencies, + }, + { + "/ten_packages/protocol", + TEN_ADDON_TYPE_PROTOCOL, + protocol_dependencies, + }, }; for (int i = 0; i < sizeof(folders) / sizeof(folders[0]); i++) { @@ -300,7 +369,8 @@ bool ten_addon_load_all_from_app_base_dir( // The modules (e.g., extensions/protocols) do not exist if only the TEN // app has been installed. if (ten_path_exists(ten_string_get_raw_str(&module_path))) { - load_all_dynamic_libraries(ten_string_get_raw_str(&module_path), + load_all_dynamic_libraries(app, ten_string_get_raw_str(&module_path), + folders[i].addon_type, folders[i].dependencies); } } while (0); @@ -335,7 +405,27 @@ bool ten_addon_load_all_from_ten_package_base_dirs(ten_app_t *app, TEN_LOGI("Load dynamic libraries under path: %s", ten_string_get_raw_str(ten_package_base_dir)); - ten_addon_load_from_base_dir(ten_string_get_raw_str(ten_package_base_dir)); + TEN_ADDON_TYPE addon_type = TEN_ADDON_TYPE_INVALID; + ten_string_t addon_name; + ten_string_init(&addon_name); + + // Construct `manifest.json` path. + ten_string_t manifest_json_file_path; + ten_string_init_from_string(&manifest_json_file_path, ten_package_base_dir); + ten_path_join_c_str(&manifest_json_file_path, TEN_STR_MANIFEST_JSON); + + // Get type and name from manifest file. + ten_manifest_get_type_and_name( + ten_string_get_raw_str(&manifest_json_file_path), &addon_type, + &addon_name, NULL); + + ten_string_deinit(&manifest_json_file_path); + + ten_addon_load_from_base_dir(app, addon_type, + ten_string_get_raw_str(&addon_name), + ten_string_get_raw_str(ten_package_base_dir)); + + ten_string_deinit(&addon_name); } return success; diff --git a/core/src/ten_runtime/addon/extension/extension.c b/core/src/ten_runtime/addon/extension/extension.c index c2886bff84..eb50f00af3 100644 --- a/core/src/ten_runtime/addon/extension/extension.c +++ b/core/src/ten_runtime/addon/extension/extension.c @@ -15,6 +15,7 @@ #include "include_internal/ten_runtime/ten_env/ten_env.h" #include "ten_runtime/addon/addon.h" #include "ten_runtime/ten_env/ten_env.h" +#include "ten_utils/backtrace/backtrace.h" #include "ten_utils/macro/check.h" #include "ten_utils/macro/mark.h" @@ -24,7 +25,10 @@ static ten_addon_store_t g_extension_store = { TEN_LIST_INIT_VAL, }; -ten_addon_store_t *ten_extension_get_store(void) { return &g_extension_store; } +ten_addon_store_t *ten_extension_get_global_store(void) { + ten_addon_store_init(&g_extension_store); + return &g_extension_store; +} bool ten_addon_create_extension(ten_env_t *ten_env, const char *addon_name, const char *instance_name, @@ -120,10 +124,8 @@ ten_addon_host_t *ten_addon_register_extension(const char *name, exit(EXIT_FAILURE); } - ten_addon_store_init(ten_extension_get_store()); - ten_addon_host_t *addon_host = - ten_addon_store_find(ten_extension_get_store(), name); + ten_addon_store_find(ten_extension_get_global_store(), name); if (addon_host) { return addon_host; } @@ -131,14 +133,29 @@ ten_addon_host_t *ten_addon_register_extension(const char *name, addon_host = ten_addon_host_create(TEN_ADDON_TYPE_EXTENSION); TEN_ASSERT(addon_host, "Should not happen."); - ten_addon_register(ten_extension_get_store(), addon_host, name, base_dir, - addon); + ten_addon_register(ten_extension_get_global_store(), addon_host, name, + base_dir, addon); return addon_host; } +// TODO(Wei): Reconsider the `register` and `unregister` mechanisms of the +// addon. +void ten_addon_register_extension_v2(const char *name, const char *base_dir, + void *register_ctx, ten_addon_t *addon) { + if (!name || strlen(name) == 0) { + TEN_LOGE("The addon name is required."); + exit(EXIT_FAILURE); + } + + ten_addon_host_t *addon_host = (ten_addon_host_t *)register_ctx; + + ten_addon_register(ten_extension_get_global_store(), addon_host, name, + base_dir, addon); +} + ten_addon_t *ten_addon_unregister_extension(const char *name) { TEN_ASSERT(name, "Should not happen."); - return ten_addon_unregister(ten_extension_get_store(), name); + return ten_addon_unregister(ten_extension_get_global_store(), name); } diff --git a/core/src/ten_runtime/addon/extension_group/extension_group.c b/core/src/ten_runtime/addon/extension_group/extension_group.c index 6963004a32..42239d9e65 100644 --- a/core/src/ten_runtime/addon/extension_group/extension_group.c +++ b/core/src/ten_runtime/addon/extension_group/extension_group.c @@ -20,7 +20,8 @@ static ten_addon_store_t g_extension_group_store = { TEN_LIST_INIT_VAL, }; -ten_addon_store_t *ten_extension_group_get_store(void) { +ten_addon_store_t *ten_extension_group_get_global_store(void) { + ten_addon_store_init(&g_extension_group_store); return &g_extension_group_store; } @@ -32,13 +33,11 @@ ten_addon_host_t *ten_addon_register_extension_group(const char *name, exit(EXIT_FAILURE); } - ten_addon_store_init(ten_extension_group_get_store()); - ten_addon_host_t *addon_host = ten_addon_host_create(TEN_ADDON_TYPE_EXTENSION_GROUP); TEN_ASSERT(addon_host, "Should not happen."); - ten_addon_register(ten_extension_group_get_store(), addon_host, name, + ten_addon_register(ten_extension_group_get_global_store(), addon_host, name, base_dir, addon); return addon_host; @@ -47,7 +46,7 @@ ten_addon_host_t *ten_addon_register_extension_group(const char *name, ten_addon_t *ten_addon_unregister_extension_group(const char *name) { TEN_ASSERT(name, "Should not happen."); - return ten_addon_unregister(ten_extension_group_get_store(), name); + return ten_addon_unregister(ten_extension_group_get_global_store(), name); } bool ten_addon_create_extension_group( diff --git a/core/src/ten_runtime/addon/protocol/protocol.c b/core/src/ten_runtime/addon/protocol/protocol.c index 18523dbf4c..810353d059 100644 --- a/core/src/ten_runtime/addon/protocol/protocol.c +++ b/core/src/ten_runtime/addon/protocol/protocol.c @@ -28,18 +28,19 @@ static ten_addon_store_t g_protocol_store = { TEN_LIST_INIT_VAL, }; -ten_addon_store_t *ten_protocol_get_store(void) { return &g_protocol_store; } +ten_addon_store_t *ten_protocol_get_global_store(void) { + ten_addon_store_init(&g_protocol_store); + return &g_protocol_store; +} ten_addon_t *ten_addon_unregister_protocol(const char *name) { TEN_ASSERT(name, "Should not happen."); - return ten_addon_unregister(ten_protocol_get_store(), name); + return ten_addon_unregister(ten_protocol_get_global_store(), name); } void ten_addon_register_protocol(const char *name, const char *base_dir, ten_addon_t *addon) { - ten_addon_store_init(ten_protocol_get_store()); - ten_addon_host_t *addon_host = (ten_addon_host_t *)TEN_MALLOC(sizeof(ten_addon_host_t)); TEN_ASSERT(addon_host, "Failed to allocate memory."); @@ -47,8 +48,8 @@ void ten_addon_register_protocol(const char *name, const char *base_dir, addon_host->type = TEN_ADDON_TYPE_PROTOCOL; ten_addon_host_init(addon_host); - ten_addon_register(ten_protocol_get_store(), addon_host, name, base_dir, - addon); + ten_addon_register(ten_protocol_get_global_store(), addon_host, name, + base_dir, addon); } static bool ten_addon_protocol_match_protocol(ten_addon_host_t *self, @@ -87,7 +88,7 @@ ten_addon_host_t *ten_addon_protocol_find(const char *protocol) { ten_addon_host_t *result = NULL; - ten_addon_store_t *store = ten_protocol_get_store(); + ten_addon_store_t *store = ten_protocol_get_global_store(); TEN_ASSERT(store, "Should not happen."); ten_mutex_lock(store->lock); diff --git a/core/src/ten_runtime/app/metadata.c b/core/src/ten_runtime/app/metadata.c index 50c3009a6e..aca6b97ccd 100644 --- a/core/src/ten_runtime/app/metadata.c +++ b/core/src/ten_runtime/app/metadata.c @@ -10,9 +10,11 @@ #include "include_internal/ten_runtime/app/app.h" #include "include_internal/ten_runtime/app/predefined_graph.h" +#include "include_internal/ten_runtime/app/ten_property.h" #include "include_internal/ten_runtime/common/constant_str.h" #include "include_internal/ten_runtime/common/log.h" #include "include_internal/ten_runtime/extension/extension_info/extension_info.h" +#include "include_internal/ten_runtime/metadata/manifest.h" #include "include_internal/ten_utils/log/log.h" #include "include_internal/ten_utils/log/output.h" #include "ten_runtime/app/app.h" @@ -202,3 +204,15 @@ void ten_app_handle_metadata(ten_app_t *self) { // Load custom TEN app metadata. ten_metadata_load(ten_app_on_configure, self->ten_env); } + +// This function is quite special; it is specifically designed for extensions to +// fetch the read-only app manifest content. +void ten_app_get_extension_dependencies_for_extension( + ten_app_t *self, ten_list_t *extension_dependencies) { + TEN_ASSERT(self, "Invalid argument."); + TEN_ASSERT(ten_app_check_integrity(self, false), "Invalid use of app %p.", + self); + + ten_manifest_get_dependencies_type_and_name( + &self->manifest, extension_dependencies, NULL, NULL); +} diff --git a/core/src/ten_runtime/app/msg_interface/start_graph.c b/core/src/ten_runtime/app/msg_interface/start_graph.c index a2a9ddabcd..3360ea06dd 100644 --- a/core/src/ten_runtime/app/msg_interface/start_graph.c +++ b/core/src/ten_runtime/app/msg_interface/start_graph.c @@ -16,6 +16,7 @@ #include "include_internal/ten_runtime/app/metadata.h" #include "include_internal/ten_runtime/app/msg_interface/common.h" #include "include_internal/ten_runtime/app/predefined_graph.h" +#include "include_internal/ten_runtime/common/constant_str.h" #include "include_internal/ten_runtime/connection/connection.h" #include "include_internal/ten_runtime/connection/migration.h" #include "include_internal/ten_runtime/engine/engine.h" @@ -28,7 +29,6 @@ #include "ten_runtime/common/status_code.h" #include "ten_runtime/msg/cmd_result/cmd_result.h" #include "ten_runtime/msg/msg.h" -#include "ten_utils/lib/json.h" #include "ten_utils/lib/smart_ptr.h" #include "ten_utils/log/log.h" #include "ten_utils/macro/check.h" diff --git a/core/src/ten_runtime/binding/go/interface/ten/addon.go b/core/src/ten_runtime/binding/go/interface/ten/addon.go index eadbe687e6..12d96a24cf 100644 --- a/core/src/ten_runtime/binding/go/interface/ten/addon.go +++ b/core/src/ten_runtime/binding/go/interface/ten/addon.go @@ -73,24 +73,6 @@ func NewDefaultExtensionAddon(constructor func(name string) Extension) Addon { } } -// NewDefaultExtensionGroupAddon creates a new default extension group addon. -func NewDefaultExtensionGroupAddon( - constructor func(name string) ExtensionGroup, -) Addon { - return &DefaultAddon{ - onCreateInstanceImpl: func(tenEnv TenEnv, name string, context uintptr) { - extGroup := constructor(name) - if extGroup == nil { - // Should not happen. - panic("The extension group constructor returns nil.") - } - - extGroupWrapper := WrapExtensionGroup(extGroup, name) - tenEnv.OnCreateInstanceDone(extGroupWrapper, context) - }, - } -} - // RegisterAddonAsExtension registers the addon as an extension. func RegisterAddonAsExtension(addonName string, instance Addon) error { if len(addonName) == 0 { diff --git a/core/src/ten_runtime/binding/go/interface/ten/extension_group.go b/core/src/ten_runtime/binding/go/interface/ten/extension_group.go deleted file mode 100644 index e47197e9ad..0000000000 --- a/core/src/ten_runtime/binding/go/interface/ten/extension_group.go +++ /dev/null @@ -1,254 +0,0 @@ -// -// Copyright © 2024 Agora -// This file is part of TEN Framework, an open source project. -// Licensed under the Apache License, Version 2.0, with certain conditions. -// Refer to the "LICENSE" file in the root directory for more information. -// - -package ten - -// #include "extension_group.h" -import "C" - -import ( - "fmt" - "runtime" - "unsafe" -) - -// ExtensionGroup is the interface for the extension group. -type ExtensionGroup interface { - OnInit( - tenEnv TenEnv, - ) - OnDeinit(tenEnv TenEnv) - OnCreateExtensions(tenEnv TenEnv) - OnDestroyExtensions( - tenEnv TenEnv, - extensions []Extension, - ) -} - -// DefaultExtensionGroup is the default extension group. -type DefaultExtensionGroup struct{} - -var _ ExtensionGroup = new(DefaultExtensionGroup) - -// OnInit initializes the extension group. -func (p *DefaultExtensionGroup) OnInit( - tenEnv TenEnv, -) { - tenEnv.OnInitDone() -} - -// OnDeinit deinitializes the extension group. -func (p *DefaultExtensionGroup) OnDeinit( - tenEnv TenEnv, -) { - tenEnv.OnDeinitDone() -} - -// OnCreateExtensions creates the extensions. -func (p *DefaultExtensionGroup) OnCreateExtensions( - tenEnv TenEnv, -) { - extensions := make([]Extension, 0) - tenEnv.OnCreateExtensionsDone(extensions...) -} - -// OnDestroyExtensions deletes the extensions. -func (p *DefaultExtensionGroup) OnDestroyExtensions( - tenEnv TenEnv, - extensions []Extension, -) { - tenEnv.OnDestroyExtensionsDone() -} - -type extensionGroup struct { - ExtensionGroup - name string - baseTenObject[C.uintptr_t] -} - -// WrapExtensionGroup creates a new extension group. -func WrapExtensionGroup( - extGroup ExtensionGroup, - name string, -) *extensionGroup { - extGroupInstance := &extensionGroup{ - ExtensionGroup: extGroup, - name: name, - } - - extGroupObjID := newImmutableHandle(extGroupInstance) - - var bridge C.uintptr_t - status := C.ten_go_extension_group_create( - cHandle(extGroupObjID), - unsafe.Pointer(unsafe.StringData(name)), - C.int(len(name)), - &bridge, - ) - if err := withGoStatus(&status); err != nil { - return nil - } - - extGroupInstance.cPtr = bridge - - runtime.SetFinalizer(extGroupInstance, func(p *extensionGroup) { - C.ten_go_extension_group_finalize(p.cPtr) - }) - - return extGroupInstance -} - -func newExtensionGroupWithBridge( - extGroup ExtensionGroup, - name string, - bridge C.uintptr_t, -) goHandle { - extGroupInstance := &extensionGroup{ - ExtensionGroup: extGroup, - name: name, - } - - extGroupInstance.cPtr = bridge - - runtime.SetFinalizer(extGroupInstance, func(p *extensionGroup) { - C.ten_go_extension_group_finalize(p.cPtr) - }) - - return newImmutableHandle(extGroupInstance) -} - -//export tenGoExtensionGroupOnInit -func tenGoExtensionGroupOnInit( - extensionGroupID C.uintptr_t, - tenEnvID C.uintptr_t, -) { - extensionGroupObj, ok := loadImmutableHandle(goHandle(extensionGroupID)).(*extensionGroup) - if !ok { - panic( - fmt.Sprintf( - "Failed to get extension group from handle map, id: %d.", - uintptr(extensionGroupID), - ), - ) - } - - tenEnvObj, ok := handle(tenEnvID).get().(TenEnv) - if !ok { - panic( - fmt.Sprintf( - "Failed to get ten env from handle map, id: %d.", - uintptr(tenEnvID), - ), - ) - } - - tenEnvInstance, ok := tenEnvObj.(*tenEnv) - if !ok { - // Should not happen. - panic("Invalid ten object type.") - } - - tenEnvInstance.attachToExtensionGroup(extensionGroupObj) - - extensionGroupObj.OnInit( - tenEnvObj, - ) -} - -//export tenGoExtensionGroupOnDeinit -func tenGoExtensionGroupOnDeinit( - extensionGroupID C.uintptr_t, - tenEnvID C.uintptr_t, -) { - extensionGroupObj, ok := loadImmutableHandle(goHandle(extensionGroupID)).(*extensionGroup) - if !ok { - panic( - fmt.Sprintf( - "Failed to get extension group from handle map, id: %d.", - uintptr(extensionGroupID), - ), - ) - } - - tenEnvObj, ok := handle(tenEnvID).get().(TenEnv) - if !ok { - panic( - fmt.Sprintf( - "Failed to get ten env from handle map, id: %d.", - uintptr(tenEnvID), - ), - ) - } - - extensionGroupObj.OnDeinit(tenEnvObj) -} - -//export tenGoExtensionGroupOnCreateExtensions -func tenGoExtensionGroupOnCreateExtensions( - extensionGroupID C.uintptr_t, - tenEnvID C.uintptr_t, -) { - extensionGroupObj, ok := loadImmutableHandle(goHandle(extensionGroupID)).(*extensionGroup) - if !ok { - panic( - fmt.Sprintf( - "Failed to get extension group from handle map, id: %d.", - uintptr(extensionGroupID), - ), - ) - } - - tenEnvObj, ok := handle(tenEnvID).get().(TenEnv) - if !ok { - panic( - fmt.Sprintf( - "Failed to get ten env from handle map, id: %d.", - uintptr(tenEnvID), - ), - ) - } - - extensionGroupObj.OnCreateExtensions(tenEnvObj) -} - -//export tenGoExtensionGroupOnDestroyExtensions -func tenGoExtensionGroupOnDestroyExtensions( - extensionGroupID C.uintptr_t, - tenEnvID C.uintptr_t, - extensionArray *C.ten_go_handle_array_t, -) { - extensionIds := convertCArrayToGoSlice(extensionArray) - var extensions []Extension - for _, id := range extensionIds { - extensions = append( - extensions, - loadImmutableHandle(goHandle(id)).(*extension), - ) - } - - extensionGroupObj, ok := loadImmutableHandle(goHandle(extensionGroupID)).(*extensionGroup) - if !ok { - panic( - fmt.Sprintf( - "Failed to get extension group from handle map, id: %d.", - uintptr(extensionGroupID), - ), - ) - } - - tenEnvObj, ok := handle(tenEnvID).get().(TenEnv) - if !ok { - panic( - fmt.Sprintf( - "Failed to get ten env from handle map, id: %d.", - uintptr(tenEnvID), - ), - ) - } - - extensionGroupObj.OnDestroyExtensions(tenEnvObj, extensions) -} diff --git a/core/src/ten_runtime/binding/go/interface/ten/extension_group.h b/core/src/ten_runtime/binding/go/interface/ten/extension_group.h deleted file mode 100644 index 5731fcc2df..0000000000 --- a/core/src/ten_runtime/binding/go/interface/ten/extension_group.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright © 2024 Agora -// This file is part of TEN Framework, an open source project. -// Licensed under the Apache License, Version 2.0, with certain conditions. -// Refer to the "LICENSE" file in the root directory for more information. -// -#pragma once - -#include -#include - -#include "common.h" - -ten_go_status_t ten_go_extension_group_create( - ten_go_handle_t go_extension_group_index, const void *name, int name_len, - uintptr_t *bridge_addr); - -// Invoked when the Go extension group finalizes. -void ten_go_extension_group_finalize(uintptr_t bridge_addr); diff --git a/core/src/ten_runtime/binding/go/interface/ten/ten_env.go b/core/src/ten_runtime/binding/go/interface/ten/ten_env.go index 5a8453eb68..3aa0daa1fe 100644 --- a/core/src/ten_runtime/binding/go/interface/ten/ten_env.go +++ b/core/src/ten_runtime/binding/go/interface/ten/ten_env.go @@ -115,15 +115,6 @@ func (p *tenEnv) attachToExtension(ext *extension) { p.attachTo = unsafe.Pointer(ext) } -func (p *tenEnv) attachToExtensionGroup(extGroup *extensionGroup) { - if p.attachToType != tenAttachToInvalid { - panic("The ten object can only be attached once.") - } - - p.attachToType = tenAttachToExtensionGroup - p.attachTo = unsafe.Pointer(extGroup) -} - func (p *tenEnv) postSyncJob(payload job) any { // To prevent deadlock, we refuse to post jobs to the pool. So it's // recommended for developers to call async ten apis in goroutines other @@ -364,9 +355,7 @@ func (p *tenEnv) OnDestroyExtensionsDone() error { func (p *tenEnv) OnCreateInstanceDone(instance any, context uintptr) error { switch instance := instance.(type) { case *extension: - C.ten_go_ten_env_on_create_instance_done(p.cPtr, C.bool(true), instance.cPtr, C.uintptr_t(context)) - case *extensionGroup: - C.ten_go_ten_env_on_create_instance_done(p.cPtr, C.bool(false), instance.cPtr, C.uintptr_t(context)) + C.ten_go_ten_env_on_create_instance_done(p.cPtr, instance.cPtr, C.uintptr_t(context)) default: panic("instance must be extension or extension group.") } diff --git a/core/src/ten_runtime/binding/go/interface/ten/ten_env.h b/core/src/ten_runtime/binding/go/interface/ten/ten_env.h index 29b16e972e..118c4ec510 100644 --- a/core/src/ten_runtime/binding/go/interface/ten/ten_env.h +++ b/core/src/ten_runtime/binding/go/interface/ten/ten_env.h @@ -37,7 +37,6 @@ void ten_go_ten_env_on_create_extensions_done( void ten_go_ten_env_on_destroy_extensions_done(uintptr_t bridge_addr); void ten_go_ten_env_on_create_instance_done(uintptr_t bridge_addr, - bool is_extension, uintptr_t instance_bridge_addr, uintptr_t context_addr); diff --git a/core/src/ten_runtime/binding/go/native/BUILD.gn b/core/src/ten_runtime/binding/go/native/BUILD.gn index d26f9c0b17..4cc106b7d6 100644 --- a/core/src/ten_runtime/binding/go/native/BUILD.gn +++ b/core/src/ten_runtime/binding/go/native/BUILD.gn @@ -55,7 +55,6 @@ ten_shared_library("ten_runtime_go") { "addon", "app", "extension", - "extension_group", "internal", "msg", "ten_env", diff --git a/core/src/ten_runtime/binding/go/native/addon/addon.c b/core/src/ten_runtime/binding/go/native/addon/addon.c index 1a9cb9e8b0..bf91453f22 100644 --- a/core/src/ten_runtime/binding/go/native/addon/addon.c +++ b/core/src/ten_runtime/binding/go/native/addon/addon.c @@ -12,7 +12,6 @@ #include "include_internal/ten_runtime/addon/addon.h" #include "include_internal/ten_runtime/binding/go/addon/addon.h" #include "include_internal/ten_runtime/binding/go/extension/extension.h" -#include "include_internal/ten_runtime/binding/go/extension_group/extension_group.h" #include "include_internal/ten_runtime/binding/go/internal/common.h" #include "include_internal/ten_runtime/binding/go/ten_env/ten_env.h" #include "include_internal/ten_runtime/extension/extension.h" @@ -206,22 +205,6 @@ static void ten_go_addon_destroy_instance_helper(ten_addon_t *addon, break; } - case TEN_ADDON_TYPE_EXTENSION_GROUP: { - ten_extension_group_t *extension_group = - (ten_extension_group_t *)instance; - ten_go_extension_group_t *extension_group_bridge = - ten_binding_handle_get_me_in_target_lang( - (ten_binding_handle_t *)extension_group); - TEN_ASSERT( - extension_group_bridge && - ten_go_extension_group_check_integrity(extension_group_bridge), - "Invalid argument."); - - instance_handle = - ten_go_extension_group_go_handle(extension_group_bridge); - break; - } - default: TEN_ASSERT(0, "Not support."); break; diff --git a/core/src/ten_runtime/binding/go/native/extension_group/BUILD.gn b/core/src/ten_runtime/binding/go/native/extension_group/BUILD.gn deleted file mode 100644 index a05dbdbb8f..0000000000 --- a/core/src/ten_runtime/binding/go/native/extension_group/BUILD.gn +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright © 2024 Agora -# This file is part of TEN Framework, an open source project. -# Licensed under the Apache License, Version 2.0, with certain conditions. -# Refer to the "LICENSE" file in the root directory for more information. -# -import("//build/ten_runtime/glob.gni") - -glob("extension_group") { - file_list = all_native_files -} diff --git a/core/src/ten_runtime/binding/go/native/extension_group/extension_group.c b/core/src/ten_runtime/binding/go/native/extension_group/extension_group.c deleted file mode 100644 index c88d24407e..0000000000 --- a/core/src/ten_runtime/binding/go/native/extension_group/extension_group.c +++ /dev/null @@ -1,253 +0,0 @@ -// -// Copyright © 2024 Agora -// This file is part of TEN Framework, an open source project. -// Licensed under the Apache License, Version 2.0, with certain conditions. -// Refer to the "LICENSE" file in the root directory for more information. -// -#include "ten_runtime/binding/go/interface/ten/extension_group.h" - -#include - -#include "include_internal/ten_runtime/binding/go/extension/extension.h" -#include "include_internal/ten_runtime/binding/go/extension_group/extension_group.h" -#include "include_internal/ten_runtime/binding/go/internal/common.h" -#include "include_internal/ten_runtime/binding/go/ten_env/ten_env.h" -#include "include_internal/ten_runtime/binding/go/ten_env/ten_env_internal.h" -#include "include_internal/ten_runtime/extension/extension.h" -#include "include_internal/ten_runtime/extension_group/extension_group.h" -#include "ten_runtime/binding/common.h" -#include "ten_runtime/binding/go/interface/ten/common.h" -#include "ten_runtime/binding/go/interface/ten/ten_env.h" -#include "ten_runtime/ten_env/ten_env.h" -#include "ten_runtime/ten_env_proxy/ten_env_proxy.h" -#include "ten_utils/container/list.h" -#include "ten_utils/lib/alloc.h" -#include "ten_utils/lib/error.h" -#include "ten_utils/lib/string.h" -#include "ten_utils/macro/check.h" - -void tenGoExtensionGroupOnInit(ten_go_handle_t go_extension_group, - ten_go_handle_t go_ten_env); - -void tenGoExtensionGroupOnDeinit(ten_go_handle_t go_extension_group, - ten_go_handle_t go_ten_env); - -void tenGoExtensionGroupOnCreateExtensions(ten_go_handle_t go_extension_group, - ten_go_handle_t go_ten_env); - -void tenGoExtensionGroupOnDestroyExtensions( - ten_go_handle_t go_extension_group, ten_go_handle_t go_ten_env, - ten_go_handle_array_t *extension_array); - -bool ten_go_extension_group_check_integrity(ten_go_extension_group_t *self) { - TEN_ASSERT(self, "Should not happen."); - - if (ten_signature_get(&self->signature) != TEN_GO_EXTENSION_GROUP_SIGNATURE) { - return false; - } - - return true; -} - -ten_go_extension_group_t *ten_go_extension_group_reinterpret( - uintptr_t extension_group_bridge) { - TEN_ASSERT(extension_group_bridge > 0, "Invalid argument."); - - ten_go_extension_group_t *self = - // NOLINTNEXTLINE(performance-no-int-to-ptr) - (ten_go_extension_group_t *)extension_group_bridge; - TEN_ASSERT(ten_go_extension_group_check_integrity(self), "Invalid argument."); - - return self; -} - -ten_go_handle_t ten_go_extension_group_go_handle( - ten_go_extension_group_t *self) { - TEN_ASSERT(ten_go_extension_group_check_integrity(self), - "Should not happen."); - - return self->bridge.go_instance; -} - -ten_extension_group_t *ten_go_extension_group_c_extension_group( - ten_go_extension_group_t *self) { - TEN_ASSERT(ten_go_extension_group_check_integrity(self), - "Should not happen."); - return self->c_extension_group; -} - -static void ten_go_extension_group_bridge_destroy( - ten_go_extension_group_t *self) { - TEN_ASSERT(ten_go_extension_group_check_integrity(self), - "Should not happen."); - TEN_ASSERT(self->c_extension_group && ten_extension_group_check_integrity( - self->c_extension_group, false), - "Should not happen."); - - ten_extension_group_destroy(self->c_extension_group); - TEN_FREE(self); -} - -static void proxy_on_init(ten_extension_group_t *self, ten_env_t *ten_env) { - TEN_ASSERT(self && ten_extension_group_check_integrity(self, true), - "Should not happen."); - TEN_ASSERT(ten_env && ten_env_check_integrity(ten_env, true), - "Should not happen."); - TEN_ASSERT(self->ten_env == ten_env, "Should not happen."); - - ten_go_extension_group_t *extension_group_bridge = - ten_binding_handle_get_me_in_target_lang((ten_binding_handle_t *)self); - TEN_ASSERT(ten_go_extension_group_check_integrity(extension_group_bridge), - "Should not happen."); - - ten_go_ten_env_t *ten_env_bridge = ten_go_ten_env_wrap(ten_env); - ten_env_bridge->c_ten_env_proxy = ten_env_proxy_create(ten_env, 1, NULL); - - tenGoExtensionGroupOnInit(extension_group_bridge->bridge.go_instance, - ten_go_ten_env_go_handle(ten_env_bridge)); -} - -static void proxy_on_deinit(ten_extension_group_t *self, ten_env_t *ten_env) { - TEN_ASSERT(self && ten_extension_group_check_integrity(self, true), - "Should not happen."); - TEN_ASSERT(ten_env && ten_env_check_integrity(ten_env, true), - "Should not happen."); - TEN_ASSERT(self->ten_env == ten_env, "Should not happen."); - - ten_go_extension_group_t *extension_group_bridge = - ten_binding_handle_get_me_in_target_lang((ten_binding_handle_t *)self); - TEN_ASSERT(ten_go_extension_group_check_integrity(extension_group_bridge), - "Should not happen."); - - ten_go_ten_env_t *ten_env_bridge = ten_go_ten_env_wrap(ten_env); - - tenGoExtensionGroupOnDeinit(extension_group_bridge->bridge.go_instance, - ten_go_ten_env_go_handle(ten_env_bridge)); -} - -static void proxy_on_create_extensions(ten_extension_group_t *self, - ten_env_t *ten_env) { - TEN_ASSERT(self && ten_extension_group_check_integrity(self, true), - "Should not happen."); - TEN_ASSERT(ten_env && ten_env_check_integrity(ten_env, true), - "Should not happen."); - TEN_ASSERT(self->ten_env == ten_env, "Should not happen."); - - ten_go_extension_group_t *extension_group_bridge = - ten_binding_handle_get_me_in_target_lang((ten_binding_handle_t *)self); - TEN_ASSERT(ten_go_extension_group_check_integrity(extension_group_bridge), - "Should not happen."); - - ten_go_ten_env_t *ten_env_bridge = ten_go_ten_env_wrap(ten_env); - - tenGoExtensionGroupOnCreateExtensions( - extension_group_bridge->bridge.go_instance, - ten_go_ten_env_go_handle(ten_env_bridge)); -} - -static void proxy_on_destroy_extensions(ten_extension_group_t *self, - ten_env_t *ten_env, - ten_list_t extensions) { - TEN_ASSERT(self && ten_extension_group_check_integrity(self, true), - "Should not happen."); - TEN_ASSERT(ten_env && ten_env_check_integrity(ten_env, true), - "Should not happen."); - TEN_ASSERT(self->ten_env == ten_env, "Should not happen."); - - ten_go_extension_group_t *extension_group_bridge = - ten_binding_handle_get_me_in_target_lang((ten_binding_handle_t *)self); - TEN_ASSERT(ten_go_extension_group_check_integrity(extension_group_bridge), - "Should not happen."); - - ten_go_ten_env_t *ten_env_bridge = ten_go_ten_env_wrap(ten_env); - - ten_go_handle_array_t *extensions_array = - ten_go_handle_array_create(ten_list_size(&extensions)); - - int i = 0; - ten_list_foreach (&extensions, iter) { - ten_extension_t *extension = ten_ptr_listnode_get(iter.node); - TEN_ASSERT(extension && ten_extension_check_integrity(extension, true), - "Should not happen."); - - ten_go_extension_t *extension_bridge = - ten_binding_handle_get_me_in_target_lang( - (ten_binding_handle_t *)extension); - TEN_ASSERT( - extension_bridge && ten_go_extension_check_integrity(extension_bridge), - "Should not happen."); - - ten_go_handle_t go_extension = ten_go_extension_go_handle(extension_bridge); - extensions_array->array[i++] = go_extension; - } - - tenGoExtensionGroupOnDestroyExtensions( - extension_group_bridge->bridge.go_instance, - ten_go_ten_env_go_handle(ten_env_bridge), extensions_array); - - ten_go_handle_array_destroy(extensions_array); -} - -ten_go_extension_group_t *ten_go_extension_group_create_internal( - ten_go_handle_t go_extension_group, const char *name) { - ten_go_extension_group_t *extension_group_bridge = - (ten_go_extension_group_t *)TEN_MALLOC(sizeof(ten_go_extension_group_t)); - TEN_ASSERT(extension_group_bridge, "Failed to allocate memory."); - - ten_signature_set(&extension_group_bridge->signature, - TEN_GO_EXTENSION_GROUP_SIGNATURE); - extension_group_bridge->bridge.go_instance = go_extension_group; - - // The extension group bridge instance is created and managed only by Go. When - // the Go extension group is finalized, the extension group bridge instance - // will be destroyed. Therefore, the C part should not hold any reference to - // the extension group bridge instance. - extension_group_bridge->bridge.sp_ref_by_go = ten_shared_ptr_create( - extension_group_bridge, ten_go_extension_group_bridge_destroy); - extension_group_bridge->bridge.sp_ref_by_c = NULL; - - extension_group_bridge->c_extension_group = ten_extension_group_create( - name, NULL, proxy_on_init, proxy_on_deinit, proxy_on_create_extensions, - proxy_on_destroy_extensions); - - ten_binding_handle_set_me_in_target_lang( - (ten_binding_handle_t *)(extension_group_bridge->c_extension_group), - extension_group_bridge); - - return extension_group_bridge; -} - -ten_go_status_t ten_go_extension_group_create( - ten_go_handle_t go_extension_group_index, const void *name, int name_len, - uintptr_t *bridge_addr) { - ten_go_status_t status; - ten_go_status_init_with_errno(&status, TEN_ERRNO_OK); - - ten_string_t extension_group_name; - ten_string_init_formatted(&extension_group_name, "%.*s", name_len, name); - - ten_go_extension_group_t *self = ten_go_extension_group_create_internal( - go_extension_group_index, ten_string_get_raw_str(&extension_group_name)); - - ten_string_deinit(&extension_group_name); - - *bridge_addr = (uintptr_t)self; - - return status; -} - -void ten_go_extension_group_finalize(uintptr_t bridge_addr) { - ten_go_extension_group_t *self = - ten_go_extension_group_reinterpret(bridge_addr); - TEN_ASSERT(self && ten_go_extension_group_check_integrity(self), - "Should not happen."); - ten_go_bridge_destroy_go_part(&self->bridge); -} - -void ten_go_extension_group_set_go_handle(ten_go_extension_group_t *self, - ten_go_handle_t go_handle) { - TEN_ASSERT(self && ten_go_extension_group_check_integrity(self), - "Invalid argument."); - - self->bridge.go_instance = go_handle; -} diff --git a/core/src/ten_runtime/binding/go/native/ten_env/ten_env_create_instance_done.c b/core/src/ten_runtime/binding/go/native/ten_env/ten_env_create_instance_done.c index 00ea9515a1..0ed2067cfe 100644 --- a/core/src/ten_runtime/binding/go/native/ten_env/ten_env_create_instance_done.c +++ b/core/src/ten_runtime/binding/go/native/ten_env/ten_env_create_instance_done.c @@ -4,18 +4,15 @@ // Licensed under the Apache License, Version 2.0, with certain conditions. // Refer to the "LICENSE" file in the root directory for more information. // -#include - #include "include_internal/ten_runtime/binding/go/extension/extension.h" -#include "include_internal/ten_runtime/binding/go/extension_group/extension_group.h" #include "include_internal/ten_runtime/binding/go/ten_env/ten_env.h" #include "include_internal/ten_runtime/binding/go/ten_env/ten_env_internal.h" #include "ten_runtime/binding/go/interface/ten/ten_env.h" +#include "ten_runtime/extension/extension.h" #include "ten_runtime/ten.h" #include "ten_utils/macro/check.h" void ten_go_ten_env_on_create_instance_done(uintptr_t bridge_addr, - bool is_extension, uintptr_t instance_bridge_addr, uintptr_t context_addr) { ten_go_ten_env_t *self = ten_go_ten_env_reinterpret(bridge_addr); @@ -23,22 +20,12 @@ void ten_go_ten_env_on_create_instance_done(uintptr_t bridge_addr, TEN_ASSERT(instance_bridge_addr, "Invalid argument."); TEN_ASSERT(context_addr, "Invalid argument."); - void *c_extension_or_extension_group = NULL; - if (is_extension) { - ten_go_extension_t *extension_bridge = - ten_go_extension_reinterpret(instance_bridge_addr); - TEN_ASSERT(ten_go_extension_check_integrity(extension_bridge), - "Should not happen."); - c_extension_or_extension_group = - ten_go_extension_c_extension(extension_bridge); - } else { - ten_go_extension_group_t *extension_group_bridge = - ten_go_extension_group_reinterpret(instance_bridge_addr); - TEN_ASSERT(ten_go_extension_group_check_integrity(extension_group_bridge), - "Should not happen."); - c_extension_or_extension_group = - ten_go_extension_group_c_extension_group(extension_group_bridge); - } + ten_go_extension_t *extension_bridge = + ten_go_extension_reinterpret(instance_bridge_addr); + TEN_ASSERT(ten_go_extension_check_integrity(extension_bridge), + "Should not happen."); + ten_extension_t *c_extension_or_extension_group = + ten_go_extension_c_extension(extension_bridge); TEN_GO_TEN_ENV_IS_ALIVE_REGION_BEGIN(self, {}); diff --git a/core/src/ten_runtime/binding/python/interface/ten/__init__.py b/core/src/ten_runtime/binding/python/interface/ten/__init__.py index ca3eb43b8c..d0a45d3410 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/__init__.py +++ b/core/src/ten_runtime/binding/python/interface/ten/__init__.py @@ -11,7 +11,6 @@ from .addon import Addon from .decorator import ( register_addon_as_extension, - register_addon_as_extension_group, ) from .ten_env import TenEnv from .cmd import Cmd @@ -27,7 +26,6 @@ __all__ = [ "Addon", "register_addon_as_extension", - "register_addon_as_extension_group", "App", "Extension", "AsyncExtension", diff --git a/core/src/ten_runtime/binding/python/interface/ten/decorator.py b/core/src/ten_runtime/binding/python/interface/ten/decorator.py index e20c85a7f8..681062cccf 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/decorator.py +++ b/core/src/ten_runtime/binding/python/interface/ten/decorator.py @@ -8,7 +8,6 @@ import sys from libten_runtime_python import ( _register_addon_as_extension, - _register_addon_as_extension_group, ) @@ -28,21 +27,3 @@ def register_addon_as_extension(name: str, base_dir: str | None = None): base_dir = os.path.dirname(base_dir) return _register_addon_as_extension(name, base_dir) - - -def register_addon_as_extension_group(name: str, base_dir: str | None = None): - if base_dir is None: - try: - # Attempt to get the caller's file path using sys._getframe() - caller_frame = sys._getframe(1) - base_dir = os.path.dirname(caller_frame.f_code.co_filename) - except (AttributeError, ValueError): - # Fallback in case sys._getframe() is not available or fails. - # Ex: in cython. - base_dir = None - - # If base_dir is not None, convert it to its directory name. - if base_dir is not None: - base_dir = os.path.dirname(base_dir) - - return _register_addon_as_extension_group(name, base_dir) diff --git a/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi b/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi index 0cc5bdd5c1..f1896a9618 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi +++ b/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi @@ -179,4 +179,3 @@ class _ExtensionTester: def run(self) -> None: ... def _register_addon_as_extension(name: str, base_dir: str | None): ... -def _register_addon_as_extension_group(name: str, base_dir: str | None): ... diff --git a/core/src/ten_runtime/binding/python/native/addon/decorator.c b/core/src/ten_runtime/binding/python/native/addon/decorator.c index ca7e3cf72a..e94a6030b5 100644 --- a/core/src/ten_runtime/binding/python/native/addon/decorator.c +++ b/core/src/ten_runtime/binding/python/native/addon/decorator.c @@ -115,13 +115,6 @@ static PyObject *ten_py_decorator_register_addon_as_extension_call( ten_addon_register_extension); } -static PyObject *ten_py_decorator_register_addon_as_extension_group_call( - PyObject *self, PyObject *args, TEN_UNUSED PyObject *kwds) { - return ten_py_decorator_register_addon_call( - (ten_py_decorator_register_addon_t *)self, args, - ten_addon_register_extension_group); -} - static PyTypeObject *ten_py_decorator_register_addon_as_extension_py_type( void) { static PyMethodDef decorator_methods[] = { @@ -146,26 +139,6 @@ static PyTypeObject *ten_py_decorator_register_addon_as_extension_py_type( return &py_type; } -static PyTypeObject *ten_py_decorator_register_addon_as_extension_group_py_type( - void) { - static PyTypeObject py_type = { - PyVarObject_HEAD_INIT(NULL, 0).tp_name = - "libten_runtime_python.register_addon_as_extension_group", - .tp_doc = PyDoc_STR("register_addon_as_extension_group"), - .tp_basicsize = 0, - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_new = ten_py_decorator_register_addon_create, - .tp_init = NULL, - .tp_dealloc = ten_py_decorator_register_addon_destroy, - .tp_call = ten_py_decorator_register_addon_as_extension_group_call, - .tp_getset = NULL, - .tp_methods = NULL, - }; - - return &py_type; -} - static bool ten_py_decorator_register_addon_module_init(PyObject *module, PyTypeObject *py_type, const char *name) { @@ -191,10 +164,3 @@ bool ten_py_decorator_register_addon_as_extension_init_for_module( module, ten_py_decorator_register_addon_as_extension_py_type(), "_register_addon_as_extension"); } - -bool ten_py_decorator_register_addon_as_extension_group_init_for_module( - PyObject *module) { - return ten_py_decorator_register_addon_module_init( - module, ten_py_decorator_register_addon_as_extension_group_py_type(), - "_register_addon_as_extension_group"); -} diff --git a/core/src/ten_runtime/binding/python/native/init.c b/core/src/ten_runtime/binding/python/native/init.c index 6cab3b90bf..01f96cc34f 100644 --- a/core/src/ten_runtime/binding/python/native/init.c +++ b/core/src/ten_runtime/binding/python/native/init.c @@ -70,12 +70,6 @@ PyMODINIT_FUNC PyInit_libten_runtime_python(void) { return NULL; } - if (!ten_py_decorator_register_addon_as_extension_group_init_for_module( - module)) { - Py_DECREF(module); - return NULL; - } - if (!ten_py_app_init_for_module(module)) { Py_DECREF(module); return NULL; diff --git a/core/src/ten_runtime/metadata/manifest.c b/core/src/ten_runtime/metadata/manifest.c index ff244618ae..0e3d8bbd67 100644 --- a/core/src/ten_runtime/metadata/manifest.c +++ b/core/src/ten_runtime/metadata/manifest.c @@ -6,9 +6,15 @@ // #include "include_internal/ten_runtime/metadata/manifest.h" +#include "include_internal/ten_runtime/addon/addon.h" +#include "include_internal/ten_runtime/common/constant_str.h" +#include "ten_utils/lib/file.h" +#include "ten_utils/lib/json.h" +#include "ten_utils/lib/string.h" #include "ten_utils/log/log.h" +#include "ten_utils/macro/memory.h" -void ten_manifest_dependencies_get_dependencies_type_and_name( +static void ten_manifest_dependencies_get_dependencies_type_and_name( ten_value_t *manifest_dependencies, ten_list_t *extension_list, ten_list_t *extension_group_list, ten_list_t *protocol_list) { TEN_ASSERT(manifest_dependencies, @@ -18,10 +24,6 @@ void ten_manifest_dependencies_get_dependencies_type_and_name( // Ensure that "dependencies" is an array. TEN_ASSERT(ten_value_is_array(manifest_dependencies), "The 'dependencies' field should be an array."); - TEN_ASSERT(extension_list, "Invalid argument: extension_list is NULL."); - TEN_ASSERT(extension_group_list, - "Invalid argument: extension_group_list is NULL."); - TEN_ASSERT(protocol_list, "Invalid argument: protocol_list is NULL."); // Iterate over each dependency in the array. ten_value_array_foreach(manifest_dependencies, iter) { @@ -48,14 +50,20 @@ void ten_manifest_dependencies_get_dependencies_type_and_name( // Add the dependency name to the appropriate list based on its type. if (ten_string_is_equal_c_str(type_str, "extension")) { - TEN_LOGI("Collect extension dependency: %s", name_cstr); - ten_list_push_str_back(extension_list, name_cstr); + if (extension_list) { + TEN_LOGI("Collect extension dependency: %s", name_cstr); + ten_list_push_str_back(extension_list, name_cstr); + } } else if (ten_string_is_equal_c_str(type_str, "extension_group")) { - TEN_LOGI("Collect extension_group dependency: %s", name_cstr); - ten_list_push_str_back(extension_group_list, name_cstr); + if (extension_group_list) { + TEN_LOGI("Collect extension_group dependency: %s", name_cstr); + ten_list_push_str_back(extension_group_list, name_cstr); + } } else if (ten_string_is_equal_c_str(type_str, "protocol")) { - TEN_LOGI("Collect protocol dependency: %s", name_cstr); - ten_list_push_str_back(protocol_list, name_cstr); + if (protocol_list) { + TEN_LOGI("Collect protocol dependency: %s", name_cstr); + ten_list_push_str_back(protocol_list, name_cstr); + } } } } @@ -64,10 +72,6 @@ void ten_manifest_get_dependencies_type_and_name( ten_value_t *manifest, ten_list_t *extension_list, ten_list_t *extension_group_list, ten_list_t *protocol_list) { TEN_ASSERT(manifest, "Invalid argument: manifest is NULL."); - TEN_ASSERT(extension_list, "Invalid argument: extension_list is NULL."); - TEN_ASSERT(extension_group_list, - "Invalid argument: extension_group_list is NULL."); - TEN_ASSERT(protocol_list, "Invalid argument: protocol_list is NULL."); TEN_ASSERT(ten_value_check_integrity(manifest), "Invalid manifest value."); TEN_ASSERT(ten_value_is_object(manifest), "Manifest should be an object."); @@ -81,3 +85,36 @@ void ten_manifest_get_dependencies_type_and_name( ten_manifest_dependencies_get_dependencies_type_and_name( dependencies, extension_list, extension_group_list, protocol_list); } + +bool ten_manifest_get_type_and_name(const char *filename, TEN_ADDON_TYPE *type, + ten_string_t *name, ten_error_t *err) { + TEN_ASSERT(type, "Invalid argument."); + TEN_ASSERT(name, "Invalid argument."); + + if (!filename || strlen(filename) == 0) { + TEN_LOGW("Try to load manifest but file name not provided"); + return false; + } + + char *buf = ten_file_read(filename); + if (!buf) { + TEN_LOGW("Can not read content from %s", filename); + return false; + } + + ten_json_t *json = ten_json_from_string(buf, err); + TEN_FREE(buf); + if (!json) { + return false; + } + + const char *type_str = ten_json_object_peek_string(json, TEN_STR_TYPE); + *type = ten_addon_type_from_string(type_str); + + const char *name_str = ten_json_object_peek_string(json, TEN_STR_NAME); + ten_string_set_from_c_str(name, name_str, strlen(name_str)); + + ten_json_destroy(json); + + return true; +} diff --git a/core/src/ten_runtime/ten_env/internal/peek_manifest.c b/core/src/ten_runtime/ten_env/internal/peek_manifest.c deleted file mode 100644 index 9124c1b2b2..0000000000 --- a/core/src/ten_runtime/ten_env/internal/peek_manifest.c +++ /dev/null @@ -1,465 +0,0 @@ -// -// Copyright © 2024 Agora -// This file is part of TEN Framework, an open source project. -// Licensed under the Apache License, Version 2.0, with certain conditions. -// Refer to the "LICENSE" file in the root directory for more information. -// -#include "include_internal/ten_runtime/app/app.h" -#include "include_internal/ten_runtime/app/ten_env/metadata.h" -#include "include_internal/ten_runtime/engine/engine.h" -#include "include_internal/ten_runtime/extension/extension.h" -#include "include_internal/ten_runtime/extension/metadata.h" -#include "include_internal/ten_runtime/extension/ten_env/metadata.h" -#include "include_internal/ten_runtime/extension_context/extension_context.h" -#include "include_internal/ten_runtime/extension_group/extension_group.h" -#include "include_internal/ten_runtime/extension_group/ten_env/metadata.h" -#include "include_internal/ten_runtime/extension_thread/extension_thread.h" -#include "include_internal/ten_runtime/ten_env/metadata.h" -#include "include_internal/ten_runtime/ten_env/metadata_cb.h" -#include "include_internal/ten_runtime/ten_env/ten_env.h" -#include "ten_runtime/app/app.h" -#include "ten_runtime/ten_env/internal/metadata.h" -#include "ten_runtime/ten_env/ten_env.h" -#include "ten_utils/lib/alloc.h" -#include "ten_utils/lib/error.h" -#include "ten_utils/macro/check.h" -#include "ten_utils/macro/mark.h" - -static ten_env_peek_manifest_sync_context_t * -ten_env_peek_manifest_sync_context_create(void) { - ten_env_peek_manifest_sync_context_t *context = - TEN_MALLOC(sizeof(ten_env_peek_manifest_sync_context_t)); - TEN_ASSERT(context, "Failed to allocate memory."); - - context->res = NULL; - context->completed = ten_event_create(0, 0); - - return context; -} - -static void ten_env_peek_manifest_sync_context_destroy( - ten_env_peek_manifest_sync_context_t *self) { - TEN_ASSERT(self, "Should not happen."); - - ten_event_destroy(self->completed); - TEN_FREE(self); -} - -static void ten_app_peek_manifest_sync_cb(ten_app_t *app, ten_value_t *res, - void *cb_data) { - TEN_ASSERT(app && ten_app_check_integrity(app, true), "Should not happen."); - - ten_env_peek_manifest_sync_context_t *context = cb_data; - TEN_ASSERT(context, "Should not happen."); - - context->res = res; - ten_event_set(context->completed); -} - -static ten_env_peek_manifest_async_context_t * -ten_env_peek_manifest_async_context_create(ten_env_t *ten_env, - ten_env_peek_manifest_async_cb_t cb, - void *cb_data) { - ten_env_peek_manifest_async_context_t *context = - TEN_MALLOC(sizeof(ten_env_peek_manifest_async_context_t)); - TEN_ASSERT(context, "Failed to allocate memory."); - - context->ten_env = ten_env; - context->cb = cb; - context->cb_data = cb_data; - - return context; -} - -static void ten_env_peek_manifest_async_context_destroy( - ten_env_peek_manifest_async_context_t *self) { - TEN_ASSERT(self, "Invalid argument."); - - TEN_FREE(self); -} - -static void ten_extension_peek_manifest_async_cb(ten_extension_t *extension, - ten_value_t *res, - void *cb_data, - ten_error_t *err) { - TEN_ASSERT(extension && ten_extension_check_integrity(extension, true), - "Should not happen."); - - ten_env_peek_manifest_async_context_t *context = cb_data; - TEN_ASSERT(context, "Should not happen."); - - if (context->cb) { - context->cb(context->ten_env, res, context->cb_data, err); - } - - ten_env_peek_manifest_async_context_destroy(context); -} - -static void ten_extension_group_peek_manifest_async_cb( - ten_extension_group_t *extension_group, ten_value_t *res, void *cb_data) { - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Should not happen."); - - ten_env_peek_manifest_async_context_t *context = cb_data; - TEN_ASSERT(context, "Should not happen."); - - if (context->cb) { - context->cb(context->ten_env, res, context->cb_data, NULL); - } - - ten_env_peek_manifest_async_context_destroy(context); -} - -static void ten_env_peek_manifest_done_task(TEN_UNUSED void *from, void *arg) { - ten_env_peek_manifest_async_context_t *context = arg; - TEN_ASSERT(context, "Should not happen."); - TEN_ASSERT(context->from.extension != NULL, "Invalid argument."); - - if (context->cb) { - context->cb(context->ten_env, context->res, context->cb_data, NULL); - } - - ten_env_peek_manifest_async_context_destroy(context); -} - -static void ten_app_peek_manifest_async_cb_go_back_to_extension( - ten_app_t *app, ten_value_t *res, void *cb_data) { - TEN_ASSERT(app && ten_app_check_integrity(app, true), "Should not happen."); - - ten_env_peek_manifest_async_context_t *context = cb_data; - TEN_ASSERT(context, "Should not happen."); - TEN_ASSERT(context->from.extension != NULL, "Invalid argument."); - - context->res = res; - - ten_runloop_post_task_tail( - ten_extension_get_attached_runloop(context->from.extension), - ten_env_peek_manifest_done_task, NULL, context); -} - -static void ten_app_peek_manifest_async_cb_go_back_to_extension_group( - ten_app_t *app, ten_value_t *res, void *cb_data) { - TEN_ASSERT(app && ten_app_check_integrity(app, true), "Should not happen."); - - ten_env_peek_manifest_async_context_t *context = cb_data; - TEN_ASSERT(context, "Should not happen."); - TEN_ASSERT(context->from.extension_group != NULL, "Invalid argument."); - - context->res = res; - - ten_runloop_post_task_tail( - ten_extension_group_get_attached_runloop(context->from.extension_group), - ten_env_peek_manifest_done_task, NULL, context); -} - -static void ten_app_peek_manifest_async_cb(ten_app_t *app, ten_value_t *res, - void *cb_data) { - TEN_ASSERT(app && ten_app_check_integrity(app, true), "Should not happen."); - - ten_env_peek_manifest_async_context_t *context = cb_data; - TEN_ASSERT(context, "Should not happen."); - - if (context->cb) { - context->cb(context->ten_env, res, context->cb_data, NULL); - } - - ten_env_peek_manifest_async_context_destroy(context); -} - -ten_value_t *ten_env_peek_manifest(ten_env_t *self, const char *path, - ten_error_t *err) { - TEN_ASSERT(self && ten_env_check_integrity(self, true), - "Invalid use of ten_env %p.", self); - TEN_ASSERT(path && strlen(path), "path should not be empty."); - - ten_value_t *res = NULL; - const char **p_path = &path; - - TEN_METADATA_LEVEL level = - ten_determine_metadata_level(self->attach_to, p_path); - - switch (self->attach_to) { - case TEN_ENV_ATTACH_TO_EXTENSION: { - ten_extension_t *extension = ten_env_get_attached_extension(self); - TEN_ASSERT(extension && ten_extension_check_integrity(extension, true), - "Invalid use of extension %p.", extension); - - ten_extension_thread_t *extension_thread = extension->extension_thread; - TEN_ASSERT(extension_thread && ten_extension_thread_check_integrity( - extension_thread, true), - "Invalid use of extension_thread %p.", extension_thread); - - switch (level) { - case TEN_METADATA_LEVEL_EXTENSION: - res = ten_extension_peek_manifest(extension, *p_path, err); - break; - - case TEN_METADATA_LEVEL_EXTENSION_GROUP: { - ten_extension_group_t *extension_group = - extension->extension_thread->extension_group; - TEN_ASSERT(extension_group && ten_extension_group_check_integrity( - extension_group, true), - "Invalid use of extension group %p", extension_group); - - res = ten_extension_group_peek_manifest(extension_group, path); - break; - } - - case TEN_METADATA_LEVEL_APP: { - ten_app_t *app = extension->extension_context->engine->app; - // TEN_NOLINTNEXTLINE(thread-check): - // thread-check: Access the app's manifest from an extension, that is, - // from the extension thread. - TEN_ASSERT(app && ten_app_check_integrity(app, false), - "Invalid use of app %p", app); - - if (ten_app_thread_call_by_me(app)) { - res = ten_app_peek_manifest(app, path); - } else { - ten_env_peek_manifest_sync_context_t *context = - ten_env_peek_manifest_sync_context_create(); - TEN_ASSERT(context, "Should not happen."); - - ten_app_peek_manifest_async(app, path, - ten_app_peek_manifest_sync_cb, context); - - ten_event_wait(context->completed, -1); - res = context->res; - - ten_env_peek_manifest_sync_context_destroy(context); - } - break; - } - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - break; - } - - case TEN_ENV_ATTACH_TO_EXTENSION_GROUP: { - ten_extension_group_t *extension_group = - ten_env_get_attached_extension_group(self); - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Invalid use of extension_group %p.", extension_group); - - ten_extension_thread_t *extension_thread = - extension_group->extension_thread; - TEN_ASSERT(extension_thread && ten_extension_thread_check_integrity( - extension_thread, true), - "Invalid use of extension_thread %p.", extension_thread); - - switch (level) { - case TEN_METADATA_LEVEL_EXTENSION_GROUP: - res = ten_extension_group_peek_manifest(extension_group, path); - break; - - case TEN_METADATA_LEVEL_APP: { - ten_app_t *app = extension_group->extension_context->engine->app; - // TEN_NOLINTNEXTLINE(thread-check): - // thread-check: Access the app's manifest from an extension group, - // that is, from the extension thread. - TEN_ASSERT(app && ten_app_check_integrity(app, false), - "Invalid use of app %p", app); - - if (ten_app_thread_call_by_me(app)) { - res = ten_app_peek_manifest(app, path); - } else { - ten_env_peek_manifest_sync_context_t *context = - ten_env_peek_manifest_sync_context_create(); - TEN_ASSERT(context, "Should not happen."); - - ten_app_peek_manifest_async(app, path, - ten_app_peek_manifest_sync_cb, context); - - ten_event_wait(context->completed, -1); - res = context->res; - - ten_env_peek_manifest_sync_context_destroy(context); - } - break; - } - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - break; - } - - case TEN_ENV_ATTACH_TO_APP: { - ten_app_t *app = ten_env_get_attached_app(self); - TEN_ASSERT(app && ten_app_check_integrity(app, true), - "Invalid use of app %p.", app); - - switch (level) { - case TEN_METADATA_LEVEL_APP: { - res = ten_app_peek_manifest(app, path); - break; - } - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - break; - } - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - - if (!res) { - if (err) { - ten_error_set(err, TEN_ERRNO_GENERIC, "Failed to find manifest: %s", - path); - } - } - - return res; -} - -bool ten_env_peek_manifest_async(ten_env_t *self, const char *path, - ten_env_peek_manifest_async_cb_t cb, - void *cb_data, ten_error_t *err) { - TEN_ASSERT(self, "Invalid argument."); - TEN_ASSERT(ten_env_check_integrity(self, true), "Invalid use of ten_env %p.", - self); - TEN_ASSERT(path && strlen(path), "path should not be empty."); - - const char **p_path = &path; - - ten_env_peek_manifest_async_context_t *context = - ten_env_peek_manifest_async_context_create(self, cb, cb_data); - TEN_ASSERT(context, "Should not happen."); - - TEN_METADATA_LEVEL level = - ten_determine_metadata_level(self->attach_to, p_path); - - switch (self->attach_to) { - case TEN_ENV_ATTACH_TO_EXTENSION: { - ten_extension_t *extension = ten_env_get_attached_extension(self); - TEN_ASSERT(extension && ten_extension_check_integrity(extension, true), - "Invalid use of extension %p.", extension); - - ten_extension_thread_t *extension_thread = extension->extension_thread; - TEN_ASSERT(extension_thread && ten_extension_thread_check_integrity( - extension_thread, true), - "Invalid use of extension_thread %p.", extension_thread); - - switch (level) { - case TEN_METADATA_LEVEL_EXTENSION: - return ten_extension_peek_manifest_async( - extension, path, ten_extension_peek_manifest_async_cb, context, - err); - break; - - case TEN_METADATA_LEVEL_EXTENSION_GROUP: { - ten_extension_group_t *extension_group = - extension->extension_thread->extension_group; - TEN_ASSERT(extension_group && ten_extension_group_check_integrity( - extension_group, true), - "Invalid use of extension group %p", extension_group); - - ten_extension_group_peek_manifest_async( - extension_group, path, ten_extension_group_peek_manifest_async_cb, - context); - break; - } - - case TEN_METADATA_LEVEL_APP: { - ten_app_t *app = extension->extension_context->engine->app; - // TEN_NOLINTNEXTLINE(thread-check): - // thread-check: Access the app's manifest from an extension, that - // is, from the extension thread. - TEN_ASSERT(app && ten_app_check_integrity(app, false), - "Invalid use of app %p", app); - - context->from.extension = extension; - - ten_app_peek_manifest_async( - app, path, ten_app_peek_manifest_async_cb_go_back_to_extension, - context); - break; - } - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - break; - } - - case TEN_ENV_ATTACH_TO_EXTENSION_GROUP: { - ten_extension_group_t *extension_group = - ten_env_get_attached_extension_group(self); - TEN_ASSERT(extension_group && - ten_extension_group_check_integrity(extension_group, true), - "Invalid use of extension_group %p.", extension_group); - - ten_extension_thread_t *extension_thread = - extension_group->extension_thread; - TEN_ASSERT(extension_thread && ten_extension_thread_check_integrity( - extension_thread, true), - "Invalid use of extension_thread %p.", extension_thread); - - switch (level) { - case TEN_METADATA_LEVEL_EXTENSION_GROUP: - ten_extension_group_peek_manifest_async( - extension_group, path, ten_extension_group_peek_manifest_async_cb, - context); - break; - - case TEN_METADATA_LEVEL_APP: { - ten_app_t *app = extension_group->extension_context->engine->app; - // TEN_NOLINTNEXTLINE(thread-check): - // thread-check: Access the app's manifest from an extension group, - // that is, from the extension thread. - TEN_ASSERT(app && ten_app_check_integrity(app, false), - "Invalid use of app %p", app); - - context->from.extension_group = extension_group; - - ten_app_peek_manifest_async( - app, path, - ten_app_peek_manifest_async_cb_go_back_to_extension_group, - context); - break; - } - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - break; - } - - case TEN_ENV_ATTACH_TO_APP: { - ten_app_t *app = ten_env_get_attached_app(self); - TEN_ASSERT(app && ten_app_check_integrity(app, true), - "Invalid use of app %p.", app); - - switch (level) { - case TEN_METADATA_LEVEL_APP: - ten_app_peek_manifest_async(app, path, ten_app_peek_manifest_async_cb, - context); - break; - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - break; - } - - default: - TEN_ASSERT(0, "Should not happen."); - break; - } - - return true; -} diff --git a/core/src/ten_runtime/ten_env/ten_env.c b/core/src/ten_runtime/ten_env/ten_env.c index 0a0d92c456..4245be970a 100644 --- a/core/src/ten_runtime/ten_env/ten_env.c +++ b/core/src/ten_runtime/ten_env/ten_env.c @@ -87,12 +87,21 @@ static ten_env_t *ten_create_with_attach_to(TEN_ENV_ATTACH_TO attach_to_type, TEN_ASSERT(attach_to_type != TEN_ENV_ATTACH_TO_INVALID, "Should not happen."); ten_env_t *self = ten_env_create(); + TEN_ASSERT(self, "Should not happen."); ten_env_set_attach_to(self, attach_to_type, attach_to); return self; } +ten_env_t *ten_env_create_for_addon(ten_addon_host_t *addon_host) { + TEN_ASSERT(addon_host, "Invalid argument."); + TEN_ASSERT(ten_addon_host_check_integrity(addon_host), + "Invalid use of addon_host %p.", addon_host); + + return ten_create_with_attach_to(TEN_ENV_ATTACH_TO_ADDON, addon_host); +} + ten_env_t *ten_env_create_for_extension(ten_extension_t *extension) { TEN_ASSERT(extension, "Invalid argument."); TEN_ASSERT(ten_extension_check_integrity(extension, true), diff --git a/core/src/ten_utils/lib/sys/general/file.c b/core/src/ten_utils/lib/sys/general/file.c index d35d864e61..1cc1a838a3 100644 --- a/core/src/ten_utils/lib/sys/general/file.c +++ b/core/src/ten_utils/lib/sys/general/file.c @@ -16,10 +16,10 @@ #include #include "include_internal/ten_utils/log/log.h" -#include "ten_utils/macro/check.h" #include "ten_utils/lib/alloc.h" #include "ten_utils/lib/path.h" #include "ten_utils/lib/string.h" +#include "ten_utils/macro/check.h" #define FILE_COPY_BUF_SIZE 4096 @@ -44,6 +44,31 @@ int ten_file_remove(const char *filename) { return 0; } +static char *ten_file_read_from_open_file(FILE *fp) { + TEN_ASSERT(fp, "Invalid argument."); + + if (fseek(fp, 0, SEEK_END) == -1) { + TEN_LOGE("Failed to fseek to the end of the file."); + return NULL; + } + + unsigned long length = ftell(fp); + if (length <= 0) { + TEN_LOGW("File size is 0."); + return NULL; + } + + char *buf = (char *)TEN_MALLOC(sizeof(char) * (length + 1)); + TEN_ASSERT(buf, "Failed to allocate memory."); + + rewind(fp); + + length = fread(buf, 1, length, fp); + buf[length] = '\0'; + + return buf; +} + char *ten_file_read(const char *filename) { TEN_ASSERT(filename, "Invalid argument."); @@ -72,31 +97,6 @@ char *ten_file_read(const char *filename) { return buf; } -char *ten_file_read_from_open_file(FILE *fp) { - TEN_ASSERT(fp, "Invalid argument."); - - if (fseek(fp, 0, SEEK_END) == -1) { - TEN_LOGE("Failed to fseek to the end of the file."); - return NULL; - } - - unsigned long length = ftell(fp); - if (length <= 0) { - TEN_LOGW("File size is 0."); - return NULL; - } - - char *buf = (char *)TEN_MALLOC(sizeof(char) * (length + 1)); - TEN_ASSERT(buf, "Failed to allocate memory."); - - rewind(fp); - - length = fread(buf, 1, length, fp); - buf[length] = '\0'; - - return buf; -} - int ten_file_write(const char *filename, ten_buf_t buf) { TEN_ASSERT(filename && buf.data, "Invalid argument."); diff --git a/core/src/ten_utils/lib/sys/posix/darwin/pc/module.c b/core/src/ten_utils/lib/sys/posix/darwin/pc/module.c index 3381012a94..ab7f079909 100644 --- a/core/src/ten_utils/lib/sys/posix/darwin/pc/module.c +++ b/core/src/ten_utils/lib/sys/posix/darwin/pc/module.c @@ -8,8 +8,67 @@ #include +#include "ten_utils/lib/string.h" +#include "ten_utils/log/log.h" + void *ten_module_load(const ten_string_t *name, int as_local) { - return dlopen(name->buf, RTLD_NOW | (as_local ? RTLD_LOCAL : RTLD_GLOBAL)); + if (!name || !ten_string_check_integrity(name)) { + TEN_LOGE("Invalid argument: module name is null."); + return NULL; + } + + void *handle = dlopen(ten_string_get_raw_str(name), + RTLD_NOW | (as_local ? RTLD_LOCAL : RTLD_GLOBAL)); + + if (!handle) { + const char *err_msg = dlerror(); + TEN_LOGE("Failed to dlopen %s: %s", ten_string_get_raw_str(name), + err_msg ? err_msg : "Unknown error"); + } + + return handle; +} + +int ten_module_close(void *handle) { + if (!handle) { + TEN_LOGE("Invalid argument: handle is null."); + return -1; + } + + int result = dlclose(handle); + if (result != 0) { + const char *err_msg = dlerror(); + TEN_LOGE("Failed to dlclose handle: %s", + err_msg ? err_msg : "Unknown error"); + } + + return result; } -int ten_module_close(void *handle) { return dlclose(handle); } \ No newline at end of file +void *ten_module_get_symbol(void *handle, const char *symbol_name) { + if (!handle) { + TEN_LOGE("Invalid argument: handle is null."); + return NULL; + } + + if (!symbol_name) { + TEN_LOGE("Invalid argument: symbol name is null or corrupted."); + return NULL; + } + + // Clear previous errors. + dlerror(); + + void *symbol = dlsym(handle, symbol_name); + + const char *error = dlerror(); + if (error != NULL) { + // Enable the code below if debugging is needed. +#if 0 + TEN_LOGD("Failed to find symbol %s: %s", symbol_name, error); +#endif + return NULL; + } + + return symbol; +} diff --git a/core/src/ten_utils/lib/sys/posix/linux/pc/module.c b/core/src/ten_utils/lib/sys/posix/linux/pc/module.c index ed85f9386e..86d2b9a45b 100644 --- a/core/src/ten_utils/lib/sys/posix/linux/pc/module.c +++ b/core/src/ten_utils/lib/sys/posix/linux/pc/module.c @@ -46,3 +46,31 @@ int ten_module_close(void *handle) { return result; } + +void *ten_module_get_symbol(void *handle, const char *symbol_name) { + if (!handle) { + TEN_LOGE("Invalid argument: handle is null."); + return NULL; + } + + if (!symbol_name) { + TEN_LOGE("Invalid argument: symbol name is null or corrupted."); + return NULL; + } + + // Clear previous errors. + dlerror(); + + void *symbol = dlsym(handle, symbol_name); + + const char *error = dlerror(); + if (error != NULL) { + // Enable the code below if debugging is needed. +#if 0 + TEN_LOGD("Failed to find symbol %s: %s", symbol_name, error); +#endif + return NULL; + } + + return symbol; +} diff --git a/core/src/ten_utils/lib/sys/win/module.c b/core/src/ten_utils/lib/sys/win/module.c index 8e5e58b051..244f72f9e7 100644 --- a/core/src/ten_utils/lib/sys/win/module.c +++ b/core/src/ten_utils/lib/sys/win/module.c @@ -8,6 +8,8 @@ #include +#include "ten_utils/log/log.h" + void *ten_module_load(const ten_string_t *name, int as_local) { (void)as_local; if (!name || ten_string_is_empty(name)) { @@ -26,3 +28,39 @@ void *ten_module_load(const ten_string_t *name, int as_local) { int ten_module_close(void *handle) { return FreeLibrary((HMODULE)handle) ? 0 : -1; } + +void *ten_module_get_symbol(void *handle, const char *symbol_name) { + if (!handle) { + TEN_LOGE("Invalid argument: handle is null."); + return NULL; + } + + if (!symbol_name) { + TEN_LOGE("Invalid argument: symbol name is null or empty."); + return NULL; + } + + FARPROC symbol = GetProcAddress((HMODULE)handle, symbol_name); + if (!symbol) { + DWORD error_code = GetLastError(); + LPVOID error_message = NULL; + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&error_message, 0, NULL); + + // Enable the code below if debugging is needed. +#if 0 + TEN_LOGE("Failed to find symbol %s: %s", symbol_name, + error_message ? (char *)error_message : "Unknown error"); +#endif + + if (error_message) { + LocalFree(error_message); + } + + return NULL; + } + + return (void *)symbol; +} diff --git a/packages/core_extensions/default_extension_cpp/tests/basic.cc b/packages/core_extensions/default_extension_cpp/tests/basic.cc index a5ab918f1e..1f47ede295 100644 --- a/packages/core_extensions/default_extension_cpp/tests/basic.cc +++ b/packages/core_extensions/default_extension_cpp/tests/basic.cc @@ -4,6 +4,7 @@ // See the LICENSE file for more information. // #include "gtest/gtest.h" +#include "ten_runtime/addon/addon.h" #include "ten_runtime/binding/cpp/ten.h" #include "ten_utils/lib/path.h" #include "ten_utils/lib/string.h" diff --git a/packages/core_extensions/py_init_extension_cpp/src/main.cc b/packages/core_extensions/py_init_extension_cpp/src/main.cc index 464dc5d2c4..a502cda285 100644 --- a/packages/core_extensions/py_init_extension_cpp/src/main.cc +++ b/packages/core_extensions/py_init_extension_cpp/src/main.cc @@ -6,9 +6,14 @@ #include #include +#include "include_internal/ten_runtime/addon/extension/extension.h" +#include "include_internal/ten_runtime/app/metadata.h" +#include "include_internal/ten_runtime/binding/cpp/internal/ten_env_internal_accessor.h" #include "include_internal/ten_runtime/binding/python/common.h" #include "include_internal/ten_runtime/common/base_dir.h" #include "include_internal/ten_runtime/common/constant_str.h" +#include "include_internal/ten_runtime/metadata/manifest.h" +#include "include_internal/ten_runtime/ten_env/metadata.h" #include "ten_runtime/binding/cpp/internal/ten_env.h" #include "ten_runtime/binding/cpp/ten.h" #include "ten_utils/container/list_str.h" @@ -141,14 +146,10 @@ class py_init_addon_t : public ten::addon_t { ten_py_mem_free((void *)sys_path); - // Traverse the addon extensions directory and import module. - ten_string_t *addon_extensions_path = get_addon_extensions_path(); - start_debugpy_server_if_needed(ten_env); - load_all_python_modules(ten_env, addon_extensions_path); - - ten_string_destroy(addon_extensions_path); + // Traverse `ten_packages/extension` directory and import module. + load_python_extensions_according_to_app_manifest_dependencies(ten_env); // The `app_base_dir` is no longer needed afterwards, so it is released. ten_string_destroy(app_base_dir); @@ -253,6 +254,34 @@ class py_init_addon_t : public ten::addon_t { return result; } + void load_python_extensions_according_to_app_manifest_dependencies( + ten::ten_env_t &ten_env) { + ten_string_t *addon_extensions_path = get_addon_extensions_path(); + + // Note: The behavior below is not something a typical user-defined addon + // can perform. Through a private API, it accesses the C `ten_env_t`, + // enabling special operations that only TEN framework developers are + // allowed to execute. + ten::ten_env_internal_accessor_t ten_env_internal_accessor(&ten_env); + ten_env_t *c_ten_env = ten_env_internal_accessor.get_c_ten_env(); + auto *c_app = static_cast( + c_ten_env->attached_target.addon_host->user_data); + TEN_ASSERT(c_app, "Should not happen."); + + ten_list_t extension_dependencies; + ten_list_init(&extension_dependencies); + + ten_app_get_extension_dependencies_for_extension(c_app, + &extension_dependencies); + + load_all_python_modules(ten_env, addon_extensions_path, + &extension_dependencies); + + ten_list_clear(&extension_dependencies); + + ten_string_destroy(addon_extensions_path); + } + // Start the debugpy server according to the environment variable and wait for // the debugger to connect. static void start_debugpy_server_if_needed(ten::ten_env_t &ten_env) { @@ -299,7 +328,8 @@ class py_init_addon_t : public ten::addon_t { // Load all python addons by import modules. static void load_all_python_modules(ten::ten_env_t &ten_env, - ten_string_t *addon_extensions_path) { + ten_string_t *addon_extensions_path, + ten_list_t *extension_dependencies) { if (addon_extensions_path == nullptr || ten_string_is_empty(addon_extensions_path)) { TEN_ENV_LOG_ERROR( @@ -334,11 +364,35 @@ class py_init_addon_t : public ten::addon_t { if (!(ten_string_is_equal_c_str(short_name, ".") || ten_string_is_equal_c_str(short_name, ".."))) { - // The full module name is "ten_packages.extension." - ten_string_t *full_module_name = ten_string_create_formatted( - "ten_packages.extension.%s", ten_string_get_raw_str(short_name)); - ten_py_import_module(ten_string_get_raw_str(full_module_name)); - ten_string_destroy(full_module_name); + // Check if short_name is in extension_dependencies list. + bool should_load = false; + if (extension_dependencies != nullptr) { + // Iterate over extension_dependencies to check if short_name matches + // any. + ten_list_foreach (extension_dependencies, dep_iter) { + ten_string_t *dep_name = ten_str_listnode_get(dep_iter.node); + if (ten_string_is_equal(short_name, dep_name)) { + should_load = true; + break; + } + } + } else { + // If extension_dependencies is NULL, we load all extensions. + should_load = true; + } + + if (should_load) { + // The full module name is "ten_packages.extension." + ten_string_t *full_module_name = ten_string_create_formatted( + "ten_packages.extension.%s", ten_string_get_raw_str(short_name)); + ten_py_import_module(ten_string_get_raw_str(full_module_name)); + ten_string_destroy(full_module_name); + } else { + TEN_ENV_LOG_INFO(ten_env, (std::string("Skipping python module '") + + ten_string_get_raw_str(short_name) + + "' as it's not in extension dependencies.") + .c_str()); + } } ten_string_destroy(short_name); @@ -368,10 +422,11 @@ class py_init_addon_t : public ten::addon_t { static ten::addon_t *g_py_init_default_extension_addon = nullptr; -TEN_CONSTRUCTOR(____ctor_ten_declare_py_init_extension_addon____) { +extern "C" void ____ten_addon_py_init_extension_cpp_register____( + void *register_ctx) { g_py_init_default_extension_addon = new py_init_addon_t(); - ten_addon_register_extension( - "py_init_extension_cpp", nullptr, + ten_addon_register_extension_v2( + "py_init_extension_cpp", nullptr, register_ctx, g_py_init_default_extension_addon->get_c_addon()); } diff --git a/tests/ten_runtime/integration/cpp/standalone_test_cpp/test_case.py b/tests/ten_runtime/integration/cpp/standalone_test_cpp/test_case.py index 6390e340b9..25537c2a8b 100644 --- a/tests/ten_runtime/integration/cpp/standalone_test_cpp/test_case.py +++ b/tests/ten_runtime/integration/cpp/standalone_test_cpp/test_case.py @@ -4,10 +4,40 @@ import subprocess import os +import pytest from sys import stdout from .common import build_config +# TODO(Wei): Remove this after solving the dlsym memory leakages. +@pytest.fixture(scope="function") +def manage_env_var_for_memory_issue_detection(): + original_ten_enable_memory_sanitizer = os.environ.get( + "TEN_ENABLE_MEMORY_TRACKING" + ) + original_asan_options = os.environ.get("ASAN_OPTIONS") + + # Set the environment variable before the test. + os.environ["TEN_ENABLE_MEMORY_TRACKING"] = "false" + os.environ["ASAN_OPTIONS"] = "detect_leaks=0" + + yield + + # Remove the environment variable after the test. + if original_ten_enable_memory_sanitizer is not None: + os.environ["TEN_ENABLE_MEMORY_TRACKING"] = ( + original_ten_enable_memory_sanitizer + ) + else: + del os.environ["TEN_ENABLE_MEMORY_TRACKING"] + + if original_asan_options is not None: + os.environ["ASAN_OPTIONS"] = original_asan_options + else: + del os.environ["ASAN_OPTIONS"] + + +@pytest.mark.usefixtures("manage_env_var_for_memory_issue_detection") def test_standalone_test_cpp(): base_path = os.path.dirname(os.path.abspath(__file__)) root_dir = os.path.join(base_path, "../../../../../") diff --git a/tests/ten_runtime/smoke/extension_test/extension/extension_with_same_name.cc b/tests/ten_runtime/smoke/extension_test/extension/extension_with_same_name.cc index a3c8a52752..f01509ee7d 100644 --- a/tests/ten_runtime/smoke/extension_test/extension/extension_with_same_name.cc +++ b/tests/ten_runtime/smoke/extension_test/extension/extension_with_same_name.cc @@ -6,7 +6,6 @@ // #include #include -#include #include "gtest/gtest.h" #include "include_internal/ten_runtime/binding/cpp/ten.h" @@ -30,48 +29,6 @@ class test_extension : public ten::extension_t { } }; -class test_extension_group_1 : public ten::extension_group_t { - public: - explicit test_extension_group_1(const std::string &name) - : ten::extension_group_t(name) {} - - void on_create_extensions(ten::ten_env_t &ten_env) override { - std::vector extensions; - extensions.push_back(new test_extension("same_name")); - ten_env.on_create_extensions_done(extensions); - } - - void on_destroy_extensions( - ten::ten_env_t &ten_env, - const std::vector &extensions) override { - for (auto *extension : extensions) { - delete extension; - } - ten_env.on_destroy_extensions_done(); - } -}; - -class test_extension_group_2 : public ten::extension_group_t { - public: - explicit test_extension_group_2(const std::string &name) - : ten::extension_group_t(name) {} - - void on_create_extensions(ten::ten_env_t &ten_env) override { - std::vector extensions; - extensions.push_back(new test_extension("same_name")); - ten_env.on_create_extensions_done(extensions); - } - - void on_destroy_extensions( - ten::ten_env_t &ten_env, - const std::vector &extensions) override { - for (auto *extension : extensions) { - delete extension; - } - ten_env.on_destroy_extensions_done(); - } -}; - class test_app : public ten::app_t { public: void on_configure(ten::ten_env_t &ten_env) override { diff --git a/tests/ten_runtime/smoke/extension_test/timer/timer_one_shot.cc b/tests/ten_runtime/smoke/extension_test/timer/timer_one_shot.cc index d45be9b774..81ef654503 100644 --- a/tests/ten_runtime/smoke/extension_test/timer/timer_one_shot.cc +++ b/tests/ten_runtime/smoke/extension_test/timer/timer_one_shot.cc @@ -6,7 +6,6 @@ // #include #include -#include #include "gtest/gtest.h" #include "include_internal/ten_runtime/binding/cpp/ten.h" @@ -51,27 +50,6 @@ class test_extension : public ten::extension_t { std::unique_ptr hello_world_cmd; }; -class test_extension_group : public ten::extension_group_t { - public: - explicit test_extension_group(const std::string &name) - : ten::extension_group_t(name) {} - - void on_create_extensions(ten::ten_env_t &ten_env) override { - std::vector extensions; - extensions.push_back(new test_extension("test_extension")); - ten_env.on_create_extensions_done(extensions); - } - - void on_destroy_extensions( - ten::ten_env_t &ten_env, - const std::vector &extensions) override { - for (auto *extension : extensions) { - delete extension; - } - ten_env.on_destroy_extensions_done(); - } -}; - class test_app : public ten::app_t { public: void on_configure(ten::ten_env_t &ten_env) override {