PDA

View Full Version : staticMetaObject



Tiber
22nd April 2008, 23:25
I'm sort of new to Qt, but I've run this by some more experienced coworkers, and they're stumped as well.

My job is to port the application from Qt3 to Qt4.3. I am using VS2005 with vs integration.

Pretty much all of the code is divided into dll projects. I've got one of the projects pretty much done except for a linker error.

Here's what it is:


class MyClass : public BaseClass
{
Q_OBJECT
public:
...


class DLL_EXPORT_MACRO BaseClass : public QObject
{
Q_OBJECT
public:
...
Then I get this:


moc_myclass.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const BaseClass::staticMetaObject" (?staticMetaObject@BaseClass@@2UQMetaObject@@B)

Note that the base class and child class are in different projects in different directories, though the child project obviously includes the folder the base class's header is in.

In my search, I haven't seen anyone else with quite this situation, but there are people who have had a similar problem because they didn't qmake properly. Because of this, I'm wondering if I need to mess with the project settings to link in the base class's moc file, though I'm not sure how to go about this.

Any questions/suggestions would be greatly appreciated.

wysota
22nd April 2008, 23:35
Is the file created by moc updated when you change contents of your class? In other words - are you mocing the class?

Tiber
23rd April 2008, 15:41
The vs integration automatically re-mocs when you rebuild unless you manually disable it I believe. The parent class is up to date and builds properly, including the moc. The child class compiles, but the child's moc gives the linker error.

I forgot to mention, I've also tried making the child project dependent on the parent project.

wysota
23rd April 2008, 15:53
What does DLL_EXPORT_MACRO contain? Why don't you use the one Qt provides for you?

Tiber
23rd April 2008, 17:13
It's a #define for __declspec(dllexport).

As for why, I asked a coworker, and he said he saw no advantage to using one way over the other, since the Qt way is probably internally the same or very similar(at least for windows).

wysota
23rd April 2008, 17:33
It's a #define for __declspec(dllexport).
In that case that's probably wrong.


As for why, I asked a coworker, and he said he saw no advantage to using one way over the other, since the Qt way is probably internally the same or very similar(at least for windows).

Similar and the same are much different :) The point is that it should be dllexport when building a library and dllimport when using it. Are you building or using? If the latter then probably the library didn't export the symbols needed.

Tiber
23rd April 2008, 18:39
My coworker wants to confirm this with Qt Support, but it looks like he found a solution.

For anyone else who has this problem, I'll explain as best I can his answer.

Between Qt 3 and Qt 4, the Q_OBJECT macro underwent some changes. In Qt 3, the macro made a static struct in a private section, then made accessor and modifier functions.
In Qt 4, there's now a static const struct in the public section. Don't ask me how exactly that creates errors, but here's the short version:

In Qt 3, it was perfectly valid to have a class with the Q_OBJECT macro, and then have a child class that also has Q_OBJECT. In Qt 4, it is not. So just remove Q_OBJECT from the child class and it will still work.

wysota
23rd April 2008, 20:26
In Qt 3, it was perfectly valid to have a class with the Q_OBJECT macro, and then have a child class that also has Q_OBJECT. In Qt 4, it is not. So just remove Q_OBJECT from the child class and it will still work.

Huh? That's not true. QWidget has Q_OBJECT declared. If what you are saying was true, you couldn't have any subclass of QWidget that implements new signals, slots or properties. And that's obviously not the case. I still say you have a problem with moc and linker.

Tiber
24th April 2008, 20:19
Actually you're right. It compiles (which I thought it wouldn't do without Q_OBJECT), but I haven't tested it. I got a little overeager when my coworker said he found a solution, and didn't stop to think about it. Chalk it up to absentmindedness.

Anyway, looking at it more, you had the right idea. The problem was that some preprocessor definitions that were needed (including the one necessary for __declspec(dllimport)) weren't in the project file. Somehow everything managed to work for everyone else still using the Qt 3 build, but not for me working on the Qt 4 port. Just another unexplained mystery of the universe.

Anyway, thanks for your help.

berw
12th January 2011, 10:49
Hi,
I had a similar problem with deriving my own classes from QtAbstractPropertyManager and QtAbstractEditorFactory for the customization of Qtpropertybrowser.

