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. Unresolved External Symbols Because of __declspec
Forum Updated to NodeBB v4.3 + New Features

Unresolved External Symbols Because of __declspec

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 5 Posters 7.3k Views 4 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.
  • B Offline
    B Offline
    Bihlerben
    wrote on last edited by
    #1

    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!

    JKSHJ 1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        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
        2
        • SGaistS SGaist

          Hi,

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

          B Offline
          B Offline
          Bihlerben
          wrote on last edited by
          #4

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

          kshegunovK 1 Reply Last reply
          0
          • mrjjM mrjj

            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 Offline
            B Offline
            Bihlerben
            wrote on last edited by
            #5

            @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
            0
            • B Bihlerben

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

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by kshegunov
              #6

              @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
              1
              • B Bihlerben

                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!

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

                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
                0
                • JKSHJ 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?

                  B Offline
                  B Offline
                  Bihlerben
                  wrote on last edited by
                  #8

                  @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
                  0
                  • kshegunovK 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.

                    B Offline
                    B Offline
                    Bihlerben
                    wrote on last edited by
                    #9

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

                    kshegunovK 1 Reply Last reply
                    0
                    • B Bihlerben

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

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @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
                      0
                      • kshegunovK kshegunov

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

                        B Offline
                        B Offline
                        Bihlerben
                        wrote on last edited by
                        #11

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

                        kshegunovK 1 Reply Last reply
                        0
                        • B Bihlerben

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

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by kshegunov
                          #12

                          @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
                          2
                          • kshegunovK 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;
                            };
                            
                            B Offline
                            B Offline
                            Bihlerben
                            wrote on last edited by
                            #13

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

                            kshegunovK 1 Reply Last reply
                            0
                            • B Bihlerben

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

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by
                              #14

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

                              • Login

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