-
Notifications
You must be signed in to change notification settings - Fork 14
Python Bindings
I have added an early version of Python bindings for SMILI, still WIP. You can access the latest version from topic-python-bindings branch. Stable versions will be merged into topic-qt5 and topic-qt6 branches.
For an example, I used this simple and useful code base: https://github.com/KDAB/KDDockWidgets
IMPORTANT: Qt 6 and PySide6 is highly recommended because PySide2 is no longer supported and has limited Numpy conversion support.
Note: Some difficulties have been encountered on Windows in ensuring the classes show up in the Python module, I suspect its to do with DLLs as the Linux version is fine.
- Get VS 2022 here, may work for a newer version.
Use this version rather than 6.9.3 because Shiboken Tools are supposed to be better. Support for it is currently provided in topic-python-bindings branch. I followed the steps below:
- Download Qt clang used for the Shiboken wheel from here (6.10 & 6.9 uses v20) and set the LLVM_INSTALL_DIR environment variable to the extracted path of these binaries. If you get errors for "undeclared identifier '__builtin_ia32" etc., you are using the wrong Clang for the Shiboken wheels installed.
- Installed Qt 6.10.2 with optional extension Webkit
- Built ITK 5
- Built VTK 9.6+ with Qt support
- Build SMILI with NO Python Bindings
- Setup python environment and install Pyside6 etc. to match your Qt install version. I used the command to get to match 6.9.3:
pip install --index-url=https://download.qt.io/official_releases/QtForPython/ --trusted-host download.qt.io shiboken6 pyside6 shiboken6_generator - Build SMILI with Python Bindings
- I used VS 2022 because Qt 6.9.3 had its binaries.
-
Make sure to install the clang compiler in custom install/addons in VS 2022. Download Qt clang used for the Shiboken wheel from here (6.10uses v21, 6.9 uses v20) and set the LLVM_INSTALL_DIR environment variable to the extracted path of these binaries. - Installed Qt 6.9.3 with optional extension Webkit
- Built ITK 5
- Built VTK 9 with Qt support
- Build SMILI with NO Python Bindings
- Setup python environment and install Pyside6 etc. to match your Qt install version. I used the command to get to match 6.9.3:
pip install --index-url=https://download.qt.io/official_releases/QtForPython/ --trusted-host download.qt.io shiboken6==6.9.3 pyside6==6.9.3 shiboken6_generator==6.9.3 - Build SMILI with Python Bindings
I had issues with CMake command not running because shiboken6 command string was too long. It kept giving 'The system cannot execute the specified program' errors during the build. I had to fix the repetitions in the include dirs in ITK and VTK manually in the CMake config of PySMILI to shrink the paths so that it would fit.
I also had `byte is ambiguous' and std:: errors from the Windows SDK, so had to fix SMILI to not use '''using namespace std''' within milxQt library to fix it, see commit
7fc54e1 ("Fixes for Python bindings under Windows VS 2022 Qt 6.9.3 Fixed STL namesspace not being properly used Fixed milxQt MOCS not being properly compiles into bindings Updated CMake config to fix binding compilation", 2026-02-28)
If you have trouble, try using the NMake or Ninja generator in the terminal instead of the solution generator and you'll get more verbose output in the terminal. You can also use the NMake JOM for parallel build from here.
For some reason, Qt 5 is a dependency for ITK libs for ITK in the repository, so for Qt 6 I built ITK myself. If you do build ITK yourself, make sure to install it (locally via the CMAKE_INSTALL_PREFIX). Seems CMake sometimes messes up VNL includes especially for vnl/vnl_vector_fixed.h.
Using the Qt installer, I installed Qt 6.9.3 making sure to install the Qt WebEngine additional package. I did this via a custom install and checking the relevant sections to install. I followed the PySide6 build instructions:
- Get the source and select the matching branch, in this case 6.9.3 following https://doc.qt.io/qtforpython-6.9/building_from_source/linux.html#getting-the-source
- Created the PySide6 venv, this meant I had to use Python < 3.12. You can get older Python versions via Deadsnakes PPA https://launchpad.net/%7Edeadsnakes/+archive/ubuntu/ppa
- Building PySide6 using https://doc.qt.io/qtforpython-6.9/building_from_source/linux.html#building-and-installing-setuptools
python setup.py install --ignore-git --parallel=12 --qtpaths=/home/shakes/Qt/6.9.3/gcc_64/bin/qtpaths
You can follow the official instructions to get the wheels: https://doc.qt.io/qtforpython-6/shiboken6/gettingstarted.html
- Create the pyside6 venv, I had Qt 6.4.2 via the official Ubuntu repository, this meant I had to use Python < 3.12. You can get older Python versions via Deadsnakes PPA https://launchpad.net/%7Edeadsnakes/+archive/ubuntu/ppa
- Install PySide6, Shiboken6 and Shiboken Generator as per official instructions making sure to match the Qt version of SMILI to this version of PySide6 etc.
pip install \
--index-url=https://download.qt.io/official_releases/QtForPython/ \
--trusted-host download.qt.io \
shiboken6==6.4.2 pyside6==6.4.2 shiboken6_generator==6.4.2
I built SMILI on Arch with the latest branch experimental using VTK 9, ITK 5 and Qt 6. This means I could use PySide6.
- Setup python virtual env
- Installed pyside6 in the python venv with pip
- Install shiboken-generator (only available via Qt servers)
pip install \
--index-url=https://download.qt.io/official_releases/QtForPython/ \
--trusted-host download.qt.io \
shiboken6 pyside6 shiboken6_generator
- Make sure to match the above packages to your Qt 6 version
- Enable the PYTHON_BINDINGS ON to build the bindings
- If on the latest version in the topic-python-bindings branch, bindings should work correctly!
The build will be successful if you ensure that CMake config detects PySide and Shiboken properly. Check to ensure that the correct Python env is detected and has the installed PySide and Shiboken. If you get wrapper missing errors and SBK errors, likely the CMake config does match the SMILI classes being built or Shiboken is not setup properly. See https://www.eso.org/~ahoffsta/qt_widgets_binding/ for troubleshooting.
Errors from wrapper missing were because FindPySide and FindShiboken CMake config modules were old and didn't work, thus files weren't being generated at all. This has been fixed in the SMILI source in the topic-python-bindings branch and should work correctly now. I got PySide::Signal errors because pysidesignal.h was not being found. I had SDK...._IDX errors because the XML and global.h files and classes within them were inconsistently being wrapped.
Confirmed Works
- Used the Qt from the official repository for building SMILI, which was version 5.15.13.
- Install extra Qt5 libs for pyside2 to avoid private/xxx.h errors: qtbase5-private-dev qtdeclarative5-private-dev
- Downloaded PySide2 source for this version from https://download.qt.io/official_releases/QtForPython/pyside2/
- Made sure I had older Python < 3.10 via deadsnakes PPA of Python versions for Ubuntu: https://launchpad.net/%7Edeadsnakes/+archive/ubuntu/ppa OR use Micromamba/Miniconda etc.
- Set up Python environment for older Python and PySide2 to be installed in and activate it.
- Install clang 15 (IMPORTANT PySide2 only supports clang <= 15 apparently, see here) from the repository. If you use clang-15, make sure to install libclang-15-dev as well otherwise you'll get clang-c/index.h not found errors. If you use clang > 15, you will get ‘DragMove’ is not a member of ‘QOpenGLShader’ error as the code generated will have these errors.
- Install prereq packages in the Python env by pip install -r requirements.txt
- Build PySide2 wheels from source using Python rather than CMake, I did:
python setup.py install --parallel=16 --no-examples --ignore-git
Note that no-examples is important as I had RCC not found errors but this only occurred in the examples and not the main libraries.
- Install the wheels into the Python env, should be done by the step above
- Build SMILI with PYTHON_BINDINGS ON with the activated Python environment
- Install PySMILI into the current env
- To run the test scripts found in the 'python' directory, you might need to set the 'Python3_ROOT_DIR' for your venv in the CMake config.
Currently this works only for PySide2, Qt 5.15.3 right now. Getting PySide built to compile Python bindings for SMILI is challenging and is only necessary if you are looking to fix/extend SMILI bindings or learning to add bindings to your own library.
-
Build SMILI with Qt5 and VTK 7 from official repo packages by installing cmake-curses-gui, libvtk7-qt-dev, libinsighttoolkit4-dev, qtwebengine5-dev
-
Install extra Qt5 libs for pyside2 to avoid private/xxx.h errors: qtbase5-private-dev qtdeclarative5-private-dev
-
Setup Python 3.8 or 3.9 environment (Install miniconda or micromamba to create Py 3.8 env within 22.04 LTS) and activate. Note that some of the wheels are not available for 3.10+.
-
Set the Pyside2 source from releases link below, repo tags and branches have issues with missing pyside2-tools source missing so you want to use the tarball
-
Patch the source tarball according to https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/shiboken2/nix_compile_cflags.patch else you will get type_traits.h errors because libshiboken doesn't setup libclang paths properly. See also https://bugreports.qt.io/browse/PYSIDE-1012
-
Setup Clang as advised https://doc.qt.io/qtforpython-6/gettingstarted/linux.html
-
Install prereq packages in Python env by pip install -r requirements.txt
-
Build PySide and install it into current environment
-
Build SMILI with PYTHON_BINDINGS ON with the activated Python environment
If you encounter private/XXXX.h missing, installed the qtbase*-private-dev packages
If you get rcc missing error, make sure Qt5UITools packages are installed and then ensure the symbolic links being used are set to actual Qt rcc and uic apps
(In progress ...)
- Setup conda env with Python 3.9
- Install PySide 2 and shiboken2_generator into this env using wheels from Qt Server. The PyPI version misses shiboken2_generator, hence the Qt version. I used the command following https://doc.qt.io/qtforpython-6/shiboken6/gettingstarted.html
pip install --upgrade --index-url=https://download.qt.io/official_releases/QtForPython/ --trusted-host download.qt.io shiboken2 pyside2 shiboken2_generator
- Run CMake from this command prompt with the env activated (important!), this will allow CMake to find pyside etc. I had to use full path
C:\'Program Files'\CMake\bin\cmake-gui.exe
- Build SMILI with PYTHON_BINDINGS ON with the activated Python environment. Mine successfully found everything, but required a few Configures.
- Build the solution from the command line with this env activated. I first enabled the VS build env
C:\'Program Files (x86)'\'Microsoft Visual Studio'\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
Then I used the MSBuild tool from the command line to build the solution after changing to the SMILI build directory.
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe .\SMILI.sln /property:Configuration=Release
I had errors which I have to fix, probably path related.
2nd attempt - Using NMake (see Build page) After building SMILI using NMake JOM, I did the following:
- activated the pyside 2 conda env
- Build SMILI with PYTHON_BINDINGS ON with the activated Python environment. Mine successfully found everything, but required a few Configures.
- Built in command line by running jom -j 12 Got errors again, different ones though
Bug found for 5.15.3 https://bugreports.qt.io/browse/PYSIDE-1865
Releases Source for PySide2 https://download.qt.io/official_releases/QtForPython/pyside2/
Clang download https://download.qt.io/development_releases/prebuilt/libclang/
Other dependencies https://wiki.qt.io/Install_Qt_5_on_Ubuntu
More evidence for bug on type traits https://bugreports.qt.io/browse/PYSIDE-1012
Walkthrough for getting Python bindings working and common issues https://www.eso.org/~ahoffsta/qt_widgets_binding/
Great of example of how to do Python Bindings with PySide2/6 https://github.com/KDAB/KDDockWidgets