进入主题前,先看看两点预备知识。
一、显式调用和隐式调用的区别
我们知道,动态库相比静态库的区别是:静态库是编译时就加载到可执行文件中的,而动态库是在程序运行时完成加载的,所以使用动态库的程序的体积要比使用静态库程序的体积小,并且使用动态库的程序在运行时必须依赖所使用的动态库文件(.so文件),而使用静态库的程序一旦编译好,就不再需要依赖的静态库文件了(.a文件)。
动态库的调用又分为显示和隐式两种方式,区别如下:
1、 隐式调用需要调用者写的代码量少,调用起来和使用当前项目下的函数一样直接;而显式调用则要求程序员在调用时,指明要加载的动态库的名称和要调用的函数名称。
2、隐式调用由系统加载完成,对程序员透明;显式调用由程序员在需要使用时自己加载,不再使用时,自己负责卸载。
3、由于显式调用由程序员负责加载和卸载,好比动态申请内存空间,需要时就申请,不用时立即释放,因此显式调用对内存的使用更加合理, 大型项目中应使用显示调用。
4、当动态链接库中只提供函数接口,而该函数没有封装到类里面时,如果使用显式调用的方式,调用方甚至不许要包含动态链接库的头文件(需要调用的函数名是通过dlsym函数的参数指明的),而使用隐式调用时,则调用方必须要加上动态库中的头文件,g++编译时还需要要用参数-I指明包含的头文件的位置。需要注意的是,当动态链接库中的接口函数是作为成员函数封装在类里面时,即使使用显式调用的方式,调用方也必须包含动态库中的相应头文件(详见五、显示调用动态链接中的类成员函数)。
5、显式调用更加灵活,可以模拟多态效果(具体见后文)。
6、显式调用的方式,必须加入头文件dlfcn.h,makefile中的链接命令中要加入参数-ldl,需要用dlopen加载库,dlsym取函数符号(函数名应用新定义的),dlclose卸载库。
7、隐式调用的方式,makefile中的链接命令中要加入参数-l加库名,直接用库里的函数名就可以。
二、extern "C"的作用
C++程序(或库、目标文件)中,所有非静态(non-static)函数在二进制文件中都是以“符号(symbol)”形式出现的。这些符号都是唯一的字符串,从而把各个函数在程序、库、目标文件中区分开来。在C中,符号