Error messages while linking in VS2008 were:

1>moc_QtImgCoordPropertyManager.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const QtAbstractPropertyManager::staticMetaObject" (?staticMetaObject@QtAbstractPropertyManager@@2UQM etaObject@@B)
1>moc_QtPointImgEditFactory.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const QtAbstractEditorFactoryBase::staticMetaObject" (?staticMetaObject@QtAbstractEditorFactoryBase@@2U QMetaObject@@B)

including "#define QT_QTPROPERTYBROWSER_IMPORT" in the header files of the derived classes resolved the problem (the effect is that it changes the QT_QTPROPERTYBROWSER_EXPORT define in file qtpropertybrowser\src\qtpropertybrowser.h

Hope this info can be helpful for somebody.

dresha48
11th May 2011, 14:44
I just found what is this problem about and how to solve it. I`m changing big project from QT3 to QT4 - and last mistakes was :
"error LNK2001: unresolved external symbol "public: static struct QMetaObject const <CLASS_NAME>::staticMetaObject" (?staticMetaObject@<CLASS_NAME>@@2UQMetaObject@@B)"

The most closest to solution was 'Tiber' here :"The problem was that some preprocessor definitions that were needed (including the one necessary for __declspec(dllimport)) weren't in the project file. Somehow everything managed to work for everyone else still using the Qt 3 build, but not for me working on the Qt 4 port. Just another unexplained mystery of the universe."
and 'nobledeveloper' from other forum: http://www.qtforum.org/article/17697/porting-from-qt3-to-qt4-unresolved-externals.html

At first I wasn't so sure that they are correct and I was trying to find the reason from other ways. I created tested solution with 2 dll`s . With such classes:
parent ( C/C++ -> Preprocessor Difinitions: ...TESTLIB_LIB; ):

#ifdef TESTLIB_LIB
# define TESTLIB_EXPORT Q_DECL_EXPORT
#else
# define TESTLIB_EXPORT Q_DECL_IMPORT
#endif
class TESTLIB_EXPORT testLib: public QObject
{
Q_OBJECT
....
}

child ( C/C++ -> Preprocessor Difinitions: ...TEST2LIBCHILD_LIB; ):

#ifdef TEST2LIBCHILD_LIB
# define TEST2LIBCHILD_EXPORT Q_DECL_EXPORT
#else
# define TEST2LIBCHILD_EXPORT Q_DECL_IMPORT
#endif

class TEST2LIBCHILD_EXPORT test2LibChild:
public testLib
{
Q_OBJECT
...
}


and I get no errors...
But if I add to child "C/C++ -> Preprocessor Difinitions: TESTLIB_LIB" I will get such a link error "error LNK2001: unresolved external symbol "public: static struct QMetaObject const testLib::staticMetaObject" (?staticMetaObject@testLib@@2UQMetaObject@@B)"

To solve my problem I added for each sub-project dlldefslocal.h with corresponding defines , for example:

#ifdef DVL_HIO_DIALOGIO_PLUGIN
# define DVL_HIO_DIALOGIO_PLUGIN_EXPORT Q_DECL_EXPORT
#else
# define DVL_HIO_DIALOGIO_PLUGIN_EXPORT Q_DECL_IMPORT
#endif


It looks like ,if child uses the same define as parent then parent class gets __declspec(dllimport) and we have such a error like LNK2001, why it was normally for QT3 - I think some changes for QObject are resulted in an error for old defines.

dresha48
13th May 2011, 12:27
Small addition:
if you already have big project where you get such errors (I think it only could happens if you are changing yours projects from qt3 to qt4) - just use for parent classes different macro (not like for the children) , where you got errors - thats all . For exapmle I added for all parents which gives me LNK2001 error :
add to parent classes from same dll ( in dll project property add to C/C++ ->Prprocessor->Preprocessor Definitions : DVL_DVL2_DLL_API; ):

#include "dllDefines.h"

class DVL_DVL2_API someParentClassName{...};

dllDefines.h :

#ifdef DVL_DVL2_DLL_API
#define DVL_DVL2_API __declspec(dllexport)
#else
#define DVL_DVL2_API __declspec(dllimport)
#endif