LINUX.ORG.RU

QTcpServer: No such slot


0

1

Тупой вопрос по Qt5:

#include <QObject>
#include <QTcpServer>
#include <stdio.h>
#include <unistd.h>

class x : public QObject
{
        QTcpServer *tcpServer;

public:
        x(QObject *parent = 0) : QObject(parent)
        {
                tcpServer = new QTcpServer(this);
        }

        bool init(const QString &host, const qint16 port)
        {
                bool rc;

                connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slotNewUser()));

                if (host.isEmpty() == true)
                {
                        rc = tcpServer->listen(QHostAddress::Any, port);
                }
                else
                {
                        rc = tcpServer->listen(QHostAddress(host), port);
                }

                return rc;
        }

public slots:
        void slotNewUser()
        {
            printf("slotNewUser()\n"); fflush(stdout);
        }
};

int main(int argc, char *argv[])
{
        x xxx;
        if (xxx.init("", 8001) == false)
        {
                printf("ERROR[listen()]: failed\n");
                return 1;
        }

        sleep(60);

        return 0;
}

Компилю так:

g++ test.cpp -o test -fPIC -lQt5Concurrent -lQt5Core -lQt5DBus -lQt5Gui -lQt5Network -lQt5OpenGL -lQt5PrintSupport -lQt5Script -lQt5ScriptTools -lQt5Sql -lQt5Test -lQt5V8 -lQt5Widgets -lQt5Xml -I/usr/include/qt5/ -I/usr/include/qt5/QtNetwork/ -I/usr/include/qt5/QtCore/

запускаю и получаю: QObject::connect: No such slot QObject::slotNewUser() in test.cpp:25

как это лечить?

★★★★

Ответ на: комментарий от wota

заменил, скомпилил, запустил - молчит. telnet конектится а сервер молчит...

quest ★★★★ ()
Ответ на: комментарий от timon-ltv

добавляю Q_OBJECT

делаю qmake -project qmake

доабавляю в Makefile инклюды и либы, делаю make

test.cpp:(.text.startup+0x1c): undefined reference to `vtable for x'

quest ★★★★ ()
Ответ на: комментарий от timon-ltv

без разницы и обычный и виртуальный, та же ошибка

quest ★★★★ ()

Поехавший

как это лечить?

Так:

main.cpp:

#include <QObject>
#include <QTcpServer>
#include <stdio.h>
#include <unistd.h>

class x : public QObject
{
        Q_OBJECT

        QTcpServer *tcpServer;

public:
        x(QObject *parent = 0) : QObject(parent)
        {
                tcpServer = new QTcpServer(this);
        }

        bool init(const QString &host, const qint16 port)
        {
                bool rc;

                connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slotNewUser()));

                if (host.isEmpty() == true)
                {
                        rc = tcpServer->listen(QHostAddress::Any, port);
                }
                else
                {
                        rc = tcpServer->listen(QHostAddress(host), port);
                }

                return rc;
        }

public slots:
        void slotNewUser()
        {
            printf("slotNewUser()\n"); fflush(stdout);
        }
};

int main(int argc, char *argv[])
{
        x xxx;
        if (xxx.init("", 8001) == false)
        {
                printf("ERROR[listen()]: failed\n");
                return 1;
        }

        sleep(60);

        return 0;
}

#include "moc_main.cpp"

project.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2014-02-17T16:39:44
#
#-------------------------------------------------

QT       += core network

QT       -= gui

TARGET = untitled
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp

HEADERS += main.cpp

EXL ★★★★★ ()

Ты пытаешься использовать сигналы и слоты без предварительной обработки кода MOC'ом. Это никуда не годится. Если хочется запихать все в main.cpp, то необходимо выполнить следующее:

  1. Удостовериться в наличие хэдера QObject в файле «main.cpp»;
  2. Удостовериться в наличие макроса Q_OBJECT в классе или его реализации;
  3. Дать возможность пройти MOC'у по файлу и развернуть слоты и прочую мишуру. Для этого следует добавить в «*.pro»-файл строку HEADERS += main.cpp (MOC проходится именно по хэдерам, ища в них макрос Q_OBJECT);
  4. Добавить в конец файла «main.cpp» директиву препроцессора: #include "moc_main.cpp", чтобы не возникало всяких там main.cpp:13: error: undefined reference to `vtable for x'

