NEURON
nrnpy_utils.h
Go to the documentation of this file.
1 #ifndef nrnpy_utils_h
2 #define nrnpy_utils_h
3 
4 #include <nrnwrap_Python.h>
5 #include <cassert>
6 
7 inline bool is_python_string(PyObject* python_string) {
8  return PyUnicode_Check(python_string) || PyBytes_Check(python_string);
9 }
10 
11 class Py2NRNString {
12  public:
13  Py2NRNString(PyObject* python_string, bool disable_release = false) {
14  disable_release_ = disable_release;
15  str_ = NULL;
16  if (PyUnicode_Check(python_string)) {
17  PyObject* py_bytes = PyUnicode_AsASCIIString(python_string);
18  if (py_bytes) {
19  str_ = strdup(PyBytes_AsString(py_bytes));
20  if (!str_) { // errno is ENOMEM
21  PyErr_SetString(PyExc_MemoryError, "strdup in Py2NRNString");
22  }
23  }
24  Py_XDECREF(py_bytes);
25  } else if (PyBytes_Check(python_string)) {
26  str_ = strdup(PyBytes_AsString(python_string));
27  // assert(strlen(str_) == PyBytes_Size(python_string))
28  // not checking for embedded '\0'
29  if (!str_) { // errno is ENOMEM
30  PyErr_SetString(PyExc_MemoryError, "strdup in Py2NRNString");
31  }
32  } else { // Neither Unicode or PyBytes
33  PyErr_SetString(PyExc_TypeError, "Neither Unicode or PyBytes");
34  }
35  }
36 
38  if (!disable_release_ && str_) {
39  free(str_);
40  }
41  }
42  inline char* c_str() const {
43  return str_;
44  }
45  inline bool err() const {
46  return str_ == NULL;
47  }
48  inline void set_pyerr(PyObject* type, const char* message) {
49  PyObject* ptype = NULL;
50  PyObject* pvalue = NULL;
51  PyObject* ptraceback = NULL;
52  if (err()) {
53  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
54  }
55  if (pvalue && ptype) {
56  PyObject* umes = PyUnicode_FromFormat("%s (Note: %S: %S)", message, ptype, pvalue);
57  PyErr_SetObject(type, umes); // umes is borrowed reference
58  Py_XDECREF(umes);
59  } else {
60  PyErr_SetString(type, message);
61  }
62  Py_XDECREF(ptype);
63  Py_XDECREF(pvalue);
64  Py_XDECREF(ptraceback);
65  }
66  inline char* get_pyerr() {
67  PyObject* ptype = NULL;
68  PyObject* pvalue = NULL;
69  PyObject* ptraceback = NULL;
70  if (err()) {
71  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
72  if (pvalue) {
73  PyObject* pstr = PyObject_Str(pvalue);
74  if (pstr) {
75  const char* err_msg = PyUnicode_AsUTF8(pstr);
76  if (err_msg) {
77  str_ = strdup(err_msg);
78  } else {
79  str_ = strdup("get_pyerr failed at PyUnicode_AsUTF8");
80  }
81  Py_XDECREF(pstr);
82  } else {
83  str_ = strdup("get_pyerr failed at PyObject_Str");
84  }
85  } else {
86  str_ = strdup("get_pyerr failed at PyErr_Fetch");
87  }
88  }
89  PyErr_Clear(); // in case could not turn pvalue into c_str.
90  Py_XDECREF(ptype);
91  Py_XDECREF(pvalue);
92  Py_XDECREF(ptraceback);
93  return str_;
94  }
95 
96  private:
100 
101  char* str_;
103 };
104 
105 
106 class PyLockGIL {
107  public:
109  : state_(PyGILState_Ensure())
110  , locked_(true) {}
111 
112  /* This is mainly used to unlock manually prior to a hoc_execerror() call
113  * since this uses longjmp()
114  */
115  void release() {
116  assert(locked_);
117  locked_ = false;
118  PyGILState_Release(state_);
119  }
120 
122  release();
123  }
124 
125  private:
128 
129  PyGILState_STATE state_;
130  bool locked_; /* check if double unlocking */
131 };
132 
133 extern void nrnpy_sec_referr();
134 #define CHECK_SEC_INVALID(sec) \
135  { \
136  if (!sec->prop) { \
137  nrnpy_sec_referr(); \
138  return NULL; \
139  } \
140  }
141 
142 #endif /* end of include guard: nrnpy_utils_h */
short type
Definition: cabvars.h:9
bool disable_release_
Definition: nrnpy_utils.h:102
Py2NRNString(PyObject *python_string, bool disable_release=false)
Definition: nrnpy_utils.h:13
bool err() const
Definition: nrnpy_utils.h:45
char * c_str() const
Definition: nrnpy_utils.h:42
Py2NRNString(const Py2NRNString &)
Py2NRNString & operator=(const Py2NRNString &)
void set_pyerr(PyObject *type, const char *message)
Definition: nrnpy_utils.h:48
char * get_pyerr()
Definition: nrnpy_utils.h:66
PyLockGIL(const PyLockGIL &)
PyLockGIL & operator=(const PyLockGIL &)
void release()
Definition: nrnpy_utils.h:115
bool locked_
Definition: nrnpy_utils.h:130
PyGILState_STATE state_
Definition: nrnpy_utils.h:129
#define assert(ex)
Definition: hocassrt.h:32
void nrnpy_sec_referr()
Definition: nrnpy_nrn.cpp:135
bool is_python_string(PyObject *python_string)
Definition: nrnpy_utils.h:7
#define NULL
Definition: sptree.h:16