Hi,
ich weiß, dass es hier schon einige Beiträge dazu gibt, wie man damit umgeht wenn nach dem adden des Q_OBJECT-Makros das Programm nicht mehr ordentlich kompiliert. Ich habe mir dazu auch die FAQ von Christian81 durchgelesen und entsprechend in QT den "Bereinigen" und "Neu erstellen"-Schritt ausgeführt, was aber keinen Erfolg zeigte. Hier meine kleine Klasse die das Problem verursacht. Rot hervorgehoben was ich hinzugefügt habe.
#ifndef LISTENER_H
#define LISTENER_H
#include <QThread>
#include <qextserialport.h>
class listener : public QThread
{
Q_OBJECT
public:
inline listener(QextSerialPort *comPort, int Length):
Port(comPort),
length(Length)
{
connect(this,SIGNAL(finished()),this,SLOT(deleteLater()));
}
signals:
inline void ready(){}
private:
inline virtual void run(){
while(true)
if(Port->bytesAvailable()==length)emit ready();
}
QextSerialPort *Port;
int length;
};
#endif // LISTENER_H
Grüße, LotB
vtable Problem
Re: vtable Problem
Hallo!
Wo in den Qt-Beispielen werden Signals als "inline" deklariert..?
hth..
"keinen Erfolg zeigen" ist keine Fehlerbeschreibung..wir brauchen präzise Angaben, wie z.B. konkrete Fehlermeldungen des Compilers/Linkers.LotB hat geschrieben:...was aber keinen Erfolg zeigte.
Code: Alles auswählen
inline void ready(){}
hth..
Also die Fehlermeldung war: undefined reference to vtable of listener.
Allerdings funktioniert das Programm jetzt obwohl ich nichts weiter getan habe als ein altes Projekt von mir nochmal auszuführen, was überhaupt nichts mit dem zu tun gehabt hat. War auch nur aus Langeweile. Der Code sieht jetzt so aus und funktioniert. Keine Ahung was passiert ist.. manchmal ist Qt schon so ein kleines zickiges Mädchen...
PS: @solarix. Das mit dem Signal war echt Blödsinn. Hatte die Variante ohne das "inline" vorher aber auch schon getestet. Daran lags also nicht.
Danke trotzdem.
Allerdings funktioniert das Programm jetzt obwohl ich nichts weiter getan habe als ein altes Projekt von mir nochmal auszuführen, was überhaupt nichts mit dem zu tun gehabt hat. War auch nur aus Langeweile. Der Code sieht jetzt so aus und funktioniert. Keine Ahung was passiert ist.. manchmal ist Qt schon so ein kleines zickiges Mädchen...
Code: Alles auswählen
#ifndef LISTENER_H
#define LISTENER_H
#include <QThread>
#include <qextserialport.h>
class listener : public QThread
{
Q_OBJECT
public:
inline listener(QextSerialPort *comPort, int Length):
Port(comPort),
length(Length)
{
connect(this,SIGNAL(finished()),this,SLOT(deleteLater()));
}
signals:
void ready();
private:
inline virtual void run(){
while(true)
if(Port->bytesAvailable()==length)emit ready();
}
QextSerialPort *Port;
int length;
};
#endif // LISTENER_H
Danke trotzdem.
Schön, dass es nun klappt..
BTW:
die Art wie du "inline" einsetzt ist nicht schön... Wenn du nicht auf "inline" angewiesen bist, implementiere die Methoden immer in der Source-Datei, nicht in der Header! Denk daran, dass "Faulheit" immer ein schlechter Begleiter beim Programmieren ist...
BTW2:
Ich glaube, dass du Threading noch nicht so ganz verstanden hast.. denn
1. ist QextSerialPort vermutlich nicht MT-tauglich sondern nur reentrant
2. belegt deine run-Methode durch das "active-Wait" einen ganzen CPU-Kern
3. kann, wenn du die run-Methode nie verlässt, kein finished-Signal kommen
Daher: beim vorliegenden Beispiel würde ich keinen Thread nehmen, sondern lediglich ein QTimer (oder gleich das readyRead()-Signal des QextSerialPorts verwenden).
hth!
BTW:
die Art wie du "inline" einsetzt ist nicht schön... Wenn du nicht auf "inline" angewiesen bist, implementiere die Methoden immer in der Source-Datei, nicht in der Header! Denk daran, dass "Faulheit" immer ein schlechter Begleiter beim Programmieren ist...
BTW2:
Ich glaube, dass du Threading noch nicht so ganz verstanden hast.. denn
1. ist QextSerialPort vermutlich nicht MT-tauglich sondern nur reentrant
2. belegt deine run-Methode durch das "active-Wait" einen ganzen CPU-Kern
3. kann, wenn du die run-Methode nie verlässt, kein finished-Signal kommen
Daher: beim vorliegenden Beispiel würde ich keinen Thread nehmen, sondern lediglich ein QTimer (oder gleich das readyRead()-Signal des QextSerialPorts verwenden).
hth!
Danke für deine Antwort. Ich kann dir ja mal kurz darlegen warum ich mich für einen Thread entschieden hab:
zu der Inline-Sache: Ich wollte wegen diesem kleinen Konstrukt nicht notwendigerweise 2 Dateien anlegen, und hab deswegen das bisschen Code in der Header-Datei untergebracht.
zu dem Thread:
Ich hab im Prinzip eine serielle Schnittstelle der ich einen Befehl zuschiebe. Die Maschine die daran angeschlossen ist schickt mir dann irgendwann eine Antwort zurück. Das alles läuft über diesen comPort der im Code vorkommt. Vor dem Thread hatte ich diese Variante um die Antwort auszulesen:
comPort.writeCommand(...);
QTimer::singleshot(500,receive);
receive(){
..
}
Das hat auch in 95% der Fälle geklappt, aber eben nicht in 100%.
Dann hatte ich:
comPort.writeCommand(...);
while(comPort.bytesAvailable() != 20) {} // Die Antwort ist immer 20 bytes groß.
receive();
Dabei ist aber immer die GUI eingefroren logischerweise, die ich ja brauche. Allerdings 100% Erfolg bei der Art und Weise.
Deshalb wollt ich dasselbe Konstrukt dem Thread überlassen, damit ich die GUI weiternutzen kann.
Ich hätte ja gerne solche Funktionen wie QIODevice::waitForBytesWritten , aber diese Funktionen sind mir leider komplett schleierhaft. Habt ihr vielleicht noch eine Idee?
Beste Grüße
zu der Inline-Sache: Ich wollte wegen diesem kleinen Konstrukt nicht notwendigerweise 2 Dateien anlegen, und hab deswegen das bisschen Code in der Header-Datei untergebracht.
zu dem Thread:
Ich hab im Prinzip eine serielle Schnittstelle der ich einen Befehl zuschiebe. Die Maschine die daran angeschlossen ist schickt mir dann irgendwann eine Antwort zurück. Das alles läuft über diesen comPort der im Code vorkommt. Vor dem Thread hatte ich diese Variante um die Antwort auszulesen:
comPort.writeCommand(...);
QTimer::singleshot(500,receive);
receive(){
..
}
Das hat auch in 95% der Fälle geklappt, aber eben nicht in 100%.
Dann hatte ich:
comPort.writeCommand(...);
while(comPort.bytesAvailable() != 20) {} // Die Antwort ist immer 20 bytes groß.
receive();
Dabei ist aber immer die GUI eingefroren logischerweise, die ich ja brauche. Allerdings 100% Erfolg bei der Art und Weise.
Deshalb wollt ich dasselbe Konstrukt dem Thread überlassen, damit ich die GUI weiternutzen kann.
Ich hätte ja gerne solche Funktionen wie QIODevice::waitForBytesWritten , aber diese Funktionen sind mir leider komplett schleierhaft. Habt ihr vielleicht noch eine Idee?
Beste Grüße