diff --git a/core/include/ten_runtime/addon/extension/extension.h b/core/include/ten_runtime/addon/extension/extension.h index 489bc10ef..38e4a78db 100644 --- a/core/include/ten_runtime/addon/extension/extension.h +++ b/core/include/ten_runtime/addon/extension/extension.h @@ -20,9 +20,20 @@ typedef struct ten_addon_t ten_addon_t; typedef struct ten_extension_t ten_extension_t; typedef struct ten_addon_host_t ten_addon_host_t; +typedef ten_addon_host_t *(*ten_addon_register_extension_func_t)( + const char *name, const char *base_dir, ten_addon_t *addon); + +typedef ten_addon_host_t *(*ten_addon_register_extension_v2_func_t)( + const char *name, const char *base_dir, ten_addon_t *addon, + void *register_ctx); + TEN_RUNTIME_API ten_addon_host_t *ten_addon_register_extension( const char *name, const char *base_dir, ten_addon_t *addon); +TEN_RUNTIME_API ten_addon_host_t *ten_addon_register_extension_v2( + const char *name, const char *base_dir, ten_addon_t *addon, + void *register_ctx); + TEN_RUNTIME_API ten_addon_t *ten_addon_unregister_extension(const char *name); TEN_RUNTIME_API bool ten_addon_create_extension( diff --git a/core/include_internal/ten_runtime/addon/extension/extension.h b/core/include_internal/ten_runtime/addon/extension/extension.h index b1e5532f5..f840976dd 100644 --- a/core/include_internal/ten_runtime/addon/extension/extension.h +++ b/core/include_internal/ten_runtime/addon/extension/extension.h @@ -12,8 +12,3 @@ 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_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/binding/python/addon/decorator.h b/core/include_internal/ten_runtime/binding/python/addon/decorator.h index a8c1c8d09..0176d96bd 100644 --- a/core/include_internal/ten_runtime/binding/python/addon/decorator.h +++ b/core/include_internal/ten_runtime/binding/python/addon/decorator.h @@ -19,5 +19,13 @@ typedef struct ten_py_decorator_register_addon_t { ten_string_t base_dir; } ten_py_decorator_register_addon_t; +typedef struct ten_py_decorator_register_addon_v2_t { + PyObject_HEAD +} ten_py_decorator_register_addon_v2_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_init_for_module_v2( + PyObject *module); diff --git a/core/include_internal/ten_runtime/engine/internal/remote_interface.h b/core/include_internal/ten_runtime/engine/internal/remote_interface.h index 941d2c047..e2b5c8197 100644 --- a/core/include_internal/ten_runtime/engine/internal/remote_interface.h +++ b/core/include_internal/ten_runtime/engine/internal/remote_interface.h @@ -25,19 +25,6 @@ typedef struct ten_engine_on_protocol_created_info_t { void *user_data; } ten_engine_on_protocol_created_info_t; -TEN_RUNTIME_PRIVATE_API ten_engine_on_protocol_created_info_t * -ten_engine_on_protocol_created_info_create(ten_engine_on_remote_created_cb_t cb, - void *user_data); - -TEN_RUNTIME_PRIVATE_API void ten_engine_on_protocol_created_info_destroy( - ten_engine_on_protocol_created_info_t *self); - -TEN_RUNTIME_PRIVATE_API void ten_engine_add_remote(ten_engine_t *self, - ten_remote_t *remote); - -TEN_RUNTIME_PRIVATE_API void ten_engine_add_weak_remote(ten_engine_t *self, - ten_remote_t *remote); - TEN_RUNTIME_PRIVATE_API void ten_engine_upgrade_weak_remote_to_normal_remote( ten_engine_t *self, ten_remote_t *remote); @@ -62,8 +49,5 @@ TEN_RUNTIME_PRIVATE_API void ten_engine_on_remote_closed(ten_remote_t *remote, TEN_RUNTIME_PRIVATE_API bool ten_engine_receive_msg_from_remote( ten_remote_t *remote, ten_shared_ptr_t *msg, void *user_data); -TEN_RUNTIME_PRIVATE_API ten_remote_t *ten_engine_find_remote(ten_engine_t *self, - const char *uri); - TEN_RUNTIME_PRIVATE_API void ten_engine_link_connection_to_remote( ten_engine_t *self, ten_connection_t *connection, const char *uri); diff --git a/core/src/ten_runtime/addon/extension/extension.c b/core/src/ten_runtime/addon/extension/extension.c index eb50f00af..cce5c7c8d 100644 --- a/core/src/ten_runtime/addon/extension/extension.c +++ b/core/src/ten_runtime/addon/extension/extension.c @@ -15,7 +15,6 @@ #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" @@ -139,10 +138,10 @@ ten_addon_host_t *ten_addon_register_extension(const char *name, 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) { +ten_addon_host_t *ten_addon_register_extension_v2(const char *name, + const char *base_dir, + ten_addon_t *addon, + void *register_ctx) { if (!name || strlen(name) == 0) { TEN_LOGE("The addon name is required."); exit(EXIT_FAILURE); @@ -150,8 +149,16 @@ void ten_addon_register_extension_v2(const char *name, const char *base_dir, ten_addon_host_t *addon_host = (ten_addon_host_t *)register_ctx; + // If no `addon_host` is provided, create one here. Whether it is created here + // or received, pass it out in the end. + if (!addon_host) { + addon_host = ten_addon_host_create(TEN_ADDON_TYPE_EXTENSION); + } + ten_addon_register(ten_extension_get_global_store(), addon_host, name, base_dir, addon); + + return addon_host; } ten_addon_t *ten_addon_unregister_extension(const char *name) { 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 d0a45d341..e4ea1da52 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/__init__.py +++ b/core/src/ten_runtime/binding/python/interface/ten/__init__.py @@ -11,6 +11,7 @@ from .addon import Addon from .decorator import ( register_addon_as_extension, + register_addon_as_extension_v2, ) from .ten_env import TenEnv from .cmd import Cmd @@ -26,6 +27,7 @@ __all__ = [ "Addon", "register_addon_as_extension", + "register_addon_as_extension_v2", "App", "Extension", "AsyncExtension", diff --git a/core/src/ten_runtime/binding/python/interface/ten/addon.py b/core/src/ten_runtime/binding/python/interface/ten/addon.py index b60c68793..83b643e58 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/addon.py +++ b/core/src/ten_runtime/binding/python/interface/ten/addon.py @@ -8,13 +8,21 @@ import os import importlib.util from glob import glob +from typing import Callable, Any, Dict from libten_runtime_python import _Addon from .ten_env import TenEnv -class Addon(_Addon): +class _AddonManager: + # Use the simple approach below, similar to a global array, to detect + # whether a Python module provides the registration function required by the + # TEN runtime. This avoids using `setattr` on the module, which may not be + # supported in advanced environments like Cython. The global array method + # is simple enough that it should work in all environments. + _registration_registry: Dict[str, Callable[[Any], None]] = {} + @classmethod - def _load_all(cls): + def _load_all(cls, register_ctx: object): base_dir = cls._find_app_base_dir() # Read manifest.json under base_dir. @@ -47,28 +55,105 @@ def _load_all(cls): module_name = os.path.basename(module) if module_name in extension_names: - # Proceed to load the module. - spec = importlib.util.find_spec( - "ten_packages.extension.{}".format(module_name) + cls._load_module( + module_full_name=( + f"ten_packages.extension.{module_name}" + ), + module_name=module_name, + register_ctx=register_ctx, ) - if spec is not None: - _ = importlib.import_module( - "ten_packages.extension.{}".format(module_name) - ) - print("imported module: {}".format(module_name)) else: - print("Skipping module: {}".format(module_name)) + print(f"Skipping module: {module_name}") @classmethod - def _load_from_path(cls, path): - module_name = os.path.basename(path) - spec = importlib.util.find_spec(module_name) - if spec is not None: - mod = importlib.import_module(module_name) + def _load_module( + cls, + module_full_name: str, + module_name: str, + register_ctx: object, + ): + """ + Helper method to load a module, check for the special function, + invoke it, and unload the module if the special function is missing. + """ + try: + spec = importlib.util.find_spec(module_full_name) + if spec is None: + raise ImportError(f"Cannot find module: {module_full_name}") + + _ = importlib.import_module(module_full_name) print(f"Imported module: {module_name}") - return mod - else: - raise ImportError(f"Cannot find module: {module_name}") + + # Retrieve the registration function from the global registry + registration_func_name = _AddonManager._get_registration_func_name( + module_name + ) + + registration_func = _AddonManager._get_registration_func( + module_name + ) + + if registration_func: + try: + registration_func(register_ctx) + print(f"Successfully registered addon '{module_name}'") + except Exception as e: + print( + ( + "Error during registration of addon " + f"'{module_name}': {e}" + ) + ) + finally: + # Remove the registration function from the global registry. + if ( + registration_func_name + in _AddonManager._registration_registry + ): + del _AddonManager._registration_registry[ + registration_func_name + ] + print( + ( + "Removed registration function for addon " + f"'{registration_func_name}'" + ) + ) + else: + print(f"No {registration_func_name} found in {module_name}") + + except ImportError as e: + print(f"Error importing module {module_name}: {e}") + + @staticmethod + def _get_registration_func_name(addon_name: str) -> str: + return f"____ten_addon_{addon_name}_register____" + + @staticmethod + def _get_registration_func(addon_name: str) -> Callable[[Any], None] | None: + return _AddonManager._registration_registry.get( + _AddonManager._get_registration_func_name(addon_name) + ) + + @staticmethod + def _set_registration_func( + addon_name: str, + registration_func: Callable[[Any], None], + ) -> None: + registration_func_name = _AddonManager._get_registration_func_name( + addon_name + ) + + print( + ( + f"Injected registration function '{registration_func_name}' " + "into module '{module.__name__}'" + ) + ) + + _AddonManager._registration_registry[registration_func_name] = ( + registration_func + ) @staticmethod def _find_app_base_dir(): @@ -92,12 +177,10 @@ def _find_app_base_dir(): "App base directory with a valid manifest.json not found." ) + +class Addon(_Addon): def on_init(self, ten_env: TenEnv) -> None: ten_env.on_init_done() def on_deinit(self, ten_env: TenEnv) -> None: ten_env.on_deinit_done() - - def on_create_instance( - self, ten_env: TenEnv, name: str, context - ) -> None: ... diff --git a/core/src/ten_runtime/binding/python/interface/ten/cmd.py b/core/src/ten_runtime/binding/python/interface/ten/cmd.py index 1e69b7e65..d941d2b89 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/cmd.py +++ b/core/src/ten_runtime/binding/python/interface/ten/cmd.py @@ -4,7 +4,6 @@ # Licensed under the Apache License, Version 2.0, with certain conditions. # Refer to the "LICENSE" file in the root directory for more information. # -import json from libten_runtime_python import _Cmd 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 681062ccc..6bc8574e7 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/decorator.py +++ b/core/src/ten_runtime/binding/python/interface/ten/decorator.py @@ -6,8 +6,11 @@ # import os import sys +from typing import Type +from .addon import _AddonManager, Addon from libten_runtime_python import ( _register_addon_as_extension, + _register_addon_as_extension_v2, ) @@ -27,3 +30,66 @@ 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_v2(name: str, base_dir: str | None = None): + """ + Decorator to register a class as an addon extension and create a special + registration function required by the Addon loader. + + Args: + name (str): The name of the addon extension. + base_dir (str, optional): The base directory of the addon. Defaults to + None. + + Returns: + Callable: The decorator function. + """ + + def decorator(cls: Type[Addon]) -> Type[Addon]: + # Resolve base_dir. + if base_dir is None: + try: + # Attempt to get the caller's file path using sys._getframe() + caller_frame = sys._getframe(1) + resolved_base_dir = os.path.dirname( + caller_frame.f_code.co_filename + ) + except (AttributeError, ValueError): + # Fallback in case sys._getframe() is not available or fails. + # Example: in Cython or restricted environments. + resolved_base_dir = None + else: + # If base_dir is provided, ensure it's the directory name + resolved_base_dir = os.path.dirname(base_dir) + + # Define the registration function that will be called by the Addon + # loader. + def registration_func(register_ctx): + """ + Registration function injected into the module to handle addon + registration. + + Args: + register_ctx: An opaque parameter provided by the Addon loader. + """ + # Instantiate the addon class. + instance = cls() + + try: + _register_addon_as_extension_v2( + name, resolved_base_dir, instance, register_ctx + ) + print( + f"Called '_register_addon_as_extension' for addon '{name}'" + ) + except Exception as e: + print(f"Failed to register addon '{name}': {e}") + + # Define the registration function name based on the addon name. + _AddonManager._set_registration_func(name, registration_func) + + # Return the original class without modification. + return cls + + return decorator 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 f1896a961..5cfe2ba1c 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 @@ -6,6 +6,7 @@ # from .ten_env_attach_to_enum import _TenEnvAttachTo from .log_level import LogLevel +from .addon import Addon class _Msg: def to_json(self) -> str: ... @@ -179,3 +180,6 @@ class _ExtensionTester: def run(self) -> None: ... def _register_addon_as_extension(name: str, base_dir: str | None): ... +def _register_addon_as_extension_v2( + name: str, base_dir: str | None, instance: Addon, register_ctx: object +): ... diff --git a/core/src/ten_runtime/binding/python/interface/ten/ten_env.py b/core/src/ten_runtime/binding/python/interface/ten/ten_env.py index 09612cf85..95ef78716 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/ten_env.py +++ b/core/src/ten_runtime/binding/python/interface/ten/ten_env.py @@ -38,11 +38,18 @@ def _on_release(self) -> None: self._release_handler() def on_configure_done(self) -> None: - from .addon import Addon + from .addon import _AddonManager if self._internal._attach_to == _TenEnvAttachTo.APP: # Load all python addons when app on_configure_done. - Addon._load_all() + # + # In the current use of the TEN framework's Python environment, + # there is no need to pass any `register_ctx` object into the + # registration function of the Python addon. Therefore, for now, + # simply passing `None` is sufficient. If needed in the future, we + # can consider what information should be passed to the registration + # function of the Python addon. + _AddonManager._load_all(None) return self._internal.on_configure_done() def on_init_done(self) -> 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 e94a6030b..27068cf8a 100644 --- a/core/src/ten_runtime/binding/python/native/addon/decorator.c +++ b/core/src/ten_runtime/binding/python/native/addon/decorator.c @@ -8,7 +8,6 @@ #include "include_internal/ten_runtime/binding/python/addon/addon.h" #include "include_internal/ten_runtime/binding/python/common/error.h" -#include "ten_runtime/addon/addon.h" #include "ten_runtime/addon/extension/extension.h" #include "ten_runtime/addon/extension_group/extension_group.h" #include "ten_utils/lib/string.h" @@ -31,6 +30,20 @@ static PyObject *ten_py_decorator_register_addon_create( return (PyObject *)py_decorator; } +static PyObject *ten_py_decorator_register_addon_create_v2( + PyTypeObject *ty, PyObject *args, TEN_UNUSED PyObject *kwds) { + ten_py_decorator_register_addon_v2_t *py_decorator = + (ten_py_decorator_register_addon_v2_t *)ty->tp_alloc(ty, 0); + if (!py_decorator) { + PyObject *result = ten_py_raise_py_memory_error_exception( + "Failed to allocate memory for addon decorator."); + TEN_ASSERT(0, "Failed to allocate memory."); + return result; + } + + return (PyObject *)py_decorator; +} + static int ten_py_decorator_register_addon_init(PyObject *self, PyObject *args, TEN_UNUSED PyObject *kwds) { ten_py_decorator_register_addon_t *py_decorator = @@ -52,6 +65,12 @@ static int ten_py_decorator_register_addon_init(PyObject *self, PyObject *args, return 0; } +static int ten_py_decorator_register_addon_init_v2(PyObject *self, + PyObject *args, + TEN_UNUSED PyObject *kwds) { + return 0; +} + static void ten_py_decorator_register_addon_destroy(PyObject *self) { ten_py_decorator_register_addon_t *py_decorator = (ten_py_decorator_register_addon_t *)self; @@ -64,11 +83,17 @@ static void ten_py_decorator_register_addon_destroy(PyObject *self) { Py_TYPE(self)->tp_free(self); } +static void ten_py_decorator_register_addon_destroy_v2(PyObject *self) { + ten_py_decorator_register_addon_v2_t *py_decorator = + (ten_py_decorator_register_addon_v2_t *)self; + TEN_ASSERT(py_decorator, "Invalid argument."); + + Py_TYPE(self)->tp_free(self); +} + static PyObject *ten_py_decorator_register_addon_call( ten_py_decorator_register_addon_t *self, PyObject *args, - ten_addon_host_t *(*ten_addon_register)(const char *name, - const char *base_dir, - ten_addon_t *addon)) { + ten_addon_register_extension_func_t register_addon_func) { PyTypeObject *py_addon_type_object = NULL; if (!PyArg_ParseTuple(args, "O", &py_addon_type_object)) { @@ -98,7 +123,7 @@ static PyObject *ten_py_decorator_register_addon_call( // existing within the Python VM memory space can be safely used within the // TEN world. ten_py_addon_t *py_addon = (ten_py_addon_t *)py_addon_object; - ten_addon_host_t *c_addon_host = ten_addon_register( + ten_addon_host_t *c_addon_host = register_addon_func( ten_string_get_raw_str(&self->addon_name), ten_string_get_raw_str(&self->base_dir), &py_addon->c_addon); TEN_ASSERT(c_addon_host, "Should not happen."); @@ -115,6 +140,48 @@ static PyObject *ten_py_decorator_register_addon_as_extension_call( ten_addon_register_extension); } +static PyObject *ten_py_decorator_register_addon_call_v2( + ten_py_decorator_register_addon_v2_t *self, PyObject *args, + ten_addon_register_extension_v2_func_t register_addon_func) { + const char *name = NULL; + const char *base_dir = NULL; + PyObject *py_addon_object = NULL; + PyObject *py_register_ctx = NULL; + + if (!PyArg_ParseTuple(args, "ssOO", &name, &base_dir, &py_addon_object, + &py_register_ctx)) { + return ten_py_raise_py_value_error_exception( + "Failed to parse arguments when registering addon."); + } + + if (!PyObject_TypeCheck(py_addon_object, ten_py_addon_py_type())) { + return ten_py_raise_py_type_error_exception( + "Object is not an instance of Python Addon."); + } + + ten_py_addon_t *py_addon = (ten_py_addon_t *)py_addon_object; + + ten_addon_host_t *c_addon_host = + register_addon_func(name, base_dir, &py_addon->c_addon, NULL); + if (!c_addon_host) { + return ten_py_raise_py_value_error_exception( + "Failed to register addon in register_addon_func."); + } + + py_addon->c_addon_host = c_addon_host; + + Py_INCREF(py_addon_object); // Ensure the object is kept alive. + + return py_addon_object; +} + +static PyObject *ten_py_decorator_register_addon_as_extension_call_v2( + PyObject *self, PyObject *args, TEN_UNUSED PyObject *kwds) { + return ten_py_decorator_register_addon_call_v2( + (ten_py_decorator_register_addon_v2_t *)self, args, + ten_addon_register_extension_v2); +} + static PyTypeObject *ten_py_decorator_register_addon_as_extension_py_type( void) { static PyMethodDef decorator_methods[] = { @@ -139,6 +206,30 @@ static PyTypeObject *ten_py_decorator_register_addon_as_extension_py_type( return &py_type; } +static PyTypeObject *ten_py_decorator_register_addon_as_extension_py_type_v2( + void) { + static PyMethodDef decorator_methods[] = { + {NULL, NULL, 0, NULL}, + }; + + static PyTypeObject py_type = { + PyVarObject_HEAD_INIT(NULL, 0).tp_name = + "libten_runtime_python.register_addon_as_extension_v2", + .tp_doc = PyDoc_STR("register_addon_as_extension_v2"), + .tp_basicsize = sizeof(ten_py_decorator_register_addon_t), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = ten_py_decorator_register_addon_create_v2, + .tp_init = ten_py_decorator_register_addon_init_v2, + .tp_dealloc = ten_py_decorator_register_addon_destroy_v2, + .tp_call = ten_py_decorator_register_addon_as_extension_call_v2, + .tp_getset = NULL, + .tp_methods = decorator_methods, + }; + + return &py_type; +} + static bool ten_py_decorator_register_addon_module_init(PyObject *module, PyTypeObject *py_type, const char *name) { @@ -164,3 +255,10 @@ 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_init_for_module_v2( + PyObject *module) { + return ten_py_decorator_register_addon_module_init( + module, ten_py_decorator_register_addon_as_extension_py_type_v2(), + "_register_addon_as_extension_v2"); +} diff --git a/core/src/ten_runtime/binding/python/native/init.c b/core/src/ten_runtime/binding/python/native/init.c index 01f96cc34..56ec7e380 100644 --- a/core/src/ten_runtime/binding/python/native/init.c +++ b/core/src/ten_runtime/binding/python/native/init.c @@ -70,6 +70,12 @@ PyMODINIT_FUNC PyInit_libten_runtime_python(void) { return NULL; } + if (!ten_py_decorator_register_addon_as_extension_init_for_module_v2( + 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/engine/internal/remote_interface.c b/core/src/ten_runtime/engine/internal/remote_interface.c index 9f539174f..e39e6ff82 100644 --- a/core/src/ten_runtime/engine/internal/remote_interface.c +++ b/core/src/ten_runtime/engine/internal/remote_interface.c @@ -68,7 +68,7 @@ static size_t ten_engine_weak_remotes_cnt_in_specified_uri(ten_engine_t *self, return cnt; } -ten_engine_on_protocol_created_info_t * +static ten_engine_on_protocol_created_info_t * ten_engine_on_protocol_created_info_create(ten_engine_on_remote_created_cb_t cb, void *user_data) { ten_engine_on_protocol_created_info_t *self = @@ -81,7 +81,7 @@ ten_engine_on_protocol_created_info_create(ten_engine_on_remote_created_cb_t cb, return self; } -void ten_engine_on_protocol_created_info_destroy( +static void ten_engine_on_protocol_created_info_destroy( ten_engine_on_protocol_created_info_t *self) { TEN_ASSERT(self, "Invalid argument."); @@ -150,7 +150,7 @@ void ten_engine_on_remote_closed(ten_remote_t *remote, void *on_closed_data) { } } -void ten_engine_add_remote(ten_engine_t *self, ten_remote_t *remote) { +static void ten_engine_add_remote(ten_engine_t *self, ten_remote_t *remote) { TEN_ASSERT(self, "Invalid argument."); TEN_ASSERT(ten_engine_check_integrity(self, true), "Invalid use of engine %p.", self); @@ -167,7 +167,8 @@ void ten_engine_add_remote(ten_engine_t *self, ten_remote_t *remote) { ten_remote_destroy); } -void ten_engine_add_weak_remote(ten_engine_t *self, ten_remote_t *remote) { +static void ten_engine_add_weak_remote(ten_engine_t *self, + ten_remote_t *remote) { TEN_ASSERT(self, "Invalid argument."); TEN_ASSERT(ten_engine_check_integrity(self, true), "Invalid use of engine %p.", self); @@ -205,6 +206,22 @@ void ten_engine_upgrade_weak_remote_to_normal_remote(ten_engine_t *self, ten_engine_add_remote(self, remote); } +static ten_remote_t *ten_engine_find_remote(ten_engine_t *self, + const char *uri) { + TEN_ASSERT(self, "Invalid argument."); + TEN_ASSERT(ten_engine_check_integrity(self, true), + "Invalid use of engine %p.", self); + + TEN_ASSERT(uri, "Should not happen."); + + ten_hashhandle_t *hh = ten_hashtable_find_string(&self->remotes, uri); + if (hh) { + return CONTAINER_OF_FROM_FIELD(hh, ten_remote_t, hh_in_remote_table); + } + + return NULL; +} + void ten_engine_link_connection_to_remote(ten_engine_t *self, ten_connection_t *connection, const char *uri) { @@ -606,18 +623,3 @@ bool ten_engine_receive_msg_from_remote(ten_remote_t *remote, return true; } - -ten_remote_t *ten_engine_find_remote(ten_engine_t *self, const char *uri) { - TEN_ASSERT(self, "Invalid argument."); - TEN_ASSERT(ten_engine_check_integrity(self, true), - "Invalid use of engine %p.", self); - - TEN_ASSERT(uri, "Should not happen."); - - ten_hashhandle_t *hh = ten_hashtable_find_string(&self->remotes, uri); - if (hh) { - return CONTAINER_OF_FROM_FIELD(hh, ten_remote_t, hh_in_remote_table); - } - - return NULL; -} 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 711fd7ba9..2d06d8dc6 100644 --- a/packages/core_extensions/py_init_extension_cpp/src/main.cc +++ b/packages/core_extensions/py_init_extension_cpp/src/main.cc @@ -426,8 +426,8 @@ 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_v2( - "py_init_extension_cpp", nullptr, register_ctx, - g_py_init_default_extension_addon->get_c_addon()); + "py_init_extension_cpp", nullptr, + g_py_init_default_extension_addon->get_c_addon(), register_ctx); } TEN_DESTRUCTOR(____dtor_ten_declare_py_init_extension_addon____) { diff --git a/tests/ten_runtime/integration/python/send_cmd_python/send_cmd_python_app/ten_packages/extension/default_extension_python/addon.py b/tests/ten_runtime/integration/python/send_cmd_python/send_cmd_python_app/ten_packages/extension/default_extension_python/addon.py new file mode 100644 index 000000000..cbb565e8f --- /dev/null +++ b/tests/ten_runtime/integration/python/send_cmd_python/send_cmd_python_app/ten_packages/extension/default_extension_python/addon.py @@ -0,0 +1,19 @@ +# +# This file is part of TEN Framework, an open source project. +# Licensed under the Apache License, Version 2.0. +# See the LICENSE file for more information. +# +from ten import ( + Addon, + register_addon_as_extension_v2, + TenEnv, +) +from .extension import DefaultExtension + + +@register_addon_as_extension_v2("default_extension_python") +class DefaultExtensionAddon(Addon): + + def on_create_instance(self, ten_env: TenEnv, name: str, context) -> None: + ten_env.log_info("DefaultExtensionAddon on_create_instance") + ten_env.on_create_instance_done(DefaultExtension(name), context)