+/**
+ * collectd - src/cpython.h
+ * Copyright (C) 2009 Sven Trenkel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Sven Trenkel <collectd at semidefinite.de>
+ **/
+
/* These two macros are basicly Py_BEGIN_ALLOW_THREADS and Py_BEGIN_ALLOW_THREADS
* from the other direction. If a Python thread calls a C function
* Py_BEGIN_ALLOW_THREADS is used to allow other python threads to run because
} while (0)
#endif
+/* Python 2.4 has this macro, older versions do not. */
+#ifndef Py_RETURN_NONE
+# define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+/* This macro is a shortcut for calls like
+ * x = PyObject_Repr(x);
+ * This can't be done like this example because this would leak
+ * a reference the the original x and crash in case of x == NULL.
+ * This calling syntax is less than elegant but it works, saves
+ * a lot of lines and avoids potential refcount errors. */
+
+#define CPY_SUBSTITUTE(func, a, ...) do {\
+ if ((a) != NULL) {\
+ PyObject *__tmp = (a);\
+ (a) = func(__VA_ARGS__);\
+ Py_DECREF(__tmp);\
+ }\
+} while(0)
+
+/* Python3 compatibility layer. To keep the actual code as clean as possible
+ * do a lot of defines here. */
+
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#endif
+
+#ifdef IS_PY3K
+
+#define PyInt_FromLong PyLong_FromLong
+#define CPY_INIT_TYPE PyVarObject_HEAD_INIT(NULL, 0)
+#define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyBytes_Check(o))
+#define CPY_STRCAT PyUnicode_Concat
+
+#else
+
+#define CPY_INIT_TYPE PyObject_HEAD_INIT(NULL) 0,
+#define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyString_Check(o))
+#define CPY_STRCAT PyString_Concat
+
+#endif
+
+static inline const char *cpy_unicode_or_bytes_to_string(PyObject **o) {
+ if (PyUnicode_Check(*o)) {
+ PyObject *tmp;
+ tmp = PyUnicode_AsEncodedString(*o, NULL, NULL); /* New reference. */
+ if (tmp == NULL)
+ return NULL;
+ Py_DECREF(*o);
+ *o = tmp;
+ }
+ return PyBytes_AsString(*o);
+}
+
+static inline PyObject *cpy_string_to_unicode_or_bytes(const char *buf) {
+#ifdef IS_PY3K
+/* Python3 preferrs unicode */
+ PyObject *ret;
+ ret = PyUnicode_Decode(buf, strlen(buf), NULL, NULL);
+ if (ret != NULL)
+ return ret;
+ PyErr_Clear();
+#endif
+ return PyBytes_FromString(buf);
+}
+
+ /* Python object declarations. */
+
typedef struct {
PyObject_HEAD /* No semicolon! */
PyObject *parent; /* Config */