- 一、前言
- 二、用gcc生成静态库和动态库
- (一).hello实例
- 1.准备过程
- 2.静态库的使用
- 3.动态库的使用
- (二).linux下静态库.a和.so库文件的生成和使用实例
- 1.准备过程
- 2.静态库.a文件的生成与使用
- 3.动态库.so文件的生成与使用
- (三).其他实例
- 1.准备过程
- 2.静态库使用
- 3.动态库的使用
- 4.静态库与动态库的生成文件大小的比较
- 三、参考资料
我们通常把一些公用函数制作成函数库,供其他程序使用,函数库分为静态库和动态库两种。
静态库在程序编译时会连接到目标代码中,程序运行时将不再需要该静态库。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入。
本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。
(1) .创建一个作业目录,保存本次练习的文件
#mkdir test1 #cd test1
(2) .程序代码
hello.h为该函数库的头文件
#ifndef HELLO_H #define HELLO_H void hello(const char *name) #endif //HELLO_H
hello1.c是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出“Hello,XXX!"。
#includevoid hello(const char *name) { printf("Hello %s!n",name); }
main.c为测试库文件的主程序,在主程序中调用了公用函数hello
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
(3) .将hello.c编译成.o文件
在系统提示符下键入以下命令得到hello.o文件
gcc -c hello.c
运行ls命令看看是否生成了hello.o文件
ls
看到有hello.o文件,说明本部操作完成。
(1) .由.o文件创建静态库
静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名.a。
ar -crv libmyhello.a hello.o
运行ls命令看看是否生成了静态库文件文件
ls
看到libmyhello.a文件,说明本部操作完成。
(2) .在程序中使用静态库
静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包 含这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明静态库名,gcc 将会从 静态库中将公用函数连接到目标文件中。注意,gcc 会在静态库名前加上前缀 lib,然后追 加扩展名.a 得到的静态库文件名来查找静态库文件。 在程序 main.c 中,我们包含了静态库的头文件 hello.h,然后在主程序 main 中直接调用 公用函数 hello。下面先生成目标程序 hello,然后运行 hello 程序看看结果如何。
方法一:
gcc -o hello main.c -L. –lmyhello
自定义的库时,main.c 还可放在-L.和 –lmyhello 之间,但是不能放在它俩之后,否则会提 示 myhello 没定义,但是是系统的库时,如 g++ -o main(-L/usr/lib) -lpthread main.cpp 就不出错。
方法二:
gcc main.c libmyhello.a -o hello
方法三:
先生成 main.o:
gcc -c main.c
再生成可执行文件:
gcc -o hello main.o libmyhello.a
动态库连接时也可以这样做。
输入./hello
说明操作成功了。
然后我们删除静态库文件试试公用函数hello是否真的连接到目标文件hello中了
rm libmyhello.a ./hello
可以看到libmyhello.a已经被删除,而程序照常运行,说明静态库中的公用函数已经连接到目标文件中。
(1) .由.o文件创建动态库文件
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。例如:我们将创建的动态库名为 myhello,则动态库文件名就是 libmyh ello.so。用 gcc 来创建动态库。
在系统提示符下键入以下命令得到动态库文件 libmyhello.so。
gcc -shared -fPIC -o libmyhello.so hello.o
提示错误
这是因为在创建hello.o文件时没有键入-fPIC使不一致导致的
重新输入
gcc -o -fPIC hello.c
之后再输入
gcc -shared -fPIC -o libmyhello.so hello.o
用ls命令查看,发现动态库已经创建成功
(2) .在程序中使用动态库
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含 这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明动态库名进行编译。程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提 示类似上述错误而终止程序运行。我们将文件 libmyhello.so 复制到目录/usr/lib 中在运行,否则会报错。
gcc -o hello main.c -L. -lmyhello
之后输入./hello看程序是否执行
./hello
果然出现了错误。
解决方法是将文件 libmyhello.so 复制到目录/usr/lib 中在运行
输入mv libmyhello.so 提示权限不够
所以我们需要临时权限提高
输入sudo mv libmyhello.so就可以解决
之后输入./hello,程序成功运行,如下图所示
(1) .先创建一个作业目录,保存本次示例文件
mkdir test2 cd test2
(2) .实例代码
A1.c:
#includevoid print1(int arg) { printf("A1 print arg:%dn",arg); }
A2.c:
#includevoid print2(char *arg) { printf("A2 printf arg:%sn", arg); }
A.h:
#ifndef A_H #define A_H void print1(int); void print2(char *); #endif
test.c:
#include2.静态库.a文件的生成与使用#include "A.h" int main() { print1(1); print2("test"); exit(0); }
gcc -c A1.c A2.c ar crv libafile.a A1.o A2.o
使用.a 库文件,创建可执行程序(若采用此种方式,需保证生成的.a 文件与.c 文件保 存在同一目录下,即都在当前目录下)
如图都在libafile文件夹内
gcc -o test test.c libafile.a ./test
如图所示,说明使用成功
生成目标文件(xxx.o() 此处生成.o 文件必须添加"-fpic"(小模式,代码少),否则在生成.so 文件时会出错)
gcc -c -fpic A1.c A2.c
生成共享库.so 文件
gcc -shared *.o -o libsofile.so
使用.so 库文件,创建可执行程序
gcc -o test test.c libsofile.so
./test
发现出现错误:
./test: error while loading shared libraries: libsofile.so: cannot open shared object file: No such file or directory
运行 ldd test,查看链接情况
ldd test linux-vdso.so.1 => (0x00007fff0fd95000) libsofile.so => not found libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f937b5de000) /lib64/ld-linux-x86-64.so.2 (0x0000563f7028c000)
发现确实是找不到对应的.so 文件。 这是由于 linux 自身系统设定的相应的设置的原因,即其只在/lib and /usr/lib 下搜索对应 的.so 文件,故需将对应 so 文件拷贝到对应路径。
sudo cp libsofile.so /usr/lib
再次执行./test,即可成功运行。
全过程如图所示
(1) .创建一个作业目录,保存本次练习的文件
#mkdir example1 #cd example1
(2) .实例代码
sub1.c:
float x2x(int a,int b)
{
float c=0;
c=a+b;
return c;
}
sub2.c:
float x2y(int a,int b)
{
float c=0;
c=a/b;
return c;
}
sub.h:
#ifndef SUB_H #define SUB_H float x2x(int a,int b); float x2y(int a,int b); #endif
main.c:
#include2.静态库使用#include"sub.h" void main() { int a,b; printf("Please input the value of a:"); scanf("%d",&a); printf("Please input the value of b:"); scanf("%d",&b); printf("a+b=%.2fn",x2x(a,b)); printf("a/b=%.2fn",x2y(a,b)); }
gcc -c sub1.c sub2.c
ar crv libsub.a sub1.o sub2.o
gcc -o main main.c libsub.a
可以看到输入./main,按要求输入a,b,可以看到输出是正确的,说明程序正确执行。
gcc -shared -fPIC -o libsub.so sub1.o sub2.o gcc -o main main.c libsub.so sudo mv libsub.so /usr/lib
可以看到输入./main,按要求输入a,b,可以看到输出是正确的,说明程序正确执行。
静态库
动态库
可以看到态库要比动态库要小很多,生成的可执行文件大小也存在较小的差别。
gcc生成静态库.a和动态库.so.



