Panda3D
Loading...
Searching...
No Matches
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 */
19template<class T> INLINE bool
20DtoolInstance_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 */
44template<class T> INLINE bool
45DtoolInstance_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 */
65INLINE 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 */
75INLINE 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 */
88INLINE 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 */
96ALWAYS_INLINE void
97Dtool_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 */
109INLINE 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 */
123template<class T> INLINE PyObject *
124DTool_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
130template<class T> INLINE PyObject *
131DTool_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
137template<class T> INLINE PyObject *
138DTool_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
144template<class T> INLINE PyObject *
145DTool_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 */
154INLINE int
155DTool_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 */
166ALWAYS_INLINE bool
167Dtool_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 */
174ALWAYS_INLINE bool
175Dtool_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 */
183ALWAYS_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
191ALWAYS_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
205ALWAYS_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
213ALWAYS_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
223ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value) {
224 return PyLong_FromLongLong(value);
225}
226
227ALWAYS_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
239ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value) {
240 PyObject *result = (value ? Py_True : Py_False);
241 Py_INCREF(result);
242 return result;
243}
244
245ALWAYS_INLINE PyObject *Dtool_WrapValue(double value) {
246 return PyFloat_FromDouble(value);
247}
248
249ALWAYS_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
262ALWAYS_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
271ALWAYS_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
279ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value) {
280 return PyUnicode_FromWideChar(value.data(), (Py_ssize_t)value.length());
281}
282
283ALWAYS_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
296ALWAYS_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
305ALWAYS_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
313ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value) {
314 return PyUnicode_FromWideChar(&value, 1);
315}
316
317ALWAYS_INLINE PyObject *Dtool_WrapValue(std::nullptr_t) {
318 Py_INCREF(Py_None);
319 return Py_None;
320}
321
322ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value) {
323 return value;
324}
325
326ALWAYS_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
335ALWAYS_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
344template<class T1, class T2>
345ALWAYS_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 * Dtool_WrapValue(int value)
The following functions wrap an arbitrary C++ value into a PyObject.
Definition py_panda.I:183
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
PyObject * DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op)
Rich comparison function that compares objects by pointer.
Definition py_panda.I:88
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