We are hard at work on the BlackBerry 10 Native SDK helper class for cloudbase.io – this means C++ and Qt. It has been a learning process and we thought we’d share some of our newly found wisdom.
ApplicationPrivate::resourceManager: ERROR called from non-UI thread QThread…
How many times have we seen this? When we began working on the helper class we were relatively new to Qt development. Let’s face it, BlackBerry specific information is not exactly abundant on the net. So here’s our simple tutorial.
For the purpose of this example and the cloudbase.io helper class the scenario is fairly simple. The CBHelper object – i.e. the helper class – runs on the main UI thread. Whenever an API is called, a CBHttpConnection object handles the request and the response. The HttpConnection object implements QThread, this way the entire http connection is executed asynchronously without slowing down the main UI thread.
Once the processing is completed we need to call a method on the CBHelperResponder object, which was passed to the helper class to manage the response. This method may very well need to update the application’s GUI. We need to get back to the main UI thread!

The Qt libraries used by the BlackBerry 10 Native SDK have implemented this in the form of SIGNALS and SLOTS. Any class inheriting from QObject will be able to declare a number of SIGNALS it can emit as well as SLOTS to receive these SIGNALS.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// first we declare our slot to receive the SIGNAL emitted by the http connection // in the main CBHelper class class CBHelper : public QObject { // the Q_OBJECT macro tells the pre-processor we are implementing a QObject Q_OBJECT public: // our public methods // in this case we are using the Q_SLOTS macro to declare slots // you could also use the public slots: syntax public Q_SLOTS: // here is our slot method to handle the response from the http // connection. It receives the populated and parsed response data // and a responder object initially given by the main application to the // CBHelper class. the parseResponse method of the CBResponder // object will be triggered from here void handleRequestCompleted(CBHelperResponseInfo resp, CBHelperResponder* responder); } // now we can declare the http connection class which is our implementation // of QThread and will need to emit the signal intercepted by the handleRequestCompleted // SLOT we have declared above class CBHttpConnection : public QThread { Q_OBJECT public: // our public methods // here we use the Q_SIGNALS macro to declare the signals that can be emitted // by the CBHttpConnection class. This could have also been written as "signals:" Q_SIGNALS: void requestCompleted(CBHelperResponseInfo resp, CBHelperResponder* responder); } |
You will have noticed that what we have been writing is not exactly standard C++ syntax and keywords. The Q_OBJECT, Q_SLOTS and Q_SIGNALS macros we have put in our class declaration will be used to generate meta-object information by a Qt utility aptly named MOC (Meta Object Compiler). Moc will process our headers and generate as output additional header files with all the information Qt needs to connect the SIGNALS and SLOTS and trigger them. The BlackBerry 10 documentation has an extensive guide on how to use moc and automate it in your project’s Makefile. In this example we will manually run moc over the two headers we have modified, CBHelper.h and CBHttpConnection.h.
The moc tool is located under your BlackBerry SDK installation folder in the host_xx_x_xx_xxx/${HOST_OS}/${HOST_CPU}/usr/bin – We are building this on a MacBook Pro so our path will be /Applications/bbndk/host_10_0_10_534/darwin/x86/usr/bin/moc
|
1 2 3 4 5 |
# first we generate the CBHelper.moc file # the syntax is pretty straightforward. -i <input file> -o <output file> /Applications/bbndk/host_10_0_10_534/darwin/x86/usr/bin/moc -i src/CBHelper.h -o src/CBHelper.moc /Applications/bbndk/host_10_0_10_534/darwin/x86/usr/bin/moc -i src/CBHttpConnection.h -o src/CBHttpConnection.moc |
Now that we have generated the two new .moc files we can include them in our source. We will add them at the bottom of the implementation files for the two classes. For example, at the bottom of CBHelper.cpp we will add the #include “CBHelper.moc” instruction.
We are nearly there. All we have to do now is tell Qt how to connect the dots and associate the requestCompleted SIGNAL with the handleRequestCompleted SLOT in the CBHelper object. We do not need to implement the requestCompleted SIGNAL as it is there only as a declaration. We will add the implementation of the SLOT to the CBHelper.cpp file.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// this is a dummy method to start a new CBHttpConnection thread void CBHelper::startConnection() { CBHttpConnection* con = new CBHttpConnection() // at this point we will hand a CBHelperResponder* to the connection // so it can be called later. // We need to inform the Qt Meta Object System that we are going // to use these object types qRegisterMetaType< CBHelperResponder* >("CBHelperResponder*"); qRegisterMetaType< CBHelperResponseInfo >("CBHelperResponseInfo"); // here we connect the dots. We are telling Qt that the requestCompleted // SIGNAL on the "con" object should be associated with the handleRequestCompleted // SLOT on "this" QObject::connect( con, SIGNAL(requestCompleted(CBHelperResponseInfo, CBHelperResponder*)), this, SLOT(handleRequestCompleted(CBHelperResponseInfo, CBHelperResponder*)) ); } // implementation of our SLOT void CBHelper::handleRequestCompleted(CBHelperResponseInfo resp, CBHelperResponder* responder) { if ( responder != NULL ) { responder->parseResponse(resp); } } |
There is only one thing left to do. Emit the signal from the CBHttpConnection class. This couldn’t be easier. Emit’s the keyword.
|
1 2 3 |
// we are done parsing all the output and our Thread is about to // finish emit requestCompleted(resp, this->CBResponder); |
Hope this was helpful.
Happy coding.
The Team @ cloudbase.io
Pingback: cloudbase.io comes to BlackBerry - Cloudbase.io Blog