链接到不同版本的 .dll 的 .lib 可能会产生哪些副作用?

zoo*_*opa 4 c c++ dll

我链接到较新的 .lib,但在我的应用程序中使用较旧的 .dll。这样做可能有哪些副作用?如果两个版本之间的函数原型相同,不是一切都可以工作吗?如果新版本更改了参数的默认值怎么办?该值是在 .lib 中还是在 .dll 中?

Mic*_*urr 5

在 C++ 中,默认值是在调用站点编译的 - 因此 DLL 或 .lib 文件与此无关 - 更改标头将产生效果,而 ABI 不会发生任何更改。

如果导出函数中的 ABI 没有改变,只要程序不使用新的 .lib 中的新导出,您应该能够将旧的 DLL 与链接到较新的 .lib 的程序一起使用。 .lib 但不在旧版 DLL 中。

影响 ABI 的因素(我并不是说这是一个全面的列表):

- calling convention
- export name
- parameter list (including types)
Run Code Online (Sandbox Code Playgroud)

“libtool 版本控制系统”(http://www.gnu.org/s/libtool/manual/libtool.html#Versioning)是一种用于识别共享库兼容性的技术。

请注意,如果您不使用 C 调用约定(即,导出名称将是“C++ 损坏”),那么从技术上讲,您对导出的名称几乎没有控制权。


下面解释了一些 Windows 库(cygwin、pngdll)如何使用遵循 libtool 库版本控制技术的命名约定来管理向后兼容性。这是来自http://home.att.net/~perlspinr/libversioning.html的网络存档- 我将其镜像在这里:

几个定义:

入口点是DLL 导出的外部可访问函数或变量。接口是给定版本的库中所有这些导出函数和变量的集合。关于makefile.cygwin中的libPNG版本宏:

如果新 dll 删除了旧 dll 提供的入口点,则仅需要碰撞 PNGDLL。如果您添加一个新的入口点,那么新的 dll 就会替代旧的入口点,因为新的 dll 提供了旧的入口点所做的一切。

当然,针对新版本编译的应用程序使用额外的入口点,无法与旧的 dll 一起工作——但没有人承诺向前兼容性,只承诺向后兼容性。这是 cygwin DLL 版本控制的工作方式:

1)遵循 libtool 版本控制方案来自 http://www.gnu.org/software/libtool/manual.html#Versioning

So, libtool library versions are described by three integers:
current
    The most recent interface number that this library implements.
revision
    The implementation number of the current interface.
age
    The difference between the newest and oldest interfaces that this
Run Code Online (Sandbox Code Playgroud)

库实现。换句话说,该库实现了从当前编号到当前编号范围内的所有接口编号。

Updating libtool versioning:

   1.     Start with version information of 0:0:0 for each libtool
Run Code Online (Sandbox Code Playgroud)

图书馆。

   2. Update the version information only immediately before a
Run Code Online (Sandbox Code Playgroud)

公开发布您的软件。更频繁的更新是没有必要的,只能保证当前接口数变大更快。

   3. If the library source code has changed at all since the last
      update, then increment revision (c:r:a becomes c:r+1:a).

   4. If any interfaces have been added, removed, or changed since the
      last update, increment current, and set revision to 0.

   5. If any interfaces have been added since the last public release,
      then increment age.

   6. If any interfaces have been removed since the last public
      release, then set age to 0. 


Never try to set the interface numbers so that they correspond to the
release number of your package. This is an abuse that only fosters
misunderstanding of the purpose of library versions. Instead, use the
-release flag (see Release numbers), but be warned that every
Run Code Online (Sandbox Code Playgroud)

您的软件包的版本不会与任何其他版本二进制兼容。

2) On windows/cygwin, the DLLVER is 'c - a' (trust me, this is correct,
Run Code Online (Sandbox Code Playgroud)

但通过例子更容易解释)。

因此,这里有一个例子:libtool 版本是 5:4:3,它表示接口 5 的实现的修订版 4,它恰好向后兼容之前的三个接口定义。(即,链接到接口 5、4、3 和 2 的应用程序在运行时加载 5:4:3 dll 是安全的)。

那么,让我们看看这个神秘 dll 的可能历史。我遵循上述 c:r:a 更新规则。

oldest: interface definition 0, initial release:
0:0:0 (DLLVER = 0)    
removed an entry point:
1:0:0 (DLLVER = 1)    NOT backwards compatible!
but DLLVER does the right thing.
source code changed, but no added or removed entry points:
1:1:0 (DLLVER = 1)    
more source code changes:
1:2:0 (DLLVER = 1)    

In all of the previous three releases, 'c' - 'a' = DLLVER = 1.
removed an entry point (or renamed it):
2:0:0 (DLLVER = 2)    This is INCOMPATIBLE.
(But look: 'c' - 'a' = 2, so the DLLVER does the right thing)
added a new function:
3:0:1 (DLLVER = 2)    (this is BACKWARDS but not FORWARDS compatible.
However, the DLLVER 'c' - 'a' still is 2, so that is good.)
add eight more exported functions all at once
4:0:2 (DLLVER = 2)    
add another function:
5:0:3 (DLLVER = 2)
source code changes, but no new interfaces:
5:1:3 (DLLVER = 2)    
again:
5:2:3 (DLLVER = 2)    
again:
5:3:3 (DLLVER = 2)    
again:
5:4:3 (DLLVER = 2)    
Run Code Online (Sandbox Code Playgroud)

所有这些 DLLVER = 2 (2:0:0, 3:0:1, 4:0:2, 5:0:3, 5:1:3, 5:2:3, 5:3:3 、5:4:3)都是严格向后兼容的:保证该系列中的任何较新的 DLL 都可以由针对该系列中较旧的 DLL 编译的 exe 加载。

在 1.2.3 中,DLLVER 为 12。假设 'c' - 'a' 为 12,并且 'c' = 12 且 'a' = 0。

在 [libpng] 1.2.4 中,您只是添加了一些新函数——但没有删除任何函数。因此,新的 libtool 编号为 13:0:1,而 DLLVER 仍为 12。