我们在写c语言的时候,经常会去包含一个.h的头文件,这个头文件就是库文件,比如
那么用一张图先来说明一下,介绍一下头文件的用法与作用:
比如我们做一个没有引入.h文件的库:
add.c
minus.c
先把这两个文件函数做成一个动态库:
然后移动到相应我们存放自己库文件位置:
然后demo1.c测试一把,注意我们没有引入头文件
运行
所以,头文件是不是可以不加,但是其实不然 ,头文件可以帮我们定义数据类型,规范函数接口,就当相于是一个手册参考
OK,话不多说,上代码:
上面就是我在/home/pxx/include下面放的我自己的头文件,在/home/pxx/lib放的我的库文件,这是一个静态库,至于静态库怎么来制作,我们后面再来说。
然后我在/home/pxx/c里面放的我的测试文件demo2.c
demo2.c:
1 #include
2 #include
3 #include "add.h"
4
5 int main()
6 {
7 int res1 = add(1,2);
8 int res2 = sum(2,3);
9 printf("%d %d\n",res1,res2);
10 return 0;
11 }
上面就是引用我们add.h的头文件,这个文件默认会去找当前目录有没有这个头文件,没有就去找我们指定的地方,然后去调用实现它的库文件。
下面我们来编译一下,首先我们看第一个情况,链接了头文件没有链接库文件:
再来看一个情况,我们链接了库,但是没链接头:
下面看一个标准链接:
下面来具体说一下静态库与动态库:
一张图说明什么是静态库与动态库:
下面说一下静态库与动态库的制作方法:
我们在使用库的时候,往往是与头文件一起使用的,头文件定义函数,库文件实现函数。另外就是,我们一般用动态链接库比较多,节约内存嘛,然后就是整体升级也方便。但是如果你要考虑程序的移植性,就考虑用静态库吧。
话不多说,上代码。
静态库太简单,不说了,这里重点说一下动态库:
add.h:(/home/pxx/include)
1 #ifndef _ADD_H_
2 #define _ADD_H_
3
4
5 int add(int num1,int num2);
6
7 #endif
add.c:(/home/pxx/include)
1 #include
2 #include
3
4 int add(int num1,int num2)
5 {
6 return num1 + num2;
7 }
~
然后编译成.o文件用来制作动态库:
然后我们在来制作成动态库:
现在可以把这个共享库放到/home/pxx/lib里面:
现在去到我们/home/pxx/c里面:
demo3.c:
1 #include
2 #include
3 #include "add.h"
4
5
6 int main()
7 {
8 int res = add(1,2);
9 printf("%d\n",res);
10 return 0;
11 }
现在我们来链接一下共享库,调用这个函数:
上面很明显的有一个出现一个问题,这个问题的出现也说明了一个问题,就是我们在gcc链接库的时候没有报这个错误,运行程序的时候才报错,说明,动态库就是在链接的时候运行的。
我们来分析一下为什么提示找不到这个文件或者目录呢
ldd->可以查看可执行文件的可依赖的库文件
很明显libadd1.so找不到,那么下面就要延伸一个文件路径查找问题:
我们不是在编译程序的时候加入了-L/home/pxx/lib这个库文件位置吗,为什么还会提醒我们找不到。
那是因为库文件没有加载到环境变量中,因此程序在加载库的时候,就无法找到它的绝对路径,然后就无法加载到内存中。那么如何把这个库加入到环境变量中,下面给又得延伸一个可执行程序路径查找问题,一般来说可执行程序是elf格式的,那么我们就必须知道elf格式文件路径是怎么查找的。先来看一下dmeo3可执行文件是否是elf格式:
上面很明显看到demo3是elf格式的文件,那么现在说一下elf格式文件路径查找:
那么我们只要在上面任何一个设置好共享库的位置,就肯定可以让我们的共享库加载到内存中
那么说一下解决办法:
我们用推荐的方法:
注意.bashrc是一个隐藏文件
再来ldd一下执行文件,看看我们需要的库是否都找到了
我们也可以去测试一下其他方法都可以找到动态库的问题。好了,就说到这吧。