Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Unresolved External Symbols Because of __declspec

    General and Desktop
    5
    14
    5707
    Loading More Posts
    • 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.
    • B
      Bihlerben last edited by

      I use MSVC 2014, MinGw-w64 4.2.0 and Qt 5.6.0 and qmake for creating my build Makefiles.

      My project consists of several .dll files and depends itself on 3rd party dlls. I would like to declare a class in one of my dlls that inherits from QObject and from another class from one of the 3rd party dlls.

      If I add "__declspec(dllexport)" to some methods of my class, build the dll and link other dlls against that dll, I get the following linker errors:

      ... unresolved external symbol ... MyClass::metaObject(void)const...
      ... unresolved external symbol ... MyClass::qt_metacast(char const *)...
      ... unresolved external symbol ... MyClass::qt_metacall(enum QMetaObject::Call,int,void * *)...

      This seems to have nothing to do with my project configuration (build.pro), since when I add "__declspec(dllexport)" to the class instead of some of its methods, the linker errors disappear. To make it clear:

      This snippet leads to the linker error:


      class MyClass: public QObject, ...
      {
      Q_OBJECT

      public:

      __declspec(dllexport) MyClass();
      

      ...


      while this snippet works great:


      class __declspec(dllexport) MyClass: public QObject, ...
      {
      Q_OBJECT

      public:
      MyClass();
      ...


      Therefore it seems to me as if the respective symbols "metaObject", "qt_metacast" and "qt_metacall" are not exported from the dll as long as I do not tell the compiler to export the whole class. This annoys me, since it might be impossible to export the whole class. Let's assume that it inherits from another 3rd party dll class which is not completely exported, but has just some exported methods. In this case I cannot export the whole child class as far as I know. The only thing I can do is selectively export child class methods. But in this case these linker errors appear, since the Qt symbols are not exported.

      Am I understanding the issue correctly? What is the standard way to deal with that? Is there an easy way to not export the whole class, but to export the Qt symbols?

      Thank you very much!

      JKSH 1 Reply Last reply Reply Quote 0
      • mrjj
        mrjj Lifetime Qt Champion last edited by

        hi
        Its not an option to use
        http://doc.qt.io/qt-5/plugins-howto.html
        The Low-Level API: Extending Qt Applications

        and use interfaces classes?

        B 1 Reply Last reply Reply Quote 0
        • SGaist
          SGaist Lifetime Qt Champion last edited by

          Hi,

          Export/import declaration are a bit more complex than that. See the Creating Shared Libraries chapter of Qt's documentation.

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

          B 1 Reply Last reply Reply Quote 2
          • B
            Bihlerben @SGaist last edited by

            @SGaist But isn't this exactly what I have done?! Q_DECL_EXPORT will just expand to something like __declspec(dllexport)! Or did you want to tell me to export the whole class always?

            kshegunov 1 Reply Last reply Reply Quote 0
            • B
              Bihlerben @mrjj last edited by

              @mrjj Thanks for your reply, but I guess this is no option, if I have understood you correctly. The exact type hierarchy is necessary, since I want to use the classes inside a given framework. But on the other hand... perhaps another class could emit the Qt signal, therefore I could perhaps simplify my type hierarchies... I will think about it. Thank you!

              1 Reply Last reply Reply Quote 0
              • kshegunov
                kshegunov Moderators @Bihlerben last edited by kshegunov

                @Bihlerben
                You have to export the whole class, how else the members generated by the moc (the Q_OBJECT macro) will be found? Additionally, only your public members are exported from the class, so this begs the question, why would you want to export only some of the public methods?

                And a note: Exporting symbols is only relevant for Windows, on Linux Q_DECL_EXPORT would simply expand to nothing. Linux exports the whole public interface of the class by default.

                Note 2:
                You should use Q_DECL_EXPORT and Q_DECL_IMPORT wrapped in the preprocessor ifdef (as in the link @SGaist sourced), so when including the headers from the user application/libarary you get the __declspec(dllimport) specifier, which is required for Windows.

                Read and abide by the Qt Code of Conduct

                B 1 Reply Last reply Reply Quote 1
                • JKSH
                  JKSH Moderators @Bihlerben last edited by JKSH

                  Hi,

                  @kshegunov said:

                  You have to export the whole class, how else the members generated by the moc (the Q_OBJECT macro) will be found?

                  @Bihlerben said:

                  it seems to me as if the respective symbols "metaObject", "qt_metacast" and "qt_metacall" are not exported from the dll as long as I do not tell the compiler to export the whole class.

                  That's correct, for classes that inherit QObject.

                  To clarify @kshegunov's post, the Q_OBJECT macro expansion includes additional members like metaObject, qt_metacast, etc.. If you don't export the class, then these members don't get exported since you can't add __declspec to the individual members.

                  This annoys me, since it might be impossible to export the whole class. Let's assume that it inherits from another 3rd party dll class which is not completely exported

                  Are you planning to create a class that mulitply-inherits a partially-exported 3rd party class as well as QObject?

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

                  B 1 Reply Last reply Reply Quote 0
                  • B
                    Bihlerben @JKSH last edited by

                    @JKSH Yes, this was my intention. But if this is not easily possible, the easiest workaround will be to simplify my type hierarchy. And this should be possible here. Therefore I consider this issue as solved. Thanks to all for the answers.

                    1 Reply Last reply Reply Quote 0
                    • B
                      Bihlerben @kshegunov last edited by

                      @kshegunov Just a small remark: if I have understood it correctly, also g++ has introduced visibility that allows preventing export of all members (search for gcc and visibility).

                      kshegunov 1 Reply Last reply Reply Quote 0
                      • kshegunov
                        kshegunov Moderators @Bihlerben last edited by

                        @Bihlerben

                        Just a small remark: if I have understood it correctly, also g++ has introduced visibility that allows preventing export of all members (search for gcc and visibility).

                        Yes, the feature had been around for ages. However, by default (as I mentioned before) you have full visibility. Additionally, this is supported in Qt through Q_DECL_HIDDEN not by Q_DECL_EXPORT/Q_DECL_IMPORT.

                        Also, by the way, I don't see a reason for you not to be able to derive from multiple types (not that it's a good practice), and why hiding part of the interface would be important.

                        Read and abide by the Qt Code of Conduct

                        B 1 Reply Last reply Reply Quote 0
                        • B
                          Bihlerben @kshegunov last edited by

                          @kshegunov My explanation was bad (the topic is quite complicated for my poor brains).

                          A better explanation is this:
                          I use Open CASCADE, a free CAD kernel. They have some sophisticated RTTI mechanisms which they implement with macros. Now these macros sometimes add an export hint to the methods defined by themselves (like DEFINE_STANDARD_RTTIEXT for those who know it). This is okay, since in Open CASCADE classes are never completely exported, but only methods are exported.

                          Now I want to subclass Open CASCADE classes and I want to use their macros to have the RTTI mechanisms available. But if I export my whole subclass and the macro adds export hints to the macro-defined methods, MSVC gives error C2487 "member of dll interface class may not be declared with dll interface". I have not found a way to suppress this.

                          kshegunov 1 Reply Last reply Reply Quote 0
                          • kshegunov
                            kshegunov Moderators @Bihlerben last edited by kshegunov

                            @Bihlerben
                            Then, delegate the interface. You're not required to subclass both classes anyways. For example hold a reference to one of the CAD classes in your QObject objects and inline the calls you're going to use, or better yet have an access method that returns the CAD object.

                            class SomeCadClassThatComesFromDll;
                            
                            class MyQObjectDelegatingToCAD : public QObject
                            {
                                Q_OBJECT
                            
                            public:
                                MyQObject(int someParameterForInitialization, QObject * parent = NULL)
                                    : QObject(parent), cadObjectInstance(someParameterForInitialization)
                                {
                                }
                            
                                SomeCadClassThatComesFromDll & cadObject()
                                {
                                    return cadObjectInstance;
                                }
                            
                                const SomeCadClassThatComesFromDll & cadObject() const
                                {
                                    return cadObjectInstance;
                                }
                            
                            private: 
                                SomeCadClassThatComesFromDll cadObjectInstance;
                            };
                            

                            Read and abide by the Qt Code of Conduct

                            B 1 Reply Last reply Reply Quote 2
                            • B
                              Bihlerben @kshegunov last edited by

                              @kshegunov You are right! This is also what I had meant with "simplifying the type hierarchy". Thank you very much for your help!

                              kshegunov 1 Reply Last reply Reply Quote 0
                              • kshegunov
                                kshegunov Moderators @Bihlerben last edited by

                                @Bihlerben

                                This is also what I had meant with "simplifying the type hierarchy".

                                If you ask me, this should be the preferred approach anyway. I particularly dislike the idea of having multiple-inheritance, especially when there doesn't seem to be a good reason for it.

                                Read and abide by the Qt Code of Conduct

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post