Seite 1 von 1

SIGNALs, SLOTs und die lieben Zeiger

Verfasst: 21. Juni 2011 16:09
von Mr_Burns
Moin moin,

derzeit probiere ich folgendes zu realisieren (Auszug):

Code: Alles auswählen

//a.h

#ifndef A_H
#define A_H

#include <QObject>

class a : public QObject {
	Q_OBJECT
public:
	a();
    ~a();

protected slots:
	void sendData(QByteArray *data);
};

#endif // a_H

Code: Alles auswählen

// a.cpp


#include "a.h"

a::a() {
}

a::~a() {
}

void a::sendData(QByteArray *data) {

// naja, hier mache ich dann halt was mit meinen Daten

}

Code: Alles auswählen

//b.h

#ifndef B_H
#define B_H

#include <QObject>

class b : public QObject{
	Q_OBJECT

public:
    explicit b();
    ~b();

signals:
	void sendToUart(QByteArray *data);

public slots:
   void stop();
};

#endif // b_H

Code: Alles auswählen

//b.cpp

#include "b.h"
b::b() {
}

b::~b() {
}

void b::stop() {
	QString data	= "Hallo";
	QByteArray strAscii;

	strAscii.append(data.toAscii());

	emit sendToUart(&strAscii);
}

In der Mainfunktion erstelle ich sowohl von a, als auch b ein Objekt und verbinde die dann mit einem connect:

Code: Alles auswählen

connect(obj_b, SIGNAL(sendToUart(QByteArray *data)), obj_a, SLOT(sendData(QByteArray *data)));
Die Methode b::stop() wird über einen Button aufgerufen. Mein Problem ist jetzt, dass mein Slot sendData nie zum Einsatz kommt. Sprich, wenn ich dort ein einfaches printf() reinbaue, gibt dies nichts aus. Wenn ich jetzt aber den Übergabeparameter QByteArray *data herausnehme oder statt diesem ein einfaches char data verwende geht alles prima; nur dass ich meine Daten von dem Signal nicht an den Slot übergeben bekomme. Da ich auch selbige Probleme mit einem Pointer char *data habe frage ich mich ob Signale und Slots einfach keine Pointer übergeben bekommen dürfen.

Kann mir hier jemand bitte weiterhelfen? Im Internet habe ich leider nichts befriedigendes gefunden.

Also noch einmal zusammengefasst:

sendData(char data) --> funktioniert mit entsprechendem Signal
sendData(char *data) --> funktioniert nicht und mein gewünschtes
sendData(QByteArray *data) --> geht leider gar nicht.

Viele Grüße und besten Dank im Voraus
Mr_Burns

Verfasst: 21. Juni 2011 16:16
von Marco26
Hallo,

ich vermute mal es liegt daran, dass man in der Connect-Funktion beim Slot und beim Signal zwar den Typ als Übergabeparameter angiebt aber nicht den Parameter selbst.

connect(obj_b, SIGNAL(sendToUart(QByteArray*)), obj_a, SLOT(sendData(QByteArray*)));

Gruß Marco

Verfasst: 21. Juni 2011 16:22
von Mr_Burns
Hallo Marco,

da scheinst du Recht zu haben. Jetzt funktioniert bei mir alles wie gewünscht und viel wichtiger, habe es auch verstanden ;-).

Tausend Dank,
Mr_Burns

Verfasst: 21. Juni 2011 17:09
von solarix
Offtopic, aber:

Code: Alles auswählen

void b::stop() {
   QString data   = "Hallo";
   QByteArray strAscii;

   strAscii.append(data.toAscii());

   emit sendToUart(&strAscii);
} 
Durch den Pointer schaffst du dir unnötige Probleme: Wird das Signal als QueuedConnection (z.B. über Threads) connected, bekommst du hier ein Crash. Besser wäre eine Reference (void sendToUart(const QByteArray &)). Die ist bei einer Direct-Connection so schnell wie ein Pointer aber funktioniert auch via QueuedConnection (da wird dann eine Kopie erzeugt).

Oder du lässt es gleich komplett bleiben und übergibst gleich direkt ein QByteArray (void sendToUart(QByteArray)), weil es "implicit shared" ist (kein DeepCopy beim Slotaufruf).

http://doc.qt.nokia.com/latest/implicit-sharing.html

hth!

Verfasst: 21. Juni 2011 18:54
von Mr_Burns
Oder du lässt es gleich komplett bleiben und übergibst gleich direkt ein QByteArray (void sendToUart(QByteArray)), weil es "implicit shared" ist (kein DeepCopy beim Slotaufruf).
Das mit dem "implicit shared" wusste ich noch gar nicht und ist ja richtig genial :wink:

Auch dir vielen Dank.

Verfasst: 21. Juni 2011 19:14
von Mr_Burns
Okay, anscheinend war ich zu voreilig. Wenn ich das richtig verstanden habe, dann ist es so, dass mit "implicit shared" keine echte Kopie angelegt wird. Vielmehr wird auf den ursprünglichen Speicherbereich gezeigt (also ein Zeiger) und eine Variable hochgezählt, dass es jetzt zwei dieser Variablen gibt. Ändert man eine, werden beide in separate Speicherbereiche getrennt, da sie ja verschiedene Inhalte haben sollen. So weit so gut, wenn ich das jetzt auf mein Problem übertrage bedeutet dies doch für mich, dass ich dies wie folgt löse:

Code: Alles auswählen

void b::stop() { 
   QString data   = "Hallo"; 
   QByteArray strAscii; 

   strAscii.append(data.toAscii()); 

   emit sendToUart(strAscii); 
}
Und mein SLOT und mein SIGNAL sehen dann so aus:

Code: Alles auswählen

void sendData(QByteArray data); 

Code: Alles auswählen

void sendToUart(QByteArray data); 
und mein connect wie folgt:

Code: Alles auswählen

connect(obj_b, SIGNAL(sendToUart(QByteArray)), obj_a, SLOT(sendData(QByteArray)));
Anscheinend habe ich das Prinzip nicht richtig verstanden, da in der Methode sendData(QByteArray data) absolut nichts ausgelöst wird.

Verfasst: 21. Juni 2011 19:33
von Mr_Burns
... scheint doch alles gut zu sein. Ich hatte den Quellcode mit den Pointern schon weiter geschrieben gehabt, so dass der Fehler woanders lag.