静态库和动态库
静态库和动态库
引言
将多个目标文件打包到一起,形成一个文件,叫库
库文件名字都是以lib开头的
本次我们将《UNIX环境高级编程》(第三版)的error.c源码打包成静态库或者动态库
#ifndef __ERROR_H__#define __ERROR_H__/*** Nonfatal error related to a system call.* Print a message and return.*/void err_ret(constchar*fmt,...);/*** Fatal error related to a system call.* Print a message and terminate.*/void err_sys(constchar*fmt,...);/*** Nonfatal error unrelated to a system call.* Error code passed as explict parameter.* Print a message and return.*/void err_cont(int error,constchar*fmt,...);/*** Fatal error unrelated to a system call.* Error code passed as explict parameter.* Print a message and terminate.*/void err_exit(int error,constchar*fmt,...);/*** Fatal error related to a system call.* Print a message, dump core, and terminate.*/void err_dump(constchar*fmt,...);/*** Nonfatal error unrelated to a system call.* Print a message and return.*/void err_msg(constchar*fmt,...);/*** Fatal error unrelated to a system call.* Print a message and terminate.*/void err_quit(constchar*fmt,...);#endif/* __ERROR_H__ */
代码1 error.h头文件
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>/* for definition of errno */#include<stdarg.h>/* ISO C variable aruments */#include"error.h"#define MAXLINE 4096/* max line length */staticvoid err_doit(int,int,constchar*, va_list);void err_ret(constchar*fmt,...){va_list ap;va_start(ap, fmt);err_doit(1, errno, fmt, ap);va_end(ap);}void err_sys(constchar*fmt,...){va_list ap;va_start(ap, fmt);err_doit(1, errno, fmt, ap);va_end(ap);exit(1);}void err_cont(int error,constchar*fmt,...){va_list ap;va_start(ap, fmt);err_doit(1, error, fmt, ap);va_end(ap);}void err_exit(int error,constchar*fmt,...){va_list ap;va_start(ap, fmt);err_doit(1, error, fmt, ap);va_end(ap);exit(1);}void err_dump(constchar*fmt,...){va_list ap;va_start(ap, fmt);err_doit(1, errno, fmt, ap);va_end(ap);abort();/* dump core and terminate */exit(1);/* shouldn't get here */}void err_msg(constchar*fmt,...){va_list ap;va_start(ap, fmt);err_doit(0,0, fmt, ap);va_end(ap);}void err_quit(constchar*fmt,...){va_list ap;va_start(ap, fmt);err_doit(0,0, fmt, ap);va_end(ap);exit(1);}staticvoid err_doit(int errnoflag,int error,constchar*fmt, va_list ap){char buf[MAXLINE];vsnprintf(buf, MAXLINE-1, fmt, ap);if(errnoflag){snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1,": %s",strerror(error));}strcat(buf,"\n");fflush(stdout);/* in case stdout and stderr are the same */fputs(buf, stderr);fflush(NULL);/* flushes all stdio output streams */}
代码2. error.h的实现
静态库
静态库都是以.a作为后缀,表示Archive
例如: libmy.a (my就是库名)
创建静态库
编译
gcc -c -static a.c b.c ...
1) -static可选,可阻止gcc使用共享库
不使用共享库会使可执行文件变大,但会减少运行时间开销
2) 写头文件(里面是那些函数的声明)
源文件可以是多个或一个,里面是想要放到库中的函数的定义
打包
ar r libxxx.a a.o b.o ...
ar[选项] 归档文件名 目标文件列表
-r 将指定文件插入文档,如果存在则更新
示例: ar r libxxx.a *.o
-t 显示目标文件列表
示例: ar t libxxx.a
使用静态库
写调用源程序: main.c
第一种方式
gcc libxxx.a main.c(或者main.o) -o main
第二种方式
如果没有配置LIBRARY_PATH的环境变量,可以采用如下方式编译:
gcc -lxxx(静态库名) -LXXX(静态库所在的路径) main.c -o main
或者-l和xxx空一个空格
gcc -l xxx -L XXX main.c -o main
或者加-static选项
gcc -static -lxxx -LXXX main.c -o main
其中-static表示如果同时存在同名的动态库和静态库,使用静态库(默认使用动态库)
示例:
gcc main.c -lerror -Llib
第三种方式
如果libxxx.a在LIBRARY_PATH的指定目录中,还可以采用如下方式编译
gcc -lxxx main.c -o main
配置环境变量LIBRARY_PATH
export LIBRARY_PATH=库文件所在的路径
第三方静态库示例
sqrt函数
库: libm.a (/usr/lib/libm.a)
头文件: math.h (/usr/include/math.h)
静态库的优缺点
运行时不再依赖静态库,代码已经嵌入到可执行文件中
升级时需要重新编译链接
动态库
又叫共享对象库(shared object library,简称共享库)
我的git库主页:https://gitee.com/firewaycoding

浙公网安备 33010602011771号