c++ - 针对不同版本的 .dll 的 .lib 进行链接可能产生的副作用是什么?

标签 c++ c dll

我正在链接较新的 .lib,但在我的应用程序中使用较旧的 .dll。这样做可能产生的副作用是什么?如果两个版本之间的函数原型(prototype)相同,难道不应该一切正常吗?如果较新的版本更改了参数的默认值怎么办?该值是在 .lib 中还是在 .dll 中?

最佳答案

在 C++ 中,默认值是在调用站点编译的 - 因此 DLL 或 .lib 文件与此无关 - 更改 header 会产生影响,而不会更改 ABI。

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

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

- calling convention
- export name
- parameter list (including types)

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

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


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

A couple of definitions:

entry points are externally accessible functions or variables exported by the DLL. The interface is the set of all these exported functions and variables in a given version of the library. Regarding the libPNG version macros in makefile.cygwin:

You ONLY need to bump PNGDLL if the new dll REMOVES an entry point that the old dll provided. If you ADD a new entry point, then the new dll is a drop in replacement for the old one, since the new one provides everything the old one did.

Of course, an app compiled against the new version, which uses the additional entry points, won't work with the old dll -- but nobody ever promised FORWARD compatibility, only BACKWARD compatibility. This is the way cygwin DLL versioning works:

1) follow the libtool versioning scheme From 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

library implements. In other words, the library implements all the interface numbers in the range from number current - age to current.

Updating libtool versioning:

   1.     Start with version information of 0:0:0 for each libtool

library.

   2. Update the version information only immediately before a

public release of your software. More frequent updates are unnecessary, and only guarantee that the current interface number gets larger faster.

   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

release of your package will not be binary compatible with any other release.

2) On windows/cygwin, the DLLVER is 'c - a' (trust me, this is correct,

but it's easier to explain by example).

So, here's an example: the libtool version is 5:4:3, which indicates revision 4 of the implementation of interface 5, which happens to be backwards compatible with the three previous interface definitions. (ie. it is safe for applications linked against interfaces 5, 4, 3 and 2 to load the 5:4:3 dll at runtime).

So, let's look at the likely history of the mystery dll. I am following the c:r:a update rules described above.

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)    

All of these DLLs with DLLVER = 2 (2:0:0, 3:0:1, 4:0:2, 5:0:3, 5:1:3, 5:2:3, 5:3:3, and 5:4:3) are all strictly backwards compatible: it is guaranteed that any newer DLL in the series can be loaded by an exe that was compiled against an older DLL in the series.

In 1.2.3, the DLLVER was 12. Let's pretend that was a 'c' - 'a' of 12, and that 'c' = 12 and 'a' = 0.

In [libpng] 1.2.4, you simply added some new functions -- but did NOT remove any. So, the new libtool number is 13:0:1 -- and DLLVER remains 12.

关于c++ - 针对不同版本的 .dll 的 .lib 进行链接可能产生的副作用是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6099767/

相关文章:

c++ - 在 C++ 中用零初始化局部数组

c - unistd.h中 `sleep`和 `pause`库函数的区别

c - 为什么我的信号处理程序无法使用 sigaction 函数工作?

c++ - 函数名称修改。 _cdecl约定

c++ - 如何重构现在驻留在静态库中的全局记录器?

c++ - GDB 回溯中的源代码行号基本上没有对应

c++ - 在哪个编译单元中有一个 constexpr 变量?

c++ - 未加载 QMYSQL 驱动程序,已尝试所有提示

c - 错误的 strlen 输出

C++更改dll中的类,其中指向该类的指针返回给其他dll