QPy
Python-Qt dynamic bindings
QPy

...in progress...

QPy is a Qt <--> Python run-time binding framework.

QObjects are exposed to Python through Python wrapper objects. Properties are mapped to Python class instance attributes; signals, slots and Q_INVOKABLE methods to Python class instance methods.

It is possible to add both types and pre-instantiated objects to the Python interpreter; in case of types new instances are created from within the Python interpreter by calling object constructors matching their C++ invokable counterparts. All the QObject constructors declared as Q_INVOKABLE are automatically accessible from Python.

Development site: http://github.com/candycode/qpy

Usage

The main usage for QPy is:

The public interface is defined in the qpy::PyContext class. All it's needed to access QPy functionality is to create an instance of PyContext and use its methods to add types and objects to Python modules.

You make QPy functions such as connect and disconnect available from Python code by explicitly initializing a module with the function table returned by qpy::PyContext::ModuleFunctions() method.

You add new types and instances by invoking qpy::PyContext::Add<Type> and PyContext::AddObject methods.

Initialization

Create:

  1. an instance of PyContext
  2. a Python module to host the QPy functions and initialize the module with the function table returned by ::ModuleFunctions()
  3. a separate Python module to host user-defined objects and types

Add both modules to Python's __main__ module.

Py_Initialize();
qpy::PyContext py;
PyObject* qpyModule = Py_InitModule3( "qpy", py.ModuleFunctions(),
                                "QPy module - where qpy functions reside" );
py.AddGlobals( qpyModule ); // optional, adds '__version__' info
Py_INCREF( qpyModule );
PyObject* userModule = Py_InitModule3( "qpy_test", py.ModuleFunctions(),
                                         "User module - client code" );
Py_INCREF( userModule );
PyObject* mainModule = PyImport_AddModule( "__main__" );

Add types and pre-existing instances to the Python module

py.Add< QpyTestObject >( userModule );

QpyTestObject* to = new QpyTestObject( 71 );
py.AddObject( to, // QObject-derived instance
              mainModule, // location where instance is added
              userModule, // location where class type is defined
              "myqobj" // global instance name
            );

Method invocation

QObject-derived constructors and methods are readily available to Python code.

import qpy
import qpy_test

to = qpy_test.QpyTestObject(3)
to.Print()

myqobj.SetValue(123)
myqobj.Print()

Property Access

Q_PROPERTIES are as well available, maintaining the read/write permissions as defined in the Q_PROPERTY declaration.

to.value = 234
print("PROPERTY: {0}".format(to.value))

Signals

Qt signals can be connected to:

To connect/disconnect signals you use the connect/disconnect functions in the QPy Python module(e.g. 'qpy') where the QPy functions are added.

Two syntax formats supported:

Explicit signature:

def cback(v):
    print('Got {received}'.format(received=v))
to2 = qpy_test.QpyTestObject(123)
qpy.connect(to, "aSignal(int)", to2, "catchSignal(int)")
qpy.connect(to, "aSignal(int)", cback)

Method name:

qpy.connect(to.aSignal, to2.catchSignal)
qpy.connect(to.aSignal, cback)

Types

Data are marshalled between Python and Qt with specializations of the following abstract classes:

passed to the PyContext::Register* methods.

All Classes Namespaces Files Functions