PDA

View Full Version : Link errors for plugin under windows



QPlace
2nd November 2008, 14:56
I am using Qt4.5 technology preview with VS2008 and I am having problem building a test plugin:

1>pltest.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall MyClearing::metaObject(void)const " (?metaObject@MyClearing@@UBEPBUQMetaObject@@XZ)
1>pltest.obj : error LNK2001: unresolved external symbol "public: virtual void * __thiscall MyClearing::qt_metacast(char const *)" (?qt_metacast@MyClearing@@UAEPAXPBD@Z)
1>pltest.obj : error LNK2001: unresolved external symbol "public: virtual int __thiscall MyClearing::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@MyClearing@@UAEHW4Call@QMetaObject@@ HPAPAX@Z)

This plugin has following code:

test.h file
class Clearing
{
public:
virtual ~Clearing(){};
virtual int Count () = 0;
};

Q_DECLARE_INTERFACE(Clearing,
"TestPlugin.1");

pltest.cpp file
#include <QObject>
#include <QtPlugin>
#include "test.h"

class MyClearing : public QObject, public Clearing
{
Q_OBJECT
Q_INTERFACES(Clearing)
public:
int Count () {return 1;}
};
Q_EXPORT_PLUGIN2(PLTest, MyClearing)

Linker options:
/OUT:"<pathtoproject>\PLTest.dll" /NOLOGO /LIBPATH:"<pathtoQT45\lib" /DLL /MANIFEST /MANIFESTFILE:"Debug\PLTest.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"<pathtoproject>\Debug\PLTest.pdb" /SUBSYSTEM:WINDOWS /DYNAMICBASE /NXCOMPAT /ERRORREPORT:PROMPT qtmaind.lib QtGuid4.lib QtCored4.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

pastor
2nd November 2008, 15:07
You have to moc your MyClearing class with the Qt tool "moc". If you have
a qt project file (.pro) you can:

1) Run qmake && nmake for building through console
or
2) Run qmake -t vcapp for building in MSVS2008

QPlace
2nd November 2008, 15:25
Well, I don't know if that is the problem. The reason I think that it might be something else is an output from the compiler when I build the project. MyClearing class implementation is in pltest.cpp, so it looks like it is "moc"-ed. And pltest.moc is generated and placed in GeneratedFiles\Debug directory


Deleting intermediate and output files for project 'PLTest', configuration 'Debug|Win32'
1>Moc'ing pltest.cpp...
1>Compiling...
1>pltest.cpp
1>Linking...
1> Creating library <pathtoproject>\Debug\PLTest.lib and object <pathtoproject>\Debug\PLTest.exp
1>pltest.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall MyClearing::metaObject(void)const " (?metaObject@MyClearing@@UBEPBUQMetaObject@@XZ)
1>pltest.obj : error LNK2001: unresolved external symbol "public: virtual void * __thiscall MyClearing::qt_metacast(char const *)" (?qt_metacast@MyClearing@@UAEPAXPBD@Z)
1>pltest.obj : error LNK2001: unresolved external symbol "public: virtual int __thiscall MyClearing::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@MyClearing@@UAEHW4Call@QMetaObject@@ HPAPAX@Z)
1><pathtoproject>\PLTest.dll : fatal error LNK1120: 3 unresolved externals

pastor
2nd November 2008, 15:31
Did you include pltest.moc in pltest.cpp? It should be like this:


//pltest.cpp file
#include <QObject>
#include <QtPlugin>
#include "test.h"

class MyClearing : public QObject, public Clearing
{
Q_OBJECT
Q_INTERFACES(Clearing)
public:
int Count () {return 1;}
};Q_EXPORT_PLUGIN2(PLTest, MyClearing)


#include "pltest.moc"

QPlace
2nd November 2008, 15:40
Thank you so much! That was it. I wonder, though, is it mentioned anywhere in Qt docs? I mean, that "<file>.moc has to be included directly? I personally did not find it anywhere in the docs...

pastor
2nd November 2008, 15:51
You're welcome!

Please see http://doc.trolltech.com/4.4/moc.html

Writing Make Rules for Invoking moc


....
For Q_OBJECT class declarations in implementation (.cpp) files, we suggest a makefile rule like this:

foo.o: foo.moc

foo.moc: foo.cpp
moc $(DEFINES) $(INCPATH) -i $< -o $@

This guarantees that make will run the moc before it compiles foo.cpp. You can then put

#include "foo.moc"

at the end of foo.cpp, where all the classes declared in that file are fully known.