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?
QtWS25 Last Chance

How do you export a QtWidget class from a library?

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 3 Posters 6.2k Views
  • 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.
  • JKSHJ JKSH

    Hi, see http://doc.qt.io/qt-5/sharedlibrary.html

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

    @JKSH

    OK, I tried using the guidelines you pointed me to. (In fact I had already found them on my own, and had tried them.

    So in a small header file dll_defns.h, I added these definitions:

    #ifdef COMPILING_DLL_SOURCE
    #define QTCLASS Q_DECL_EXPORT
    #else
    #define QTCLASS Q_DECL_IMPORT
    #endif

    Then in my QtWidget class header I define my class using the QTCLASS macro

    class QTCLASS ZStatusBar: public QWidget
    {
    Q_OBJECT
    ...
    }

    Finally in the .pro file of the library I add the definition:

    DEFINES += COMPILING_DLL_SOURCE

    This is exactly what the export guidelines suggest, yet when I compile with these changes, I get many warnings, and 1 error:

    The warnings all are of this type:
    warning C4273: 'ZStatusBar::qt_static_metacall' : inconsistent dll linkage

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

    Is there something else I'm missing?

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

      Hi,

      Did you do a full rebuild after adding the macro ?

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

      M 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

        Did you do a full rebuild after adding the macro ?

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

        @SGaist
        I sure thought so, but I'll try again. Are you saying that the changes outlined above are adequate to export a class of this type?

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

          Yes it should.

          I didn't realise, moc_public.cpp looks unusual. What part are you compiling ?

          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 Offline
            M Offline
            Michael.R.LegakoL-3com.com
            wrote on last edited by
            #7

            SGaist,

            I put these definitions in dll_defns.h (I have changed some of the macro names to see if I've got some weird name conflict):

            #ifdef COMPILING_QT_SOURCE
            #define EXPORTQTCLASS Q_DECL_EXPORT
            #else
            #define EXPORTQTCLASS Q_DECL_IMPORT
            #endif

            Then I include this header in my class definition header:
            #include "dll_defns.h"
            class EXPORTQTCLASS ZStatusBar: public QWidget
            {
            Q_OBJECT
            ...
            }

            Finally, I put this define in my Library .pro file

            DEFINES += COMPILING_QT_SOURCE

            After wiping out the previous build files, and any previous output dll, the compile fails with the 1st error being:

            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

            But if I remove EXPORTQTCLASS from the class definition, everything compiles and links. (But in that case, the class is not exported).

            Is there perhaps some include required to define Q_DECL_{EX,IM}PORT? (Not that I'm seeing it complain about this)...

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

              SGaist,

              I put these definitions in dll_defns.h (I have changed some of the macro names to see if I've got some weird name conflict):

              #ifdef COMPILING_QT_SOURCE
              #define EXPORTQTCLASS Q_DECL_EXPORT
              #else
              #define EXPORTQTCLASS Q_DECL_IMPORT
              #endif

              Then I include this header in my class definition header:
              #include "dll_defns.h"
              class EXPORTQTCLASS ZStatusBar: public QWidget
              {
              Q_OBJECT
              ...
              }

              Finally, I put this define in my Library .pro file

              DEFINES += COMPILING_QT_SOURCE

              After wiping out the previous build files, and any previous output dll, the compile fails with the 1st error being:

              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

              But if I remove EXPORTQTCLASS from the class definition, everything compiles and links. (But in that case, the class is not exported).

              Is there perhaps some include required to define Q_DECL_{EX,IM}PORT? (Not that I'm seeing it complain about this)...

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

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

              Is there perhaps some include required to define Q_DECL_{EX,IM}PORT? (Not that I'm seeing it complain about this)...

              That's the downside of macros: If they're not defined, the compiler has absolutely no idea what they're meant to be.

              Q_DECL_IMPORT and Q_DECL_EXPORT are defined in #include <QtGlobal>: http://doc.qt.io/qt-5/qtglobal.html

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

              1 Reply Last reply
              0
              • 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