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. How do you export a QtWidget class from a library?
Forum Updated to NodeBB v4.3 + New Features

How do you export a QtWidget class from a library?

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 3 Posters 6.3k Views 3 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.
  • M Offline
    M Offline
    Michael.R.LegakoL-3com.com
    wrote on last edited by
    #9

    SGaist,
    The class I'm compiling is a class that builds a statusbar for MainWindow::statusBar. It does have signals, and slots, and sets up a number of connect()'s to tie them together. Basically, when my app gets status messages, they get decoded into various things on the status bar the user needs to see; icons get selected for display, text is displayed, etc....

    So the class is a QWidget class that contains various Qt controls:

    QLineEdit -- used for text output
    QLabel -- used for icons
    QPixmap -- used to hold the icon images
    A timer is started to so I can display a clock with the current time in one of the text fields.

    Nothing particularly unusual. I've been using this status bar for some time in 3 separate GUI's, but I was also maintaining 3 separate sets of source code. The idea of creating a custom Widget to implement the status bar is basically my attempt to condense 3 sets of redundant code into one custom QWidget that works for all of them.

    I confess I haven't had to understand the moc files since they have previously just worked....

    Mike

    1 Reply Last reply
    0
    • M Offline
      M Offline
      Michael.R.LegakoL-3com.com
      wrote on last edited by
      #10

      sGaist,
      I was missing the #include <QtGlobal> but adding it has not changed the result. I still get

      D:\Year_2015\svn_nyfr_sw_1\SW\include\API_NYFR_Msg_ICD/public.hpp(75) : error C2470: 'ZStatusBar' : looks like a functio
      n definition, but there is no parameter list; skipping apparent body

      The header skipping only fields of the same type is:

      #ifndef ZSTATUSBAR_H
      #define ZSTATUSBAR_H
      #include <QtGlobal> /* Defines: Q_DECL_EXPORT, Q_DECL_IMPORT /
      #include <QWidget>
      #include <QStatusBar>
      #include <QLineEdit>
      #include <QLabel>
      #include <QTimerEvent>
      #include <API_NYFR_Msg_ICD/public_types.h> /
      Defines: StatusMsg_TYPE /
      #include <Protos/common_macros.h> /
      Defines: LIN_SIZ */

      #include <Protos/dll_defns.h>

      class EXPORTQTCLASS ZStatusBar: public QWidget
      {
      Q_OBJECT
      public:
      ZStatusBar(QWidget *parent=0);
      virtual ~ZStatusBar();
      int Create(QStatusBar *statusBar);

      void EmitValue(int item,int iSubItem,int iValue);
      void EmitText(int item,char *sValue);
      void EmitStatus(StatusMsg_TYPE Msg2,int bHeartBeat,int iRole);
      void EmitInit(); /
      Used to put status bar status as 'unknown' */

      signals:
      void updateStatusSignal(StatusMsg_TYPE *Msg2,int bHeartBeat,int iRole);
      void updateValueSignal(int item,int iSubItem,int iValue);
      void updateTextSignal(int item,char *sValue);
      void initSignal(void);

      protected:
      void timerEvent(QTimerEvent *event);

      private slots:
      void updateValueSlot(int item, int iSubItem, int iValue);
      void updateTextSlot(int item, char *sValue);
      void updateStatusSlot(StatusMsg_TYPE *Msg2,int bHeartBeat,int iRole);
      void initSlot();
      private:
      char *get_today(char *format1,char *sResult);
      bool m_bCAC;
      // Status Bar Content

      QLabel m_oConnectivityIcon[8]; /* 8 LEDs showing system connectivity /
      QLineEdit m_oNavTime;
      /
      PixMaps */
      QPixmap m_oRC_Lock[2];

      int m_iNavTimerID;
      char m_sPathFile[LIN_SIZ];
      };

      #endif // ZSTATUSBAR_H

      JKSHJ 1 Reply Last reply
      0
      • M Michael.R.LegakoL-3com.com

        sGaist,
        I was missing the #include <QtGlobal> but adding it has not changed the result. I still get

        D:\Year_2015\svn_nyfr_sw_1\SW\include\API_NYFR_Msg_ICD/public.hpp(75) : error C2470: 'ZStatusBar' : looks like a functio
        n definition, but there is no parameter list; skipping apparent body

        The header skipping only fields of the same type is:

        #ifndef ZSTATUSBAR_H
        #define ZSTATUSBAR_H
        #include <QtGlobal> /* Defines: Q_DECL_EXPORT, Q_DECL_IMPORT /
        #include <QWidget>
        #include <QStatusBar>
        #include <QLineEdit>
        #include <QLabel>
        #include <QTimerEvent>
        #include <API_NYFR_Msg_ICD/public_types.h> /
        Defines: StatusMsg_TYPE /
        #include <Protos/common_macros.h> /
        Defines: LIN_SIZ */

        #include <Protos/dll_defns.h>

        class EXPORTQTCLASS ZStatusBar: public QWidget
        {
        Q_OBJECT
        public:
        ZStatusBar(QWidget *parent=0);
        virtual ~ZStatusBar();
        int Create(QStatusBar *statusBar);

        void EmitValue(int item,int iSubItem,int iValue);
        void EmitText(int item,char *sValue);
        void EmitStatus(StatusMsg_TYPE Msg2,int bHeartBeat,int iRole);
        void EmitInit(); /
        Used to put status bar status as 'unknown' */

        signals:
        void updateStatusSignal(StatusMsg_TYPE *Msg2,int bHeartBeat,int iRole);
        void updateValueSignal(int item,int iSubItem,int iValue);
        void updateTextSignal(int item,char *sValue);
        void initSignal(void);

        protected:
        void timerEvent(QTimerEvent *event);

        private slots:
        void updateValueSlot(int item, int iSubItem, int iValue);
        void updateTextSlot(int item, char *sValue);
        void updateStatusSlot(StatusMsg_TYPE *Msg2,int bHeartBeat,int iRole);
        void initSlot();
        private:
        char *get_today(char *format1,char *sResult);
        bool m_bCAC;
        // Status Bar Content

        QLabel m_oConnectivityIcon[8]; /* 8 LEDs showing system connectivity /
        QLineEdit m_oNavTime;
        /
        PixMaps */
        QPixmap m_oRC_Lock[2];

        int m_iNavTimerID;
        char m_sPathFile[LIN_SIZ];
        };

        #endif // ZSTATUSBAR_H

        JKSHJ Offline
        JKSHJ Offline
        JKSH
        Moderators
        wrote on last edited by JKSH
        #11

        @Michael.R.LegakoL-3com.com said:

        D:\Year_2015\svn_nyfr_sw_1\SW\include\API_NYFR_Msg_ICD/public.hpp(75) : error C2470: 'ZStatusBar' : looks like a functio
        n definition, but there is no parameter list; skipping apparent body

        What's at line 75?

        Usually, that message means the compiler saw "class EXPORTQTCLASS ZStatusBar: public QWidget" but doesn't understand what EXPORTQTCLASS is. So, the compiler thought that ZStatusBar is a function that returns class EXPORTQTCLASS, and so it looks for the parameter list after the "function" name (e.g. "ZStatusBar(int param1, const QString& param2)"). However, it couldn't find a parameter list, so it skips everything that comes after that.

        In short, the compiler is confused because your EXPORTQTCLASS doesn't eventually expand to _declspec(dllexport).

        Are you using Qt Creator? If so, hover your mouse cursor over EXPORTQTCLASS and see what it expands to. Also, try replacing all instances of EXPORTQTCLASS with Q_DECL_EXPORT and see what happens. (Again, hover your mouse cursor over Q_DECL_EXPORT and see what it expands to)

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        M 1 Reply Last reply
        0
        • JKSHJ JKSH

          @Michael.R.LegakoL-3com.com said:

          D:\Year_2015\svn_nyfr_sw_1\SW\include\API_NYFR_Msg_ICD/public.hpp(75) : error C2470: 'ZStatusBar' : looks like a functio
          n definition, but there is no parameter list; skipping apparent body

          What's at line 75?

          Usually, that message means the compiler saw "class EXPORTQTCLASS ZStatusBar: public QWidget" but doesn't understand what EXPORTQTCLASS is. So, the compiler thought that ZStatusBar is a function that returns class EXPORTQTCLASS, and so it looks for the parameter list after the "function" name (e.g. "ZStatusBar(int param1, const QString& param2)"). However, it couldn't find a parameter list, so it skips everything that comes after that.

          In short, the compiler is confused because your EXPORTQTCLASS doesn't eventually expand to _declspec(dllexport).

          Are you using Qt Creator? If so, hover your mouse cursor over EXPORTQTCLASS and see what it expands to. Also, try replacing all instances of EXPORTQTCLASS with Q_DECL_EXPORT and see what happens. (Again, hover your mouse cursor over Q_DECL_EXPORT and see what it expands to)

          M Offline
          M Offline
          Michael.R.LegakoL-3com.com
          wrote on last edited by
          #12

          @JKSH
          I think you were right. The macro I was using to export with (EXPORTQTCLASS) is somehow not getting equated to Q_DECL_EXPORT. Replacing the class definition:

          class EXPORTQTCLASS ZStatusBar: public QWidget

          with

          class Q_DECL_EXPORT ZStatusBar: public QWidget

          solves the issue and everything compiles and links. Of course that won't work when I include that header in the application that needs to use ZStatusBar, but that does narrow the issue down to figuring out why the macro is not assigned the correct value.

          Thanks! Essentially I think this solves the issue...

          Mike

          M 1 Reply Last reply
          0
          • M Michael.R.LegakoL-3com.com

            @JKSH
            I think you were right. The macro I was using to export with (EXPORTQTCLASS) is somehow not getting equated to Q_DECL_EXPORT. Replacing the class definition:

            class EXPORTQTCLASS ZStatusBar: public QWidget

            with

            class Q_DECL_EXPORT ZStatusBar: public QWidget

            solves the issue and everything compiles and links. Of course that won't work when I include that header in the application that needs to use ZStatusBar, but that does narrow the issue down to figuring out why the macro is not assigned the correct value.

            Thanks! Essentially I think this solves the issue...

            Mike

            M Offline
            M Offline
            Michael.R.LegakoL-3com.com
            wrote on last edited by
            #13

            @JKSH,

            OK, now I think I've isolated why the macro Q_DECL_EXPORT never gets assigned. It was never defined. SGaist suggested that the macros QDECL_EXPORT, and Q_DECL_IMPORT are given values by <QtGlobal>, but I have discovered that these two macros are actually assigned within qcompilerdetection.h. Maybe QtGlobal is supposed to include something that eventually is supposed to include qcompilerdetection.h??? The path to qcompilerdetection.h is C:/Qt/Qt5.2.0/5.2.0/msvc2012_64/include/QtCore/qcompilerdetection.h. I would think the file would be included using

            #include <QtCore/qcompilerdetection.h>

            But this doesn't seem to work. I think getting the two macros defined somehow is the issue. On the machine I'm on, MSVS2012 is the compiler, the machine is 64 bits, and 5.2.0 is the version of Qt in use.

            M 1 Reply Last reply
            0
            • M Michael.R.LegakoL-3com.com

              @JKSH,

              OK, now I think I've isolated why the macro Q_DECL_EXPORT never gets assigned. It was never defined. SGaist suggested that the macros QDECL_EXPORT, and Q_DECL_IMPORT are given values by <QtGlobal>, but I have discovered that these two macros are actually assigned within qcompilerdetection.h. Maybe QtGlobal is supposed to include something that eventually is supposed to include qcompilerdetection.h??? The path to qcompilerdetection.h is C:/Qt/Qt5.2.0/5.2.0/msvc2012_64/include/QtCore/qcompilerdetection.h. I would think the file would be included using

              #include <QtCore/qcompilerdetection.h>

              But this doesn't seem to work. I think getting the two macros defined somehow is the issue. On the machine I'm on, MSVS2012 is the compiler, the machine is 64 bits, and 5.2.0 is the version of Qt in use.

              M Offline
              M Offline
              Michael.R.LegakoL-3com.com
              wrote on last edited by
              #14

              @JKSH, and @SGaist ,
              Thanks both of you. The problem wasn't your advice. <QtGlobal> DOES define Q_DECL_{EX,IM}PORT (both of them). The real issue was a fairly subtle mistake on my part. I was using the macro COMPILING_Q_LIB to switch between these two macros, but in my .pro there was a DEFINE statement using = following the DEFINE for COMPILING_Q_LIB (which also used the = operator). So the 2nd define statement wiped out all previous defines including the one for COMPILING_Q_LIB.

              (It would be a good thing to have the compiler detect when more than one DEFINE statement is using the = operator. I'm sure quite a number of the really subtle issues you are seeing are because of that one thing!)

              M 1 Reply Last reply
              0
              • M Michael.R.LegakoL-3com.com

                @JKSH, and @SGaist ,
                Thanks both of you. The problem wasn't your advice. <QtGlobal> DOES define Q_DECL_{EX,IM}PORT (both of them). The real issue was a fairly subtle mistake on my part. I was using the macro COMPILING_Q_LIB to switch between these two macros, but in my .pro there was a DEFINE statement using = following the DEFINE for COMPILING_Q_LIB (which also used the = operator). So the 2nd define statement wiped out all previous defines including the one for COMPILING_Q_LIB.

                (It would be a good thing to have the compiler detect when more than one DEFINE statement is using the = operator. I'm sure quite a number of the really subtle issues you are seeing are because of that one thing!)

                M Offline
                M Offline
                Michael.R.LegakoL-3com.com
                wrote on last edited by
                #15

                Apparently my odyssey isn't over yet. Although I was able to get my QWidget to compile and link, and although depends does show that the object is exported, now I'm seeing an entirely new kind of issue when I try to link the new QWidget object in with an application. In the compiler output of the application, I now get the error:

                debug\moc_public.cpp(148) : error C2491: 'ZStatusBar::staticMetaObject' : definition of dllimport static data member not allowed

                And sure enough, looking at the depends exports I see the static meta object in the export list. In fact there is both a qt_static_metacall, and a staticMetaObject although the above error seems to point just to the latter.

                Since I don't directly generate the files that create these things, how do I prevent them from being included when the object is exported?

                JKSHJ 1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #16

                  I haven't got bitten by that one while building Qt based shared libraries. Can you try to make a small minimal library to see if it's still happening ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • M Michael.R.LegakoL-3com.com

                    Apparently my odyssey isn't over yet. Although I was able to get my QWidget to compile and link, and although depends does show that the object is exported, now I'm seeing an entirely new kind of issue when I try to link the new QWidget object in with an application. In the compiler output of the application, I now get the error:

                    debug\moc_public.cpp(148) : error C2491: 'ZStatusBar::staticMetaObject' : definition of dllimport static data member not allowed

                    And sure enough, looking at the depends exports I see the static meta object in the export list. In fact there is both a qt_static_metacall, and a staticMetaObject although the above error seems to point just to the latter.

                    Since I don't directly generate the files that create these things, how do I prevent them from being included when the object is exported?

                    JKSHJ Offline
                    JKSHJ Offline
                    JKSH
                    Moderators
                    wrote on last edited by
                    #17

                    @JKSH said:

                    debug\moc_public.cpp(148) : error C2491: 'ZStatusBar::staticMetaObject' : definition of dllimport static data member not allowed

                    The project that uses ZStatusBar should treat its header as an external file, and add the header to INCLUDEPATH. That project should not contain a copy of the header (in other words, that project should not have "HEADERS += public.h").

                    Think of it this way: You #include qwidget.h, but you don't copy qwidget.h into your project. You should treat your ZStatusBar header in the same manner.

                    If your project contains a copy of the header, the meta-object compiler will try to generate code for the QObjects in that header. However, this is illegal because the generated code already exists in your library.

                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                    M 1 Reply Last reply
                    1
                    • JKSHJ JKSH

                      @JKSH said:

                      debug\moc_public.cpp(148) : error C2491: 'ZStatusBar::staticMetaObject' : definition of dllimport static data member not allowed

                      The project that uses ZStatusBar should treat its header as an external file, and add the header to INCLUDEPATH. That project should not contain a copy of the header (in other words, that project should not have "HEADERS += public.h").

                      Think of it this way: You #include qwidget.h, but you don't copy qwidget.h into your project. You should treat your ZStatusBar header in the same manner.

                      If your project contains a copy of the header, the meta-object compiler will try to generate code for the QObjects in that header. However, this is illegal because the generated code already exists in your library.

                      M Offline
                      M Offline
                      Michael.R.LegakoL-3com.com
                      wrote on last edited by
                      #18

                      @JKSH ,
                      Direct hit! Score 1 for JKSH.

                      I guess in retrospect your suggestion is obvious since a class header is more than just prototypes, but can also contain implementations. Removing the ZStatusBar header from HEADERS yet making sure the path to the header is in INCLUDEPATH did the trick. Good Catch!

                      At this point, both the ZStatusBar library, and the application that uses it are compiling and linking, so this is pretty good evidence that the original issue of this thread has been solved.

                      Mike

                      1 Reply Last reply
                      0

                      • Login

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