Mar*_*nio 5 static poppler dllimport dllexport visual-c++-2008
我迫切需要你的帮助。
我尝试使用 Visual C++ 2008 编译器在 Windows 上静态编译 poppler 库(特别是 qt4)。为了完成这个任务,我还需要静态编译一堆其他库作为 poppler 的依赖项。当我最终生成 poppler 的静态版本时,我在构建应用程序时遇到链接错误:
error LNK2019: unresolved external symbol "__declspec(dllimport)...
Run Code Online (Sandbox Code Playgroud)
我已经添加了新的包含路径并链接了 poppler-qt4.lib 但我仍然收到错误。寻找解决方案我在 stackoverflow 中找到了这个讨论
根据这些信息,我查看了库的包含文件(poppler 的依赖项,如 zlib、libpng、cairo 等),我发现在各种情况下,它们没有预处理器指令来指定静态版本图书馆。静态指令示例(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 */
Run Code Online (Sandbox Code Playgroud)
没有静态指令的示例(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
Run Code Online (Sandbox Code Playgroud)
我的问题是:将项目的属性从动态更改为静态还不够,所以我还必须更改此标头?如果这是真的,我在哪里可以定义这个新指令来区分静态或动态编译?
提前致谢。
首先请注意 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,则会失败。因为当库实际上包含普通 function() 时,您正在引用 __imp_function() 。
因此,使用静态链接,您必须删除 dllimport。AFAIK dllexport 是无关紧要的。请注意,这适用于库的客户端,而不是库本身。
这意味着什么?静态链接到一个库,然后动态链接到另一个库是完全可以的。事实上,默认情况下,Windows 上的静态链接会动态链接到 C 运行时和操作系统 DLL。所以规则是:客户端必须选择链接到库的方法,提供者应该提供两个版本。但要小心他们有不同的名字!(否则制作DLL的LINK将制作fred.LIB,LIB也将制作fred.LIB)
如果要将项目属性从动态链接更改为静态链接(如 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
Run Code Online (Sandbox Code Playgroud)