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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31446363/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:57:10  来源:igfitidea点击:

Proper way to link static libraries with dll

c++visual-c++dllvisual-studio-2013declspec

提问by triclosan

My project builds through few static libraries which should linked to main dll library gain one single dll as a result.

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

Using __declspec(dllexport)attribute does not lead to appearance of specified functions of static libraries to dll, libraries not linked with dll at all.

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

Then I tried to build each library as shared for getting proper names of exported functions and created .def file based on them. Using .def file leaded to result.

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

  1. Should __declspec(dllexport)and .def-fileact equally in my case?

  2. Is it possible to generate a .def file from sources? Since I have C++ code I'm not able to write .def file by myself because of mangling and presence classes in API, the approach described above with temporary generated dlls is inconsistent for production.

  1. 在我的情况下,应该__declspec(dllexport).def-file行为平等吗?

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

Update

更新

I'd like to explain in detail about the structure of my project. The solution consists of a few projects (modules).

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

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

Each sub-project weakly depends on others, let's assume they are not connected for clearness. Each module has own public interface. I want to have all modules as single dynamic library so my artifact is dynamic_lib.dll, but in fact static libraries are not linked with it.

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

回答by Mateusz Grzejek

Static libraries should not contain any __declspecor __attribute((dll...))things. They are nothing more than multiple object files (usually *.objor *.o), composed into one, single file.

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

All you need to do in order to use such library (either in .exeor .dll) is to include proper headers and link them - with Visual Studio it's pretty easy.

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

First of all, you need to know 1)where your static libraries are placed and 2)their exact names. Go to project properties and then General. Target namecontains name for the output file, while Output directoryindicates in which folder your .libwill be placed.

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

Note:This path may be different for every project! For multi-project solution, I always set this to a common path to avoid configuration problems.

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

Now, go to properties of project, that will consume this library (link with it). Go to Linker-> Inputand then add name of your .libto Additional dependencies(entries are separated with semicolon):

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

Linker input

链接器输入

You need to add all libraries you want have linked in. Also, folder, in which these libraries are placed, must added to Linker-> General-> Additional library directories. If all .libs are placed in the same place - good, otherwise copy them into shared location or add multiple entries to Additional library directorieslist.

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

And the last thing - remember, that you also need to include headers with declarations of functions and objects, that you want to use. Basic thing, I know, but has to be mentioned.

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



UPDATE

更新

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

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

Your problem is notrelated to linking at all. The thing is, that you misunderstood what, linking a static library exactly does.

您的问题根本与链接无关。问题是,你误解了什么,链接一个静态库正是这样做的

I am guessing, that functions reported as unresolvedare not used by your DLL, right? But you expect them to be inside it, right?

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

When your DLLrefers to an external content (like function or variable), it is resolved at linking time - together with all dependencies. But that's all. If your static library has a function named print_sample_string(), but your DLLdoes not use it, it won't be attached to DLLimage. Think about this carefully - why should it be?

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

Even more - functions, that are not dllexported explicitly won't be visible anyway. Functions have by default external storage - so basically, they are private DLL's content.

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

So to answer your question directly - if you need to use functions/variables from static_lib1.lib, attach it to client application - just like you are attaching it now to dynamic_lib. There is no other way. (*)

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



(*)Truly speaking - there is. You can create intermediate function in DLL, that is exported and call desired function inside:

(*)老实说 - 有。您可以在 中创建中间函数DLL,即导出并在内部调用所需的函数:

Somewhere in dynamic_lib:

某处dynamic_lib

DLL_EXP_IMP long CallFunctionFromA_Lib()
{
     return some_function(); //this function is from static_lib1.lib
}

Somewhere in .exe:

某处.exe

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

I can't imagine, however, why would you want to do this and not simply link A.liband use it directly.

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

回答by dewaffled

HereRaymond 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 - thisdiscussion looks like a good starting point.

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