Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Is it possible to create a dll without dllexport?
QtWS25 Last Chance

Is it possible to create a dll without dllexport?

Scheduled Pinned Locked Moved Solved C++ Gurus
dllexporttemplate libmingw weirdnessmingw dll
14 Posts 3 Posters 6.7k 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.
  • K Offline
    K Offline
    koahnig
    wrote on 12 Jun 2016, 16:05 last edited by koahnig 6 Dec 2016, 19:35
    #1

    As the title already almost says, is it possible to create a dll without explicit dllexport?

    I am splitting off an application into different dll. So far, I have compiled everything in one run into a static application using only Qt dlls. The whole application is composed of several "libs" as code is used in multiple applications. Each time I had cut off some source the application size was shrinking as expected. The main part of the application was still 1.2 MB.

    At last I intended to separate the typically main program with the event loop as used in many Qt based applications. Basically I duplicated the .pro file and did change one copy using the lib template while the other still used the app template. Certainly I ensured that the code file of main is only in the app pro-file. I have tried to compile and link for checking that all is in place before adding the typically dllimport and dllexport for the last change required to have all separated.

    All compiled and linked well and also the execution of the application performed as expected. Out of curiosity I checked the size of the exe and expected something of a similar size as before (1.2 MB) because the mimic for import and export was still missing for the large main class and several other also large classes. However, the size of the new exe collapsed already to 50 kB. That caught me by surprize.

    The main class, which is instanciated in the main program is a class which inherits from another class already exported to one of the previous dlls as well those classes are inferiting from QObject.

    All done on Win 10 with MinGW 4.9.1.

    I have tried to find an explanation in the web, but what I have found from Microsoft I understand that all the class have to be marked with dllexport. So the behaviour is probably not possible for MS compilers. For gcc I could not find a similar documentation.

    Has anybody an explanation for this behaviour?

    Vote the answer(s) that helped you to solve your issue(s)

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on 12 Jun 2016, 17:05 last edited by
      #2

      I'm not sure if I got you right.
      You have a "main" class and it inherits from a class defined in a shared library, and this caused the size of the executable to shrink. Is that right? Sounds logical. What's the issue?

      K 1 Reply Last reply 12 Jun 2016, 18:15
      0
      • C Chris Kawa
        12 Jun 2016, 17:05

        I'm not sure if I got you right.
        You have a "main" class and it inherits from a class defined in a shared library, and this caused the size of the executable to shrink. Is that right? Sounds logical. What's the issue?

        K Offline
        K Offline
        koahnig
        wrote on 12 Jun 2016, 18:15 last edited by
        #3

        @Chris-Kawa

        Not exactly.

        More like this here:

        First classes level1 are exprted to dll1

        class DLL1SHARED_EXPORT level1_1
        {
        };
        

        Second classes level2 are exported to dll2

        class DLL2SHARED_EXPORT level2_1 : public level1_1
        {
        };
        

        Finally classes level_main are initially statically linked with code in program main.

        class level_main_1: public level2_1
        {
        };
        

        main.exe has sized of about 1.2 MB as long as the compilation is done with all those "level_main_" classes through a project template "app" and one .pro file.
        Duplication of .pro-file, renaming in one "TEMPLATE = app" -> "TEMPLATE = lib". Also ensured that only the file with "TEMPLATE = app" holds the source file with "program main(...)". LIBS += statement added to point to location of .lib (all the resulting dll).
        The other .pro holds all remaining code files.

        Since I did NOT add so far the macro "DLL_MAIN_SHARED_EXPORT" or something to the definition of classes starting with "level_main_" I did expect that the size of the resulting .exe is statically linked and has a similar size of 1.2 MB.

        However, apparently there is a dll already created and the exe size has dropped to 50 kB of .exe.

        The only explanation I have at the moment is that a dynamic lib is default for "TEMPLATE=LIB" and I did not bother to change to make the library static through qmake. However, I thought that I would need also the macro "DLL_MAIN_SHARED_EXPORT" mimic for actually creating a dll.

        Vote the answer(s) that helped you to solve your issue(s)

        K 1 Reply Last reply 12 Jun 2016, 18:23
        0
        • C Offline
          C Offline
          Chris Kawa
          Lifetime Qt Champion
          wrote on 12 Jun 2016, 18:21 last edited by
          #4

          TEMPLATE = lib creates a dynamic shared library (lib+dll) by default. To make a static library (lib) you need to pass CONFIG += staticlib in the .pro of your library.

          K 1 Reply Last reply 12 Jun 2016, 18:45
          2
          • K koahnig
            12 Jun 2016, 18:15

            @Chris-Kawa

            Not exactly.

            More like this here:

            First classes level1 are exprted to dll1

            class DLL1SHARED_EXPORT level1_1
            {
            };
            

            Second classes level2 are exported to dll2

            class DLL2SHARED_EXPORT level2_1 : public level1_1
            {
            };
            

            Finally classes level_main are initially statically linked with code in program main.

            class level_main_1: public level2_1
            {
            };
            

            main.exe has sized of about 1.2 MB as long as the compilation is done with all those "level_main_" classes through a project template "app" and one .pro file.
            Duplication of .pro-file, renaming in one "TEMPLATE = app" -> "TEMPLATE = lib". Also ensured that only the file with "TEMPLATE = app" holds the source file with "program main(...)". LIBS += statement added to point to location of .lib (all the resulting dll).
            The other .pro holds all remaining code files.

            Since I did NOT add so far the macro "DLL_MAIN_SHARED_EXPORT" or something to the definition of classes starting with "level_main_" I did expect that the size of the resulting .exe is statically linked and has a similar size of 1.2 MB.

            However, apparently there is a dll already created and the exe size has dropped to 50 kB of .exe.

            The only explanation I have at the moment is that a dynamic lib is default for "TEMPLATE=LIB" and I did not bother to change to make the library static through qmake. However, I thought that I would need also the macro "DLL_MAIN_SHARED_EXPORT" mimic for actually creating a dll.

            K Offline
            K Offline
            kshegunov
            Moderators
            wrote on 12 Jun 2016, 18:23 last edited by kshegunov 6 Dec 2016, 18:23
            #5

            @koahnig
            Hi,

            As the title already almost says, is it possible to create a dll without explicit dllexport?

            If I remember correctly, if you don't export anything the linker will not generate any code (thus no dll).

            The only explanation I have at the moment is that a dynamic lib is default for "TEMPLATE=LIB"

            It is. If you don't put "CONFIG += static" qmake will generate a makefile that compiles into a dynamic library.

            However, I thought that I would need also the macro "DLL_MAIN_SHARED_EXPORT" mimic for actually creating a dll.

            I don't follow. You don't export from static libraries in the first place. A static library has no notion of visibility, it doesn't have a header or any way to load dependencies. It's only a collection of translation units (object files). So exporting/importing is not relevant to static libraries at all.

            Kind regards.

            Read and abide by the Qt Code of Conduct

            1 Reply Last reply
            2
            • C Chris Kawa
              12 Jun 2016, 18:21

              TEMPLATE = lib creates a dynamic shared library (lib+dll) by default. To make a static library (lib) you need to pass CONFIG += staticlib in the .pro of your library.

              K Offline
              K Offline
              koahnig
              wrote on 12 Jun 2016, 18:45 last edited by
              #6

              @Chris-Kawa said:

              TEMPLATE = lib creates a dynamic shared library (lib+dll) by default. To make a static library (lib) you need to pass CONFIG += staticlib in the .pro of your library.

              @kshegunov

              I can live with that, but why should I handle an additional include file?

              Just created a new lib project called "testDll" and 4 files are created plus .pro.user. Those files are:
              TestDll.cpp

              #include "TestDll.h"
              TestDll::TestDll()
              {
              }
              
              

              TestDll.h

              #ifndef TESTDLL_H
              #define TESTDLL_H
              #include "testdll_global.h"
              class TESTDLLSHARED_EXPORT TestDll
              {
              public:
                  TestDll();
              };
              #endif // TESTDLL_H
              

              testdll_global.h

              #ifndef TESTDLL_GLOBAL_H
              #define TESTDLL_GLOBAL_H
              #include <QtCore/qglobal.h>
              #if defined(TESTDLL_LIBRARY)
              #  define TESTDLLSHARED_EXPORT Q_DECL_EXPORT
              #else
              #  define TESTDLLSHARED_EXPORT Q_DECL_IMPORT
              #endif
              #endif // TESTDLL_GLOBAL_H
              

              and the TestDll.pro

              #-------------------------------------------------
              #
              # Project created by QtCreator 2016-06-12T20:32:38
              #
              #-------------------------------------------------
              QT       -= gui
              
              TARGET = testDll
              TEMPLATE = lib
              
              DEFINES += TESTDLL_LIBRARY
              
              SOURCES += TestDll.cpp
              
              HEADERS += TestDll.h\
                      testdll_global.h
              unix {
                  target.path = /usr/lib
                  INSTALLS += target
              }
              

              My conclusion was that I need to have always the "testdll_global.h" and the macro "TESTDLLSHARED_EXPORT" in every header and every class declared which I like to export to the dll.

              Vote the answer(s) that helped you to solve your issue(s)

              1 Reply Last reply
              0
              • K Offline
                K Offline
                koahnig
                wrote on 12 Jun 2016, 18:50 last edited by
                #7

                To add to previous post:
                The new conclusion would be that one can save quite a bit of work when ignoring the "testdll_global.h" and the macro "TESTDLLSHARED_EXPORT" stuff.
                So why is that stuff added in the project template, if I do not need to have it at least with Qt?

                Vote the answer(s) that helped you to solve your issue(s)

                1 Reply Last reply
                0
                • C Offline
                  C Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on 12 Jun 2016, 18:51 last edited by Chris Kawa 6 Dec 2016, 18:51
                  #8

                  @koahnig said:

                  Just created a new lib project called "testDll" and 4 files are created plus .pro.user.

                  Note that the wizard lets you choose the type of the project. The default is "Shared Library" i.e. a DLL. That is what you got and for that the macros are required.

                  The other settings in the wizard are "Statically Linked Library" and "Qt Plugin". The statically linked library has only two files - a .h/.cpp of your class without the extra export/import macros.

                  K 1 Reply Last reply 12 Jun 2016, 19:01
                  0
                  • C Chris Kawa
                    12 Jun 2016, 18:51

                    @koahnig said:

                    Just created a new lib project called "testDll" and 4 files are created plus .pro.user.

                    Note that the wizard lets you choose the type of the project. The default is "Shared Library" i.e. a DLL. That is what you got and for that the macros are required.

                    The other settings in the wizard are "Statically Linked Library" and "Qt Plugin". The statically linked library has only two files - a .h/.cpp of your class without the extra export/import macros.

                    K Offline
                    K Offline
                    koahnig
                    wrote on 12 Jun 2016, 19:01 last edited by
                    #9

                    @Chris-Kawa said:

                    @koahnig said:

                    Just created a new lib project called "testDll" and 4 files are created plus .pro.user.

                    Note that the wizard lets you choose the type of the project. The default is "Shared Library" i.e. a DLL. That is what you got and for that the macros are required.

                    The other settings in the wizard are "Statically Linked Library" and "Qt Plugin". The statically linked library has only two files - a .h/.cpp of your class without the extra export/import macros.

                    Agreed and all this is fine, but actually one can create a dll without using "testdll_global.h".

                    Possibly our posts crossed:
                    @koahnig said:

                    To add to previous post:
                    The new conclusion would be that one can save quite a bit of work when ignoring the "testdll_global.h" and the macro "TESTDLLSHARED_EXPORT" stuff.
                    So why is that stuff added in the project template, if I do not need to have it at least with Qt?

                    Basically there is my issue, why shall I add an include not required?

                    It looks logical to have the include "testdll_global.h", because it makes the look compatible to the typical things you have to do for creating a dll. However, as long as you stay within the Qt world it is additional work which is not required?

                    Vote the answer(s) that helped you to solve your issue(s)

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on 12 Jun 2016, 19:26 last edited by
                      #10

                      @koahnig said:

                      However, as long as you stay within the Qt world it is additional work which is not required?

                      It has nothing to do with Qt.
                      For a dynamically linked library you do need the import/export stuff, at least if you want to behave nicely. If you try it with MSVC you will see that your symbols are not visible if you don't export them.

                      The thing you experience is a weirdness of GCC (or MinGW in this case). It has this weird behavior that if you don't export anything explicitly it will export everything (sic!). I'm guessing it's to keep libraries that didn't have MSVC in mind working. As soon as you export any symbol the MSVC-like behavior kicks in and only those symbols declared as export will be exported.

                      To test that try to build your lib without any symbols exported (comment out the macros). Use DependencyWalker to examine the library - note that everytihing is exported. Now add this single export in your header: ___declspec( dllexport ) int foo; and inspect the library again - only foo is exported.

                      K K 2 Replies Last reply 12 Jun 2016, 19:34
                      2
                      • C Chris Kawa
                        12 Jun 2016, 19:26

                        @koahnig said:

                        However, as long as you stay within the Qt world it is additional work which is not required?

                        It has nothing to do with Qt.
                        For a dynamically linked library you do need the import/export stuff, at least if you want to behave nicely. If you try it with MSVC you will see that your symbols are not visible if you don't export them.

                        The thing you experience is a weirdness of GCC (or MinGW in this case). It has this weird behavior that if you don't export anything explicitly it will export everything (sic!). I'm guessing it's to keep libraries that didn't have MSVC in mind working. As soon as you export any symbol the MSVC-like behavior kicks in and only those symbols declared as export will be exported.

                        To test that try to build your lib without any symbols exported (comment out the macros). Use DependencyWalker to examine the library - note that everytihing is exported. Now add this single export in your header: ___declspec( dllexport ) int foo; and inspect the library again - only foo is exported.

                        K Offline
                        K Offline
                        koahnig
                        wrote on 12 Jun 2016, 19:34 last edited by
                        #11

                        @Chris-Kawa said:

                        The thing you experience is a weirdness of GCC (or MinGW in this case). It has this weird behavior that if you don't export anything explicitly it will export everything (sic!). I'm guessing it's to keep libraries that didn't have MSVC in mind working. As soon as you export any symbol the MSVC-like behavior kicks in and only those symbols declared as export will be exported.

                        OK, that is the explanation I was looking for.
                        I thought already right from the beginning that this might have something to do with MinGW. However, assuming such weirdness right away is typically not a good choice. Similar to assuming it is a compiler error if you do not find something right away.

                        Thanks a lot for confirmation. I was trying to find a note somewhere, but I could not.

                        Vote the answer(s) that helped you to solve your issue(s)

                        1 Reply Last reply
                        0
                        • C Chris Kawa
                          12 Jun 2016, 19:26

                          @koahnig said:

                          However, as long as you stay within the Qt world it is additional work which is not required?

                          It has nothing to do with Qt.
                          For a dynamically linked library you do need the import/export stuff, at least if you want to behave nicely. If you try it with MSVC you will see that your symbols are not visible if you don't export them.

                          The thing you experience is a weirdness of GCC (or MinGW in this case). It has this weird behavior that if you don't export anything explicitly it will export everything (sic!). I'm guessing it's to keep libraries that didn't have MSVC in mind working. As soon as you export any symbol the MSVC-like behavior kicks in and only those symbols declared as export will be exported.

                          To test that try to build your lib without any symbols exported (comment out the macros). Use DependencyWalker to examine the library - note that everytihing is exported. Now add this single export in your header: ___declspec( dllexport ) int foo; and inspect the library again - only foo is exported.

                          K Offline
                          K Offline
                          kshegunov
                          Moderators
                          wrote on 12 Jun 2016, 19:36 last edited by
                          #12

                          @Chris-Kawa

                          It has nothing to do with Qt.

                          Nor with C++ actually. These things are OS specific and depend on the implementation of the linker/loader and the ABI.

                          I'm guessing it's to keep libraries that didn't have MSVC in mind working.

                          Most probably, yes. This is the default behavior on Linux - everything is exported by default, so I would assume this is to "facilitate" porting from *nix to windows.

                          @koahnig

                          Basically there is my issue, why shall I add an include not required?

                          As Chris said, it might not be an include file, but you do need the linkage specifiers.

                          Read and abide by the Qt Code of Conduct

                          K 1 Reply Last reply 12 Jun 2016, 19:51
                          1
                          • K kshegunov
                            12 Jun 2016, 19:36

                            @Chris-Kawa

                            It has nothing to do with Qt.

                            Nor with C++ actually. These things are OS specific and depend on the implementation of the linker/loader and the ABI.

                            I'm guessing it's to keep libraries that didn't have MSVC in mind working.

                            Most probably, yes. This is the default behavior on Linux - everything is exported by default, so I would assume this is to "facilitate" porting from *nix to windows.

                            @koahnig

                            Basically there is my issue, why shall I add an include not required?

                            As Chris said, it might not be an include file, but you do need the linkage specifiers.

                            K Offline
                            K Offline
                            koahnig
                            wrote on 12 Jun 2016, 19:51 last edited by
                            #13

                            @kshegunov

                            That makes sense.

                            I have added the import/export stuff in the mean time. So basically all is broadened to hopefully all compilers and OSs. ;)

                            Vote the answer(s) that helped you to solve your issue(s)

                            K 1 Reply Last reply 12 Jun 2016, 19:57
                            0
                            • K koahnig
                              12 Jun 2016, 19:51

                              @kshegunov

                              That makes sense.

                              I have added the import/export stuff in the mean time. So basically all is broadened to hopefully all compilers and OSs. ;)

                              K Offline
                              K Offline
                              kshegunov
                              Moderators
                              wrote on 12 Jun 2016, 19:57 last edited by kshegunov
                              #14

                              @koahnig

                              So basically all is broadened to hopefully all compilers and OSs.

                              It should be. To be honest, this default exporting behavior is one of the more suspicious decisions in Linux. Windows' way of enforcing symbols to be hidden by default (like we have with classes' members) is much more logical. I actually define two macros when making shared libraries - one that is for the export/import and one that forces symbols not explicitly exported to be hidden on Linux, thus getting a similar binary interface on all platforms; like done here.

                              Kind regards.

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              0

                              8/14

                              12 Jun 2016, 18:51

                              • Login

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