101 Python and C extension modules
This is a little example of how to develop a C extension module for Python. Python provides the possibility to extend its power developing code in C.
The example shows a simple maths module (called simplemaths), with methods: add, subtract, multiplicate and divide two integer numbers. All functions are developed using C code. We will call these C functions from Python.
With the possibility to extend Python functionalities using C code, we can harness the power and performance features of C language, this is only a little example that how we can do it.
We are going to develop a new module for Python called simplemaths. The module has four methods add(a,b), sub(a,b), mult(a,b), div(a,b).
The new module allows us to use C functions as a Python method. For example:
import simplemaths as mathsresult = maths.add(1000,2)
print(result)
Step 1: Developing the C code
We have to create a C file to write our code. The file will be maths.c.
Note: We are going to use the development of the add() function to show how to create the methods.
#include <Python.h>
#include <stdio.h>static PyObject *simplemathsError;PyObject *add(PyObject *self,PyObject *args)
{
int a, b, result; if(!PyArg_ParseTuple(args,”ii”,&a,&b)) {
PyErr_SetString(simplemathsError,”You have to enter two values”);
return NULL;
} result = a + b;
return Py_BuildValue(“i”,result);
}
We need to use Python.h library to have access to the objects and functions needed for the development of C extension.
The PyObject is a data structure to define a common and generic way to pass information between Python and C and vice-versa. How you can see we define a C function called add() with two parameters, the parameter *self is used only if we are going to create a built-in method, in this case, is NULL, because of we are going to create a function. The second parameter is *arg and this is used to pass our arguments from Python to C function.
We use the function PyArg_ParseTuple(args, “ii”, &a, &b) to get our parameters (two integers) passed from Python, “ii” means that two integers will be passed to the function, finally, the values are loaded in a and b. If there is a problem with the arguments we will return a message.
After sum result = a + b, we have to return the result. For this, we use the function PyBuildValue(“i”, result) to build an integer (“i”) value and return the result to Python.
The rest of the operations are the same.
Now we have to configure the module. In the same file at the end, we have to write the next code:
static PyMethodDef Methods[] = {
{"add",add,METH_VARARGS,"add two integer numbers"},
{"sub",sub,METH_VARARGS,"sub two integer numbers"},
{"mult",mult,METH_VARARGS,"mult integer two numbers"},
{"div",divide,METH_VARARGS,"divide integer two numbers"},
{NULL,NULL,0,NULL}
};
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"simplemaths",
NULL,
sizeof(struct module_state),
Methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit_simplemaths(void)
#else
void initsimplemaths(void)
#endif
{
simplemathsError = PyErr_NewException("simplemaths.simplemathsError",
NULL,NULL);#if PY_MAJOR_VERSION >= 3
PyObject *mod = PyModule_Create(&moduledef);
return mod;
#else
Py_InitModule("simplemaths",Methods);
#endif
}
This code will allow initializing the module. We use directives and PY_MAJOR_VERSION to indicate to the compiler build the program depending on the version of Python. This code will be compatible with Python 2 and 3.
Step 2: Setting the module
To build and install the module we have to create a setup.py file.
from distutils.core import setup, Extensionmodule=Extension('simplemaths',sources=['maths.c'])
setup(name='simplemaths',
version='1.0',
description='Simple C Maths',
author='Your name',
author_email='youremail',
ext_modules = [module,])
Step 3: Building and Installing the module
Now, we can build and install the module inside our Python environment. We just execute the next command:
$ sudo python setup.py install
This command will compile and install a new module called simplemaths inside the Python Interpreter.
Step 4: Testing the module
To test the module simplemaths we may execute the Python Interactive mode:
$ python
[GCC 6.4.1 20170727 (Red Hat 6.4.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import simplemaths as maths
>>> maths.add(10,10)
20
>>> maths.sub(10,11)
-1
>>> maths.mult(10,10)
100
>>> maths.div(10,2)
5
>>>
Conclusion
I think the possibility to use C inside Python in a clear and transparent way allows us to get the best of both worlds.
To get the entire code used to explain how to develop a new C module for Python go to the Github repository simplemaths.
If you want to see a little more complex example go to orderC example. This is an example of how to implements a Python module with sort functions written in C to order a list of integers.
And if you really want to see an entire module go to pyEtherIP. This is a Python module that implements an IP sniffer.