Background
In a style not dissimilar to PyQt, SIP is used to generate native bindings for a custom library that is based on Qt (Source). I am trying to diagnose an issue relating to signals that provide parameters for custom types not being converted when passed to their respective slots, and am looking for pointers for things to try. The code is open source, and I encourage anyone to give the code a try for themselves, but for those wanting a slightly more concise / distilled description I have made a best-attempt here.
The Problem
Let's start with the Python code which uses the generated module that is causing the problem (Interactions Example). Here's the standard signal / slot connection code in the constructor of MainWindow, the full source code can be found in mainwindow.py.
class MainWindow(QMainWindow):
def __init__(self, argv, parent=None):
# ... snipped other setup code ...
# connect slot that shows a message in the status bar when a graph is clicked:
self.customPlot.plottableClick.connect(self.graphClicked)
The definition for QCustomPlot and the plottableClick signal are in sip/core.sip. Note that the plottableClick signal provides a QCPAbstractPlottable* object as the first parameter.
class QCustomPlot : public QWidget
{
// ... snipped other methods of QCustomPlot type ...
signals:
void plottableClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event);
Now let's look at the slot method, which is where the problem may be observed. When the slot is invoked, an exception is raised because plottable is a valid PyObject, but it has no type members, causing the call to interface1D to fail:
def graphClicked(self, plottable, dataIndex):
dataValue = plottable.interface1D().dataMainValue(dataIndex) # fails because plottable has no member method called "interface1D"
The bindings for QCPAbstractPlottable show that the member is defined.
class QCPAbstractPlottable : public QCPLayerable /Abstract/
{
// ... snipped other methods here ...
virtual QCPPlottableInterface1D *interface1D();
As an aside, the generated bindings do correctly convert the type when calling member functions of QCustomPlot, such as QCustomPlot.selectedPlottables() which returns a QList. This leads me to believe that the problem is specific to signals.
The Question
After banging my head against this issue for several days, it is beginning to look a lot like SIP doesn't have the information it needs to to recognise that the types defined in the library are types that it can convert when passed to a signal.
Looking at the PyQt5 source code, I have found examples where types defined in the library are passed as signal parameters, for example QWidget::mousePressEvent accepts a QMouseEvent*, which is the same pattern that I am trying to replicate in my own signal. However, I cannot find any special SIP glue code to hint the code generator how to convert the type.
What have I done wrong?