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

时间:2015-07-16 06:03:32

标签: c++ visual-c++ dll visual-studio-2013 declspec

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

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

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

  1. __declspec(dllexport).def-file应该在我的案件中采取同等行动吗?

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

  3. 更新

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

    + 
    |    
    +-+ static_lib1                                          
    |       +                                                
    |       +--+ src                                         
    |                                                        
    +-+ static_lib2                                          
    |       +                                                
    |       +--+ src                                         
    |                                                        
    +-+ dynamic_lib (linked with static_lib1 and static_lib2)
            +                                                
            +--+ src
    

    每个子项目都依赖于其他子项目,让我们假设它们没有联系以保持清晰。每个模块都有自己的公共接口。我希望将所有模块作为单个动态库,因此我的工件是dynamic_lib.dll,但实际上静态库没有与它链接。

2 个答案:

答案 0 :(得分:13)

静态库不应包含任何__declspec__attribute((dll...))内容。它们只不过是多个目标文件(通常为*.obj*.o),组成一个单个文件。

要使用此类库(在.exe.dll中),您只需要包含正确的标题并将其链接起来 - 使用Visual Studio非常容易。

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

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

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

Linker input

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

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

<强>更新

  

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

您的问题 与链接完全无关。问题是,你误解了什么,链接静态库完全是

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

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

更多 - 明确不是dllexport ed的函数无论如何都不会显示。函数默认具有外部存储 - 基本上,它们是私有的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
}

.exe中的某处:

long result = CallFunctionFromA_Lib(); //internally this will call function from static_lib1.lib

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

答案 1 :(得分:3)

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