链接:静态与动态

时间:2011-01-16 20:54:16

标签: c++ cross-platform dynamic-linking static-linking

在我的申请中,我有3个主要部分:

  • Exe:可执行文件
  • Lib_A:一个库包含一个单例类和一个基类,用于在单例中使用的一些计算 类
  • Lib_B:库包含从Lib_A
  • 中的基础派生的许多类

我在Lib_B中有派生类的原因是,我想在运行时从Exe编译Lib_B。我需要在计算过程中生成派生类而不终止整个系统。这对我来说太重要了。这意味着最初我可能会说Lib_B1是动态加载的,我也可以将其他版本的Lib_B编译为Lib_B2,Lib_B3,Lib_B4等,并动态加载它们。所有Lib_Bx库都有入口点函数来导出它们中的类。

因此,请考虑以下事实:

  • 在运行时,将有不同数量的文件共享相同的Lib_A。
  • 应用程序必须在Windows和Linux中运行。因此,部分跨平台性是一个问题。
  • 我将使用一些像TBB,Boost,Qt这样的库,它们可能有自己的库,如tbb.dll等。

Lib_A与Exe和Lib_Bx的静态或动态链接有哪些优缺点?如何影响性能,系统大小等?除了我需要为Exe,Lib_A和Lib_Bx使用相同编译器的每个操作系统之外,是否还有任何危险或困难的情况。

整个系统的设计对我来说是一个非常难的问题,所以任何评论都会受到赞赏。

非常感谢。

4 个答案:

答案 0 :(得分:6)

根据我对项目描述的理解,您应该动态链接Lib_A:如果将Lib_A静态链接到每个Lib_Bx共享库,则将复制Lib_A代码和静态变量的x倍。

比如说,如果你在Lib_A中有一个类,其格式为:

class BaseKlass
{
  static int instance_count;
  ...
};

instance_count将在所有共享库中重复,因此BaseKlass无法计算其实例。

您可能会被虚拟表或RTTI(dynamic_cast)等更微妙的问题所困扰。

你应该看看这个boost.python document,它描述了与我提到的相关的问题。

Boost.python允许创建要在同一进程中加载​​的python模块(动态库)。使用boost.python创建的每个python模块,如果它们要在c ++级别一起通信,例如从另一个模块中的类A派生模块中的类B,则应该与boost.python lib动态链接以避免问题。

答案 1 :(得分:3)

静态链接的一大优点是您不必运送一堆DLL。除非您计划运送裸露的可执行文件,否则我认为这不是问题。

动态链接有一些很大的优势。每次进行更改时,您不必重新编译整个应用程序,只需修改DLL。您可以将更新的dll与应用程序的其余部分分开,只要它们与ABI兼容即可。

在Windows和Linux上使用相同的编译器可能更简单,但您绝对不必使用相同的编译器。

只要您坚持使用便携式库,Windows和Linux之间的最大区别通常是构建系统。一些开发人员维护完全独立的构建系统,但是有很多跨平台构建系统,比如cmake。

答案 2 :(得分:2)

您想要创建新的类运行时吗? C ++并不意味着像那样工作。 C ++类是静态的,应该都存在于编译时。共享的,可动态加载的库并不意味着解决问题。

最简单的解决方案可能是嵌入具有动态类型的语言的解释器(例如Lua)并在其中编写运行时动态对象。

如果您真的想以平台无关的方式与运行时编译的模块进行交互,那么您最好使用一些语言中立和平台中立的接口,如CORBA。然后在Linux机器和Windows机器上编译和运行的东西都可以互相交互并编译新成员以加入该团伙。

答案 3 :(得分:0)

原则上,如果所有三个都是DLL,这都是可能的 - 您可以从您的应用程序触发编译器,然后动态加载新的DLL。这实际上就像任何其他插件架构一样(将Lib_Bx DLL视为插件)。

我会质疑这是否是一种明智的方法。您是否需要为您的解决方案提供C ++编译器的完全灵活性?您是否介绍了解决问题的不同方法?如果您正在进行数字处理,那么像OpenCL这样的方法会更好吗?