PDA

View Full Version : Where does QMetaObject "live"? A .dll, a .lib, a moose in the Ukraine, etc.?



amdreallyfast
24th May 2014, 23:23
I'm trying to follow some examples to get signal and slot connections to work in Visual Studio 2013. Here's the basic code:



#include <QtCore/QObject>

class my_derived_object : public QObject
{
private:
// http://qt-project.org/doc/qt-4.8/qobject.htm#Q_OBJECT
// "The Q_OBJECT macro must appear in the private section of a class definition
// that declares its own signals and slots or that uses other services provided
// by Qt's meta-object system."
Q_OBJECT;

public:
// http://qt-project.org/doc/qt-4.8/qobject.html#Q_INVOKABLE
// "Apply this macro to definitions of member functions to allow them to be
// invoked via the meta-object system. The macro is written before the return
// type..."
Q_INVOKABLE int say_hi(int number)
{
cout << "hello with number '" << number << "'" << endl;

return (number * 2);
}
};

int main(int argc, char **argv)
{
my_derived_object my_obj;

int method_index = my_obj.metaObject()->indexOfMethod("say_hi(int)");
cout << "method index = '" << method_index << "'" << endl;

return 0;
}


The problem is that "Q_OBJECT" macro. Having that in my code produces a link error like so:


LNK2019: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall my_derived_object ::metaObject(void)const " (?metaObject@my_derived_object @@UBEPBUQMetaObject@@XZ) referenced in function _main *error location has personal folder locations and is therefore redacted*


But that macro, as per the documentation referenced in the comment above it, is required to specify my own slot and signal functions, which in turn are required for anything using SIGNAL(...) or SLOT(...), such as a call to QObject::connect(...). This code worked just dandy in QtCreator, but not in Visual Studio.

I tried a brute force approach of linking every possible Qt .lib file into my program and including all possible Qt .dll files into my project, but that did nothing. I still had the linker error.

So where does QMetaObject "live"? I've tried some "moc"-related tutorials that tried to generate certain files, but I didn't get anywhere.

Infinity
25th May 2014, 00:20
You don't need a ";" after the Q_OBJECT macro.


So where does QMetaObject "live"?
QMetaObject is a class of the Qt framework. It is part of the core module (and thus "lives" in the corresponding library, eg. libQt5Core.so).

It looks like as if moc isn't configured probably. Do you get, compile and link moc_*.cpp-files which should be generated by moc?

amdreallyfast
25th May 2014, 00:51
What is "libQt5Core.so"? I don't see any files in the /lib folder that end in ".so".

What is "moc", anyway? Whatever it is, I haven't used it before, so it probably isn't. What are "moc_*.cpp-files"?

I don't think that "moc" is part of my build routine. I tried a tutorial (http://ldmartin68.com/QTSetup4VSNET.html), but that didn't work. I got errors saying that "$(QTDIR)\bin\moc MyHeaderFile.h -o tmp\moc\moc_MyHeaderFile.cpp" didn't work (the error wasn't particularly explicit; it just said that the command didn't work).

I'm trying to go through this (http://qt.developpez.com/doc/4.7/moc/) but I'm not understanding it.

All the tutorials around moc seem to assume (1) that QtCreator is the IDE, (2) linux is the OS, or (3) both (1) and (2). Can you point me at some tutorial that shows how to set up "moc", whatever it is?

ChrisW67
25th May 2014, 00:55
Since you put the Q_OBJECT code in the CPP file and not in a separate header it is not listed in HEADERS and therefore does not get the automated Metaobject compiler (moc) handling from qmake. You need to trigger qmake to generate moc pre-processing in the Makefile, and include the moc generated C++ source, an the easiest way to do that with a one-file-wonder is:


#include "main.moc"

at the bottom of the main.cpp file and re-run qmake.

Normally the header for the QObject class would be in separate file listed in HEADERS. Then qmake ensures that moc is run, the resulting C++ code is compiled, and the result included in your linker run.

amdreallyfast
25th May 2014, 02:09
I get the compile error


error C1083: Cannot open include file: 'main.moc': No such file or directory


Remember that I am running Visual Studio. That command works in QtCreator, but not Visual Studio. "main.moc" doesn't exist.

Any other ideas on how to initialize this "moc" thing?

anda_skoa
25th May 2014, 13:28
Try putting the class declaration into a header.

Do you use qmake to generate the VS project file or do you use the Qt plugin?

Cheers,
_

amdreallyfast
25th May 2014, 15:51
I figured it out in this thread: http://www.qtcentre.org/threads/59231-QMetaObject-use-in-visual-studio-(or-quot-asyncronous-QSocketNotifier-use-quot-)?p=263169#post263169

I was using neither qmake nor the Qt plugin (I'm using VS express, and the plugin download description says that it doesn't work in express). I used VS's build system and had to add a custom build step that executed moc.exe before the first of the build steps.