5

我非常需要你的帮助。

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

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

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

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

有了这些信息,我查看了库的包含文件(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 */

没有静态指令的示例(来自 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

我的问题是:将项目的属性从动态更改为静态还不够,所以我还必须更改此标头?如果这是真的,我在哪里可以定义这个新指令以区分静态或动态编译?

提前致谢。

4

2 回答 2

4

首先请注意,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 运行时和 OS DLL。所以规则是:客户端必须选择链接到库的方法,提供者应该提供两个版本。但要注意他们有不同的名字!!(否则生成 DLL 的 LINK 会生成 fred.LIB,而 LIB 也会生成 fred.LIB)

于 2015-09-12T04:47:50.017 回答
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
于 2011-01-30T07:39:49.743 回答