Signal not found at runtime
-
QThread uses Qt::QueuedConnection so the arguments passed from signals must be valid metatypes you have to register IclStreamMessage* as metatype
The way to confirm this is the source of the problem is replacing
void messageReceived(IclStreamMessage *msg);
withvoid messageReceived(int);
and see if it works -
@CentralScrutinizer said:
connect(ui->btnStop, &QPushButton::clicked, streamer, &IclStreamController::stopStream);
By the way, doesn't this give you a compile error - argument mismatch (no possible conversion)?
-
@VRonin Oh yes those are in a header file on their own.
Q_DECLARE_METATYPE(IclStreamMessage) Q_DECLARE_METATYPE(IclStreamMessage*)
Without those I get a compile error to the effect of:
error: 'qt_metatype_id' is not a member of 'QMetaTypeId<IclStreamMessage*>The problem I'm having shows up at runtime. I also tried putting this in my main.cpp which had no effect:
qRegisterMetaType<IclStreamMessage>(); qRegisterMetaType<IclStreamMessage*>();
Does QObject::connect automatically use a queued connection if the object is has been moved to a different thread or do I have to specify that?
-
@CentralScrutinizer said:
When I try to connect the signals in IclStreamController, I get "QObject::connect: signal not found in IclStreamController" on the console
Strange, I can't see anything wrong with the code you posted.
What happens if you completely delete your build directory, and re-build your project from scratch?
Does QObject::connect automatically use a queued connection if the object is has been moved to a different thread
Yes, by default. See http://doc.qt.io/qt-5/qt.html#ConnectionType-enum
As an experiment, keep your object in the main thread and run your program again. Do the error messages still persist?
@kshegunov said:
Well, the signal's signature is
void (QPushButton::*)(bool)
while the slot's signature isvoid (IclStreamController::*)()
.That's perfectly fine. The signal has a
bool
parameter, while the slot has no parameters. Therefore, they are compatible -- the slot simply ignores the signal's parameter value. However, it would be incompatible if, say, the signal has no parameters but the slot has abool
parameter. -
@JKSH said:
What happens if you completely delete your build directory, and re-build your project from scratch?
Nothing... though I haven't ruled out this being a build issue. I'm using qmake with a subdirs project. The code that I posted is actually in two different projects. The class definition of the IclStreamController is in a library and the client code is in the app itself. There are also a couple of other projects in the subdirs but I haven't had any other build problems and everything seems like its building in the right order.
I also tried your suggestion of keeping it all in the main thread:
IclStreamController *streamer = new IclStreamController(); connect(streamer, &IclStreamController::messageReceived, this, handleStreamMessage); // connect stop button to stopStream connect(ui->btnStop, &QPushButton::clicked, streamer, &IclStreamController::stopStream); // quit the thread and clean up if the stream is stopped or error occurs connect(streamer, &IclStreamController::streamStopped, this, &MainWindow::signalDbg); connect(streamer, &IclStreamController::error, this, &MainWindow::signalDbg); connect(streamer, &IclStreamController::streamStopped, streamer, &IclStreamController::deleteLater);
I still get the same errors... but the signals work anyway (at least the stop button one does). SO what's going on here? Maybe its something to do with QTHread after all?
-
@CentralScrutinizer said:
The class definition of the IclStreamController is in a library and the client code is in the app itself.
Hmm...
- Check that
IclStreamController
is exported by the library - Make sure you're not copying the
IclStreamController
header into the client project (in other words, make sure your client .pro file doesn't containHEADERS += iclstreamcontroller.h
or similar).- Copying the header results in 2 copies of the
IclStreamController
meta object in your client app, which causes issues in Qt's signal-slot mechanism.
- Copying the header results in 2 copies of the
I still get the same errors... but the signals work anyway (at least the stop button one does). SO what's going on here? Maybe its something to do with QTHread after all?
Sounds like two different issues here. See if the 2 steps above help at all first, and then we'll go from there.
- Check that
-
Check that IclStreamController is exported by the library
This is a possible cause... It was not exported. I've been doing things statically until now but the last little app I created was getting too big so I'm trying to make this one dynamic. So I included some common macros for this (i know there is Q_DECL_EXPORT but its exactly the same thing behind the macros I'm using for non QT stuff) and exported the signals and public member functions.
The problem I get now with things (I think) properly exported is:
C:\Qt\5.5\mingw492_32\include\QtCore\qobject.h:239: error: undefined reference to `IclStreamController::staticMetaObject'
I'm out of time today (I shouldn't be working on Sunday anyway :S) but I'll have another look at this tomorrow. Any idea about the new error I'm getting? I'm not sure I'm doing the exports right so that could be the problem but... if anyone recognizes this error as an obvious thing that would be good to know.
-
That's perfectly fine.
Yes, I'd tested it and had glanced at the source, because I wasn't sure about the new syntax. I know this "reduction" of parameters worked without issue with the old syntax.
Any idea about the new error I'm getting?
Well, it looks like you didn't export the class? The error means the linker couldn't find the static member generated by the
Q_OBJECT
macro, which usually means that either you don't have theQ_OBJECT
macro, or the class wasn't exported/imported.Kind regards.
-
The export (or lack thereof) definitely was the problem. Once I got in this morning and cleaned up by code a little and rebuilt everything the export is now working fine. I must have had an old build of something that wasn't getting cleaned.
Anyway thanks for the help!
-
Necropost; but I hope the solution I found will help other people who also has meet the same problem.
Looks like the problem occurs only when you don't use "C++ Library" project template for shared libs and manually edit .pro file, mainly by just adding
TEMPLATE = lib
string.
By default, Qt generate special global file if you has selected "C++ Library" project template. The file will have the same name as your project but with "_global.h" postfix. For example, if a project's name is "Test", the auto-generated file name will be "Test_global.h".The global file contains very simple code:
#ifndef TEST_GLOBAL_H #define TEST_GLOBAL_H #include <QtCore/qglobal.h> #if defined(TEST_LIBRARY) # define TEST_EXPORT Q_DECL_EXPORT #else # define TEST_EXPORT Q_DECL_IMPORT #endif #endif // TEST_GLOBAL_H
If you want to export a class with signals that you want to use OTSIDE the project, you MUST use the
TEST_EXPORT
macro instead of build-in__declspec(dllexport)
orQ_DECL_EXPORT
macros.Hovewer, if you already created a project with wrong template, all you need is to manually add the global file, and
DEFINES += TEST_LIBRARY
string in your .pro file.P.S. TEST here is just an example, you can use any other macro names you want, but be sure they are match in .pro and global.h files.
-
@Zerkg hi,
Just in case, it's described in the Creating Shared Libraries chapter of Qt's documentation.
-
@seyed said in Signal not found at runtime:
So there MUST not be two class with equal name in the library and main app. did I understand correctly?
You can define the class in the library, and use it in the main app.
But you cannot define the class in both the library and the main app at the same time.