Qregistermetatype как пользоваться qt
Перейти к содержимому

Qregistermetatype как пользоваться qt

qRegisterMetaType usage

user avatar

«qRegisterMetaType» is a function. It must appear in a code block.

You need to add Q_DECLARE_METATYPE(IntList) before you can register it.

Not the answer you're looking for? Browse other questions tagged qt or ask your own question.

Related
Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2022.6.10.42345

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Qt и Q_REGISTER_METATYPE — что это такое, и как его использовать?

Для класса QAbstractSocket генерируется сигнал error с параметром QAbstractSocket::SocketError socketError. В документации написано: "QAbstractSocket::SocketError is not a registered metatype, so for queued connections, you will have to register it with Q_REGISTER_METATYPE", но про этот Q_REGISTER_METATYPE нет упоминания вообще нигде. Сталкивался-ли кто-нить с этим жЫвотным? (А я пока погуглю, мало-ли).

Re: Qt и Q_REGISTER_METATYPE — что это такое, и как его использовать?

у тебя объект сокета и слот, принимающий сигнал error(), находятся в одном потоке?

QMetaType knows your types

QMetaType is Qt’s way to have run-time dynamic information about your types. It enables things such as QVariant wrapping of custom types, copy of queued connection arguments, and more.

If you ever wondered what does Q_DECLARE_META_TYPE or qRegisterMetaType do and when to use (or not to use) them, read on. This article will describe what you need to know about QMetaType: What is its purpose; How to use it; And how it works.

Why does Qt need runtime dynamic type information?

Let’s start with a bit of history. QMetaType was introduced in Qt 4.0. It was created in order to have the possibility to have asynchronous signals and slots ( Qt::QueuedConnection ). For queued slots to work, we have to copy the arguments and store them in an event that will be processed later. We also need to delete those copies when we are finished invoking the slot. (Note: This is not needed when using Qt::DirectConnection : pointers to arguments directly on the stack are used.)

The code dispatching signals in QMetaObject::activate has an array of pointers to arguments void* . (For more info read how signals and slots work). But, at the time, all Qt knows about the argument types are their name as a string, extracted by moc.

QMetaType provides a way from the string (e.g. «QPoint» ) to get a to copy or destroy the object. Qt would then use void *QMetaType::create(int type, void *copy) and QMetaType::destroy(int type, void *data) to copy and destroy the arguments, where the int type is obtained using QMetaType::type(const char *typeName) using the type name of the argument, as provided by moc. QMetaType also provides a way for the developer to register any kind of type in the meta type database.

Another use case for QMetaType is QVariant. The QVariant from Qt 3.x only supported built-in Qt types because a contained arbitrary type would also need to be copied or destroyed together with the wrapping QVariant. But with the help of QMetaType, QVariant was able to contain any registered type since QVariant can now copy and destroy contained instances of objects.

What information does QMetaType keep?

Since Qt 4.0 a lot has changed. We now have QtScript and QML which are making intensive use of the dynamic type integration. And we had to optimize a lot.

Here is the list of information kept for each type in the meta-type system:

  • The Type Name as registered. There is a name index for fast lookup of the meta type id. Since Qt 4.7, it is even possible to register the same type with different names (useful for typedefs).
  • (Copy) Constructor and Destructor (in-place or not).
  • Size to know how much space to allocate for a stack or inline member construction.
  • Flags specifying the same information as QTypeInfo (see bellow) or the type of conversion.
  • Custom conversion functions, set by QMetaType::registerConverter .
  • QMetaObject, containing the meta QObject data associated with a type if it exists.

QTypeInfo

QTypeInfo is a trait class orthogonal to QMetaType, it allows the developer to manually specify (using the Q_DECLARE_TYPEINFO ) that a type is movable (using memmove) or if its constructor/destructor need to be run. This is mainly used for optimization in containers like QVector.

For example, the implicitly shared classes may be moved with memmove. While a normal copy should first increase the reference count with the copy constructor and then decrease it in the destructor.

C++11 introduces move constructors and standard type traits to solve this problem, but since QTypeInfo was designed way before C++11 and Qt still has to work with older compiler, we have to do without.

How does it work?

For historical reason, there is a big difference between built-in types and custom types. For built-ins types in QtCore, each meta-type function is basically a switch that has special code for each type. In Qt 5.0 this was re-factored to use templates a lot. (See QMetaTypeSwitcher.) But what is going to interest us in this article is how it works for custom registered types.

There is simply a QVector<QCustomTypeInfo> that holds all the information and a bunch of function pointer.

The Q_DECLARE_METATYPE macro.

That macro specializes the template class QMetaTypeId for the specific type. (In fact, it actually specializes the class QMetaTypeId2 and most of the code uses QMetaTypeId2. I don’t know the exact reason behind QMetaTypeId2. Maybe so that Qt can add more built-in types without breaking code that used Q_DECLARE_METATYPE before.)

QMetaTypeId is used to determine the meta-type id at compile time for a type.
QMetaTypeId::qt_metatype_id is the function called by the qMetaType<T>() . On the first call of this function, it will call to some internal function within QMetaType to register and allocate a meta-type id for this type, using the name specified in the macro. It will then store that id in a static variable.

Apart from the name, all other information is automatically inferred by the compiler using templates.

qRegisterMetaType

Type registered using Q_DECLARE_METATYPE are going to be actually registered (and be assigned an id) on the first use of qMetaTypeId() . That’s the case when a type is wrapped in a QVariant for example. But this is not yet registered when connecting signals and slots. In that case you need to force the first use using qRegisterMetaType

Automatic registration.

Developers often forget to register their meta-type until they see the compilation error or run-time error telling them to do so. But wouldn’t it be nice if it would not be necessary? The only reason Q_DECLARE_METATYPE is necessary is to get the name. But there are cases where we can know the name at run-time without that macro. For example, QList<T> if T is already registered, we can query the meta-type system and construct the name using «QList<» + QMetaType::name(qMetaTypeId<T>()) + «>»
We do that for a bunch of templated classes, for example: QList, QVector, QSharedPointer, QPointer, QMap, QHash, .
We can also determine the name of a pointer to a QObject subclass thanks to the information provided by moc: T::staticMetaObject.className() + «*»
And from Qt 5.5, we will also automatically declare the Q_GADGET and Q_ENUM .

That was it for Q_DECLARE_METATYPE , but you would still need to call qRegisterMetaType to use these type in a Q_PROPERTY or as a parameter in a signal/slot queued connection. Since Qt 5.x however, the code generated by moc will call qRegisterMetaType for you if moc can determine that the type may be registered as a meta-type.

Research

Before Qt 5.0, I was trying to investigate if we would not be able to get rid of Q_DECLARE_METATYPE for cases in which we do not need the name. This worked somehow like this:

According to the C++ standard, there shall be exactly one instance of the variable QMetaTypeId::qt_metatype_id()::typeId for each type. But in practice some compilers or linkers do not obey this rule. In particular, on Windows, there would be one instance per library even when using the proper export macro. We would therefore always need a name identifier which we don’t have. (And we don’t want to rely on RTTI). Therefore we only register the type for which we can know the name in Qt 5.

Woboq is a software company that specializes in development and consulting around Qt and C++. Hire us!

If you like this blog and want to read similar articles, consider subscribing via our RSS feed (Via Google Feedburner, Privacy Policy), by e-mail (Via Google Feedburner, Privacy Policy) or follow us on twitter or add us on G+.

Load Comments.
Loading comments embeds an external widget from disqus.com.
Check disqus privacy policy for more information.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *