Couldn't connect() to QTcpSocket::error with the new signal/slot syntax in Qt5



  • Environment:

    Gentoo ~amd64, x11-libs/qt-core-5.0.1 (c++11 glib icu -debug -test) from qt overlay, and qt-network-5.0.1 (c++11 ssl -connman -debug -networkmanager -test). I have Qt 5.0.1 and Qt 4.8.4 installed side by side.

    The problem:

    I just started programming with Qt and C++ and wishes to write a network application. I spotted "the new signal/slot syntax":http://qt-project.org/wiki/New_Signal_Slot_Syntax introduced in Qt 5 and found it interesting. I tried using the new syntax to connect() to other signals of QTcpSocket and it works beautifully:

    @
    QTcpSocket socket;

    // ...

    connect(&socket, &QTcpSocket::connected, this, &MarketInfoWorkerDzh::onConnected);
    connect(&socket, &QTcpSocket::readyRead, this, &MarketInfoWorkerDzh::onReadyRead);
    @

    However, I simply couldn't connect() to QTcpSocket::error:

    @
    connect(&socket, static_cast<void (QTcpSocket::*) (QAbstractSocket::SocketError)>(&QAbstractSocket::error), this, &MarketInfoWorkerDzh::onError);
    @

    It works during compilation -- not even a warning with clang++ -Weverything -- but at runtime I spot this:

    bq. QObject::connect: signal not found in QTcpSocket

    The old syntax works correctly:

    @
    connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)))
    @

    Things I've tried:

    • Switching between clang-3.1 and gcc-4.7.2. No luck.

    • Try compiling from qt-creator-2.6.4 and manually with qmake/make. No changes.

    • Make a skeleton project with Qt Creator, and copy the example code from "New Signal Slot Syntax Coming in Qt 5":http://qt-project.org/wiki/New_Signal_Slot_Syntax directly.

    @
    QByteArray page;
    QTcpSocket *socket = new QTcpSocket;
    socket->connectToHost("qt.nokia.com", 80);
    QObject::connect(socket, &QTcpSocket::connected, [socket, page] () {
    socket->write(QByteArray("GET " + page + "\r\n"));
    });
    QObject::connect(socket, &QTcpSocket::readyRead, [socket] () {
    qDebug()<< "GOT DATA "<< socket->readAll();
    });
    QObject::connect(socket, &QTcpSocket::disconnected, [socket] () {
    qDebug()<< "DISCONNECTED ";
    socket->deleteLater();
    });

    QObject::connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), [socket] (QAbstractSocket::SocketError) {
        qDebug()<< "ERROR " << socket->errorString();
        socket->deleteLater();
    });
    

    @

    I get the same error.

    • Grab the fortuneclient example from qtbase-opensource-src-5.0.1.tar.xz, modify two lines to use the new signal/slot syntax:

    @
    connect(tcpSocket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
    //! [3]
    this, &Client::displayError);
    @

    Then it exhibits the very issue.

    • "LD_PRELOAD=/usr/lib64/libQt5Network.so.5.0.1". Doesn't help.

    • Build qt-core with debugging symbols. I traced down to QObject::connectImpl(), ./src/corelib/kernel/qobject.cpp, line 4202:

    @
    QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
    const QObject *receiver, void **slot,
    QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
    const int *types, const QMetaObject *senderMetaObject)
    {
    if (!sender || !signal || !slotObj || !senderMetaObject) {
    qWarning("QObject::connect: invalid null parametter");
    if (slotObj)
    slotObj->destroyIfLastRef();
    return QMetaObject::Connection();
    }
    int signal_index = -1;
    void *args[] = { &signal_index, signal };
    senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
    if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
    qWarning("QObject::connect: signal not found in %s", senderMetaObject->className());
    slotObj->destroyIfLastRef();
    return QMetaObject::Connection(0);
    }
    // ...
    @

    I believe the parameter "signal" is passed to it correctly:

    @
    $1 = (void *) 0x7ffff7f48ed0 QAbstractSocket::error(QAbstractSocket::SocketError)
    @

    But the static_metacall(QMetaObject::IndexOfMethod, ...) call later doesn't modify signal_index at all:

    @
    (gdb) p signal_index
    $2 = -1
    (gdb) p senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args)
    $3 = -1
    (gdb) p signal_index
    $4 = -1
    (gdb) p signal_index = -2
    $5 = -2
    (gdb) p senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args)
    $6 = -1
    (gdb) p signal_index
    $7 = -2
    @

    (The forum says "The maximum number of allowed characters is 6000"..., so I have to break my post down here.)



  • (My thread continues here...)

    It feels like there's something wrong in static_metacall(QMetaObject::IndexOfMethod, ...), but I do not know where static_metacall() actually goes to:

    @
    (gdb) n
    4213 int signal_index = -1;
    (gdb) n
    4214 void *args[] = { &signal_index, signal };
    (gdb) n
    4215 senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
    (gdb) s
    QMetaObject::static_metacall (this=0x7ffff7fc64e0 QTcpSocket::staticMetaObject,
    cl=QMetaObject::IndexOfMethod, idx=0, argv=0x7fffffffdfa0)
    at /var/tmp/portage/x11-libs/qt-core-5.0.1/work/qtbase-opensource-src-5.0.1/src/corelib/kernel/q
    metaobject.cpp:291
    291 {
    (gdb) s
    293 if (!d.static_metacall)
    (gdb) s
    291 {
    (gdb) s
    293 if (!d.static_metacall)
    (gdb) s
    295 d.static_metacall(0, cl, idx, argv);
    (gdb) s
    296 return -1;
    (gdb) s
    297 }
    (gdb) s
    QObject::connectImpl (sender=0x55555575ccc0, signal=<optimized out>, receiver=0x55555575ccc0,
    slot=0x0, slotObj=0x55555575e1a0, type=Qt::DirectConnection, types=0x0,
    senderMetaObject=0x7ffff7fc64e0 QTcpSocket::staticMetaObject)
    at /var/tmp/portage/x11-libs/qt-core-5.0.1/work/qtbase-opensource-src-5.0.1/src/corelib/kernel/qobject.cpp:4216
    4216 if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
    (gdb) s
    4217 qWarning("QObject::connect: signal not found in %s", senderMetaObject->className())
    @

    So, any ideas what's wrong? Thanks in advance.



  • what about your makfile, maybe you forget to add flag "-fPIE"?



  • @deter:

    Thanks for the hint. :-) I'm using qmake, the default configuration:

    @
    QMAKE_CXXFLAGS += -std=c++11

    QT += core gui network sql

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    INCLUDEPATH += $$[QT_INSTALL_PREFIX]/src/3rdparty/zlib

    TARGET = ssa
    TEMPLATE = app

    SOURCES += \

    ...

    @

    "As far as I know qmake in Qt 5 is already forcing -fPIE":http://qt.gitorious.org/qt/qtbase/commit/482d96a0c5d523ace63f56bda6851926b4469dd0/diffs , and I could confirm the generated Makefile has -fPIE in C(XX)FLAGS indeed.

    I updated to Qt 5.1.0-beta1 and seemingly nothing changed.



  • The bad news is that it's a Qt bug I found some weeks ago.

    The good news is that it's fixed in the upcoming 5.1 by this commit https://codereview.qt-project.org/#change,55606 :)



  • [quote author="peppe" date="1370793539"]The bad news is that it's a Qt bug I found some weeks ago.

    The good news is that it's fixed in the upcoming 5.1 by this commit https://codereview.qt-project.org/#change,55606 :)[/quote]

    I see. Thanks! :-)



  • -Did the change make it in Qt5.1.1?-
    -I just installed the latest version and still have this issue.-

    Forget it, my bad. QtCreator seduced me with a slot instead of a signal...


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.