将静态库与dll链接的正确方法

tri*_*san 12 c++ dll visual-c++ declspec visual-studio-2013

我的项目通过几个静态库构建,这些库应该链接到主dll库,因此获得一个单独的dll.

使用__declspec(dllexport)属性不会导致静态库的指定函数出现到dll,库根本没有与dll链接.

然后我尝试将每个库构建为共享以获取导出函数的正确名称,并基于它们创建.def文件.使用.def文件导致结果.

  1. 应该__declspec(dllexport).def-file我的情况一样行事吗?

  2. 是否可以从源生成.def文件?由于我有C++代码,因为API中的修改和存在类,我不能自己编写.def文件,上面描述的临时生成的dll方法与生产不一致.

更新

我想详细解释一下我项目的结构.该解决方案包含一些项目(模块).

+ 
|    
+-+ static_lib1                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ static_lib2                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ dynamic_lib (linked with static_lib1 and static_lib2)
        +                                                
        +--+ src
Run Code Online (Sandbox Code Playgroud)

每个子项目都弱于其他子项目,让我们假设它们之间没有联系是为了清晰.每个模块都有自己的公共接口.我想将所有模块作为单个动态库,所以我的工件是dynamic_lib.dll,但实际上静态库没有与它链接.

Mat*_*jek 15

静态库不应该包含任何__declspec__attribute((dll...))事物.它们只不过是多个目标文件(通常*.obj或者*.o),组成一个单个文件.

你需要做的就是使用这样的库(在.exe或中.dll)是包含正确的标题并链接它们 - 使用Visual Studio它非常容易.

首先,您需要知道1)放置静态库的位置和2)它们的确切名称.转到项目属性,然后General.Target name包含输出文件的名称,同时Output directory指示您.lib将放置在哪个文件夹中.

注意:每个项目的路径可能不同!对于多项目解决方案,我总是将其设置为通用路径以避免配置问题.

现在,转到将使用此库的项目属性(与其链接).转到Linker- > Input然后添加的名字你.libAdditional dependencies(条目用分号隔开):

链接器输入

您需要添加您想要链接的所有库.此外,放置这些库的文件夹必须添加到Linker- > General- > Additional library directories.如果所有.libs都放在同一个地方 - 好,否则将它们复制到共享位置或添加多个条目Additional library directories列表.

最后一点 - 记住,您还需要包含要使用的函数和对象声明的标题.基本的,我知道,但必须提到.


UPDATE

尝试在外部项目中使用dll库时未解析的外部

您的问题根本与链接无关.问题是,你误解了什么,链接一个静态库确切.

我猜,报告为未解决的功能不会被您使用DLL,对吧?但你希望它们在里面,对吗?

当您DLL引用外部内容(如函数或变量)时,它会在链接时解析 - 与所有依赖项一起解析.但就是这样.如果您的静态库有一个名为的函数print_sample_string(),但您DLL没有使用它,它将不会附加到DLL图像.仔细想想 - 为什么会这样?

甚至更多 - 未dllexport明确显示的功能无论如何都不会显示.默认情况下,函数具有外部存储 - 所以基本上它们都是私有DLL内容.

因此,要直接回答您的问题 - 如果您需要使用函数/变量static_lib1.lib,请将其附加到客户端应用程序 - 就像您现在将其附加到dynamic_lib.没有其他办法.(*)


(*)真的说 - 有.您可以创建中间函数DLL,导出并调用所需的函数:

在某处dynamic_lib:

DLL_EXP_IMP long CallFunctionFromA_Lib()
{
     return some_function(); //this function is from static_lib1.lib
}
Run Code Online (Sandbox Code Playgroud)

在某处.exe:

long result = CallFunctionFromA_Lib(); //internally this will call function from static_lib1.lib
Run Code Online (Sandbox Code Playgroud)

但是,我无法想象你为什么要这样做而不是简单地直接链接A.lib和使用它.


dew*_*led 5

Raymond Chan在这里解释了这种行为,最好的解决方案实际上就是使用 def 文件。至于如何为静态库自动生成它 -这个讨论看起来是一个很好的起点。