Using Shiboken2 to create Python bindings for a Qt library

With the release of Qt 5.12, Qt for Python is officially supported and can be used to write full-fledged Qt applications using Python as the main programming language (https://blog.qt.io/blog/2018/12/18/qt-python-5-12-released/).

This prompted us to also take a closer look at the bindings (the Python module is called PySide2) and also the underlying technology, namely the binding generator called Shiboken2.

This post will show you how to create a set of Python bindings for a small Qt library from scratch.

PySide2

The Qt bindings themselves are easy to install and use.

If you have a python interpreter and the pip package manager set up on your system, whether it is Windows or Linux, you can install the module via pip install PySide2 and are ready to go.

Shiboken2

While it is nice to use the Qt framework from Python it is even better to be able to quickly create Python bindings for your own Qt libraries and use their API from Python with relatively little work.

Setup

All examples on this article have been run on Ubuntu 18.04, the setup steps for other platforms might vary.

Since the most recent documentation advises to build Shiboken2 from source for building your own bindings, we will do that now.

Install Qt 5.12

This posts assumes that you have a Qt 5.12 installation ready at $HOME/Qt/5.12.0/gcc_64/, which is the default location when using the online installer from qt.io.

If you use Qt from a different location adjust the paths accordingly.

Install all required tools and libraries

The following apt command line works for Ubuntu 18.04 and should be a good starting point for other distributions.

Get the sourcecode

The fastest way to get the PySide2 and Shiboken2 source is to clone the git repository.

Set up a python virtualenv

We advise you to work in python virtual environments, as that will keep your system installation clean and you should be able to do anything else in this post without requiring root privileges.

This will set up a python3 virtual environment in your home directory (~/.local/share/virtualenvs/pyside2build) and activate it. Your shell should have a prefix indicating that. To activate the virtualenv in the future use workon pyside2build.

Set up the environment

The API extractor of Shiboken2 requires a clang/llvm version newer than the default version in Ubuntu 18.04, and we need to tell the buildsystem where to find it.

Build

Now that we have prepared everything, the actual build is easy.

After the build has finished, which can take some time, you should have a fully working and properly linked PySide2 and Shiboken2 installation in your virtualenv.

Try it by running the shiboken2 command line tool:

If you see output similar to this, you are good to go.

Wrapping a library

Note: All files mentioned in this section can be downloaded as a tarball

The Shiboken2 post on qt.io introduces the process quite well, so you can also take a look there to better understand the process: https://blog.qt.io/blog/2018/05/31/write-python-bindings/

Shiboken2 input

Shiboken requires mainly three things to work

  1. The library to generate bindings for
  2. An ‘entry-point‘ header file which includes all other headers of classes for which bindings are generated
  3. A type description XML file which (at a minimum) tells shiboken which types to wrap

Note that the the typesystem description can do much more than describe which types to expose using which semantics: https://doc.qt.io/qtforpython/shiboken2/contents.html

The library

Our trivial library contains only a single QObject with signals, slots and a Q_ENUM which is used in the API.

qobjectwithenum.h

qobjectwithenum.cpp

See the attached project for implementation details.

The glue header

Our glue header pulls in the required library headers, which is pretty simple in our case, and also sets up a define required for generating code for the Qt specialities.

bindings.h:

The typesystem description

In our case this is also pretty simple:

bindings.xml:

As I wrote before, the typesystem description is a powerful tool but out of the scope of this particular post.

Building the bindings

Note: Due to the greatly improved Python integration CMake >= 3.12 is required here.

To simplify building and linking all the parts we adapt a CMakeLists.txt file from the sample bindings example.

The example CMakeLists.txt installs the resulting library into the source folder and adds all relevant paths as RPATHS for the built libraries which makes local usage convenient.

This is not the right thing to do for production projects, consult your local system integrator :-).

CMakeLists.txt

The CMake build file has been adapted from the official sample binding. The content is not relevant to this article. It can be found in the downloadable zip.

Make a shadow build and install

Using the module

Once the bindings have been generated and built we can now write a python script which uses the binding module.

The easiest way to use the wrapped library is to activate the virtual environment, which contains the correct PySide2 version, and run it

That’s it. Zero to Qt library bindings in one blog post.

basysKom is offering consulting, training and development services for Qt. We have recently added a Qt for Python module to our training. If you are interested get in contact with info@basyskom.com.

2 thoughts on “Using Shiboken2 to create Python bindings for a Qt library”

  1. Hi, I cannot build your example under Windows 10 64bit. My toolkits are: MSVC 2017, Qt 5.12.3 msvc 2017 64bit, Python 2.7.3 64bit. The error is: fatal error LNK1107: file invalid: cannot read at 0x320
    Could you provide me any hints?

    1. Hi,

      the error you posted is unfortunately not enough information and I do not have a similar setup available at the moment to reproduce the issue. Can you paste the whole build output somewhere?

Leave a Reply

Your email address will not be published. Required fields are marked *