Commits

Henning Schröder  committed 7a3a9fc

some experiments how to use qt/c++ libraries from Python without SIP

  • Participants
  • Parent commits 993ce20

Comments (0)

Files changed (8)

File experimental/README

+The other direction:
+Use Qt/C++ libaries from inside Python without using SIP

File experimental/hello.cpp

+#include "hello.h"
+#include <QApplication>
+#include <QVariant>
+
+#include "pyqtwrapper.h"
+
+
+Hello::Hello(QWidget *parent) : QPushButton("Hello, world", parent)
+{
+    resize(320, 240);
+}
+
+
+Hello::Hello() : QPushButton("Hello, world without parent", 0)
+{
+    resize(512, 240);
+}
+
+
+void Hello::test()
+{
+ animateClick();
+}
+
+
+extern "C"
+{
+  void *init() {
+      PyQtWrapper *wrapper = new PyQtWrapper(QApplication::instance());
+      wrapper->registerMetaObject(Hello::staticMetaObject);
+      return (void*)wrapper;
+  }
+}
+
+

File experimental/hello.h

+#ifndef HELLO_H
+#define HELLO_H
+
+#include <QPushButton>
+#include <QWidget>
+#include <QMap>
+#include <QString>
+#include <QMetaObject>
+
+class Hello : public QPushButton
+{
+   Q_OBJECT
+   
+public:
+   Q_INVOKABLE Hello();
+   Q_INVOKABLE Hello(QWidget *parent);
+   
+public slots:
+   void test();
+};
+
+
+extern "C"
+{
+  void *init();
+}
+
+
+#endif // HELLO_H

File experimental/hello.pro

+#TEMPLATE = app
+TEMPLATE = lib
+CONFIG += qt debug
+HEADERS += hello.h pyqtwrapper.h
+SOURCES += hello.cpp pyqtwrapper.cpp
+SOURCES += main.cpp
+
+TARGET = helloworld

File experimental/main.cpp

+#include <QApplication>
+#include "hello.h"
+
+/*
+int main( int argc, char **argv )
+{
+   
+       QApplication a( argc, argv );
+   
+       Hello hello(0);
+   
+       hello.show();
+       return a.exec();
+}
+*/

File experimental/pyqtwrapper.cpp

+#include "pyqtwrapper.h"
+#include <QApplication>
+#include <QVariant>
+#include <QPushButton>
+#include <qdebug.h>
+
+
+PyQtWrapper *PyQtWrapper::_instance = 0;
+
+
+PyQtWrapper::PyQtWrapper(QObject *parent) :
+    QObject(parent)
+{
+    PyQtWrapper::_instance = this;
+    setObjectName("PyQtWrapper");
+    QApplication::instance()->setProperty("pyqtwrapper",
+                                          qVariantFromValue((QObject*)this));
+    //registerObject(this);
+}
+
+
+void PyQtWrapper::deleteLater() {
+    QApplication::instance()->setProperty("pyqtwrapper",
+                                          qVariantFromValue(NULL));
+}
+
+
+
+void* PyQtWrapper::metaObjectByName(const QString &name) {
+    return (void*)classes[name];
+}
+
+QObject* PyQtWrapper::objectByName(const QString &name) {
+    return (QObject*)objects[name];
+}
+
+
+QStringList PyQtWrapper::availableClasses() {
+    return classes.keys();
+}
+
+
+QStringList PyQtWrapper::availableObjects() {
+    return objects.keys();
+}
+
+
+void PyQtWrapper::registerMetaObject(const QMetaObject &mo) {
+    classes[mo.className()] = &mo;
+}
+
+
+void PyQtWrapper::registerObject(const QObject &obj) {
+    //connect(obj, SIGNAL(destroyed()), unregister_objec);
+    objects[obj.objectName()] = &obj;
+}
+

File experimental/pyqtwrapper.h

+#ifndef PYQTWRAPPER_H
+#define PYQTWRAPPER_H
+
+#include <QObject>
+#include <QMetaObject>
+#include <QMap>
+#include <QStringList>
+
+#define REGISTER_CLASS(cls) PyQtWrapper::instance()->registerMetaObject(cls::staticMetaObject);
+#define REGISTER_INSTANCE(obj) PyQtWrapper::instance()->registerObject(obj);
+
+
+class PyQtWrapper : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit PyQtWrapper(QObject *parent = 0);
+    static PyQtWrapper *instance();
+
+public slots:
+    void deleteLater();
+    void* metaObjectByName(const QString &name);
+    QObject* objectByName(const QString &name);
+    QStringList availableClasses();
+    QStringList availableObjects();
+    void registerMetaObject(const QMetaObject &mo);
+    void registerObject(const QObject &obj);
+
+private:
+    static PyQtWrapper *_instance;
+    QMap<QString,const QMetaObject*> classes;
+    QMap<QString,const QObject*> objects;
+};
+
+
+#endif // PYQTWRAPPER_H

File experimental/test.py

+import sys
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+import ctypes
+import sip
+
+
+
+def cfunc(func, *args, **kwargs):
+	ptr = func(*args)
+	result_type = kwargs.pop("type", QObject)
+	if kwargs:
+		raise TypeError("Unknown keyword argument(s): %r" % kwargs)
+	return sip.wrapinstance(int(ptr), result_type)
+
+
+def new(pyqtwrapper, class_name, *args, **properties):
+	cls = cfunc(pyqtwrapper.metaObjectByName, class_name, type=QMetaObject)
+	obj = cls.newInstance(*args)
+	obj.pyqtConfigure(**properties)
+	return obj
+
+
+
+class QtLibWrapper(object):
+	
+	def __init__(self, filename):
+		self._lib = ctypes.cdll.LoadLibrary(filename)
+		self._instance = cfunc(self._lib.init)
+
+	
+	def __getattr__(self, name):
+		cls = lambda *args, **properties: new(self._instance, name, **properties)
+		return cls
+
+
+
+
+
+
+app = QApplication(sys.argv)
+
+qtlib = QtLibWrapper("./libhelloworld.so.1.0.0")
+Hello = qtlib.Hello
+
+hello = Hello(text="foo, bar")
+hello.show()
+app.exec_()
+