Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dllimport /dllexport and static libraries compilation under visual c++

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.

like image 978
Marco Antonio Avatar asked Jan 30 '11 07:01

Marco Antonio


People also ask

What is Dllimport and Dllexport?

Dllexport is used to mark a function as exported. You implement the function in your DLL and export it so it becomes available to anyone using your DLL. Dllimport is the opposite: it marks a function as being imported from a DLL.

What is Dllimport C++?

The dllexport and dllimport storage-class attributes are Microsoft-specific extensions to the C and C++ languages. You can use them to export and import functions, data, and objects to or from a DLL.

Is __ Declspec Dllimport necessary?

Using __declspec(dllimport) is optional on function declarations, but the compiler produces more efficient code if you use this keyword. However, you must use __declspec(dllimport) for the importing executable to access the DLL's public data symbols and objects.


1 Answers

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)

like image 149
Yttrill Avatar answered Sep 18 '22 17:09

Yttrill