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. Export QObject based class from DLL
Forum Updated to NodeBB v4.3 + New Features

Export QObject based class from DLL

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 5 Posters 6.3k Views 2 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.
  • D Offline
    D Offline
    deleted427
    wrote on last edited by
    #1

    If you want to export a C++ class from a DLL (Windows), you need to declare it with proper __declspec(dllexport) (if building the DLL) or __declspec(dllimport) (when using the DLL). That's just what Windows wants you to do, and it is normally done with properly defined preprocessor macros, like

    class MYDLL_EXPORT myClass
    {
    ...
    }
    

    But if now this class happens to be derived from QObject, this is not working any more - and I have not found a solution yet:

    class MYDLL_EXPORT myClass: public QObject
    {
    Q_OBJECT
    ...
    }
    

    The point is that this header will have to be MOC'ed, and this tool will generate some code that is not allowed together with __declspec(dllimport) and the compiler gives an error message like this:

    moc_myClass.cpp(89): error C2491: 'atgCategoriesManager::staticMetaObject': definition of dllimport static data member not allowed
    

    and that's it!

    Now the point is that I used Google and found MANY mentions of this problem, but bad enough: not one single solution!

    So my question still remains: What can I do so solve that problem?

    The point is simply: the Q_OBJECT macro generates code that is not acceptable for the MSVC compiler if you do not only export it from a dll, but also want to import it - which is finally the purpose of any DLL! It really starts to drive me a little crazy: Maybe I should totally redesign my software and make sure that QObject derived classes are never exported from DLLs!??

    raven-worxR 1 Reply Last reply
    0
    • D Offline
      D Offline
      deleted427
      wrote on last edited by
      #9

      Conclusion: problem solved - thanks to the hint of VRonin!

      An additional hint I found somewhere else for CMake users. There you can do it as follows:

      In the configuration file you need this:

      INCLUDE(GenerateExportHeader)
      SET(MOC_SOURCES)
      QT5_WRAP_CPP(
          MOC_SOURCES
          myDllClass.h
      )
      
      ADD_LIBRARY(MyDll
          SHARED
              myDllClass.h
              myDllClass.cpp
              ${MOC_SOURCES}
          )
      
      GENERATE_EXPORT_HEADER(MyDll)
      

      Then in the header file you need:

      #include <mydll_export.h>
      class MYDLL_EXPORT atgCategoriesManager: public QObject
      {
          Q_OBJECT
      ...
      

      This seems to be the most elegant way if you are working with CMake: the GENERATE_EXPORT_HEADER macro will generate that mydll_export.h file that keeps all that Microsoftish blah-blah, so your real code stays nice, clean and readable.

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

        Hi,

        Did you follow Qt's documentation about creating shared libraries ?

        There should be no problem for QObject based classes.

        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
        2
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by
          #3

          Only way I can think of is through exported C functions which are wrapped around the object calls. This not a elegant but it works.

          Dheerendra
          @Community Service
          Certified Qt Specialist
          http://www.pthinks.com

          1 Reply Last reply
          0
          • D deleted427

            If you want to export a C++ class from a DLL (Windows), you need to declare it with proper __declspec(dllexport) (if building the DLL) or __declspec(dllimport) (when using the DLL). That's just what Windows wants you to do, and it is normally done with properly defined preprocessor macros, like

            class MYDLL_EXPORT myClass
            {
            ...
            }
            

            But if now this class happens to be derived from QObject, this is not working any more - and I have not found a solution yet:

            class MYDLL_EXPORT myClass: public QObject
            {
            Q_OBJECT
            ...
            }
            

            The point is that this header will have to be MOC'ed, and this tool will generate some code that is not allowed together with __declspec(dllimport) and the compiler gives an error message like this:

            moc_myClass.cpp(89): error C2491: 'atgCategoriesManager::staticMetaObject': definition of dllimport static data member not allowed
            

            and that's it!

            Now the point is that I used Google and found MANY mentions of this problem, but bad enough: not one single solution!

            So my question still remains: What can I do so solve that problem?

            The point is simply: the Q_OBJECT macro generates code that is not acceptable for the MSVC compiler if you do not only export it from a dll, but also want to import it - which is finally the purpose of any DLL! It really starts to drive me a little crazy: Maybe I should totally redesign my software and make sure that QObject derived classes are never exported from DLLs!??

            raven-worxR Offline
            raven-worxR Offline
            raven-worx
            Moderators
            wrote on last edited by
            #4

            @CoBo
            the case you described definitely works as expected.
            How does your MYDLL_EXPORT macro look like? I guess you just forgot to define the macro which switched between import/export?

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            1
            • D Offline
              D Offline
              deleted427
              wrote on last edited by
              #5

              Thanks for your quick replies!

              Actually I found and followed that link by SGaist for long - and it did not work for me if the class is derived from QObject.

              And answering to raven-worx: I am pretty sure that I did it all as advertised:

              In the cpp I have code like

              #define DEF_MYDLL
              #include <myDll.h>
              

              and in the header it looks like this:

              #ifdef DEF_MYDLL
              #define MYDLL_EXPORT Q_DECL_EXPORT
              #else
              #define MYDLL_EXPORT Q_DECL_IMPORT
              #endif
              
              class MYDLL_EXPORT myDllClass: public QObject
              {
                  Q_OBJECT
              ...
              

              I am pretty sure that this is correct.

              Right at this moment I am busy implementing a solution that is similar to what dheerendra is proposing: I generate a "singleton" class in plain C++ in the way as described - with the macro Microsoft blablah. Which so far seems to work: it compiles, links - and I can pass a single "int" value from one DLL to another!

              Next step I will try to extend this as kind of a global "singleton class manager": In the main program I generate the different singleton classes and give the pointers to that "manager", and in other DLLs I retrieve the pointers from the manager and do whatever is required. And I guess that in this way I should also be able to handle classes/objects that are derived from QObject - because they will always only reside in the main program.

              PS: I have one guess why it might be possible that still both statements are true: "it works" and "it doesn't". I see that my own class is not only derived from QObject, but includes also a static function. It is not defined in the header, so I don't see why there SHOULD be trouble, but maybe the error message is actually wrong: it complains about the "staticMetaObject" (which is a MOC product), but maybe the real root cause is still the fact that there is a static function in the class!?? However, no time yet to check this option.

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #6

                The export of QObject works, Qt uses it extensively internally. It also works with custom made libraries see this for an example.

                The problem you have is that DEF_MYDLL should not go in the source or header files with #define DEF_MYDLL but should be passed to the compiler preprocessors.

                • In qmake/Qt Creator you can change the .pro file by adding DEFINES += DEF_MYDLL and re-running qmake
                • in CMake add DEF_MYDLL to the private target_compile_definitions, for example target_compile_definitions(myLibrary PRIVATE DEF_MYDLL)
                • in Visual Studio right click on the project->properties->C/C++->Preprocessor->Preprocessor Definitions->Edit and append DEF_MYDLL to the list (repeat the process for Debug, Release, 32 and 64bit versions using the comboboxes at the top)

                Now the point is that I used Google and found MANY mentions of this problem, but bad enough: not one single solution!

                If the above solves your problem could you post a link to this topic to the other forums you googled so the next time if someone googles he'll find the solution?

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                D 1 Reply Last reply
                3
                • VRoninV VRonin

                  The export of QObject works, Qt uses it extensively internally. It also works with custom made libraries see this for an example.

                  The problem you have is that DEF_MYDLL should not go in the source or header files with #define DEF_MYDLL but should be passed to the compiler preprocessors.

                  • In qmake/Qt Creator you can change the .pro file by adding DEFINES += DEF_MYDLL and re-running qmake
                  • in CMake add DEF_MYDLL to the private target_compile_definitions, for example target_compile_definitions(myLibrary PRIVATE DEF_MYDLL)
                  • in Visual Studio right click on the project->properties->C/C++->Preprocessor->Preprocessor Definitions->Edit and append DEF_MYDLL to the list (repeat the process for Debug, Release, 32 and 64bit versions using the comboboxes at the top)

                  Now the point is that I used Google and found MANY mentions of this problem, but bad enough: not one single solution!

                  If the above solves your problem could you post a link to this topic to the other forums you googled so the next time if someone googles he'll find the solution?

                  D Offline
                  D Offline
                  deleted427
                  wrote on last edited by
                  #7

                  @VRonin Wow, that sounds really promising - and I have not seen it mentioned otherwise! Also not tried at this moment, but somehow makes sense.

                  Although I must say that some of the readings were talking about adding the defines to the qmake configuration, but since I am working with CMake (+QtCreator) this did not look adequate for me.

                  But since you seem to really understand that issue I have one additional understanding question: If I add the definition to the configuration (be it qmake, cmake or vs) I basically add it either to that specific C++ implementation file (like I do it with the #define...), or I add it to all files - which then "kills" the effect because it will be defined wherever the header is included - no?

                  What I guess is that "somehow" it has to be made sure that it is also defined in some MOC generated files - and that your method SOMEHOW does this trick!?

                  Ah, ok: if I do target_compile_definitions(myLibrary PRIVATE DEF_MYDLL) I actually add it to whatever is compiled into that library - and that indeed includes also the "MOC products"...

                  Right!?

                  Regarding your last remark I am not sure I will be able to really do it - because after seeing these instructions with the macros so many times - without your important hint! - I did not really keep these links any more...

                  VRoninV 1 Reply Last reply
                  0
                  • D deleted427

                    @VRonin Wow, that sounds really promising - and I have not seen it mentioned otherwise! Also not tried at this moment, but somehow makes sense.

                    Although I must say that some of the readings were talking about adding the defines to the qmake configuration, but since I am working with CMake (+QtCreator) this did not look adequate for me.

                    But since you seem to really understand that issue I have one additional understanding question: If I add the definition to the configuration (be it qmake, cmake or vs) I basically add it either to that specific C++ implementation file (like I do it with the #define...), or I add it to all files - which then "kills" the effect because it will be defined wherever the header is included - no?

                    What I guess is that "somehow" it has to be made sure that it is also defined in some MOC generated files - and that your method SOMEHOW does this trick!?

                    Ah, ok: if I do target_compile_definitions(myLibrary PRIVATE DEF_MYDLL) I actually add it to whatever is compiled into that library - and that indeed includes also the "MOC products"...

                    Right!?

                    Regarding your last remark I am not sure I will be able to really do it - because after seeing these instructions with the macros so many times - without your important hint! - I did not really keep these links any more...

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #8

                    @CoBo said in Export QObject based class from DLL:

                    Ah, ok: if I do target_compile_definitions(myLibrary PRIVATE DEF_MYDLL) I actually add it to whatever is compiled into that library - and that indeed includes also the "MOC products"

                    Correct. That's basically equivalent to add #define DEF_MYDLL at the top of every header and source file for that target

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    1
                    • D Offline
                      D Offline
                      deleted427
                      wrote on last edited by
                      #9

                      Conclusion: problem solved - thanks to the hint of VRonin!

                      An additional hint I found somewhere else for CMake users. There you can do it as follows:

                      In the configuration file you need this:

                      INCLUDE(GenerateExportHeader)
                      SET(MOC_SOURCES)
                      QT5_WRAP_CPP(
                          MOC_SOURCES
                          myDllClass.h
                      )
                      
                      ADD_LIBRARY(MyDll
                          SHARED
                              myDllClass.h
                              myDllClass.cpp
                              ${MOC_SOURCES}
                          )
                      
                      GENERATE_EXPORT_HEADER(MyDll)
                      

                      Then in the header file you need:

                      #include <mydll_export.h>
                      class MYDLL_EXPORT atgCategoriesManager: public QObject
                      {
                          Q_OBJECT
                      ...
                      

                      This seems to be the most elegant way if you are working with CMake: the GENERATE_EXPORT_HEADER macro will generate that mydll_export.h file that keeps all that Microsoftish blah-blah, so your real code stays nice, clean and readable.

                      1 Reply Last reply
                      2

                      • Login

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