曾经有一个简单又不失牛逼的小技巧,老师教的时候我没有珍惜,等到同事因为用了这个技巧升任总工才后悔莫及,如果上天再给我一次机会,我会对老师说:我要学!如果非要定个学习时间,我希望是:立马!
拓展:
这是一个真实的故事。
一个以往的学生就职东莞易事特,一家做新能源的上市公司,去年年底升任其部门总工(软件开发总工程师)工资升到1.2w,我说你工作半年这么NB了?他说,是因为他们部门太弱鸡了,整个部门就他一个人懂插件式链接动态库。我说:啥?插件式?链接动态库? 我教过你吗?你丫说的不会是dlsym()和dlopen()这几个函数吧?他说:是的。[阴险][阴险] 我说:NB,会包装就是不一样,插件式!你小子离征服世界不远了!
扯回来,他说的没错,这个让普工变总工的牛逼吊炸天的知识点,就是所谓的动态链接动态库。我们都知道,为了减少代码的尺寸,我们会尽量将代码封装到动态库里面,比如我们将吃饭(have_meal())、理发(hair_cut())封装在一个叫life的动态库里:
liblife1.so
通常,我们会在使用了这个库代码的程序编译时加上链接选项,例如:
gcc main.c -o main -llife1
这样,程序运行所需要的吃饭(have_meal())、理发(hair_cut())的代码就跟main.c程序分离,达到可以给多个程序共用liblife.so从而节省代码量的目的,但是这个做法有一个局限性,那就是当吃饭、理发的函数接口不变,但是内部实现功能发生了改变的时候,我们需要重新执行编译命令,或者重新链接不同的库。例如:
gcc main.c -o main -llife2
这样很不方便,那怎样才能不修改源代码,也不需要重新编译main.c,直接让程序运行的时候动态地决定呢? 答案就是使用动态链接动态库。
在main.c中,这么写你的代码:
注意到上面的提薪大招了吗? dlopen()和dlsym(),dlopen用来指定动态库,并使用dlsym来获取动态库里面的某一函数(比如hava_meal),这样一来,只要传给main的参数argv[1]不同,就可以获取和链接不同的动态库,只要这些函数接口一样即可。
例如上面的例子,在运行main程序的时候,就变成:
./main liblife1.so (调用life1里面的吃饭、理发的函数) ./main liblife2.so (调用life2里面的吃饭、理发的函数)