Anzeige:
Ergebnis 1 bis 11 von 11

Thema: qt Probleme mit dem moc

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Registrierter Benutzer
    Registriert seit
    04.11.2012
    Beiträge
    23

    qt Probleme mit dem moc

    Hallo zusammen,

    ich entwickle gerade ein Programm, für das ich die qt Bibliothek verwende. Da ich damit bisher noch nie ernsthaft gearbeitet habe funktioniert natürlich nix. Da ich keine Erfahrungen habe komme ich alleine leider auch nicht weiter.
    In dem Projekt sollen verschiedene Klassen ein Signal emitieren, wenn sich bestimmte Daten ändern und eine zentrale Klasse soll das dann (zunächst nur als Terminalausgabe) Darstellen. Dazu die Headerdatei
    Code:
    #ifndef DARSTELLUNG_H_
    #define DARSTELLUNG_H_
    #include <iostream>
    
    class Darstellung{
    	Q_OBJECT
    private:
    	int *status;
    	void out();
    public:
    	Darstellung();
    public slot:
    	void setStatus(int, int);
    };
    #endif
    und die Quelldatei
    Code:
    #include "Darstellung.h"
    
    Darstellung::Darstellung() {
    	status = new int[4];
    	for(int i=0; i<5; i++){
    		status[i] = 0;
    	}
    }
    
    void Darstellung::setStatus(int n, int s){
    	status[n] = s;
    	out();
    }
    
    void Darstellung::out(){
    	for(int i=0; i<5; i++){
    		std::cout << status[i] << " ";
    	}
    	std::cout << std::endl;
    }
    versuche ich das nun über
    Code:
    qmake -project
    qmake
    make
    zu kompilieren kommen die folgenden Fehlermeldungen:
    Code:
    g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -o Darstellung.o Darstellung.cpp
    In file included from Darstellung.cpp:8:0:
    Darstellung.h:20:8: Fehler: expected »:« before »slot«
    Darstellung.h:20:8: Fehler: »slot« bezeichnet keinen Typ
    Darstellung.cpp:17:41: Fehler: keine Elementfunktion »void Darstellung::setStatus(int, int)« in Klasse »Darstellung« deklariert
    make: *** [Darstellung.o] Fehler 1
    Natürlich bezeichnet slot keinen Typ, aber diese Schlüsselwörter sollten doch eigentlich durch den moc ersetzt werden, dafür setzt man doch extra das Q_OBJECT? Muss man den moc irgendwie speziell aufrufen? So wie ich das verstanden hatte reichen die 3 Zeilen.

    Mit freundlichem Gruß
    Javatar

  2. #2
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Es sollte "slots" in der Mehrzahl heißen, oder "Q_SLOT" vor jedem Slot einzeln. Q_SLOT hat den Vorteil das es sich als Makro an die verbreitete Großbuchstaben-Konvention hält, für "slots" (ebenfalls ein Makro) ist das nicht der Fall.

    Also Beispiel:
    Code:
    class Darstellung{
    	Q_OBJECT
    private:
    	int *status;
    	void out();
    public:
    	Darstellung();
    
    Q_SLOT	void setStatus(int, int);
    };
    Nachtrag am 30.05: anda_skoa hat Recht in seinen beiden Beiträgen unten. Hier müsste noch mehr ausgebessert werden.
    Geändert von locus vivendi (30-05-2013 um 15:06 Uhr)

  3. #3
    Registrierter Benutzer
    Registriert seit
    04.11.2012
    Beiträge
    23
    Vielen Dank für die schnelle Antwort. Ich hasse es, wenn es an so kleinen Schreibfehlern scheitert Die übrigen Fehler (aufrufen des mocs und einbinden der .moc anstelle der .h) habe ich jetzt noch selbst korrigiert. Jetzt kann ich endlich anfangen die logischen Fehler im Programm zu korrigieren.

  4. #4
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von locus vivendi Beitrag anzeigen
    Q_SLOT hat den Vorteil das es sich als Makro an die verbreitete Großbuchstaben-Konvention hält, für "slots" (ebenfalls ein Makro) ist das nicht der Fall.
    Es gibt Q_SLOTS

    Der ursprüngliche Code hatte auch noch das Problem, dass #include <QObject> gefehlt hat und Darstellung keine QObject Subklasse war.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  5. #5
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von javatar Beitrag anzeigen
    Natürlich bezeichnet slot keinen Typ, aber diese Schlüsselwörter sollten doch eigentlich durch den moc ersetzt werden, dafür setzt man doch extra das Q_OBJECT? Muss man den moc irgendwie speziell aufrufen? So wie ich das verstanden hatte reichen die 3 Zeilen.
    Die Präprozessor Definitionen sind in der Datei qglobal.h, die indirekt über QObject oder eine davon abgeleitet Klasse inkludiert wird.

    Die drei Checklistenpunkte für Qt Slots sind immer
    1. QObject Subklasse (direkt oder indirekt)
    2. Q_OBJECT Macro
    3. public/protected/private slots/Q_SLOTS Sektion


    Für Signale gelten die ersten beiden Punkte plus signals/Q_SIGNALS Sektion

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  6. #6
    Registrierter Benutzer
    Registriert seit
    04.11.2012
    Beiträge
    23
    Hallo nochmal,

    ich habe jetzt noch ein weiteres Problem mit den Signal/Slots in Verbindung mit Threads. Die Threads sollen ein signal emittieren, dass eine andere Klasse dann fängt, allerdings kommt es da scheinbar nie an.
    Habe dazu auch schon viel ergoogelt, allerdings habe ich entweder die Lösungen nicht verstanden, sie haben nicht funktioniert, es gab gar keine oder das Problem lag woanders.

    Im Anhang befindet sich eine kleines Testprogramm, als Ausgabe hätte ich gerne ein paar mal die 1, allerdings kommt einfach gar nichts. Wäre super, wenn es auch dafür eine einfache Lösung gäbe.

    Liebe Grüße

    Edit: Kann mir auch noch jemand kurz erklären, warum cout Ausgaben nicht mehr im Terminal erscheinen, sonderm man stattdessen qDebug verwenden muss. Ich muss mein Programm, wenn es mal fertig ist, anderen Leuten vorstellen und da wäre es natürlich gut, wenn ich sowas auch begründen könnte
    Geändert von javatar (02-06-2013 um 12:47 Uhr)

  7. #7
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Ich kenne mich mit Qmake nicht aus, aber ich glaube in deiner Beispiel.pro muss noch eine "CONFIG += qt"-Zeile hinein. Siehe hier:
    http://qt-project.org/doc/qt-4.8/qmake-tutorial.html

    Kann mir auch noch jemand kurz erklären, warum cout Ausgaben nicht mehr im Terminal erscheinen, sonderm man stattdessen qDebug verwenden muss. Ich muss mein Programm, wenn es mal fertig ist, anderen Leuten vorstellen und da wäre es natürlich gut, wenn ich sowas auch begründen könnte
    Stichwort "Pufferung".

    Es dünkt mich übrigens, dass dein Beispielprogramm kein besonders gelungenes Beispiel für Nebenläufigkeit ist, weil du direkt nach dem Starten jedes einzelnen Threads auf dessen Ende wartest. Im Effekt werden also die Threads hintereinander ausgeführt, und nicht parallel. Natürlich könnte das auch Absicht sein, ich wollte es trotzdem erwähnen.

  8. #8
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von javatar Beitrag anzeigen
    ich habe jetzt noch ein weiteres Problem mit den Signal/Slots in Verbindung mit Threads. Die Threads sollen ein signal emittieren, dass eine andere Klasse dann fängt, allerdings kommt es da scheinbar nie an.
    Für Signal/Slot Verbindungen zwischen Objekten in zwei Threads gibt es mehr oder weniger zwei Möglichkeiten:
    1. Direkte Verbindung
    2. Indirekte Verbindung


    Bei ersterem erfolgt der Slotaufruf wie im Singlethread Fall direkt, d.h. der Thread, der emit ausführt, führt auch den Slot aus.
    Erreicht wird das durch Angabe von Qt:irectConnection als fünften Parameter von conenct().

    Logischerweise obliegt es dann dem Applikationscode die Threadsicherheit zu gewährleisten.

    Bei der zweiten Möglichkeit (normales connect() oder Angabe von Qt::QueuedConnection als fünften Parameter) werden die Argumente des Signals mittels Event an das Empfängerobjekt geschickt, der Aufruf des Slots erfolgt damit im Zielthread.

    Die Vorraussetzung dafür ist das Laufen der Eventverarbeitung im Zielthread. Im Falle des Hauptthreads ist das üblicherweise durch app.exec() gewährleistet (was in deinem Fall fehlt).

    Edit: Kann mir auch noch jemand kurz erklären, warum cout Ausgaben nicht mehr im Terminal erscheinen, sonderm man stattdessen qDebug verwenden muss. Ich muss mein Programm, wenn es mal fertig ist, anderen Leuten vorstellen und da wäre es natürlich gut, wenn ich sowas auch begründen könnte
    Funktioniert bei mir einwandfrei wenn ich qDebug() durch cout ersetze und << endl am Ende der Zeile hinzufüge.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  9. #9
    Registrierter Benutzer
    Registriert seit
    04.11.2012
    Beiträge
    23
    Vielen dank erstmal für die guten Rückmeldungen.

    Es dünkt mich übrigens, dass dein Beispielprogramm kein besonders gelungenes Beispiel für Nebenläufigkeit ist, weil du direkt nach dem Starten jedes einzelnen Threads auf dessen Ende wartest
    Da hast du natürlich vollkommen Recht, dieser Fehler ist erst beim erstellen dieses "Minimalbeispiels" entstanden, da ich dort alle Schleifen möglichst zusammenfassen wollte. Trotzdem danke für den Hinweis.

    Erreicht wird das durch Angabe von Qt:irectConnection als fünften Parameter von conenct().
    Logischerweise obliegt es dann dem Applikationscode die Threadsicherheit zu gewährleisten.
    Das ist quasi die Variante, die ich erwartet hatte. Für die Threadsicherheit würde es doch genügen, einfach in dem Slot am Anfang einen Mutex zu sperren oder?

    Bei der zweiten Möglichkeit (normales connect() oder Angabe von Qt::QueuedConnection als fünften Parameter) werden die Argumente des Signals mittels Event an das Empfängerobjekt geschickt, der Aufruf des Slots erfolgt damit im Zielthread.

    Die Vorraussetzung dafür ist das Laufen der Eventverarbeitung im Zielthread. Im Falle des Hauptthreads ist das üblicherweise durch app.exec() gewährleistet (was in deinem Fall fehlt).
    Kannst du das vielleicht noch etwas genauer erklären? Wo müsste in dem Beispiel der exec-Aufruf erfolgen?

    Funktioniert bei mir einwandfrei wenn ich qDebug() durch cout ersetze und << endl am Ende der Zeile hinzufüge.
    Da hast du wohl recht, ich weiß gerade aber auch nicht mehr ganz genau wie ich auf die Idee kam, dass das nicht funktionieren würde.

  10. #10
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von javatar Beitrag anzeigen
    Das ist quasi die Variante, die ich erwartet hatte. Für die Threadsicherheit würde es doch genügen, einfach in dem Slot am Anfang einen Mutex zu sperren oder?
    Ja.

    Zitat Zitat von javatar Beitrag anzeigen
    Kannst du das vielleicht noch etwas genauer erklären? Wo müsste in dem Beispiel der exec-Aufruf erfolgen?
    Üblicherweise sieht die main Funktion eines Qt Programms in etwas so aus
    Code:
    int main(int argc, char **argv)
    {
        QCoreApplication app(argc, argv); // oder QApplication wenn GUI benutzt wird
    
        // objekt(e) erzeugen
    
        return app.exec(); // Eventverarbeitung starten.
    }
    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •