Skip to content

Instantly share code, notes, and snippets.

@simonrw
Last active August 29, 2015 14:15
Show Gist options
  • Save simonrw/30771e74f5a63630b035 to your computer and use it in GitHub Desktop.
Save simonrw/30771e74f5a63630b035 to your computer and use it in GitHub Desktop.
Simple boilerplate code for wrapping C code into either python 2 or 3, taken from the porting guide: https://docs.python.org/3/howto/cporting.html
#include "Python.h"
/*********************************************************************************
* Taken from the porting guide: https://docs.python.org/3/howto/cporting.html
*
* Change all occurrences of
* - myextension => the extension name you want to create,
* - error_out => the function(s) you want to wrap
* - METH_NOARGS => METH_VARARGS|METH_KWARGS depending on if the function
* takes keyword arguments or not
*********************************************************************************/
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
static struct module_state _state;
#endif
static PyObject *
error_out(PyObject *m) {
struct module_state *st = GETSTATE(m);
PyErr_SetString(st->error, "something bad happened");
return NULL;
}
static char module_docstring[] = "myextension docstring";
static char error_out_docstring[] = "error_out docstring";
static PyMethodDef myextension_methods[] = {
{"error_out", (PyCFunction)error_out, METH_NOARGS, error_out_docstring},
{NULL, NULL}
};
#if PY_MAJOR_VERSION >= 3
static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
static int myextension_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"myextension",
module_docstring,
sizeof(struct module_state),
myextension_methods,
NULL,
myextension_traverse,
myextension_clear,
NULL
};
#define INITERROR return NULL
PyObject *
PyInit_myextension(void)
#else
#define INITERROR return
void
initmyextension(void)
#endif
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule3("myextension", myextension_methods, module_docstring);
#endif
if (module == NULL)
INITERROR;
struct module_state *st = GETSTATE(module);
st->error = PyErr_NewException("myextension.Error", NULL, NULL);
if (st->error == NULL) {
Py_DECREF(module);
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment