Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Linker error 2001: mainwindow.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject
Forum Updated to NodeBB v4.3 + New Features

Linker error 2001: mainwindow.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 1.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    volkerd
    wrote on 4 Apr 2018, 09:02 last edited by
    #1

    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

    kshegunovK 1 Reply Last reply 4 Apr 2018, 11:00
    0
    • V volkerd
      4 Apr 2018, 09:02

      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

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on 4 Apr 2018, 11:00 last edited by
      #2

      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. The Q_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.

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      2
      • V Offline
        V Offline
        volkerd
        wrote on 4 Apr 2018, 11:05 last edited by
        #3

        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....

        kshegunovK 1 Reply Last reply 4 Apr 2018, 11:07
        0
        • V volkerd
          4 Apr 2018, 11:05

          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....

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on 4 Apr 2018, 11:07 last edited by
          #4

          @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.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          0
          • V Offline
            V Offline
            volkerd
            wrote on 4 Apr 2018, 18:59 last edited by
            #5

            @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.

            1 Reply Last reply
            0

            1/5

            4 Apr 2018, 09:02

            • Login

            • Login or register to search.
            1 out of 5
            • First post
              1/5
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved