Trolltech’s Qt

The Trolltech development library ‘Qt’ is a useful set of lovely software libraries that has two purposes: First, it is a platform-independent way to code in C++.  Second, it offers a set of libraries with logical, documented interfaces apparently written by adults.  Even if you don’t need platform-independence in your code, you should use Qt.

That said, I have my problems with Qt.  It is insufficiently tested, insufficiently documented, and parts of the libraries suffer from poor design (beware the QTableView and QRelationalTableModel classes!).  These problems generally arise from an overly-ambitious feature list and a weak mindset for debugging.  But I suffer from these tendencies as well, so I can be a little forgiving… even if I give technical support merry hell from time to time.

Qt offers a nice plugin architecture for modular application extension.  The interface necessary to use it is a little bloated, consisting of six (!) different macros, classes, and templated functions you need to strategically sprinkle through your code with some dubious and apparently useless arguments and options, but, so long as you use the plugin architecture for dynamically linked .dll’s attached to a Qt configured for dynamic linking, it seems to work perfectly well.

Let me take a moment to define some terms that haven’t got standard usage: 

Static linking: functions from a library (a .lib in Microsoft-world) are compiled inside your executable;
Explicit linking: functions from a library (a load-time library, or .dll in Microsoft-world) are resolved by loading their definitions from the library (not the executable), as needed, after your program starts.  In this case, after resolving a function, all you get is a function pointer — you need to know how to use the function pointer yourself;
Implicit linking: a hybrid between static and explicit linking where your executable knows where to find the functions inside a load-time library (a .dll) and how to use them (from definitions in a .lib), but the functions themselves are not compiled inside your executable.  They are loaded from the (dll) library at load-time;
Dynamic linking: a program uses dynamic linking if it uses load-time libraries either explicitly or implicitly. 

Implicit linking has all of the disadvantages of static linking (you need have a .lib defined when you write your executable) and all the disadvantages of using dynamic linking (you must maintain compatibility between two different loosely-coupled code bases in two different files: the executable and the dll) without gaining the advantage of using a .dll (you can decide if you need the .dll after your program starts).

Plugins with Qt Static Builds

Here’s the rub: I generally hate .dll’s.  In my opinion they are overused and tend to create more problems than they solve.  I have no problem with modular architecture but I am an inveterate static linker.  There are times when you absolutely must use a .dll; sometimes it makes sense, but it should never be the default technique.  However, Qt does not support loading a plugin from a Qt configured for static linking.  That means that, if you want to use dynamically-linked plugins you have to go whole-hog and use dynamically-linked Qt, too.  Welcome to dll-hell.  Now, instead of releasing an executable with maybe a few optional plugins for extending your application, you have to release your application, your plugins, and every single thrice-darned Qt dll as well!  Not an acceptable solution.

By doing a little searching on the internet, it appears to be programmer lore that:

 Thou shalt not mix explicit- with static-linking.

Certainly the people at Trolltech believe this; their tech support told me so.  Qt’s documentation does not explicitly say it, but apparently it is such common knowledge that programmers just know in their bones not to do it.

Why not?

The fear seems to be that an explicitly-linked library will potentially load code that is incompatible with code loaded by the executable.  Even granting this could happen, how is this a compatibility problem a programmer doesn’t have to worry about anyway within a dynamically-linked application?  Furthermore, if the load-time library (the .dll) and the executable both statically-link to all the libraries they have in common, where is the problem?

I don’t deny there could be some problems having to do with incompatible states, shared resources, or some bizarre subtleties I don’t know about, but that’s just it; if there are problems, I don’t know about them.  So I ran a test.

The only thing in Qt’s source code preventing plugins from working within an executable statically-linked to Qt is a macro conditional at line #236 of src/corelib/plugin/qpluginloader.cpp (in release 4.3.4).  I changed the line

#if defined(QT_SHARED)

to

#if 1

Then I recompiled Qt (in the static configuration) and linked into my application.  My application attempted to load a plugin through QPluginLoader according to the techniques in Qt’s documentation.  I created a plugin .dll, linked to Qt’s static libraries, and moved it to where my executable could find it.

