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 { return str_; }
43  inline bool err() const { return str_ == NULL; }
44  inline void set_pyerr(PyObject* type, const char* message) {
45  PyObject* ptype = NULL;
46  PyObject* pvalue = NULL;
47  PyObject* ptraceback = NULL;
48  if (err()) {
49  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
50  }
51  if (pvalue && ptype) {
52  PyObject* umes = PyUnicode_FromFormat("%s (Note: %S: %S)", message, ptype, pvalue);
53  PyErr_SetObject(type, umes); // umes is borrowed reference
54  Py_XDECREF(umes);
55  }else{
56  PyErr_SetString(type, message);
57  }
58  Py_XDECREF(ptype);
59  Py_XDECREF(pvalue);
60  Py_XDECREF(ptraceback);
61  }
62  inline char* get_pyerr() {
63  PyObject* ptype = NULL;
64  PyObject* pvalue = NULL;
65  PyObject* ptraceback = NULL;
66  if (err()) {
67  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
68  if (pvalue) {
69  PyObject* pstr = PyObject_Str(pvalue);
70  if (pstr) {
71  const char* err_msg = PyUnicode_AsUTF8(pstr);
72  if (err_msg) {
73  str_ = strdup(err_msg);
74  } else {
75  str_ = strdup("get_pyerr failed at PyUnicode_AsUTF8");
76  }
77  Py_XDECREF(pstr);
78  } else {
79  str_ = strdup("get_pyerr failed at PyObject_Str");
80  }
81  } else {
82  str_ = strdup("get_pyerr failed at PyErr_Fetch");
83  }
84  }
85  PyErr_Clear(); // in case could not turn pvalue into c_str.
86  Py_XDECREF(ptype);
87  Py_XDECREF(pvalue);
88  Py_XDECREF(ptraceback);
89  return str_;
90  }
91  private:
92  Py2NRNString();
93  Py2NRNString(const Py2NRNString&);
95 
96  char* str_;
98 };
99 
100 
102 {
103 public:
105  : state_(PyGILState_Ensure())
106  , locked_(true)
107  {}
108 
109  /* This is mainly used to unlock manually prior to a hoc_execerror() call
110  * since this uses longjmp()
111  */
112  void release() {
113  assert(locked_);
114  locked_ = false;
115  PyGILState_Release(state_);
116  }
117 
119  release();
120  }
121 
122 private:
123  PyLockGIL(const PyLockGIL&);
124  PyLockGIL& operator=(const PyLockGIL&);
125 
126  PyGILState_STATE state_;
127  bool locked_; /* check if double unlocking */
128 };
129 
130 extern void nrnpy_sec_referr();
131 #define CHECK_SEC_INVALID(sec) {if (!sec->prop) { nrnpy_sec_referr(); return NULL;}}
132 
133 #endif /* end of include guard: nrnpy_utils_h */
#define assert(ex)
Definition: hocassrt.h:26
short type
Definition: cabvars.h:10
return true
Definition: savstate.cpp:357
char * c_str() const
Definition: nrnpy_utils.h:42
Py2NRNString(PyObject *python_string, bool disable_release=false)
Definition: nrnpy_utils.h:13
Py2NRNString & operator=(const Py2NRNString &)
char * str_
Definition: nrnpy_utils.h:96
void nrnpy_sec_referr()
Definition: nrnpy_nrn.cpp:135
void release()
Definition: nrnpy_utils.h:112
bool is_python_string(PyObject *python_string)
Definition: nrnpy_utils.h:7
PyGILState_STATE state_
Definition: nrnpy_utils.h:126
virtual void release(const Event &e)
Definition: ocinput.h:22
bool err() const
Definition: nrnpy_utils.h:43
void set_pyerr(PyObject *type, const char *message)
Definition: nrnpy_utils.h:44
return NULL
Definition: cabcode.cpp:461
char * get_pyerr()
Definition: nrnpy_utils.h:62
bool locked_
Definition: nrnpy_utils.h:127
bool disable_release_
Definition: nrnpy_utils.h:97