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;
77 CallbackError(
void* type,
void* 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);
133 std::string
getClass()
const override {
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);
155 throw CallbackError(err[0], err[1]);
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()) {
193 throw CallbackError(func_info);
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()) {
206 throw CallbackError(func_info);
215inline int translate_exception()
218 if (!PyErr_Occurred()) {
223 }
catch (
const CallbackError& exn) {
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");
Base class for exceptions thrown by Cantera classes.
const char * what() const override
Get a description of the error.
virtual string getMessage() const
Method overridden by derived classes to format the error message.
CanteraError()
Protected default constructor discourages throwing errors containing no information.
virtual string getClass() const
Method overridden by derived classes to indicate their type.
Base class for 'functor' classes that evaluate a function of one variable.
virtual double eval(double t) const
Evaluate the function.
An error indicating that an unimplemented function has been called.
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...