[Interest] Link Errors when Creating a Windows DLL containing Qt Widgets

Till Oliver Knoll till.oliver.knoll at gmail.com
Mon May 14 22:25:56 CEST 2012


Am 14.05.2012 um 20:21 schrieb Michael Jackson <imikejackson at gmail.com>:

> 
> On May 14, 2012, at 2:00 PM, Till Oliver Knoll wrote:
> 
>> Am 14.05.2012 um 16:35 schrieb Mike Jackson <imikejackson at gmail.com>:
>> 
>>> ...
>>> 
>>> 19>QLeeMarchingCubesWidget.obj : error LNK2001: unresolved external
>>> symbol "public: static struct QMetaObject const
>>> QFilterWidget::staticMetaObject"
>>> (?
>> 
>> Hmmm, it just crossed my mind that something else could go wrong here: staticMetaObject is off course a moc generated function.

... and I overlooked that the Q_OBJECT macro gets expanded to the proper function declarations - off course by the preprocessor, that is *before* the compiler sees the file, hence when you export the *entire* class (just as you do!) also the Qt generated functions/symbols get properly exported! No special magic going on here :)

Thiago is absolutely correct here in saying that you should *always* export the entire class, as soon as you have the Q_OBJECT macro in your class declaration - which by the way is also easily forgotten when you simply derive from QObject, but do not declare any additional signals or slots in your class: The result is that your code would link and compile just fine, but any runtime check with qobject_cast etc. would return a wrong result (because the corresponding "meta object" methods were not properly generated, so the base-class methods would be called instead, providing the misleading info of the base class, and not of /this/ class.


>> So even if you declare the whole class (the public fields thereof, according to the MSDN article) to be "exported" (just as you do) the compiler cannot possibly know the (not yet existing) public symbol "staticMetaObject" and have it exported later on.

Forget about that, it's plain wrong. Off course the Q_OBJECT macro expansion will create all necessary entries in the header, which then get properly exported.

>> This is not a problem as long as this symbol is not referenced from OUTSIDE of that particular DLL. But it seems that this is exactly the case here (that your plugin DLL is explicitly trying to call QFilterWidget::staticMetaObject - where does this call come from exactly?).

This call is most likely generated by the moc when generating the moc code for the class which derives from this QFilterWidget (the one implemented in your plugin).

But again, as the declaration of staticMetaObject() is part of the expansion of the Q_OBJECT macro it is properly accessible (I keep repeating that for myself, because I had forgotten all this myself ;))

> QLeeMarchingCubesWidget inherits from QFilterWidget.

Hence the call to QFilterWidget::staticMetaObject which I expect to find in the generated moc_qleemarchingcubes.cpp file.


> I was hoping there was something easier than having to dig through the Qt source code

Now that it is clear that the expansion of Q_OBJECT does properly declare everything, and when you export the *entire* base class that everything is properly "exported", there should be no need anymore to dig in the Qt source.

However you could have a look at your source file after the preprocessor has worked on it.


> PS: It _does_ now compile. Not sure what really changed other than doing a full "Rebuild" in Visual Studio. 

So at least my "make distclean; make" was a correct guess ;)

Best regards,
  Oliver


More information about the Interest mailing list