[SOLVED] Fully embedding python into Qt application

Issue

I am looking for a way of fully embedding python into a Qt application. With this, I mean that I want to build a Qt application that executes python code and I can fully distribute without having to care about which python version is installed in the target machine, or without having to ask the future user to install python by him/herself.

I’ve checked the libraries PythonQt, PyBind11, Boost.Python, and the native python libraries, and they are good to link C++ to Python, but any of them do what I want to do.

I have tried the following in Linux, and I was planning to do the same (or at least a similar approach) on Windows and Mac:

  1. Download source code of Python (In my case, Python 3.9).

  2. Build python.

    mkdir build
    cd build
    ../configure --enable-optimizations --enable-shared
    make
    make install DESTDIR=installed/
    
  3. Copy contents of installed into the dependencies folder of my projects. The contents of installer are the following folders:

    - bin: Contains python executable and some tools like pip.
    - include: Contains all of the headers of python.
    - lib: Contains the .so libraries and the python modules (if you install a new python module using pip, it will be installed here in python3.9/site-packages/).
    - shared: Contains the man entries of python.
    

Having Python3.9 build, I have not installed any library yet, to test if this is the python that C++ is calling.

I have linked it from my Qt application in my .pro file like this:

INCLUDEPATH += $$PWD/../dependencies/python3.9/linux/include/python3.9
DEPENDPATH += $$PWD/../dependencies/python3.9/linux/include/python3.9


LIBS += -L$$PWD/../dependencies/python3.9/linux/lib/ -lpython3.9

Once linked, I call python like this:

Py_SetPythonHome(L"/link/to/dependencies/python3.9/linux/lib/python3.9/");
Py_SetPath(L"/link/to/dependencies/python3.9/linux/lib/python3.9/");

wchar_t *program = Py_DecodeLocale("", NULL);
if (program == NULL) {
    fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
    exit(1);
}
Py_SetProgramName(program);  /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("import pgmpy");
if (Py_FinalizeEx() < 0) {
    exit(120);
}
PyMem_RawFree(program);

In this code, I am importing the library pgmpy. This package is not installed in the version of python I have build. However, it is installed in my local version of python, meaning that it is not using the python I have build, even when this is the one linked.

Is there any configuration step or something that I have missing? Is this ever feasible? I am more interested in solutions that are not specific to Qt, but can be applied to any C++ project, that is one of the reasons why I am using pybind11 and not pythonQt

Thank you.

Solution

I finally found a workaround.

I executed the python interpreter from terminal, and printed sys.path, showing the correct paths.

Then, in C++, I appended the correct paths to sys.path, removing the wrong ones.

Answered By – Alberto Casas Ortiz

Answer Checked By – Willingham (BugsFixing Volunteer)

Leave a Reply

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