Panda3D
py_compat.h
Go to the documentation of this file.
1 /**
2  * @file py_compat.h
3  * @author rdb
4  * @date 2017-12-02
5  */
6 
7 #ifndef PY_COMPAT_H
8 #define PY_COMPAT_H
9 
10 #include "dtoolbase.h"
11 
12 #ifdef HAVE_PYTHON
13 
14 // The contents of this file were originally part of py_panda.h. It
15 // specifically contains polyfills that are required to maintain compatibility
16 // with Python 2 and older versions of Python 3.
17 
18 // These compatibility hacks are sorted by Python version that removes the
19 // need for the respective hack.
20 
21 #ifdef _POSIX_C_SOURCE
22 # undef _POSIX_C_SOURCE
23 #endif
24 
25 #ifdef _XOPEN_SOURCE
26 # undef _XOPEN_SOURCE
27 #endif
28 
29 // See PEP 353
30 #define PY_SSIZE_T_CLEAN 1
31 
32 #include <Python.h>
33 
34 #ifndef LINK_ALL_STATIC
35 # define EXPCL_PYPANDA
36 #elif defined(__GNUC__)
37 # define EXPCL_PYPANDA __attribute__((weak))
38 #else
39 # define EXPCL_PYPANDA extern inline
40 #endif
41 
42 /* Python 2.4 */
43 
44 // 2.4 macros which aren't available in 2.3
45 #ifndef Py_RETURN_NONE
46 # define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
47 #endif
48 
49 #ifndef Py_RETURN_TRUE
50 # define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
51 #endif
52 
53 #ifndef Py_RETURN_FALSE
54 # define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
55 #endif
56 
57 /* Python 2.5 */
58 
59 // Prior to Python 2.5, we didn't have Py_ssize_t.
60 #if PY_VERSION_HEX < 0x02050000
61 typedef int Py_ssize_t;
62 # define PyInt_FromSsize_t PyInt_FromLong
63 # define PyInt_AsSsize_t PyInt_AsLong
64 #endif
65 
66 /* Python 2.6 */
67 
68 #ifndef Py_TYPE
69 # define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
70 #endif
71 
72 /* Python 2.7, 3.1 */
73 
74 #ifndef PyVarObject_HEAD_INIT
75  #define PyVarObject_HEAD_INIT(type, size) \
76  PyObject_HEAD_INIT(type) size,
77 #endif
78 
79 /* Python 2.7, 3.2 */
80 
81 #if PY_VERSION_HEX < 0x03020000
82 # define PyErr_NewExceptionWithDoc(name, doc, base, dict) \
83  PyErr_NewException(name, base, dict)
84 #endif
85 
86 /* Python 3.0 */
87 
88 // Always on in Python 3
89 #ifndef Py_TPFLAGS_CHECKTYPES
90 # define Py_TPFLAGS_CHECKTYPES 0
91 #endif
92 
93 // Macros for writing code that will compile in both versions.
94 #if PY_MAJOR_VERSION >= 3
95 # define nb_nonzero nb_bool
96 # define nb_divide nb_true_divide
97 # define nb_inplace_divide nb_inplace_true_divide
98 
99 # define PyLongOrInt_Check(x) PyLong_Check(x)
100 # define PyLongOrInt_AS_LONG PyLong_AS_LONG
101 # define PyInt_Check PyLong_Check
102 # define PyInt_AsLong PyLong_AsLong
103 # define PyInt_AS_LONG PyLong_AS_LONG
104 # define PyLongOrInt_AsSize_t PyLong_AsSize_t
105 #else
106 # define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
107 // PyInt_FromSize_t automatically picks the right type.
108 # define PyLongOrInt_AS_LONG PyInt_AsLong
109 
110 EXPCL_PYPANDA size_t PyLongOrInt_AsSize_t(PyObject *);
111 #endif
112 
113 // Which character to use in PyArg_ParseTuple et al for a byte string.
114 #if PY_MAJOR_VERSION >= 3
115 # define FMTCHAR_BYTES "y"
116 #else
117 # define FMTCHAR_BYTES "s"
118 #endif
119 
120 /* Python 3.2 */
121 
122 #if PY_VERSION_HEX < 0x03020000
123 typedef long Py_hash_t;
124 #endif
125 
126 /* Python 3.3 */
127 
128 #if PY_MAJOR_VERSION >= 3
129 // Python 3 versions before 3.3.3 defined this incorrectly.
130 # undef _PyErr_OCCURRED
131 # define _PyErr_OCCURRED() (PyThreadState_GET()->curexc_type)
132 
133 // Python versions before 3.3 did not define this.
134 # if PY_VERSION_HEX < 0x03030000
135 # define PyUnicode_AsUTF8 _PyUnicode_AsString
136 # define PyUnicode_AsUTF8AndSize _PyUnicode_AsStringAndSize
137 # endif
138 #endif
139 
140 /* Python 3.6 */
141 
142 #ifndef _PyObject_CallNoArg
143 INLINE PyObject *_PyObject_CallNoArg(PyObject *func) {
144  static PyTupleObject empty_tuple = {PyVarObject_HEAD_INIT(nullptr, 0)};
145 #ifdef Py_TRACE_REFS
146  _Py_AddToAllObjects((PyObject *)&empty_tuple, 0);
147 #endif
148  return PyObject_Call(func, (PyObject *)&empty_tuple, nullptr);
149 }
150 # define _PyObject_CallNoArg _PyObject_CallNoArg
151 #endif
152 
153 #ifndef _PyObject_FastCall
154 INLINE PyObject *_PyObject_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs) {
155  PyObject *tuple = PyTuple_New(nargs);
156  for (Py_ssize_t i = 0; i < nargs; ++i) {
157  PyTuple_SET_ITEM(tuple, i, args[i]);
158  Py_INCREF(args[i]);
159  }
160  PyObject *result = PyObject_Call(func, tuple, nullptr);
161  Py_DECREF(tuple);
162  return result;
163 }
164 # define _PyObject_FastCall _PyObject_FastCall
165 #endif
166 
167 // Python versions before 3.6 didn't require longlong support to be enabled.
168 #ifndef HAVE_LONG_LONG
169 # define PyLong_FromLongLong(x) PyLong_FromLong((long) (x))
170 # define PyLong_FromUnsignedLongLong(x) PyLong_FromUnsignedLong((unsigned long) (x))
171 # define PyLong_AsLongLong(x) PyLong_AsLong(x)
172 # define PyLong_AsUnsignedLongLong(x) PyLong_AsUnsignedLong(x)
173 # define PyLong_AsUnsignedLongLongMask(x) PyLong_AsUnsignedLongMask(x)
174 # define PyLong_AsLongLongAndOverflow(x) PyLong_AsLongAndOverflow(x)
175 #endif
176 
177 /* Python 3.7 */
178 
179 #ifndef PyDict_GET_SIZE
180 # define PyDict_GET_SIZE(mp) (((PyDictObject *)mp)->ma_used)
181 #endif
182 
183 #ifndef Py_RETURN_RICHCOMPARE
184 # define Py_RETURN_RICHCOMPARE(val1, val2, op) \
185  do { \
186  switch (op) { \
187  NODEFAULT \
188  case Py_EQ: if ((val1) == (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
189  case Py_NE: if ((val1) != (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
190  case Py_LT: if ((val1) < (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
191  case Py_GT: if ((val1) > (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
192  case Py_LE: if ((val1) <= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
193  case Py_GE: if ((val1) >= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
194  } \
195  } while (0)
196 #endif
197 
198 /* Other Python implementations */
199 
200 // _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.
201 // Some implementations of the CPython API (e.g. PyPy's cpyext) do not define
202 // it, so in these cases we just silently fall back to PyErr_Occurred.
203 #ifndef _PyErr_OCCURRED
204 # define _PyErr_OCCURRED() PyErr_Occurred()
205 #endif
206 
207 #endif // HAVE_PYTHON
208 
209 #endif // PY_COMPAT_H
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.