22

我的项目通过几个静态库构建,这些静态库应该链接到主 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

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

4

2 回答 2

20

静态库不应该包含任何__declspec东西__attribute((dll...))。它们只不过是多个目标文件(通常是*.objor *.o),组合成一个单独的文件。

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

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

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

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

链接器输入

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

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


更新

尝试在外部项目中使用 dll 库时无法解决外部问题

您的问题根本与链接无关。问题是,您误解了链接静态库的作用

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

当您DLL引用外部内容(如函数或变量)时,它会在链接时与所有依赖项一起解决。但仅此而已。如果您的静态库有一个名为 的函数print_sample_string()但您DLL没有使用它,则它不会附加到DLLimage. 仔细想想——为什么会这样?

甚至更多 - 没有dllexport明确编辑的功能无论如何都不会可见。函数默认具有外部存储 - 所以基本上,它们是 privateDLL的内容。

因此,要直接回答您的问题 - 如果您需要使用来自 的函数/变量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和直接使用它。

于 2015-07-16T06:34:43.473 回答
4

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

于 2015-07-16T13:58:06.883 回答