Solved Linker error 2001: mainwindow.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject
-
Hi,
I guess this has been asked about a thousand times, but for the love of god, I don't understand why I am getting this linker error. So please bear with me:
I have a project where I create a library which contains 2 ActiveX controls that are going to be used in an industrial HMI. In order to test the controls I have a test application (which is part of the same Qt project) where I dynamically link against the ActiveX control library - I do not embedd an ActiveX client in the test application though.
For creating the library I think I followed the Qt documentation guide lines.Project file:
TEMPLATE = subdirs SUBDIRS = ActiveX_Control TestApp \
The library project file:
win32 { build_pass:CONFIG(debug, debug|release) { TARGET = StaubliControlsd } else { TARGET = StaubliControls } } DESTDIR=../bin TEMPLATE = lib SOURCES += robotComm/cs8robotcomm.cpp \ main.cpp \ TrayView/cs8trayview.cpp \ TrayView/cs8trayspot.cpp \ TrayView/cs8graphicsitemtray.cpp \ TrayView/cs8graphicsitempartlist.cpp \ TrayView/cs8graphicsitempart.cpp \ CleaningTrajectoryView/parser.cpp \ CleaningTrajectoryView/cs8cleaningtrajectorywidget.cpp \ CleaningTrajectoryView/cs8cleaningview.cpp \ CleaningTrajectoryView/codeeditor.cpp \ CleaningTrajectoryView/highlighter.cpp \ TrayView/dialogpartmodifier.cpp HEADERS += robotComm/cs8robotcomm.h \ TrayView/cs8trayview.h \ TrayView/cs8trayspot.h \ TrayView/cs8graphicsitemtray.h \ TrayView/cs8graphicsitempartlist.h \ TrayView/cs8graphicsitempart.h \ CleaningTrajectoryView/parser.h \ CleaningTrajectoryView/cs8cleaningtrajectorywidget.h \ CleaningTrajectoryView/cs8cleaningview.h \ CleaningTrajectoryView/codeeditor.h \ CleaningTrajectoryView/highlighter.h \ TrayView/dialogpartmodifier.h CONFIG += qt warn_all CONFIG += dll DEFINES += CLEANINGTRAJECTORYVIEW_EXPORTS DEFINES += PALETTEVIEW_EXPORTS DEFINES += USE_SQLITE VERSION = 2.0 QT += network widgets QT += axserver sql RC_FILE = qaxserver.rc DEF_FILE = qaxserver.def FORMS += \ CleaningTrajectoryView/cs8cleaningtrajectorywidget.ui \ CleaningTrajectoryView/cs8cleaningview.ui \ TrayView/dialogpartmodifier.ui QTPLUGIN += qsqlite RESOURCES += \ ../res/ActiveX_Control.qrc
And the test application project file:
TARGET = ActiveX_Test TEMPLATE = app DESTDIR=../bin SOURCES += main.cpp \ mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.ui QT += network widgets CONFIG += qt warn_all win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../bin/ -lStaubliControls2 else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../bin/ -lStaubliControlsd2 INCLUDEPATH += $$PWD/../ActiveX_Control/CleaningTrajectoryView DEPENDPATH += $$PWD/../ActiveX_Control/CleaningTrajectoryView INCLUDEPATH += $$PWD/../ActiveX_Control/TrayView DEPENDPATH += $$PWD/../ActiveX_Control/TrayView
The h file of one of the controls looks like this:
#ifndef CS8PALETTEVIEW_H #define CS8PALETTEVIEW_H #include "../robotComm/cs8robotcomm.h" #include "cs8graphicsitemtray.h" #include "dialogpartmodifier.h" #include <QGraphicsView> // The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the PALETTEVIEW_EXPORTS // symbol defined on the command line. this symbol should not be defined on any project // that uses this DLL. This way any other project whose source files include this file see // PALETTEVIEW_API functions as being imported from a DLL, whereas this DLL sees symbols // defined with this macro as being exported. #ifdef PALETTEVIEW_EXPORTS #include <QAxBindable> #define PALETTEVIEW_API Q_DECL_EXPORT #else #define PALETTEVIEW_API Q_DECL_IMPORT #endif class cs8TrayView : public QWidget #ifdef PALETTEVIEW_EXPORTS , public QAxBindable #endif { Q_OBJECT Q_CLASSINFO("ClassID", "{14941F51-AD85-46CE-ABAF-472F5198353A}") Q_CLASSINFO("InterfaceID", "{E12482E3-C3C8-443E-8001-AFEBE58D5A1A}") Q_CLASSINFO("EventsID", "{C0B3A05B-7BD9-4C6B-8C3A-4833B8D30913}") Q_CLASSINFO("Insertable", "yes") Q_CLASSINFO("ToSuperClass", "cs8TrayView") Q_PROPERTY(double partWidth READ partWidth WRITE setPartWidth) Q_PROPERTY(double partDepth READ partDepth WRITE setPartDepth) [..] public: PALETTEVIEW_API cs8TrayView(QWidget *parent = nullptr); PALETTEVIEW_API ~cs8TrayView() override; PALETTEVIEW_API QMap<uint, cs8PartCoordinates> partCoordinates() const; PALETTEVIEW_API cs8TrayTypes paletteTypes() const; PALETTEVIEW_API double partCount(bool withDisabledParts = true); PALETTEVIEW_API QString deactivatedPositions() const; PALETTEVIEW_API void getDeactivatedPositions(QString &value); PALETTEVIEW_API bool updateTrayProperty() const; PALETTEVIEW_API void setHost(QString host); PALETTEVIEW_API QString host() const; PALETTEVIEW_API QString errorString() const; PALETTEVIEW_API void getErrorString(QString &value); PALETTEVIEW_API void mirrorView(bool mirror); PALETTEVIEW_API int currentSelectedPart() const; PALETTEVIEW_API void setCurrentSelectedPart(int currentSelectedPart); PALETTEVIEW_API int modifyCurrentSelectedPart(int delta); PALETTEVIEW_API void enableCurrentPart(bool enable); PALETTEVIEW_API bool currentPartEnabled() const; PALETTEVIEW_API double getMaxTotalWeight() const; PALETTEVIEW_API double getActualWeight() const; [..]
I was able to compile the project without problems and test the library in my test application. Since a while back now the linker complains about unresolved external symbols when I tryto compile the test application:
link /NOLOGO /DYNAMICBASE /NXCOMPAT /DEBUG /SUBSYSTEM:WINDOWS "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /MANIFEST:embed /OUT:..\bin\ActiveX_Test.exe @C:\Users\vdg.HSH\AppData\Local\Temp\ActiveX_Test.exe.7868.156.jom mainwindow.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const cs8TrayView::staticMetaObject" (?staticMetaObject@cs8TrayView@@2UQMetaObject@@B) ..\bin\ActiveX_Test.exe : fatal error LNK1120: 1 unresolved externals
I seem to be having a brain malfunction now, since I can't figure out why the linker process fails now. I tried to clean and rebuild the project multiple times, to no avail.
Any help would be very much appreciated.
Volker
-
Export the whole class, not only single members:
class PALETTEVIEW_API cs8TrayView : public QWidget // ...
this would imply also to remove
PALETTEVIEW_API
that are in front of the functions, as they're redundant. TheQ_OBJECT
macro generates some metadata (and few methods) that need to be accessible to the user binary, and since you haven't exported the whole class that data is private, thus you get the linker error. -
Hi @kshegunov,
indeed that did the trick. Then I just wonder why I could compile the project before where I exported only individual items of the class....
-
@volkerd said in Linker error 2001: mainwindow.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject:
Then I just wonder why I could compile the project before where I exported only individual items of the class
Probably you didn't reference anything related to the
QMetaObject
member (e.g.qobject_cast
) in the user code, so it never was an issue until then. -
@kshegunov said in Linker error 2001: mainwindow.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject:
@volkerd said in Linker error 2001: mainwindow.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject:
Then I just wonder why I could compile the project before where I exported only individual items of the class
Probably you didn't reference anything related to the
QMetaObject
member (e.g.qobject_cast
) in the user code, so it never was an issue until then.Yep, that might explain it.