Unresolved external symbol when using Qt derived classes in multiple DLLs
-
Hi there
I'm not sure that this is the right forum but since it has to do with compiling and MOCcing I decided to give it a try here :)
My environment:
- Windows 7 64 bit
- Visual Studio 2008 64 compiler
- Eclipse IDE
- Qt 4.8.0 64 bit as DLLs with dynamic linking
I use Qt project files and run qmake and nmake to create Makesfiles and build my projects from Eclipse.
What I did and what went right:
- wrote custom a.dll with classes deriving from Qt widget classes
- wrote a custom c.exe using my classes from a.dll
Everything ok on this end, things work as expected.
What I'm trying to do now and what drives me crazy:
- wrote custom a.dll with classes deriving from Qt widget classes
- wrote a custom b.dll with classes deriving from classes in a.dll
- wrote a custom c.exe using my classes from b.dll
That does not work and produces unresolved symbol warnings like this one:
@my_appbase_main_window.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const Tools::FilterBox::staticMetaObject" @In this example I have a class FilterBox that inherits QLineEdit. The namespace with the FilterBox class sits inside a.dll.
Now I wanted to inherit the FilterBox in b.dll. But just including the corresponding header for the FilterBox class (not yet deriving from this class and not even instanciating the FilterBox class) in my_appbase_main_window.cpp in b.dll makes the linker produces this error.
Let me add that I can actually use the FilterBox class in my c.exe project. I can even write a new class inheriting FilterBox in the c.exe project. No problem with that. But somehow it seems I cannot use my FilterBox (and all my toher classes for that matter) in yet another DLL building on top of them. :(
This problem only occurs with MOC'ced classes. I can write and use non-MOC'ed QWidget derived classes or even non-Qt classes in my a.dll and use it in b.dll.
My QMake project file for a.dll (and my other DLL for that matter) looks like so :
@
DEFINES += MY_EXPORTS
TEMPLATE = lib
TARGET =
DEPENDPATH += . source
QMAKE_CFLAGS_RELEASE += -Zi
QMAKE_CXXFLAGS_RELEASE += -Zi
QMAKE_LFLAGS_RELEASE += /DEBUG /PDB:my_tools.pdbINCLUDEPATH += "$$(MY_PATH)\include"
LIBS += -L"$$(MY_PATH)\release\lib"
LIBS += -lmy_whatsoever_dllHEADERS += ToolsFilterBox.h
SOURCES += source/tools_filter_box.cpp
@Finally, to export/import my classes I use the following macro and the now famous FilterBox looks like so:
@// MyCoreTypes.h
#ifdef MY_EXPORTS
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif
@@
#ifndef TOOLSFILTERBOX_H_
#define TOOLSFILTERBOX_H_#include <QtGui/QLineEdit>
#include <MyCoreTypes.h>class QToolButton;
namespace Tools
{class MY_DLL_API FilterBox : public QLineEdit { Q_OBJECT; public: FilterBox(const QString &ghost_text, QWidget *parent); virtual ~FilterBox();
signals:
void filterRemovedSignal();
void filterChangedSignal(const QString &filter_text);protected: virtual void resizeEvent(QResizeEvent *); private slots: void updateClearButton(const QString &text); };
} // namespace
#endif@
What I don't understand is that I can use all of my classes inheriting Qt classes inside the same DLL and even inside my EXE project. So the MOC and importing/exporting works ... basically. I can also use all of my non-MOC classes without Q_OBJECT and signals and slots inside other DLL.
But as soon as I have to MOC a class of mine I cannot use it in another DLL but only in the same DLL or in an EXE project.
Hopefully someone here can give me a helping hand? :)
thanks
Steve -
gnarg
I was of course using the same MY_DLL_API define for all of my DLL projects. So b.dll was also declaring the classes it included from a.dll as __declspec(dllexport) and not as __declspec(dllimport). I'm not quite sure why this was no issue when using non-MOC'ed classes but that somehow worked.
Now I started using different #defines for each of my DLL projects so that classes from one DLL are used as dllimport in all other DLLs utilizing or inheriting them. That not only seems plausible now but also works as expected including MOC'ed classes.
Anyway, thanks for reading :)