二进制兼容问题,主要是针对动态链接库而言的。在Windows上就是dll,在linux上就是so。 如果主程序EXE(当然也可以是客户库)不变,升级了依赖库SO1到SO2,而不需要重新编译,那么就是说so2是兼容so1库的。二进制兼容涉及到编译问题,所以和硬件平台,软件平台以及编译器等都是密切相关的。主要是语言编译后的数据在内存中的结构问题。所以很大程度上和语言相关。比如c++语言由于涉及到很多高级特性(虚函数,模板,内联函数,函数重载,name mangling),导致要编写二进制兼容的库有很多限制。

我们举个例子,在c++语言里对struct和class的数据成员的访问是通过偏移量来获取的,所以你在一个类中间插入一个成员变量,就会导致后面的变量偏移量发生变化,那么肯定是非二进制兼容的,但是你改变一个变量的名称却可以(但是这样做却是源代码不兼容的,呵呵)。

如果你改变了一个类Bar的大小,那么这样是不是二进制兼容的呢?

增加新的class: 是

在类里增加非虚函数:是

在类里面增加枚举:是

在枚举里追加一个值(在最后加):是

去掉类里一个private的非虚函数,并且这个函数没有被inline函数调用过:是

去掉类里一个private的静态变量,并且这个变量没有被inline函数使用过:是

增加一个静态变量:是

导出一个之前没有导出过的类:是

增加或去掉类的友元声明:是

给reserved变量改名:是

扩展reserved的bit位:是


对导出类remove或者去掉导出:否

改变类的继承关系:否

改变模板参数(增加,取出,改变顺序):否


extern "c" 有两重含义:

    1.这是一段C++代码,但是没有太多高级特性,我希望用C语言的习惯来编译;

    2.我希望对这段c++代码用c语言的方式来调用(或者链接)。

其实动态链接技术(Dll和so)主要是用在c语言上的,是以导出函数为基础的。如果用在c++上,兼容性确实很成问题,在导出类,成员函数时需要各种其他手段,而且没有完美解决方案。 windows的库函数就是使用c语言加dll来实现的。


对于C语言,C/Posix 这些年逐渐加入了很多新函数,同时,现有的代码不用修改也能运行得很好。如果要用这些新函数,直接用就行了,也基本不会修改已有的代码。