dllimport / dllexport和visual c ++下的静态库编译

我非常需要你的帮助。 我试图用visual c ++ 2008编译器静态编译windows上的poppler库(特别是qt4)。为了完成这个任务,我需要静态地编译一堆其他库作为poppler的依赖项。当我最终生成poppler的静态版本时,我在构建应用程序时遇到链接错误:
error LNK2019: unresolved external symbol "__declspec(dllimport)...
我已经添加了新的include路径并链接了poppler-qt4.lib,但我仍然得到了错误。 搜索解决方案我在stackoverflow中找到了这个讨论 如何在Visual C ++ 2008中链接静态库? 在这个信息中,我查看了库的包含文件(popller的依赖关系,如zlib,libpng,cairo,...),我发现,在各种情况下,他们没有预处理器指令来指定静态版本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
我的问题是:还不足以将项目的属性从动态更改为静态,因此我也必须更改此标题吗?如果这是真的,我可以在哪里定义这些新指令以区分静态或动态编译? 提前致谢。     
已邀请:
如果要将项目属性从动态链接更改为静态链接(如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
    
首先请注意Windows根本没有任何动态链接。惊喜!相反,它使用thunk。所以会发生什么:如果你创建一个符号dllexport,它有它的实际名称,就像它不是dllexport一样。但是,它在目标文件中标记为导出。 另一方面,如果你说dllimport,名称改变了,在C中大致是通过在名称前加上__imp_,在C ++中更加讨厌。 现在,当你链接一个DLL时,你得到一个DLL(当然),但你也得到一个LIB文件。这是一个静态链接库。这是链接器可以处理的唯一类型。对于从DLL导出的每个符号,该LIB文件中都有一个dllimport符号,特别是带有__imp_前缀或C ++的任何符号。 所以现在在一个程序或DLL中你想要链接到那个你链接到导入LIB的DLL。导入LIB例程是从DLL修补实际加载时间地址的thunk。 所以现在,如果您尝试通过简单地组合包含某些dllexport的OBJ文件来对LIB.EXE生成的LIB文件进行普通的静态链接,那么如果引用是dllimport,它将会失败。因为当库实际包含普通函数()时,您正在引用__imp_function()。 因此,使用静态链接,您必须删除dllimport。 AFAIK dllexport无关紧要。请注意,这适用于库的客户端,而不是库本身。 那是什么意思?好吧,静态链接到一个库,完全可以动态链接到另一个库。事实上,默认情况下,Windows上的静态链接会动态链接到C运行时和操作系统DLL。所以规则是:客户端必须选择链接到库的方法,提供者应该提供两个版本。但要注意他们有不同的名字!! (否则制作DLL的LINK将使fred.LIB和LIB也将使fred.LIB)     

要回复问题请先登录注册