Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Developer
Posts: 136
Registered: ‎02-01-2009
My Device: Not Specified
Accepted Solution

Unable to Connect 2 classes by Signals and Slots

I'm trying to transfer Strings from one class to the other.

 

Their strcutures are:

.hpp files------------
class A::public QObject{
Q_OBJECT

signals:
void emitMsg(QString* msg);
}


class B::public QObject{
signals:
void emitA(QString* msgA);
public slots:
void logMsg(QString* msg);
}

---------.cpp files

classB::classB(){
bool temp= connect(objB,SIGNAL(emitA(QString*)),this,SLOT(logMsg(QString*)));

qDebug()<<"value="<<temp;
}

 

But even running in debug mode on the Dev Alpha device, the application neither shows anything in the log messages, nor moves out of the dark spash screen.

 

Please adivse, whats missing from the other code ?

 

Is there any way through which the slots and signals of different classes could be connected for data transfer?

 

 

Retired
Posts: 499
Registered: ‎05-07-2012
My Device: developer
My Carrier: developer

Re: Unable to Connect 2 classes by Signals and Slots

The most likely culprit here is passing the string by pointer.  In some cases this might work -- the string might still be around when the signal handler is invoked -- but in other cases it might not.   QString is a smart pointer already.  Just pass by value.

 

Second most likely culprit is the connect.   Did it successfully connect?  temp will be true, and you will not get a log message.  Rule I use is any place I have connects I put a breakpoint at the end of the routine and I check for console log messages complaining about the connect .  Saves a lot of time because the console message says exactly what is wrong with a connect.

 

In your case, you probably won't get an error message on the connect, but I think you intended to connect the signal from an object of class A, not a signal from another object of class B.  So if from A you emit emitMsg nothing will happen, but if from B you emitA, then B's logMsg should be called.

 

Signals and slots is for loose coupling.  A says: "anyone who cares, here's something that happens."  B says:  "I can do this thing".   Some object -- often a separate object that hooks various pieces together -- connects up the pieces.

 

Stuart

Developer
Posts: 136
Registered: ‎02-01-2009
My Device: Not Specified

Re: Unable to Connect 2 classes by Signals and Slots

[ Edited ]

Hi Stuart,

Good points with the Smart pointers.

I tried using your strategy with the break points and the logs, and although i didnt got the 'connect failed' error in the logs, but i think something weird must be happening with my IDE.

I practically set break point on the whole flow of the program.

and for the code like

bool success1= connect(this,SIGNAL(emitMsg(QString)),connector,SLOT(logMsg(QString)));
qDebug()<<"connect1 "<<success1;

 



as I step over the connect statement, the IDE opens a ""SyncCondvarWait_r"

and then doesnt comes back the next line of qDegug.

I used to see the connect failed error in 10.04 before and also on the current 10.06 system.

Retired
Posts: 499
Registered: ‎05-07-2012
My Device: developer
My Carrier: developer

Re: Unable to Connect 2 classes by Signals and Slots

Um... hmm...

Do you have Q_OBJECT in your class declarations?

Maybe you need a clean rebuild

 

Stuart

Developer
Posts: 136
Registered: ‎02-01-2009
My Device: Not Specified

Re: Unable to Connect 2 classes by Signals and Slots

Ok, tried several times to clean and rebuild and also on different targets too.

 

And just now, tried making a new project to test it through and it still fails.

 

The code of header and class files:

 

class App : public QObject
{
    Q_OBJECT
public:
    Downloader* downloader;
    TextArea* txtArea;
    App();
    public slots:
    void logMsg(QString msg);
};

 

App::App()
{
    QmlDocument *qml = QmlDocument::create("main.qml");
    
    AbstractPane *root = qml->createRootNode<AbstractPane>();
    txtArea=root->findChild<TextArea*>("txtArea");
    txtArea->setText("Temp:");
//    downloader->connector=this;
    bool success = connect(downloader, SIGNAL(emitMsg(QString)), this,
    			SLOT(logMsg(QString)));
    	qDebug() << "connector" << success;
    downloader->init();
    Application::setScene(root);
}

void App::logMsg(QString msg){
QString temp=txtArea->text();
temp=temp+msg;
txtArea->setText(temp);
}

 

class Downloader: public QObject {
Q_OBJECT
public:
QObject* connector;
	Downloader();
	virtual ~Downloader();
	void init();
	signals:
	void emitMsg(QString msg);
};

 //Downloader.cpp , constructor and Destructor are by Default.

void Downloader::init() {
//	bool success = connect(this, SIGNAL(emitMsg(QString)), connector,
//			SLOT(logMsg(QString)));
//	qDebug() << "connector" << success;
	emit emitMsg("test");
}

 

The commented code is the other way i tried to connect the Signal with Slot but that alos fails.

 

Also, just to metion during debugs it does lands on a thread with SIGSEGV - segmentation fault.

Retired
Posts: 499
Registered: ‎05-07-2012
My Device: developer
My Carrier: developer

Re: Unable to Connect 2 classes by Signals and Slots

[ Edited ]

Do you create a Downloader object?

 

(BTW, I always initialize pointers to 0 in the initializer list.  That makes this kind of thing obvious, and it behaves the same for debug and release)

 

Stuart

Developer
Posts: 136
Registered: ‎02-01-2009
My Device: Not Specified

Re: Unable to Connect 2 classes by Signals and Slots

Awesome, initializing the object was the key.

 

Is there any tool that can be used to detect such cases?

 

Seems like obvious that the object was null and then the connection was crashing instead of failing.

Highlighted
Retired
Posts: 499
Registered: ‎05-07-2012
My Device: developer
My Carrier: developer

Re: Unable to Connect 2 classes by Signals and Slots

[ Edited ]

There are tools, but the best approach I've found is just some diligence in coding:

 

- always ensure pointers are initialized in the constructor -- by that I mean even if they are set in the body, have them set to 0 in the initializer list.  That way if someone changes the body you still know it's set to 0 if code in the body is bypassed.

- always check for 0 if a call or line of code can return 0, especially findChild or dynamic_cast

- always either log cases that should never happen or step through the code in the debugger to make sure you go through the code you intend.

- never assume a pointer is not zero -- check at top of a routine, or add a comment that it's guaranteed created in the constructor.

- when debugging any line that has a pointer, check that the pointer is valid if stepping over the line crashes.

 

Memory checking tools are just too time consuming for me.  I prefer to need those tools as rarely as possible, and prefer to find these bugs by construction early.

 

Stuart