Awasu » Extending Python: A minimal setup
Monday 4th November 2019 4:27 PM []

The main documentation for how to write a Python extension module can be found here.

These tutorials will be using Python 3, on Linux[1]Since that's what all the cool kids are using these days :cool: , but it will all translate to Windows.

We assume that running the command python will run Python 3 i.e.

  
If your system defaults to Python 2, you will need to remember to explicitly run python3 instead.

You will also need the Python development tools installed e.g. on Fedora[2]On other distros, this package may be called python3-dev.:

sudo dnf install python3-devel

Writing the extension

We'll start by writing a minimal extension, which will be a .so file[3]Or DLL, if you're on Windows., that Python can load.

To bootstrap the loading process, it needs a public entry point called PyInit_xxx(), where xxx is the name of the module. Create a file called init.c that looks like this:

#define PY_SSIZE_T_CLEAN
#include <Python.h> /* IMPORTANT: This must come before any standard headers. */

PyMODINIT_FUNC
PyInit_demo()
{
    /* create the Python module */
    PyObject* pModule = PyModule_Create( &gModuleDef ) ;

    return pModule ;
}

The Python.h header file contains all the definitions we need to interact with Python, and as per the documentation, we define PY_SSIZE_T_CLEAN, and include this file before any others.

The Python interpreter will call this function when it loads our module[4]The module is loaded when we execute the import demo command in Python., and we call PyModule_Create() to create a Python object to represent the module, that we return back to the Python interpreter.

We need to supply some basic information about our module, and for this minimal example, all we need is the module name:

static struct PyModuleDef gModuleDef = {
    PyModuleDef_HEAD_INIT,
    "demo",
} ;

Compiling the extension

The easiest way to compile our extension module is to get Python to do it. We just need a setup.py that looks something like this:

from setuptools import setup, Extension

extn = Extension( "demo", sources=["init.c"] )
setup(
    name = "demo",
    ext_modules = [ extn ]
)

We create an Extension object that specifies the name of the module, and the C source files that implement it.

Then, from the command line:

python setup.py build

The final shared library will be placed under the build/ directory, and if we look at its symbol table, we can see our PyInit_demo function there, ready to be called by Python:

  

Testing the extension

To test our new extension module, first set up a virtual environment to work in, then install the module into it:

python setup.py install

The module has now been installed into our virtualenv, and we can now import it:

  
It's not particularly impressive, since our module doesn't actually do anything yet :) , but this is the minimum you need to create a Python extension and be able to import it successfully.

Distributing the extension

To be able to use the extension elsewhere[5]i.e. outside the environment in which it was built., you just need to distribute the .so file, and make sure it's on the Python search path somewhere, either by updating the PYTHONPATH environment variable, or adjusting the search path at run-time before import'ing the module e.g.

import sys

sys.path.append( "..." ) # specify the directory containing the extension module here
import demo
Download the source code here.


Tutorial index

Calling functions »

   [ + ]

1. Since that's what all the cool kids are using these days :cool:
2. On other distros, this package may be called python3-dev.
3. Or DLL, if you're on Windows.
4. The module is loaded when we execute the import demo command in Python.
5. i.e. outside the environment in which it was built.

2 Responses to this post

I'll probably never need this, but I'll have to try to work through the tutorial just to exercise my brain.

Thanks!!!

Being able to say that you've integrated Python with C++ is a great way to impress girls at parties, and scare the children... :cool:

Have your say