Extending Python with C or C++

Wrapping a C library in Python.

Environment

Install Python.h

$ sudo apt-get install python2.7-dev

Code

// spammodule.c
#include <Python.h>

#ifdef __cplusplus
extern "C" {
#endif

static PyObject* SpamError;

static PyObject* spam_system(PyObject* self, PyObject* args) {
  const char* command;
  int sts;

  if (!PyArg_ParseTuple(args, "s", &command)) {
    return NULL;
  }
  sts = system(command);
  if (sts != 0) {
    PyErr_SetString(SpamError, "System command failed");
    return NULL;
  }
  return PyLong_FromLong(sts);
}

static PyMethodDef SpamMethods[] = {
    {"system", spam_system, METH_VARARGS, "Execute a shell command."},
    {NULL, NULL, 0, NULL}  // Sentinel
};

void initspammodule(void) {
  PyObject* m = Py_InitModule("spammodule", SpamMethods);
  if (m == NULL) {
    return;
  }

  SpamError = PyErr_NewException("spammodule.error", NULL, NULL);
  Py_INCREF(SpamError);
  PyModule_AddObject(m, "error", SpamError);
}

#ifdef __cplusplus
}
#endif

Build

$ gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c spammodule.c -o spammodule.o
$ gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro spammodule.o -o spammodule.so

Test

$ python
>>> import spammodule
>>> spammodule.system('uname')
Linux
0L
>>> spammodule.system('bad command')
sh: 1: bad: not found
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
spammodule.error: System command failed