Project Home
Project Home
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - Calling an event function in a QT thread from a QNX thread.: (6 Items)
   
Calling an event function in a QT thread from a QNX thread.  
Hello,

I have a 'AM335x EVM board' and have downloaded the BSP “Texas Instruments AM335x EVM” project. I use QNX 6.5.0 and 
Momentics 4.7.0.

 I have an issue that I don’t know how to call event/message functions inside the “QT thread” from a QNX thread in my
 QNX application.

In main I create a thread for receiving can messages.  When I have received a can message I would like to send an event/
message/signal to my “myqtclass” event function or another function inside the object. I end up in the function 
myqtcalss::event but I still execute in the “qnx function thread” not the “QT thread”. Because of this I receive an 
error message from QT. I would like to send an event/message/signal so the “QT thread” execute it. Do you have any 
suggestion how to do this?

Example code:

*********************

main.c

MyQTClass *myqtcalss;

int main(int argc, char **argv)
{
   // Creating QNX can receive function thread
   …

   QApplication app(argc, argv);

   // QT code
   …
   myqtcalss = new MyQTClass; 
   …

   return app.exec();
}

*********************

myclass.cpp

bool myqtcalss::event(QEvent *event)
{
   // Here I would like to end up in the “QT thread”
}

*********************

qnx.c

void QNX_thread_function( void *pvParameters )
{
   // Code that executes when a can message is received
   QEvent event((QEvent::Type)1001);
   QApplication::sendEvent(myqtclass, &event);
}

*********************
Re: Calling an event function in a QT thread from a QNX thread.  
Magnus-

This example has a thread which "signals" back to the UI...

http://community.qnx.com/sf/discussion/do/listPosts/projects.qt/discussion.general.topc20365

Note that the thread is created as a Qt object (not pthread_create) but thread execution is the same.  Here the thread 
is waiting to be notified by pps, but it could be waiting for a CAN message.

If you don't want your CAN logic in a Qt thread, you could wait for a pulse in the Qt thread, and send the pulse from a 
standard (non-Qt) C program with CAN knowledge.  This way, you can easier debug the more complex non-Qt portion, and 
your UI remains simple.
Re: Calling an event function in a QT thread from a QNX thread.  
Hello,

I have looked into the example. I don’t have a qml application, instead I have written all QT sw with objects.

In the example the thread calls valuesChanged, which is a signal that I guess is linked into the qml code as 
onValuesChanged. How do I do if I don’t have qml and want this “onValueChanged” to be a function in the class instead
?

/Magnus
Re: Calling an event function in a QT thread from a QNX thread.  
Yes, I realize you are not using QML... why, I don't know since that is the current Qt-preferred method.

Still, from what I have read, signals and slots existed prior to QML.  So you need to find such an example.  Some of the
 signal/slot packaging of qTstat will likely still apply.
Re: Calling an event function in a QT thread from a QNX thread.  
Hello Magnus,

>  I have an issue that I don’t know how to call event/message functions inside
>  the “QT thread” from a QNX thread in my QNX application.
> 
> In main I create a thread for receiving can messages.  When I have received a 
> can message I would like to send an event/message/signal to my “myqtclass” 
> event function or another function inside the object. I end up in the function
>  myqtcalss::event but I still execute in the “qnx function thread” not the 
> “QT thread”. Because of this I receive an error message from QT. I would 
> like to send an event/message/signal so the “QT thread” execute it. Do you 
> have any suggestion how to do this?
> 
This is because QCoreApplication::sendEvent() will call QObject::event()
directly, as if it were a simple function call, and therefore it will run on the
caller's thread context (i.e. the QNX thread in your program). Qt has a rule
that events can obly be sent to objects in the current thread, i.e. sending
events directly accross threads, using QCoreApplication::sendEvent() is
forbidden. 

The easiest way to solve your problem is to use QCoreApplication::postEvent()
(or QApplication, in your case). Unlike QCoreApplication::sendEvent(),
QCoreApplication::postEvent() will push the event to the receiver thread's event
equeue, and the event will be processed only when the control returns to the
receiver's thread main loop. This ensures that the event will be processed on
the context of the receiver's thread, which is the behavior you are expecting.
Please note that the event must be allocated on the heap, since the post event
queue will take ownership of the event and delete it once it has been posted.

In practice, your code should look like:

void QNX_thread_function( void *pvParameters )
{
    // Code that executes when a can message is received
    QEvent *event = new QEvent(static_cast<QEvent::Type>(QEvent::UserType + 1));
    QApplication::postEvent(myqtclass, event);
}

However, if all you would like to do is signalizing your Qt class that a CAN
message has arrived, you can instead take advantage of the Qt MetaObject system
instead of reimplementing QObject::event().

class myqtclass : public QObject
{
    Q_OBJECT
    
    public:
        /* ... */
    
    Q_INVOKABLE void canMessageArrived();
};

and then:

void QNX_thread_function( void *pvParameters )
{
    // Code that executs when a can message is received
    QMetaObject::invokeMethod(myqtclass, "canMessageArrived", Qt::QueuedConnection);
}

In a nutshell, the Q_INVOKABLE macro tells the Qt MetaObject system that canMessageArrived can be invoked using 
QMetaObject::invokeMethod - it is a bit more complicated than that under the hood, but let's leave it like this for the 
sake of simplicity. The caveat then is passing Qt::QueuedConnection to QMetaObject::invokeMethod. This means that, 
instead of invoking the method directly (akin to QApplication::sendEvent()), the method is invoked when control returns 
to the event loop of the receiver's thread and is executed in the context of the receiver's thread (akin to QApplication
::postEvent()). You can also use Qt::BlockingQueuedConnection - the difference is that, while QMetaObject::
invokeMethod() will return immediately with the former, when using the latter it will only return after the method has 
been executed.

I hope that helps.

Cheers,

Rafael

---
Rafael Roquetto | rafael.roquetto@kdab.com | Software Engineer
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel. Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - Qt Experts - Platform-independent software solutions
Re: Calling an event function in a QT thread from a QNX thread.  
Thanks guys,

It is now working using either “Signals and slots” or “Qt MetaObject system” way.

Thanks again for quick and very good support..

/Magnus