From 82a76e8a8163892e33be5b6ec85f842f79ccf247 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Mon, 5 Sep 2022 11:45:09 -0400 Subject: [PATCH] Ensure registration of extension rates in host Cantera library If a user application is linked statically to the Cantera library, ExtensibleRate objects need to be registered in this copy of the Cantera library rather than the one that is embedded in the Python module. This is achieved by accessing the ReactionRateFactory from the main application rather than from the Python module. --- interfaces/cython/cantera/delegator.pyx | 11 +++++++++++ src/extensions/PythonExtensionManager.cpp | 1 + src/extensions/pythonExtensions.pyx | 15 +++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/interfaces/cython/cantera/delegator.pyx b/interfaces/cython/cantera/delegator.pyx index ec80273a28..c793b75319 100644 --- a/interfaces/cython/cantera/delegator.pyx +++ b/interfaces/cython/cantera/delegator.pyx @@ -328,6 +328,11 @@ cdef int assign_delegates(obj, CxxDelegator* delegator) except -1: return 0 +# Specifications for ReactionRate delegators that have not yet been registered with +# ReactionRateFactory. This list is read by PythonExtensionManager::registerRateBuilders +# and then cleared. +_rate_delegators = [] + def extension(*, name): """ A decorator for declaring Cantera extensions that should be registered with @@ -371,8 +376,14 @@ def extension(*, name): def decorator(cls): if issubclass(cls, ExtensibleRate): cls._reaction_rate_type = name + # Registering immediately supports the case where the main + # application is Python CxxPythonExtensionManager.registerPythonRateBuilder( stringify(cls.__module__), stringify(cls.__name__), stringify(name)) + + # Deferred registration supports the case where the main application + # is not Python + _rate_delegators.append((cls.__module__, cls.__name__, name)) else: raise TypeError(f"{cls} is not extensible") return cls diff --git a/src/extensions/PythonExtensionManager.cpp b/src/extensions/PythonExtensionManager.cpp index 3ba5063f0a..9cbaf44c99 100644 --- a/src/extensions/PythonExtensionManager.cpp +++ b/src/extensions/PythonExtensionManager.cpp @@ -144,6 +144,7 @@ void PythonExtensionManager::registerRateBuilders(const string& extensionName) throw CanteraError("PythonExtensionManager::registerRateBuilders", "Problem loading module:\n{}", getPythonExceptionInfo()); } + ct_registerReactionDelegators(); } void PythonExtensionManager::registerPythonRateBuilder( diff --git a/src/extensions/pythonExtensions.pyx b/src/extensions/pythonExtensions.pyx index 6facd1b34f..9520e4b185 100644 --- a/src/extensions/pythonExtensions.pyx +++ b/src/extensions/pythonExtensions.pyx @@ -13,6 +13,7 @@ import importlib import inspect import cantera as ct +from cantera._utils cimport stringify from cantera.reaction cimport ExtensibleRate, CxxReactionRate from cantera.delegator cimport CxxDelegator, assign_delegates @@ -22,6 +23,12 @@ cdef extern from "cantera/kinetics/ReactionRateDelegator.h" namespace "Cantera": CxxReactionRateDelegator() +cdef extern from "cantera/extensions/PythonExtensionManager.h" namespace "Cantera": + cdef cppclass CxxPythonExtensionManager "Cantera::PythonExtensionManager": + @staticmethod + void registerPythonRateBuilder(string&, string&, string&) + + cdef public char* ct_getExceptionString(object exType, object exValue, object exTraceback): import traceback result = str(exValue) + "\n\n" @@ -40,3 +47,11 @@ cdef public object ct_newPythonExtensibleRate(CxxReactionRateDelegator* delegato cdef ExtensibleRate rate = getattr(mod, class_name.decode())(init=False) rate.set_cxx_object(delegator) return rate + + +cdef public ct_registerReactionDelegators(): + for module, cls, name in ct.delegator._rate_delegators: + CxxPythonExtensionManager.registerPythonRateBuilder( + stringify(module), stringify(cls), stringify(name)) + + ct.delegator._rate_delegators.clear()