4#ifndef CT_CYTHON_FUNC_WRAPPER
5#define CT_CYTHON_FUNC_WRAPPER
12typedef double(*callback_wrapper)(double,
void*,
void**);
20 , m_exception_type(
nullptr)
21 , m_exception_value(
nullptr)
26 : m_func(other.m_func)
27 , m_exception_type(other.m_exception_type)
28 , m_exception_value(other.m_exception_value)
30 Py_XINCREF(m_exception_type);
31 Py_XINCREF(m_exception_value);
35 Py_XDECREF(m_exception_type);
36 Py_XDECREF(m_exception_value);
42 void setFunc(PyObject* f) {
46 PyObject* exceptionType() {
47 return m_exception_type;
49 void setExceptionType(PyObject* obj) {
50 Py_XDECREF(m_exception_type);
52 m_exception_type = obj;
55 PyObject* exceptionValue() {
56 return m_exception_value;
58 void setExceptionValue(PyObject* obj) {
59 Py_XDECREF(m_exception_value);
61 m_exception_value = obj;
66 PyObject* m_exception_type;
67 PyObject* m_exception_value;
79 m_type((PyObject*) type),
80 m_value((PyObject*) value)
89 m_type(info.exceptionType()),
90 m_value(info.exceptionValue())
94 info.setExceptionType(0);
95 info.setExceptionValue(0);
106 PyObject* name = PyObject_GetAttrString(m_type,
"__name__");
107 PyObject* value_str = PyObject_Str(m_value);
109 PyObject* name_bytes = PyUnicode_AsASCIIString(name);
110 PyObject* value_bytes = PyUnicode_AsASCIIString(value_str);
113 msg += PyBytes_AsString(name_bytes);
114 Py_DECREF(name_bytes);
116 msg +=
"<error determining exception type>";
122 msg += PyBytes_AsString(value_bytes);
123 Py_DECREF(value_bytes);
125 msg +=
"<error determining exception message>";
129 Py_XDECREF(value_str);
146 Func1Py(callback_wrapper callback,
void* pyobj) :
147 m_callback(callback),
151 double eval(
double t)
const override {
152 void* err[2] = {0, 0};
153 double y = m_callback(t, m_pyobj, err);
161 callback_wrapper m_callback;
166#if defined(CYTHON_HEX_VERSION) && CYTHON_HEX_VERSION >= 0x001DFFFF
167extern PyObject* pyCanteraError;
170 extern PyObject* pyCanteraError;
186template <
class ... Args>
187std::function<void(Args ...)> pyOverride(PyObject* pyFunc,
void func(
PyFuncInfo&, Args ... args)) {
189 func_info.setFunc(pyFunc);
190 return [func_info, func](Args ... args)
mutable {
191 func(func_info, args ...);
192 if (func_info.exceptionType()) {
199template <
class ... Args>
200std::function<int(Args ...)> pyOverride(PyObject* pyFunc,
int func(
PyFuncInfo&, Args ... args)) {
202 func_info.setFunc(pyFunc);
203 return [func_info, func](Args ... args)
mutable {
204 int ret = func(func_info, args ...);
205 if (func_info.exceptionType()) {
215inline int translate_exception()
218 if (!PyErr_Occurred()) {
225 PyErr_SetObject(exn.m_type, exn.m_value);
226 }
catch (
const std::out_of_range& exn) {
227 PyErr_SetString(PyExc_IndexError, exn.what());
229 PyErr_SetString(PyExc_NotImplementedError, exn.
what());
231 PyErr_SetString(pyCanteraError, exn.
what());
232 }
catch (
const std::exception& exn) {
233 PyErr_SetString(PyExc_RuntimeError, exn.what());
235 PyErr_SetString(PyExc_Exception,
"Unknown exception");
std::string getClass() const override
Method overridden by derived classes to indicate their type.
CallbackError(PyFuncInfo &info)
Constructor used by pyOverride()
std::string getMessage() const override
Method overridden by derived classes to format the error message.
CallbackError(void *type, void *value)
Constructor used by Func1Py.
Base class for exceptions thrown by Cantera classes.
const char * what() const override
Get a description of the error.
CanteraError()
Protected default constructor discourages throwing errors containing no information.
Base class for 'functor' classes that evaluate a function of one variable.
An error indicating that an unimplemented function has been called.
double eval(double t) const override
Evaluate the function.
A class to hold information needed to call Python functions from delegated methods (see class Delegat...
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...