Saturday, 22 November 2014

Injeqt 0.9.0 released

First official (beta!) version of Injeqt dependency injection library for Qt was released today. I can be downloaded from GitHub releases page.

For last 3 weeks I was working on Kadu and switching some parts of it to use Injeqt for its objects and services wiring. As it turns out, it all works very well already. There is no need to postpone Injeqt release until it gains additional features (and I have big plans for it).

0.9.x series will continue until Kadu 2.0 release with only bugfixes. I don't expect a lot of them (Injeqt has very nice unit tests coverage), but better safe than sorry. Exported API is very minimal and should not be changed (only extended) in a long time.

If you wish to try it - please do it now. I would be happy to see more use cases and real world applications before committing 100% to 1.0 release.

Enjoy!

Thursday, 20 November 2014

Kadu 2.0 progress

Yesterday I finished last big infrastructure item planned for 2.0 (roster simplification). There is one big feature left to do (Unity integration) and a few bugs. As there will not be (probably) version 1.3, all of bugs assigned to it will be moved to 2.0 release.

There is one scary thing to do after Unity integration - creating Windows build. New Kadu is based on Qt5 instead of old Qt4. This means we have to update also QCA and Iris libraries. My experience with releasing 1.0 tells me that this will not be easy at all.

As for now, Injeqt integration is going very well. 0.9.0 release of this library will come this month and 1.0 before Kadu 2.0. First C++ application with Guice-like dependency injection is coming to change the world :)

Tuesday, 4 November 2014

QMetaType in plugins

I've learned that for some uses QMetaType just does not work.

Imagine that you want to read types of parameters of some signal or slot of QObject. You also know that all parameters to this method are pointers to QObject-based types. The best way to do that is to:
  1. register your type with qRegisterMetaType<QObjectDerivedType>
  2. read parameter meta type id with QMetaMethod::parameterType(int)
  3. get QMetaObject of this parameter with QMetaType::metaObjectForType(int)
In most cases it works. But not when QObjectDerivedType lives inside a plugin that is dynamically loaded and unloaded several times during program execution (and this whole sequence is run on each plugin load).

On first load everything works perfectly. On second (or third or next, it is rather random and probably depends on allocation patterns in application) your QMetaObject from point 3 is invalid and using it causes access violation. Why? QMetaType remembers address of QMetaObject for each QObject based class pointer per program execution. On load a new QMetaObject is constructed for each type that lives in plugin. And on unload its memory is freed. In result the stored pointer just must to be invalid.

Maybe I missed something, but I was not able to get it to work properly. My solution is to use custom paramter-QMetaObject mapping instead of relying on QMetaType. It is based on QMetaMethod::parametrTypes() method that returns type name and a map of type-name to QMetaObject pointer that is created on each plugin load and passed around. I'm not very happy with this solution, because it is prone to namespace issues and it does not allow usage of types that are no preregistered in plugin (on the other side, QMetaType has the same problem). Hopefully C++ reflection will become real some day.

But there is one more thing that makes me happy - replacing first solution with second in my dependency framework Injeqt took some time and required non-trivial changes in library. But API and ABI remained the same - there was no need to recompile Kadu 2 to work with new version. It means that my usage of private and public interfaces, pimpls and anonymous namespaces is at least proper. This also closed last bug that blocked 1.0 release. This means I can now prepare beta 0.9 and focus on developing Kadu (also to test if Injeqt is really ready to be released).