I executed the application.  It ran.  It found the plugin, linked to it, resolved it, executed it, and never complained.  So much for lore.

Now, my plugin isn’t doing anything exotic: it’s launching no new threads, sending no signals, capturing no events, sharing no static memory.  Maybe if I try those things it will break, but as far as I can tell it is working for me.  I’ll post the source code for my application (a news feed and blog feed text scraper) later this week.

Update (27 March 2008)

 The feed text-scraper application is released and described here.

 

3 Responses to “Qt Plugins and Static Builds”

  1. Thanks for your article! (Constructive) criticism is extremely valuable to us as it helps us to improve. Perhaps you could elaborate a bit on the shortcomings of the documentation and quality(testing) of Qt?

    Regarding linkage scenarios – one could simplify and define only dynamic and static linking. Implicit and explicit resolution is two different ways of doing dynamic linking.

    Now to explain; A potential problem when using plugins from a statically compiled executable is that you can potentially load different C runtimes for the executable and the plugin, and end up with multiple heaps in your application – again leading to esoteric and spectacular crashes when you delete() from the wrong heap. Assuming you can guarantee both plugin and executable are compiled with -MD(d) this should not be an issue.

    Furthermore, the plugin would use a different Qt version (dynamically built) than the static executable. This will in turn cause symbol conflicts.

    For the last scenario, in Qt 4 there is a namespace configuration option which could allow you to compile plugins under a different namespace and load in a static executable along with your proposed patch. However, this is not tested nor supported at the moment.

    Hope this helps with your trials :)

    Henrik, Trolltech ASA

  2. brainrack said

    Henrik,

    Thank-you for your comment. As I mentioned in my article, I have been generally very pleased with Qt. I’ve written several tens of thousands of lines of C++ within the Qt framework and think it is a valuable resource for C++ programmers. I will be glad to elaborate on some of the problems I see with Qt, but I need to consider that it may be best to take that conversation off-line. I’ll think about it and I’ll either add my comments as an addendum to the current post or I’ll e-mail you in the next couple of days.

    On the particular subject of this post, one confusion I see is that we programmers tend to use the words ’static’ and ‘dynamic’ to refer to linking (or compiling) an application as a whole; but actually the words should properly be used only to refer to the method of linking used for a particular library. I image that you agree with this minor distinction, but even in your email you refer to a ’statically compiled executable’. I understand it is a shorthand way of talking but I think it leads to confusion sometimes. Dynamic libraries can link to static libraries and dynamic libraries. An application that statically links to Qt (for instance) can dynamically link to other libraries.

    I can appreciate your concern about ‘esoteric and spectacular crashes’ if different C runtimes are loaded at runtime. I don’t know the internals of the libraries well-enough to predict any specific difficulty, but I would anticipate trouble and I second your comment about the -MD flag. However, I don’t see why this should be a particular problem for explicitly (dynamically) linking to a plugin that is statically-linked to Qt. Isn’t it a general issue with using DLL’s that you encounter with every DLL build? I don’t see why it should necessitate disabling Qt’s plugin system in a static build of Qt.

    Regarding your comment “Furthermore, the plugin would use a different Qt version (dynamically built) than the static executable. This will in turn cause symbol conflicts.” I must be misunderstanding you here. In the application described in http://brainrack.wordpress.com/2008/03/27/news-feed-scraper-application/
    I employ plugins that are statically linked to a statically built version of Qt. The plugins are explicitly linked at run time into an application which is statically linked to a statically built version of Qt. With the minor modification to Qt’s source code I described in this post above, the application compiles without symbol conflicts and runs perfectly well (so far). The need for insuring the versions of Qt match in the application and the plugin is exactly the same need encountered by plugins dynamically-linked to dynamically-built Qt — a technique Qt explicitly endorses. Perhaps you could elaborate?

    Again, Henrik, thank-you for your comment. I will follow-up in a day or two.

    Neil
    Liberty Reach, Inc.

  3. [...] 31, 2008 In a response to a previous post, Henrik Hartz of Trolltech asked for some specific comments on the documentation and testing issues [...]

Leave a Reply