深度理解:Windows DLL 二进制兼容性探究

使用C++开发工程代码的时候,一般采取模块化设计来降低项目的复杂度。一个典型的C++工程,一般分为一个EXE工程作为主启动进程,若干个DLL工程提供各种不同的功能集合。今天我们通过一个具体的实例来看看DLL的二进制兼容性。

研究环境

编译环境:VS2010

主EXE工程:Win32控制台应用,名称Test

DLL工程:MFC共享DLL,名称Function

工程代码

主EXE工程

主EXE工程采用VS2010内置的Win32控制台应用模板,在主工程中的main函数中调用了DLL工程的导出方法MyAdd。

16868175-183119711f62aa71

DLL工程

DLL工程采用VS2010内置的MFC共享DLL模板,在DLL工程中,我们定义并实现了一个导出方法MyAdd。这个方法的实现比较简单:接收两个整数,并返回这两个整数之和。

16868175-6a309af573fe8ce9

第一种情况:主EXE工程调用DLL工程

分别编译EXE和DLL工程,执行EXE工程,可以得到以下结果:

16868175-dcb0eddeed9c22f2

在上述代码中,我们传入DLL方法了两个整数,10和20,DLL方法准确的返回了它们之和30。一切都是我们预期的。

第二种情况:DLL工程中的方法实现修改且主EXE工程不重新编译

我们将DLL工程实现代码进行修改,从计算两个整数之和修改为计算两个整数之乘积。

16868175-f5d55951f0cee9d4

在只编译DLL工程的情况下,我们直接执行主EXE工程,看看执行结果:

16868175-948dee1a373c58dc

从执行结果来看,主EXE工程代码没有经过重新编译,但它”感知”到了DLL实现代码的变更,此场景我们认为:DLL的内部实现修改保持了其二进制的兼容性。

第三种情况:DLL工程中的方法声明修改且主EXE工程不重新编译

我们将DLL工程方法声明代码进行修改,从接收两个参数,我们修改为接收三个参数。

16868175-c1afa4959abd4c5e

在只编译DLL工程的情况下,再次执行主EXE工程,看看执行结果:

16868175-893b6d821237edae

我们看到,虽然DLL的参数增加了,但内部实现没有变更。但是主EXE工程在执行阶段提示找不到函数入口点,说明此时DLL工程的方法声明修改需要主EXE工程重新编译。此场景我们认为:DLL方法声明修改破坏了其二进制兼容性,任何DLL代码的方法声明的变更,其调用者必须重新编译。

结论

对于导出类C方法的DLL工程,当DLL内部实现代码变更时,DLL的调用者不需要重新编译。

对于导出类C方法的DLL工程,当DLL方法声明代码变更时,DLL的调用者需要重新编译。

16868175-c34dcaaf4a74f30e

转载于:https://www.jianshu.com/p/c2f73e05e9a9

猜你喜欢

转载自blog.csdn.net/weixin_34274029/article/details/91064732