PCB Environment 2
Loading...
Searching...
No Matches
Py.hpp
1
2#ifndef GYM_PCB_PY_H
3#define GYM_PCB_PY_H
4
5#define PY_ONLY(args...) args
6
7#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
8#define NO_IMPORT_ARRAY
9#define PY_ARRAY_UNIQUE_SYMBOL _pcbenv2_module_PyArray_API
10#include <numpy/ndarrayobject.h>
11
12#include "Geometry.hpp"
13
14namespace py
15{
16
18
19template<typename Ty = PyObject>
20inline Ty *ValueError(const char *s)
21{
22 PyErr_SetString(PyExc_ValueError, s);
23 return 0;
24}
25template<typename Ty = PyObject>
26inline Ty *MemoryError(const char *s)
27{
28 PyErr_SetString(PyExc_MemoryError, s);
29 return 0;
30}
31template<typename Ty = PyObject>
32inline Ty *Exception(PyObject *exc, const char *s)
33{
34 PyErr_SetString(exc, s);
35 return 0;
36}
37inline PyObject *Exception(const std::exception &e)
38{
39 PyErr_SetString(PyExc_Exception, e.what());
40 return 0;
41}
42
43
45
46inline PyObject *String(const char *s)
47{
48 return PyUnicode_FromString(s);
49}
50inline PyObject *String(const std::string &s)
51{
52 return PyUnicode_FromStringAndSize(s.c_str(), s.size());
53}
54
55
57
58inline bool TupleN_Check(PyObject *py, uint n)
59{
60 return PyTuple_Check(py) && PyTuple_Size(py) == n;
61}
62inline bool TupleMin_Check(PyObject *py, uint n)
63{
64 return PyTuple_Check(py) && PyTuple_Size(py) >= n;
65}
66
67inline double Number_AsDouble(PyObject *py)
68{
69 if (PyFloat_Check(py))
70 return PyFloat_AsDouble(py);
71 auto F = PyNumber_Float(py);
72 assert(F);
73 if (!F)
74 return std::numeric_limits<double>::quiet_NaN();
75 auto d = PyFloat_AsDouble(F);
76 Py_DECREF(F);
77 return d;
78}
79
80inline bool String_Check(PyObject *py)
81{
82 return py && PyUnicode_Check(py);
83}
84inline std::string String_AsStdString(PyObject *py)
85{
86#if PY_VERSION_HEX >= 0x03030000
87 return std::string(PyUnicode_AsUTF8(py));
88#else
89#error "Python version < 3.3 not supported, go upgrade!"
90#endif
91}
92inline std::string_view String_AsStringView(PyObject *py)
93{
94#if PY_VERSION_HEX >= 0x03030000
95 Py_ssize_t size;
96 const char *ucs = PyUnicode_AsUTF8AndSize(py, &size);
97 return std::string_view(ucs, size);
98#else
99#error "Python version < 3.3 not supported, go upgrade!"
100#endif
101}
102
103inline std::string String_AsStdString(PyObject *py, const char *error)
104{
105 if (!String_Check(py))
106 throw std::invalid_argument(error);
107 return String_AsStdString(py);
108}
109
110inline void Dict_StealItemString(PyObject *dict, const char *key, PyObject *v)
111{
112 PyDict_SetItemString(dict, key, v);
113 Py_DECREF(v);
114}
115inline void Dict_StealItem(PyObject *dict, PyObject *key, PyObject *v)
116{
117 PyDict_SetItem(dict, key, v);
118 Py_DECREF(v);
119}
120
121inline void DECREF_safe(PyObject *v)
122{
123 if (v)
124 Py_DECREF(v);
125}
126
127inline PyObject *None()
128{
129 Py_INCREF(Py_None);
130 return Py_None;
131}
132
133inline PyObject *NewRef(PyObject *py)
134{
135 Py_INCREF(py);
136 return py;
137}
138
139
140// SAFETY
141
143class GIL_guard
144{
145public:
146 GIL_guard()
147 {
148 state = PyGILState_Ensure();
149 }
150 ~GIL_guard()
151 {
152 PyGILState_Release(state);
153 }
154 GIL_guard(GIL_guard&& moved) noexcept : state(moved.state)
155 {
156 moved.state = PyGILState_UNLOCKED;
157 }
158 GIL_guard& operator=(GIL_guard&& moved) noexcept
159 {
160 if (this != &moved) {
161 PyGILState_Release(state);
162 state = moved.state;
163 moved.state = PyGILState_UNLOCKED;
164 }
165 return *this;
166 }
167 GIL_guard(const GIL_guard&) = delete;
168
169private:
170 PyGILState_STATE state;
171};
172
173} // namespace py
174
175#include "PyObject.hpp"
176
177#endif // GYM_PCB_PY_H