使用 dll link 静态库的正确方法

Proper way to link static libraries with dll

我的项目通过几个静态库构建,这些静态库应该链接到主 dll 库,结果获得一个 dll。

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

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

  1. __declspec(dllexport).def-file 是否应该在我的情况下同等行事?

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

更新

我想详细解释一下我的项目结构。该解决方案由几个项目(模块)组成。

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

每个子项目都弱依赖于其他子项目,为了清楚起见,我们假设它们没有连接。每个模块都有自己的 public 接口。我想将所有模块都作为单个动态库,所以我的工件是 dynamic_lib.dll,但实际上静态库并没有与之链接。

静态库不应包含任何 __declspec__attribute((dll...)) 东西。它们只不过是多个 object 个文件(通常是 *.obj*.o),组成一个文件。

要使用此类库(在 .exe.dll 中),您需要做的就是包含适当的 headers 和 link 它们 - 以及 Visual Studio 很简单。

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

注意:这个路径可能每个项目都不一样!对于 multi-project 解决方案,我总是将其设置为通用路径以避免配置问题。

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

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

最后一件事 - 请记住,您还需要包含 headers 以及您要使用的函数声明和 objects。基本的东西,我知道,但不得不提一下。


更新

unresolved external when trying to use dll library in an external prodjects

您的问题 与 linking 根本 无关。问题是,您误解了什么,link静态库 确实

我猜,报告为 unresolved 的函数没有被您的 DLL 使用,对吧?但你希望他们在里面,对吧?

当您的 DLL 引用外部内容(如函数或变量)时,它会在 linking 时解析 - 连同所有依赖项。 但仅此而已。如果您的静态库有一个名为 print_sample_string() 的函数,但您的 DLL 没有使用它 ,它不会附加到 DLL 图像。仔细想想——为什么会这样?

甚至更多 - 未明确 dllexported 的函数无论如何都将不可见。默认情况下,函数具有外部存储 - 所以基本上,它们是私有 DLL 的内容。

因此直接回答您的问题 - 如果您需要使用 static_lib1.lib 中的 functions/variables,请将其附加到客户端应用程序 - 就像您现在将其附加到 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

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

Here Raymond Chan explains this behavior and the best solution is really just to use def file. As for how to generate it automatically for static a library - this 讨论看起来是个不错的起点。