原文地址:https://blog.csdn.net/github_37157365/article/details/79653292
场景:
很多时候我们写代码的时候会经常用到某些代码段,比方说求两个或几个整数的和或者将一个整形数组转化为二叉树等等。经常使用这些代码,但是每一次又得重新再写一遍,次数多了等于就是重复无用劳动了。所以,可以自己动手写一个自己的动态链接库,保存起来。下次用到只需要加上库就ok了,这样既方便了自己又对动态链接库本身的工作原理理解更深了。
linux下动态链接库:
简介
windows的链接库和linux的链接库在实现原理上大同小异,只是名字有点区别罢了。链接库分两种,动态的和静态的。windows下分别用.lib和.dll来表示,而linux下用.a和.so来表示。静态链接库是指编译代码时即将整个库编到可执行文件中,此时该程序完全拥有库所实现的功能,即运行时不再和库有任何瓜葛。动态链接库则不一样,编译时只是将库中所用到的函数和功能的入口地址编译到可执行文件中,当程序执行到该函数时,程序即跳转到库的函数入口处,因此它们之间是动态的联系在一起的。
linux下so的命名方法
linux下动态链接库有一套自己的命名方法,只有正确命名才能够正确的加载和运行。方法为libxxx.so.x,其中xxx表示名字,一般来说就是该so库的作用,后面的x表示版本号,因为so库往往会有版本升级。
而在加载时往往用的是该so库的软链接,如上图的蓝色所示,如果版本升级了只需要将软链接链到最新的so库就能解决问题,所以这种方法很实用。
编写一个简单的so库:
比方将两个整型数相加
- //add.cc
- int add(int x, int y)
- {
- return x+y;
- }
编译
- g++ add.cc -fPIC -shared -o libadd.so
此时so库就产生了
-fPIC是指编译的so库不依赖于具体路径。接下来编译一个测试代码。
- //test.cc
- #include<iostream>
- int add(int,int);
- int main()
- {
- int a = 10;
- int b = 20;
- int c = add(a,b);
- std::cout<<"a + b = "<<c<<std::endl;
- return 0;
- }
编译
- g++ test.cc -o test -ladd
此时会编译不过,报如下错误/usr/bin/ld.bfd.real: cannot find -ladd
这说明ld也就是链接的时候找不到这个so库,因为ld有一个conf文件,它只会在规定的路径中去寻找,通常是/lib,/usr/lib或者、/usr/local/lib等等。所以我们将这个libadd.so放到/usr/local/lib中去,这表示我们自己写的库用以区分系统自带的库。再编译一次,发现能通过。
运行一下,发现报错:while loading shared libraries: libadd.so balabala...
加载的时候不能打开这个so库。我们回到ld的conf文件中去,看看conf文件都包含了哪些默认的链接路径。
cat /etc/ld.so.conf文件显示include /etc/ld.so.conf.d/*.conf
再一一查看/etc/ld.so.conf.d/目录中的所有conf文件。
发现并没有include我们编写的libadd.so的路径/usr/local/lib,所以我们需要再写一个local.conf文件再将这个路径添上去。
运行命令ldconfig,表示ld的默认路径发生了变化并将新加的路径添上。
再次运行test,成功。
总结:
以上是一个简单的so库的编写方法,我们可以在必要时按照上述方法建立自己的so库并方便以后调用。