PDA

View Full Version : Embedding PyQt4 into an Application running Python via Boost::Python



GreyHound
12th April 2010, 19:44
Hi,

first of all, i hope i chose the right forum, but it thought i am having "installation" problems, so i might be right here.

I'm developing an Application (which is Qt based itself) .. with Python integration using boost::python.

At first i want to mention that i don't have any problems running PyQt4 code using my native python interpreter /somewhere/Python26/Python.exe

Now i try to have my script sourrounding understand pyqt4 so scripts can take usage of it. Unfortunatly i am getting


ImportError: DLL load failed: The specified procedure could not be found. errors when i try to run python code like


from PyQt4 import QtGui.


import PyQt4 or
from PyQt4 import * will pass without any errors, but not giving me access to anything inside the Module.

I spent a few hours on investigation by now and couldn't find anything related so far, the most issues about PyQt + embedding are about sharing objects, not about the installation process itself.

I guess i miss some setup required for my runtime python interpreter to know where to look for the dlls or something similar.

My current application folder setup is like this:


Application.exe
boost_python-vc90-mt-1_41.dll
python26.dll
QtCore4.dll
QtGui4.dll
Qt.pyd
QtCore.pyd
QtGui.pyd
TestFile.txt


I successfully read the TestFile.txt by reading "./TestFile.txt" via Python ... so the base path of the interpreter should find those modules as well?

I also tried placing all *.pyd files from my PyQt4 installation inside the application folder to be sure its not a problem because the qt system is not complete.

I've no idea how to get PyQt working inside my application and would be very grateful for any hint that might get me into the right direction.

Thanks

Gunnar

kinnalru
6th February 2012, 06:48
This is an example how to integrate PyQt4 and boost::python

first of all we must define wrap/unwrap function to deal with bare pointers


long int unwrap(QObject* ptr) {
return reinterpret_cast<long int>(ptr);
}

template <typename T>
T* wrap(long int ptr) {
return reinterpret_cast<T*>(ptr);
}


after that we must register all classes we want integrate to


class_<QObject, QObject*, boost::noncopyable>("QObject", no_init)
.def("unwrap", unwrap)
.def("wrap", make_function( wrap<QObject>, return_value_policy<return_by_value>() ))
.staticmethod("wrap");

class_<QWidget, bases<QObject>, QWidget*, boost::noncopyable>("QWidget")
.def("wrap", make_function( wrap<QWidget>, return_value_policy<return_by_value>() ))
.staticmethod("wrap");

class_<QFrame, bases<QWidget>, QFrame*, boost::noncopyable>("QFrame")
.def("wrap", make_function( wrap<QFrame>, return_value_policy<return_by_value>() ))
.staticmethod("wrap");

class_<QLabel, bases<QFrame>, QLabel*, boost::noncopyable>("QLabel")
.def("wrap", make_function( wrap<QLabel>, return_value_policy<return_by_value>() ))
.staticmethod("wrap");


and for example we have class that works with.. QLabel:



class worker: public QObject {
...
void add_label(QLabel*);
};


we must expose this class to python too:


class_<worker, bases<QObject>, worker*, boost::noncopyable>("worker")
.def("add_label", &worker::add_label);

now we a ready to interaction,
on C++-size do something like this



worker* w = new worker;
main_namespace["worker"] = boost::ref(w);


python:


from PyQt4.Qt import *
import sip
import mylib as MyLib

#...

#If you are using QApplication on C++-size you don't need to create another one

lb = QLabel("label from PyQt4!")

lb_ptr = sip.unwrapinstance(f)

my_lb = MyLib.QLabel.wrap(lb_ptr)

worker.add_label(my_lb)



In other case if you wan't send you own Q-object to PyQt4 :



QLabel* lb = new QLabel("C++ label");
main_namespace["lb"] = boost::ref(lb);


python:


from PyQt4.Qt import *
import sip
import mylib as MyLib

#...

my_lb_ptr = lb.unwrap()

qt_lb = sip.wrapinstance(my_lb_ptr, QLabel)




And this is my real little helper:


from PyQt4.Qt import *
import sip

def toQt(object, type):
ptr = object.unwrap()
return sip.wrapinstance(ptr, type)

def fromQt(object, type):
ptr = sip.unwrapinstance(object)
return type.wrap(ptr)