Visual C ++下的dllimport/dllexport和静态库编译 [英] dllimport /dllexport and static libraries compilation under visual c++

查看:116
本文介绍了Visual C ++下的dllimport/dllexport和静态库编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我迫切需要您的帮助.

我正在尝试使用Visual c ++ 2008编译器在Windows上静态编译poppler库(特别是对于qt4).为了完成此任务,我还需要静态编译大量其他库作为poppler的依赖项.当我最终生成poppler的静态版本时,在构建我的应用程序时出现链接错误:

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

我已经添加了新的include路径并链接了poppler-qt4.lib,但无论如何我还是得到了错误.在寻找解决方案时,我在stackoverflow中找到了这个讨论

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

如何在Visual C ++中链接静态库2008年?

在查看此信息时,我查看了库的包含文件(诸如zlib,libpng,cairo等poppler的依赖关系),在各种情况下,我发现它们没有预处理器指令来指定lib的静态版本.静态指令示例(openjpeg.h):

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 */

不带静态指令的示例(来自jpeg lib的jconfig.h):

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?

谢谢.

推荐答案

首先请注意Windows根本没有任何动态链接.惊喜!相反,它使用重击.因此发生的事情是:如果您创建符号dllexport,则它具有其实际名称,与不是dllexport的名称相同.但是,它已在目标文件中标记为要导出.

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.

反之,如果您说dllimport,则名称会被更改,在C语言中,粗略地在名称前加上__imp_即可,而在C ++中则更加讨厌.

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

现在,当您链接DLL时,您将获得一个DLL(当然),但是您还将获得一个LIB文件.那是一个静态链接库.链接器只能处理哪种类型.对于从DLL导出的每个符号,该LIB文件中都有一个dllimport符号,尤其是带有__imp_前缀或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++.

因此,现在在程序或DLL中,您想要链接到该DLL,即使您链接起来而不是与导入LIB链接.导入LIB例程是thunk,可以修补DLL中的实际加载时间地址.

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.

因此,现在,如果您尝试通过简单地组合包含某些dllexport的OBJ文件来对LIB.EXE生成的LIB文件进行普通的静态链接,则如果引用是dllimport,它将失败.因为当库实际上包含普通的function()时,您是在引用__imp_function().

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

因此,使用静态链接时,必须删除dllimport.AFAIK dllexport无关紧要.请注意,这适用于库的 client ,而不适用于库本身.

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.

那是什么意思?好吧,静态链接到一个库,然后动态链接到另一个库是完全可以的.实际上,默认情况下,Windows上的静态链接会动态链接到C运行时和OS DLL.因此规则是: client 必须选择链接到库的方法, provider 应该提供两个版本.但是请注意它们有不同的名称!!(否则,制作DLL的LINK将创建fred.LIB,而LIB也将创建fred.LIB)

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)

这篇关于Visual C ++下的dllimport/dllexport和静态库编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