2011-01-30 71 views
3

我绝对需要你的帮助。dllimport/dllexport和静态库编译在visual C++

我试图静态编译visual C++ 2008编译器的窗口上的poppler库(特别是qt4)。为了完成这个任务,我需要静态编译一些其他库作为poppler的依赖项。当我终于产生poppler的静态版本我建设我的应用程序时,得到了一个链接错误:

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

我已经添加了新的包含路径和链接poppler的-qt4.lib但我得到的错误反正。 寻找解决的办法我在计算器

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

白衣这个信息,我枕着库的包含文件发现这里讨论(如zlib的poppler的相关性,的libpng,开罗......)和我在各种情况下发现它们没有预处理器指令来指定lib的静态版本。 实例静态指令(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):

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

我的问题是:是不足以改变的属性项目从动态变为静态,所以我必须更改这个头文件吗?如果这是真的,我可以在哪里定义这个新的指令来区别静态或动态编译?

在此先感谢。

回答

2

如果您将项目属性从动态链接更改为静态链接(如openjpeg.h中所指定的那样),您必须指定可使用静态链接的预处理器......除了将属性从动态更改为静态之外,预处理OPJ_STATIC ...

例如:

#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 
+0

但在这种情况下,我必须定义OPJ_STATIC所以知道如果宏定义? – 2011-01-30 17:06:01

0

首先请注意Windows没有任何动态链接的。惊喜!相反,它使用thunk。所以会发生什么:如果你创建了一个符号dllexport,它有它的实际名称,就像它不是dllexport一样。但它在目标文件中标记为导出。

如果你说dllimport,另一方面,名称被改变,在C中粗略地将__imp_加入名字,在C++中更加讨厌。

现在,当你链接一个DLL时,你会得到一个DLL(当然),但你也会得到一个LIB文件。这是一个静态链接库。链接器可以处理的唯一一种。对于从DLL导出的每个符号,该LIB文件中都有一个dllimport符号,特别是带有__imp_前缀或C++的任何符号。

因此,现在在一个程序或DLL中,您要链接到该DLL,而不是针对导入LIB链接。导入LIB例程是补丁到DLL的实际加载时间地址的thunk。

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

因此,与静态链接,你不得不放弃了dllimport的。 AFAIK dllexport无关紧要。请注意,这适用于图书馆,而不是库本身的客户

这是什么意思?那么静态链接到一个库,然后动态链接到另一个库是非常好的。事实上,默认情况下,Windows上的静态链接动态链接到C运行时和操作系统DLL。所以规则是:客户必须选择链接到库的方法,该提供商应提供两个版本。但保重他们有不同的名字! (否则LINK使得DLL将使fred.LIB和LIB也将使fred.LIB)