Panda3D
py_panda.I
Go to the documentation of this file.
1 /**
2  * @file py_panda.I
3  * @author rdb
4  * @date 2016-06-06
5  */
6 
7 #ifdef _MSC_VER
8 #define _IS_FINAL(T) (__is_sealed(T))
9 #elif defined(__GNUC__)
10 #define _IS_FINAL(T) (__is_final(T))
11 #else
12 #define _IS_FINAL(T) (0)
13 #endif
14 
15 /**
16  * Template function that can be used to extract any TypedObject pointer from
17  * a wrapped Python object.
18  */
19 template<class T> INLINE bool
20 DtoolInstance_GetPointer(PyObject *self, T *&into) {
21  if (DtoolInstance_Check(self)) {
22  Dtool_PyTypedObject *target_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
23  if (target_class != nullptr) {
24  if (_IS_FINAL(T)) {
25  if (DtoolInstance_TYPE(self) == target_class) {
26  into = (T *)DtoolInstance_VOID_PTR(self);
27  } else {
28  return false;
29  }
30  } else {
31  into = (T *)DtoolInstance_UPCAST(self, *target_class);
32  }
33  return (into != nullptr);
34  }
35  }
36  into = nullptr;
37  return false;
38 }
39 
40 /**
41  * Template function that can be used to extract any TypedObject pointer from
42  * a wrapped Python object. In this case, the Dtool_PyTypedObject is known.
43  */
44 template<class T> INLINE bool
45 DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &target_class) {
46  if (DtoolInstance_Check(self)) {
47  if (_IS_FINAL(T)) {
48  if (DtoolInstance_TYPE(self) == &target_class) {
49  into = (T *)DtoolInstance_VOID_PTR(self);
50  } else {
51  return false;
52  }
53  } else {
54  into = (T *)DtoolInstance_UPCAST(self, target_class);
55  }
56  return (into != nullptr);
57  }
58  into = nullptr;
59  return false;
60 }
61 
62 /**
63  * Function to create a hash from a wrapped Python object.
64  */
65 INLINE Py_hash_t DtoolInstance_HashPointer(PyObject *self) {
66  if (self != nullptr && DtoolInstance_Check(self)) {
67  return (Py_hash_t)(intptr_t)DtoolInstance_VOID_PTR(self);
68  }
69  return -1;
70 }
71 
72 /**
73  * Python 2-style comparison function that compares objects by pointer.
74  */
75 INLINE int DtoolInstance_ComparePointers(PyObject *v1, PyObject *v2) {
76  void *v1_this = DtoolInstance_Check(v1) ? DtoolInstance_VOID_PTR(v1) : nullptr;
77  void *v2_this = DtoolInstance_Check(v2) ? DtoolInstance_VOID_PTR(v2) : nullptr;
78  if (v1_this != nullptr && v2_this != nullptr) {
79  return (v1_this > v2_this) - (v1_this < v2_this);
80  } else {
81  return (v1 > v2) - (v1 < v2);
82  }
83 }
84 
85 /**
86  * Rich comparison function that compares objects by pointer.
87  */
88 INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op) {
89  int cmpval = DtoolInstance_ComparePointers(v1, v2);
90  Py_RETURN_RICHCOMPARE(cmpval, 0, op);
91 }
92 
93 /**
94  * Utility function for assigning a PyObject pointer while managing refcounts.
95  */
96 ALWAYS_INLINE void
97 Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value) {
98  PyObject *prev_value = ptr;
99  if (prev_value != value) {
100  Py_XINCREF(value);
101  ptr = value;
102  Py_XDECREF(prev_value);
103  }
104 }
105 
106 /**
107  * Converts the enum value to a C long.
108  */
109 INLINE long Dtool_EnumValue_AsLong(PyObject *value) {
110  PyObject *val = PyObject_GetAttrString(value, "value");
111  if (val != nullptr) {
112  long as_long = PyLongOrInt_AS_LONG(val);
113  Py_DECREF(val);
114  return as_long;
115  } else {
116  return -1;
117  }
118 }
119 
120 /**
121  * These functions wrap a pointer for a class that defines get_type_handle().
122  */
123 template<class T> INLINE PyObject *
124 DTool_CreatePyInstance(const T *obj, bool memory_rules) {
125  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
126  nassertr(known_class != nullptr, nullptr);
127  return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true);
128 }
129 
130 template<class T> INLINE PyObject *
131 DTool_CreatePyInstance(T *obj, bool memory_rules) {
132  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
133  nassertr(known_class != nullptr, nullptr);
134  return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false);
135 }
136 
137 template<class T> INLINE PyObject *
138 DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) {
139  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
140  nassertr(known_class != nullptr, nullptr);
141  return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index());
142 }
143 
144 template<class T> INLINE PyObject *
145 DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) {
146  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
147  nassertr(known_class != nullptr, nullptr);
148  return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index());
149 }
150 
151 /**
152  * Finishes initializing the Dtool_PyInstDef.
153  */
154 INLINE int
155 DTool_PyInit_Finalize(PyObject *self, void *local_this, Dtool_PyTypedObject *type, bool memory_rules, bool is_const) {
156  ((Dtool_PyInstDef *)self)->_My_Type = type;
157  ((Dtool_PyInstDef *)self)->_ptr_to_object = local_this;
158  ((Dtool_PyInstDef *)self)->_memory_rules = memory_rules;
159  ((Dtool_PyInstDef *)self)->_is_const = is_const;
160  return 0;
161 }
162 
163 /**
164  * Checks that the tuple is empty.
165  */
166 ALWAYS_INLINE bool
167 Dtool_CheckNoArgs(PyObject *args) {
168  return PyTuple_GET_SIZE(args) == 0;
169 }
170 
171 /**
172  * Checks that the tuple is empty, and that the dict is empty or NULL.
173  */
174 ALWAYS_INLINE bool
175 Dtool_CheckNoArgs(PyObject *args, PyObject *kwds) {
176  return PyTuple_GET_SIZE(args) == 0 &&
177  (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0);
178 }
179 
180 /**
181  * The following functions wrap an arbitrary C++ value into a PyObject.
182  */
183 ALWAYS_INLINE PyObject *Dtool_WrapValue(int value) {
184 #if PY_MAJOR_VERSION >= 3
185  return PyLong_FromLong((long)value);
186 #else
187  return PyInt_FromLong((long)value);
188 #endif
189 }
190 
191 ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned int value) {
192 #if PY_MAJOR_VERSION >= 3 && SIZEOF_INT < SIZEOF_LONG
193  return PyLong_FromLong((long)value);
194 #elif PY_MAJOR_VERSION >= 3
195  return PyLong_FromUnsignedLong((unsigned long)value);
196 #elif SIZEOF_INT < SIZEOF_LONG
197  return PyInt_FromLong((long)value);
198 #else
199  return (value > LONG_MAX)
200  ? PyLong_FromUnsignedLong((unsigned long)value)
201  : PyInt_FromLong((long)value);
202 #endif
203 }
204 
205 ALWAYS_INLINE PyObject *Dtool_WrapValue(long value) {
206 #if PY_MAJOR_VERSION >= 3
207  return PyLong_FromLong(value);
208 #else
209  return PyInt_FromLong(value);
210 #endif
211 }
212 
213 ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long value) {
214 #if PY_MAJOR_VERSION >= 3
215  return PyLong_FromUnsignedLong(value);
216 #else
217  return (value > LONG_MAX)
218  ? PyLong_FromUnsignedLong(value)
219  : PyInt_FromLong((long)value);
220 #endif
221 }
222 
223 ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value) {
224  return PyLong_FromLongLong(value);
225 }
226 
227 ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value) {
228  // size_t is sometimes defined as unsigned long long, and we want to map
229  // that to int in Python 2 so it can be returned from a __len__.
230 #if PY_MAJOR_VERSION >= 3
231  return PyLong_FromUnsignedLongLong(value);
232 #else
233  return (value > LONG_MAX)
234  ? PyLong_FromUnsignedLongLong(value)
235  : PyInt_FromLong((long)value);
236 #endif
237 }
238 
239 ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value) {
240  PyObject *result = (value ? Py_True : Py_False);
241  Py_INCREF(result);
242  return result;
243 }
244 
245 ALWAYS_INLINE PyObject *Dtool_WrapValue(double value) {
246  return PyFloat_FromDouble(value);
247 }
248 
249 ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value) {
250  if (value == nullptr) {
251  Py_INCREF(Py_None);
252  return Py_None;
253  } else {
254 #if PY_MAJOR_VERSION >= 3
255  return PyUnicode_FromString(value);
256 #else
257  return PyString_FromString(value);
258 #endif
259  }
260 }
261 
262 ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value) {
263  if (value == nullptr) {
264  Py_INCREF(Py_None);
265  return Py_None;
266  } else {
267  return PyUnicode_FromWideChar(value, (Py_ssize_t)wcslen(value));
268  }
269 }
270 
271 ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string &value) {
272 #if PY_MAJOR_VERSION >= 3
273  return PyUnicode_FromStringAndSize(value.data(), (Py_ssize_t)value.length());
274 #else
275  return PyString_FromStringAndSize(value.data(), (Py_ssize_t)value.length());
276 #endif
277 }
278 
279 ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value) {
280  return PyUnicode_FromWideChar(value.data(), (Py_ssize_t)value.length());
281 }
282 
283 ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value) {
284  if (value == nullptr) {
285  Py_INCREF(Py_None);
286  return Py_None;
287  } else {
288 #if PY_MAJOR_VERSION >= 3
289  return PyUnicode_FromStringAndSize(value->data(), (Py_ssize_t)value->length());
290 #else
291  return PyString_FromStringAndSize(value->data(), (Py_ssize_t)value->length());
292 #endif
293  }
294 }
295 
296 ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value) {
297  if (value == nullptr) {
298  Py_INCREF(Py_None);
299  return Py_None;
300  } else {
301  return PyUnicode_FromWideChar(value->data(), (Py_ssize_t)value->length());
302  }
303 }
304 
305 ALWAYS_INLINE PyObject *Dtool_WrapValue(char value) {
306 #if PY_MAJOR_VERSION >= 3
307  return PyUnicode_FromStringAndSize(&value, 1);
308 #else
309  return PyString_FromStringAndSize(&value, 1);
310 #endif
311 }
312 
313 ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value) {
314  return PyUnicode_FromWideChar(&value, 1);
315 }
316 
317 ALWAYS_INLINE PyObject *Dtool_WrapValue(std::nullptr_t) {
318  Py_INCREF(Py_None);
319  return Py_None;
320 }
321 
322 ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value) {
323  return value;
324 }
325 
326 ALWAYS_INLINE PyObject *Dtool_WrapValue(const vector_uchar &value) {
327 #if PY_MAJOR_VERSION >= 3
328  return PyBytes_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
329 #else
330  return PyString_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
331 #endif
332 }
333 
334 #if PY_MAJOR_VERSION >= 0x02060000
335 ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value) {
336  if (value == nullptr) {
337  return value;
338  } else {
339  return PyMemoryView_FromBuffer(value);
340  }
341 }
342 #endif
343 
344 template<class T1, class T2>
345 ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair<T1, T2> &value) {
346  PyObject *tuple = PyTuple_New(2);
347  PyTuple_SET_ITEM(tuple, 0, Dtool_WrapValue(value.first));
348  PyTuple_SET_ITEM(tuple, 1, Dtool_WrapValue(value.second));
349  return tuple;
350 }
bool Dtool_CheckNoArgs(PyObject *args)
Checks that the tuple is empty.
Definition: py_panda.I:167
int DtoolInstance_ComparePointers(PyObject *v1, PyObject *v2)
Python 2-style comparison function that compares objects by pointer.
Definition: py_panda.I:75
PyObject * DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op)
Rich comparison function that compares objects by pointer.
Definition: py_panda.I:88
int DTool_PyInit_Finalize(PyObject *self, void *local_this, Dtool_PyTypedObject *type, bool memory_rules, bool is_const)
Finishes initializing the Dtool_PyInstDef.
Definition: py_panda.I:155
long Dtool_EnumValue_AsLong(PyObject *value)
Converts the enum value to a C long.
Definition: py_panda.I:109
void Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value)
Utility function for assigning a PyObject pointer while managing refcounts.
Definition: py_panda.I:97
PyObject * DTool_CreatePyInstance(const T *obj, bool memory_rules)
These functions wrap a pointer for a class that defines get_type_handle().
Definition: py_panda.I:124
bool DtoolInstance_GetPointer(PyObject *self, T *&into)
Template function that can be used to extract any TypedObject pointer from a wrapped Python object.
Definition: py_panda.I:20
Py_hash_t DtoolInstance_HashPointer(PyObject *self)
Function to create a hash from a wrapped Python object.
Definition: py_panda.I:65
PyObject * Dtool_WrapValue(int value)
The following functions wrap an arbitrary C++ value into a PyObject.
Definition: py_panda.I:183