轻松地将许多重要的“静态库项目”重构为“ dll项目”

cpp*_*ner 9 c++ dll visual-studio c++17 visual-studio-2017

我有6个静态库项目:-

- Math
- ECS             : depends on Math
- Utility         : depends on ECS
- Physics         : depends on Utility         
- Graphics        : depends on Utility     
- BaseGame        : depends on Physics and Graphics         
- Some game (.exe): depends on BaseGame      
(The "depends" here is transitive e.g. BaseGame also depends on ECS.)    
Run Code Online (Sandbox Code Playgroud)

我通过“静态库”技术成功使用了6个项目。

今天,我听说动态库可以减少编译时间(我们不讨论这是否成立),
因此我阅读了以下链接,并成功创建了一个小演示。

这是我的测试演示中的一些代码:

#ifdef SomeName1_EXPORTS
#define SomeMacro1 __declspec(dllexport) 
#else
#define SomeMacro1 __declspec(dllimport) 
#endif
SomeMacro1 void someFunction(int someParam);
Run Code Online (Sandbox Code Playgroud)

现在,是将其应用于我的实际项目的激动人心的时刻。

第一步,我想导出我的6个库的所有函数和类。
我假设我必须SomeMacro1在所有6个项目(〜100K行)中的每个函数中添加(每个项目不同),对吗?

那是一个巨大的重构。
有没有更简单的方法?我会错过一些非常重要的事情吗?

其他说明

  • 我想轻松地将库项目切换回静态库(以防出现问题)。
  • 我更喜欢跨平台解决方案。(例如,如果我以后要在Linux中运行,则不需要普遍的重构)
  • 我更喜欢一种解决方案,当我将源文件从一个项目剪切并粘贴到另一个项目时,重构的成本(以代码形式)不会比正常情况下增加。
    SomeMacro1当前特定于项目)

相似的问题:如何在VS2005中将静态库项目转换为dll项目

赏金原因

感谢Andriy Tylychko的回答,它提供了有用的警告,并指出重构将不可避免地变得复杂,但是我仍然相信有一些简单的方法可以重构我的项目。

现在,我希望将我的库项目更改为动态库。(更快的编译)
然后,当我发货时,我会将它们转换回静态库。(更好的性能)

编辑:由于他在评论中的链接,赏金授予Robert Andrzejuk。(https://docs.microsoft.com/zh-cn/cpp/cpp/using-dllimport-and-dllexport-in-cpp-classes?view=vs-2019
听起来很简单,但我从来不知道我可以__declspec(dllexport)上课。
尽管那不是我的梦想,但它使很多事情变得容易。

And*_*hko 5

严格来说,转换为 DLL 将主要减少链接时间,但您会注意到(在大多数情况下是微妙的)性能下降,因为现在“整个程序优化”的优化空间要小得多,例如跨不同二进制文件内联函数。

动态链接库和静态链接库是完全不同的野兽,DLL 需要更多的关注。您需要仔细设计他们的公共 API 并相应地定义它(通常通过您提供的宏)。例如,不建议在依赖于特定类型的 C 运行时(如调试和发布)的 DLL 公共 API 中使用标准库类型(以及许多其他类型)——主要是关于在一个二进制文件中分配内存并在另一个二进制文件中释放应该避免的. 但这并不总是一个问题。

在静态库和动态库之间来回切换没有多大意义。

静态库通常要简单得多,并且不关心公共 API,因为一切都可以从外部自动访问。例如,数学库通常是静态的,因为几乎所有功能都应该导出,而且它们(通常)没有任何复杂的内部“业务”逻辑。

具有您想要隐藏的“业务”逻辑(例如,有更多的自由修改它)和定义明确的公共 API 的更大的库会带来长期的好处。例如,如果 API 没有改变,您只能更新一个小的 DLL 而不是巨大的单体 EXE。

由于很难提前仔细计划,随着项目的成熟,经常需要将静态库转换为 DLL(一次)。在这种情况下,您不需要导出每个类和函数,而是仔细选择应该导出的确切内容,并理想地重构现有 API 以更好地适应新的现实。幸运的是,您似乎没有任何循环依赖,因为它们可能会增加很多麻烦。

跨 DLL 的重构不可避免地变得更加复杂,但这应该不是什么大问题。如果你的 lib 看起来应该是一个 DLL - 让它成为一个 DLL,优势将大于不那么容易复制/粘贴的劣势。

从你的例子来看,知识非常有限,所以它纯粹是猜测,它看起来只有物理,也许图形应该是 DLL,也可能是 BaseGame。

  • @cppBeginner 有时内存分配器中的全局变量是静态链接和**重复**的。这意味着你不能互操作。 (2认同)