dllimport /dllexport and static libraries compilation under visual c++
Asked Answered
D

2

5

I desperatly need your help.

Im trying to compile statically the poppler library (specially for qt4) on windows with the visual c++ 2008 compiler. To achieve this task I needed to compile a bunch of other libraries as dependencies for poppler statically too. When I finally generate the static version of poppler I got a linking error when building my app:

error LNK2019: unresolved external symbol "__declspec(dllimport)...

I already added the new include path and linked the poppler-qt4.lib but i get the error anyways. Searching for a solution I found this discussion here in stackoverflow

How to link a static library in Visual C++ 2008?

whit this information I looked on the include files of the libraries (dependencies of poppler like zlib, libpng, cairo, ...) and I found, in various cases, that they don't have a preprocessor directive to especify the static version of the lib. Example static directive (openjpeg.h):

#if defined(OPJ_STATIC) || !(defined(_WIN32) || defined(WIN32) || defined(__WIN32__))
# define OPJ_API
# define OPJ_CALLCONV
#else
# define OPJ_CALLCONV __stdcall
# ifdef OPJ_EXPORTS
#  define OPJ_API __declspec(dllexport)
# else
#  define OPJ_API __declspec(dllimport)
# endif /* OPJ_EXPORTS */
#endif /* !OPJ_STATIC || !WIN32 */

Example without static directive (jconfig.h from jpeg lib):

#if defined(_WIN32)
    #if defined(libjpeg_EXPORTS)
        #define JPEG_EXPORT __declspec(dllexport)
    #else
        #define JPEG_EXPORT __declspec(dllimport)
    #endif
#else
    #define JPEG_EXPORT 
#endif

My question is: Is not enough to change the properties of the project from dynamic to static so I have to change this headers too?, and if this is true, where can I define this new directives for making a difference between static or dynamic compilation?

Thanks in advance.

Delegation answered 30/1, 2011 at 7:29 Comment(0)
G
8

First please note Windows does not have any dynamic linkage at all. Surprise! Instead, it uses thunks. So what happens is: if you make a symbol dllexport, it has its actual name, the same name as if it were not dllexport. However it is marked in the object file for exporting.

If you say dllimport, on the other hand, the name is changed, in C roughly by prepending __imp_ to the name, more nasty in C++.

Now, when you link a DLL, you get a DLL (of course) but you also get a LIB file. That is a static link library. Which is the only kind the linker can handle. For each symbol exported from the DLL there is a dllimport symbol in that LIB file, in particular with __imp_ prefix or whatever for C++.

So now in a program or DLL you want to link to that DLL you made you link instead against the import LIB. The import LIB routines are thunks that patch up to the actual load time addresses from the DLL.

So now, if you try to do ordinary static linkage against a LIB file made by LIB.EXE by simply combining OBJ files which contained some dllexport, it will fail if the reference is a dllimport. Because you're refering to __imp_function() when the library actually contains plain function().

So with static linkage, you have to drop the dllimport. AFAIK dllexport is irrelevant. Note that this applies to the client of the library, not the library itself.

What does that mean? Well it is perfectly fine to statically link to a library which in turn dynamically links to another library. In fact by default static links on Windows dynamically link to the C runtime and OS DLLs. So the rule is: the client must chose the method of linking to a library, the provider should provide both versions. But take care they have different names!! (Otherwise the LINK making the DLL will make fred.LIB and the LIB will also make fred.LIB)

Gaul answered 12/9, 2015 at 4:47 Comment(2)
Thanks a lot. I'm actually in this mess right now, I'm trying to use statically linked libs(PyTorch libs) in a console project and I am seeing the test_dummy.lib and test_dummy.exp are being created and thus getting x defined in 'c10.lib(Logging.obj)' is imported by 'Test_dummy.obj' in function x kind of errors. what exactly should I be doing? What did you mean by` take care they have different names?Fico
"Windows does not have any dynamic linkage at all."? Any reference?Panfish
F
2

If you are changing the project properties from dynamic to static linkage as specified in the openjpeg.h you have to specify preprocessor that can use the static linkage..so in addition to changing the property from dynamic to static, add the preprocessor OPJ_STATIC...

For example:

#if defined(_WIN32)
    #if defined(OPJ_STATIC)
         # define OPJ_CALLCONV __stdcall
    #el if defined(libjpeg_EXPORTS)
        #define JPEG_EXPORT __declspec(dllexport)
    #else
        #define JPEG_EXPORT __declspec(dllimport)
    #endif
#else
    #define JPEG_EXPORT 
#endif
Florenceflorencia answered 30/1, 2011 at 7:39 Comment(5)
but in this case, where i have to define OPJ_STATIC so the knows if the macro is defined?Delegation
You have to define the macro when you are creating the library as well as in the project that you are going to link the library withFlorenceflorencia
i was reading a few articles and now i'm very confused. dllexport and dllimport are ONLY used if im compiling and/or linking a SHARED library? so in the contrary case (a STATIC library), i just define the same directive without value?Delegation
dllexport and dllimport are used in case of dynamic linkage. So in my above example i have added extra if condition to check whether it's a static library and if so it will execute # define OPJ_CALLCONV __stdcall. In your project settings of preprocessor if it's specified as _EXPORTS you will have to remove that and add OP_STATIC so that it's statically linked. You may want to change directive names as per your need.Florenceflorencia
i'm going to code a few simple static and shared librarys and test this tings to get a better understanding, thnx for the suggestions.Delegation

© 2022 - 2024 — McMap. All rights reserved.