Q_OBJECT macro and meta-object code - qt

This link: http://doc.trolltech.com/4.5/moc.html#moc says
The moc tool reads a C++ header file.
If it finds one or more class
declarations that contain the Q_OBJECT
macro, it produces a C++ source file
containing the meta-object code for
those classes.
What is a meta object code?
EDIT 1
How to know in which classes I should write the Q_OBJECT? One example is the signals and slots, any other cases where that needs to be used?

You can read the article Qt internals and Reversing to get in depth knowledge about Qt and its moc compiler (meta objet compiler). In summary a meta object is created by Qt's moc compiler to add extra information to a class like signal/slot mechanism etc.

Meta objects enhance programming languages by creating new or manipulate existing objects. They provide functionalities a language does not actually have by itself. The Meta Objects are interpreted either by compile time or run time. In Qt and C++ it is done during compile time by the Meta Object Compiler (moc).
An example case is the usage of the signal/slot concept.

A meta object code in Qt environment is a C++ source file that is an expanded version of the C++ source file where you've put Q_OBJECT (and/or other related macros). The meta object code will have your implementation plus some other extra (meta) code so that signal and slots mechanism work.

A meta-object contains meta-information about an object like its name and a textual description of its signals and slots. This make it possible to call signal by "name". See the documentation about QMetaObject and this article.

Related

Qt QML and QDBus interoperability

There is a property system in Qt. Properties can be exposed from D-Bus using subclassing of QDBusAbstractInterface from the one hand and to Qt QML from the other hand. For properties and signals of D-Bus services interfaces it can be done by meta-object compiler automatically. For signals, slots and properties of QObject for QML it also can be done automatically by MOC.
But the problem arises: QML needs property and method (either signal or slot) names to be started from lowercase letter, while, say, Network Manager DBus API exports objects with all members identifiers starting with uppercase letters (sometimes with lowercase letters, say org.freedesktop.NetworkManager.state() method). But I want to use such an QDBusAbstractInterface-derived objects directly into QML code.
Is there a way to automatically translate methods' and properties' names into one form for QtQml and into another form for QDBus?
Example of how to emit a signals for all the properties of NetworkManager objects separately.
Added: KDE NetworkManager Qt is not too useful in the light of the question, because there is no properties to be exported with QObject-s in QML.

Complex initialization in Custom QML type

I am creating a C++ class that will be registered as a QML type. I want to run some non-trivial logic when the object is initialized. I don't want to put this logic in the constructor because that is bad practice. In a standard C++ class I would usually create a Startup() function with this logic and call it just after initializing the object, but I have no control over this as objects are initialized in QML.
How should I implement this custom initialization logic for a custom QML type?
For those who want the details. I am making a QAbstractListModel that keeps track of all .txt files in a directory. When it is created it will scan the directory (passed in via property) and update its internal collection with the names of all .txt files in that directory.
Edit1: After looking at Qt's example projects I found that many of them actually do all initialization logic in the constructor, including things like setting up DB connections and doing an initial DB query and query parsing. One need only search for "database" from the Qt Creator Welcom->Examples screen to see these samples. I would appreciate it if someone found and explained a better way.

How can I write a shared library with Qt that wraps another library?

I'm trying to create a Qt shared library that wraps a lower level C library, meaning that I don't want that C library's header file to be accessed by the calling code that links to the library.
I'm following the steps here, which seem to be straightforward. I've constructed a SUBDIRS project in QtCreator. The library project builds fine, all classes and C functions are marked with the macro that expands to Q_DECL_EXPORT. The library defines a some headers that I want to include in the app project. The problem here is that when I include one of those headers, the chain is followed down to the C library header that is included, and at which point the application project fails to build since it can't find that header.
Qt's documentation specifically points out this issue, but is kind of vague about how to solve it.
#include <footronics/device.h>
class MyDevice {
private:
FOOTRONICS_DEVICE_HANDLE handle;
};
When deploying the library, there should be no dependency to the internal headers footronics/device.h or ui_widget.h.
So, how can I avoid the headers that I'm including from the library, from implicitly including the headers from the C library that I'm wrapping?
If you only use pointers or references to classes of the shared library you can use Forward Declarations:
class FooTronicsDevice;
class MyDevice {
private:
FooTronicsDevice* _device;
}
The compiler doesn't need to know the structure of the class in order to define a pointer (or a reference).
If this isn't possible, you can use the Pointer to Implementation idiom which is suggested in the Qt Documentation.
This basically means you separate the implementation from your public interface.

Qt - meta object code

What do we mean by the meta object code when relating to the Meta Object Compiler (moc) in Qt?
Thanks.
Meta objects enhance programming languages by creating new or manipulate existing objects. They provide functionalities a language does not actually have by itself. The Meta Objects are interpreted either by compile time or run time. In Qt and C++ it is done during compile time by the Meta Object Compiler (moc).
An example case is the usage of the signal/slot concept.
Since you specifically asked about Meta object and moc,
From docs,
...The moc tool reads a C++ header file. If it finds one or more class declarations that contain the Q_OBJECT macro, it produces a C++ source file containing the meta-object code for those classes. ...
HTH..
Meta object code is required for Signal Slot mechanism ,Run time type information and dynamic property system.
Qt system creates "meta object code" based on "annotations" in your c++ code (eg Q_PROPERTY, Q_SLOTS etc). Qt uses them to implement meta-calls and reflection style access to class properties.
Look at the ".moc" files that the compiler produces for your class and you'll understand.
But given the uncertainty around Qt's future, may I ask why you are choosing Qt? (unless its purely for the joy of hacking..)

Qt signal wrapped in an ifdef

My Qt project links to a library that is linux-only. When the project is run under linux, I wish to have a signal fired on an event using a type defined in that library. A complication that I have, though, is that the project must also build in Windows. Obviously, this signal and the slot catching it wouldn't exist in Windows, and that's fine. I am, however, finding issues with Qt's moc tool failing to recognize the existence of an #ifdef __linux__ around the code that emits the signal. My code looks like this:
[SomeFile.h]
#ifdef __linux__
signals:
void SomeSignal(SomeTypeDefinedInTheLinuxLibrary);
#endif
[SomeFile.cpp]
#ifdef __linux__
emit SomeSignal(someObject);
#endif
When I attempt to compile this with g++, I get the error:
SomeFile.cpp:(.text+0x858c): undefined reference to SomeFile::SomeSignal(SomeTypeDefinedInTheLinuxLibrary)
Any ideas how to get moc and #ifdefs to play well together?
A much better solution is to always provide the signal and just comment out the code that fires it on Windows. That way, the public API is the same on all platforms.
[EDIT] The moc tool is really dumb. It doesn't actually understand the code; instead it just reacts on certain patterns. That's why it ignores the #ifdef.
To solve the issue, wrap the type or use #ifndef __linux__ and define your own dummy type in there so it compiles on Windows. Since the signal won't be emitted on Windows, the slot will never be used so any type that makes the code compile should be fine.
With Qt 5.3 at least using Visual Studio, I am able to pass pre-processor macros to the moc tool. In order to make this work, I had to text edit my Visual Studio project file and manually add command line arguments for each file in order to hand the pre-processor arguments to the moc tool. You can use -D[Pre-Processor], i.e. -DSPECIAL_BUILD or -DSPECIAL_BUILD=1, and the moc compiler is smart enough to see the #if SPECIAL_BUILD checks in your code and not try to moc those parts.
Just search for "moc.exe" and add the appropriate parameters for each configuration.

Resources