Обо всём этом можно вообще забыть, если бы ты использовал такую вещь, как раздельную компиляцию:

main.cpp:

#include "super_x_class.h"

#include <QObject>
#include <QTcpServer>

#include <unistd.h>

int main(int argc, char *argv[])
{
        x xxx;
        if (xxx.init("", 8001) == false)
        {
                printf("ERROR[listen()]: failed\n");
                return 1;
        }

        sleep(60);

        return 0;
}

super_x_class.h

#ifndef SUPER_X_CLASS_H
#define SUPER_X_CLASS_H

#include <QObject>
#include <QTcpServer>

class x : public QObject
{
        Q_OBJECT

        QTcpServer *tcpServer;

public:
        explicit x(QObject *parent = 0);
        bool init(const QString &host, const qint16 port);

public slots:
        void slotNewUser();
};

#endif // SUPER_X_CLASS_H

super_x_class.cpp:

#include "super_x_class.h"

x::x(QObject *parent) :
    QObject(parent)
{
    tcpServer = new QTcpServer(this);
}

bool x::init(const QString &host, const qint16 port)
{
    bool rc;

    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slotNewUser()));

    if (host.isEmpty() == true)
    {
            rc = tcpServer->listen(QHostAddress::Any, port);
    }
    else
    {
            rc = tcpServer->listen(QHostAddress(host), port);
    }

    return rc;
}

void x::slotNewUser()
{
    printf("slotNewUser()\n"); fflush(stdout);
}

project.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2014-02-17T16:39:44
#
#-------------------------------------------------

QT       += core network

QT       -= gui

TARGET = untitled
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp \
    super_x_class.cpp

HEADERS += super_x_class.h

EXL ★★★★★ ()
Ответ на: комментарий от EXL

ok, далаю как написал ты, создаю все эти файлы с твоим содержимым, qmake, make, ./untitled, telnet 127.0.0.1 8001

и тишина... не пишет нифига обработчик!

quest ★★★★ ()
Ответ на: комментарий от quest

А он и не будет писать. Ты же не создал и не запустил mainloop. События не передаются. Добавь в main создание экземпляра QApplication и запусти из него mainloop.

KblCb ★★★★★ ()
Ответ на: комментарий от quest

untitled.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2014-02-17T16:39:44
#
#-------------------------------------------------

QT       += core network
QT       -= gui

TARGET = untitled
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app

SOURCES += main.cpp
HEADERS += main.cpp

main.cpp:

#include <QObject>
#include <QCoreApplication>
#include <QTcpServer>

class x : public QObject
{
    Q_OBJECT
    QTcpServer *tcpServer;
public:
    x(QObject *parent = 0) : QObject(parent) {
        tcpServer = new QTcpServer(this);
    }
    bool init(const QString &host, const qint16 port) {
        bool rc;
        connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slotNewUser()));

        if (host.isEmpty() == true) {
            rc = tcpServer->listen(QHostAddress::Any, port);
        }
        else {
            rc = tcpServer->listen(QHostAddress(host), port);
        }
        return rc;
    }
public slots:
    void slotNewUser() {
        qDebug() << "New User Connected!";
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    x xxx;
    if (xxx.init("", 8001) == false) {
        qDebug() << "ERROR[listen()]: failed\n";
        return 1;
    }
    return app.exec();
}

#include "moc_main.cpp"

EXL ★★★★★ ()
Ответ на: комментарий от quest

Используй нормальную систему контроля версий, делай полную очистку файлов проекта и компиляй с нуля - всё будет работать, без всяких там vtable.

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

я естественно использую git работает только последний вариант EXL. Приведи свой вариант.

quest ★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

Ошибка с `vtable' у него была не из-за некорректной очистки, а из-за того, что он использовал сигналы и слоты без обработки кода Meta Object Compiler'ом.
Хотя согласен с тобой, при создании класса, содержащего Q_OBJECT, MOC может пропустить хэдер, если QMake не выполнялся. Получится тоже ошибка, связанная с `vtable'.

Вторая ошибка, из-за которой не вызывался слот - это, как уже отметили выше, из-за того, что не было вызова mainloop, (вместо него костыль sleep(60);) следовательно слоты отказывались работать.

EXL ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.