[PyQt] Advices on embedding python in Qt/C++ application

Phil Thompson phil at riverbankcomputing.com
Thu Aug 29 17:48:44 BST 2019


On 29/08/2019 17:21, Alexis Barbot wrote:
> I looked at it, but it seems I didn't catch the point (or possibly the
> moment I read it I did not figure out it could be what I needed...). I 
> now
> understand that it explains I should get the c api dynamically to call 
> it,
> whereas I was trying to call static method. I could get something 
> roughtly
> working this way, with pyqt compiled in static (see code below). I'm
> currently trying to clean everythind, but I realized I had to upgrade 
> Qt
> for that, as I can't find a PyQt package for Qt5.9 (sad, as it's a 
> LTS). So
> I'll keep you updated on my progress.

See...

https://www.riverbankcomputing.com/static/Docs/PyQt5/installation.html#understanding-the-correct-version-to-install

> In my tests I realized something: is there some special care to do with
> containers while passing from C++/python? In my first attemp to pass a
> QVariantMap the items added after SetItem to python are not visible 
> from
> python? (and items modified in python are not modified in c++). Any 
> special
> thoughts about this?

Impossible to say without example code.

> Thanks for all your help
> 
> Alexis
> 
> ```
> Py_Initialize();
> PyEval_InitThreads();

The following code...

> auto sipModule = PyImport_ImportModule("sip");
> PyImport_ImportModule("PyQt5.sip");
> auto sipAPI = (const sipAPIDef*)PyCapsule_Import("sip._C_API", 0);
> PyCapsule_Import("PyQt5.QtCore._C_API", 0);
> auto sipModuleDict = PyModule_GetDict(sipModule);
> auto sip_sipmod = PyImport_ImportModule("PyQt5.sip");
> auto sip_capiobj = PyDict_GetItemString(PyModule_GetDict(sip_sipmod),
> "_C_API");
> 
> sipAPI_QtCore = reinterpret_cast<const
> sipAPIDef*>(PyCapsule_GetPointer(sip_capiobj, "PyQt5.sip._C_API"));
> qpycore_init();
> sipExportModule(&sipModuleAPI_QtCore, SIP_API_MAJOR_NR, 
> SIP_API,MINOR_NR,
> 0);

...only needs to be...

sipAPI_QtCore = reinterpret_cast<const 
sipAPIDef*>(PyCapsule_Import("PyQt5.sip._C_API", 0));
PyImport_ImportModule("PyQt5.QtCore")

...but I haven't actually tested it.

> auto m = PyImport_AddModule("__main__");
> auto g = PyModule_GetDict(m);
> auto d = PyDictNew();
> 
> auto test = std::make_unique<QDateTIme>(QDateTIme::currentDateTime);
> auto type = sipAPI_QtCore->api_find_type("QDateTime);
> auto pyTest = sipAPI_QtCore->api_convert_from_type(test.get(), type,
> nullptr);
> // Ici je visualise l'objet C++ en python
> PyDict_SetItem(d, PyUnicode_FromString("testdate"), Py_file_input, g, 
> d);
> PyRun_String("print(testdate.toString())", Py_file_input, g, d);
> test->setDate(QDate{2000,02,03});
> // Ici je visualise en python que l'objet a été modifié en c++
> PyDict_SetItem(d, PyUnicode_FromString("testdate"), Py_file_input, g, 
> d);
> Py_FinalizeEx();
> ```

Make sure you aren't #including sipAPIQtCore.h. Those files are internal 
and contain nothing public.

Phil



More information about the PyQt mailing list