Linux环境下c语言静态链接库和动态链接库创建和使用
库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。
面对比一下两者:
静态链接库:当要使用时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。
动态库而言:某个程序在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。在程序运行的时候,被调用的动态链接库函数被安置在内存的某个地方,所有调用它的程序将指向这个代码段。因此,这些代码必须使用相对地址,而不是绝对地址。在编译的时候,我们需要告诉编译器,这些对象文件是用来做动态链接库的,所以要用地址不无关代码(Position Independent Code (PIC))。
注意:linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。
一. 静态库
下面就通过实际的例子来向大家演示一下,该怎样编译和使用静态和动态链接库:
1. 编辑测试文件
二个文件:add.c、 sub.c、add.h 、sub.h 和 main.c
/*.h */
#ifndef _Time_H_
#define _Time_H_
struct Time
{
int year;
int day;
int month;
}time;
#endif
每段程序结束这里记得多一空行
-------------------------------------------------------------------------------------------------
/*judge.h*/#ifndef _Judge_H_
#define _Judge_H_
#include "time.h"
int judge_is_leap(struct Time *point_time);
#endif
-------------------------------------------------------------------------------------------------
/*panduan*/
#ifndef _PAN_DUAN_H_
#define _PAN_DUAN_H_
#include "time.h"
int panduan(struct Time *p);
#endif
-------------------------------------------------------------------------------------------------
/*judge.c*/
#include "judge.h"
#include "time.h"
int judge_is_leap(struct Time *p)
{
int flag=0;
if(p->year%4==0&&p->year%100!=0||p->year%100==0&&p->year%400!=0)
{
flag=1;
}
return flag;
}
-------------------------------------------------------------------------------------------------
/*panduan.c*/
#include "time.h"
#include "panduan.h"
int panduan(struct Time *p)
{
int loop=0;
int Array_month[]={31,28,31,30,31,30,31,31,30,31,30,31};
if(p->day<1||p->day>Array_month[p->month-1])
loop=1;
return loop;
}
-------------------------------------------------------------------------------------------------
/*main.c*/
#include <stdio.h>
#include "time.h"
#include "judge.h"
#include "panduan.h"
#define Tops point_time->month-1
int main(void)
{
struct Time *point_time;
int Xunh_num,Sum_day=0,flag=0,flag2;
point_time=&time;
int Array_month[]={31,28,31,30,31,30,31,31,30,31,30,31};
printf("please input year month day \n");
scanf("%d %d %d",&point_time->year,&point_time->month,&point_time->day);
flag=judge_is_leap(point_time);
if(flag==1)
Array_month[1]++;
else
flag=0;
flag2=panduan(point_time);
if(flag2==1)
{
printf("parameter error");
return 1;
}
for(Xunh_num=0;Xunh_num<Tops;Xunh_num++)
{
Sum_day+=Array_month[Xunh_num];
}
Sum_day+=point_time->day;
printf("today is year's %d num\n",Sum_day);
return 0;
}
-------------------------------------------------------------------------------------------------
2. 将 judge.c 和panduan.c 编译生成 .o文件
gcc -c judge.o
gcc -c panduan.o
生成的文件:judge.o,panduan.o
无论是静态库文件还是动态库文件,都是由 .o 文件创建的。
3. 由 .o 文件创建静态库(.a 文件)
ar cr libmymonth.a judge.o panduan.o
库文件的命名规范是以lib开头(前缀),紧接着是静态库名,以 .a 为后缀名。
4. 在程序中使用静态库
gcc -o main main.c -L. -lmymonth
静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名(是mymath 而不是libmymath.a ),gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。
5. 下面先生成目标程序main,然后运行main程序看看结果如何。
./main
please input year month day
2013 8 27
today is year's 239 num
二. 动态库
1. 由 .o 文件创建静态库(.so 文件)
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为mymath,则动态库文件名就是libmamath.so。用gcc来创建动态库。在系统提示符下键入以下命令得到动态库文件libmamath.so。
gcc -shared -fPCI -o libmyhello.so hello.o
2. 在程序中使用动态库
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。
gcc -o main main.c -L. -lmymonth
./main
./main: error while loading shared libraries:libmymath.so: cannot open shared object file: No such file or directory
出错了!!!
快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。
解决方法:
我们将文件libmyhello.so复制到目录/usr/lib中:
mv libmyhello.so /usr/lib/
运行:
./main
1 + 2 = 3
1 - 2 = -1
成功了。这也进一步说明了动态库在程序运行时是需要的。我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,来试试看。先删除除.c和.h外的 所有文件,恢复成我们刚刚编辑完举例程序状态。
gcc -c add.c
gcc -c sub.c
ar cr libmymath.asub.o add.o
gcc -shared -fPCI -o libmyhello.so hello.o
现在目录有两个同名的库文件(动态库文件和静态库文件同名):
libmymath.a libmymath.so
编译运行程序:
gcc -o main main.c -L. -lmymath
./main
./main: error while loading shared libraries:libmymath.so: cannot open shared object file: No such file or directory
从程序hello运行的结果中很容易知道,当Linux静态库和Linux动态库同名时, gcc命令将优先使用动态库。
Linux环境下c语言静态链接库和动态链接库创建和使用的更多相关文章
- linux下静态链接库和动态链接库
关于链接库的知识,网上太多资料了,但是并不代表我很熟悉.今天遇到了 一个问题,就是由于静态链接库和ubuntu系统不兼容导致的,虽然花了点时间才搞定 但是,其中暴露的问题也不少. 没有区分好静态链接库 ...
- [拾零]C/C++_代码复用的实现_静态链接库_动态链接库_使用.def导出
1 静态链接库 1.1 创建静态链接库: 1.在VC6中创建项目:Win32 Static Library 2.在项目中创建两个文件:xxx.h 和 xxx.cpp 3.编译 1.2 使用静态链接库 ...
- Linux环境下的编译,链接与库的使用
参考博客: http://www.cnblogs.com/qytan36/archive/2010/05/25/1743955.html http://m.blog.csdn.net/article/ ...
- Linux环境下C语言线程创建---简单代码
在Linux环境下用C语言编写线程创建. //file name: pthreadtext.c #include <stdio.h> #include <pthread.h> ...
- linux c静态链接库与动态链接库
库函数是我们编程的时候经常用到的,我们协作编程的时候可以将常用的函数封装成库供大家使用,这样能够提高大家的工作效率.对于库函数,它分为动态链接库和静态链接库.对于静态链接库我们必须是连接到可执行文件中 ...
- linux静态链接库与动态链接库详解
一顺便说说了哦 通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(e ...
- vc下的静态链接库与动态链接库(一)
一.静态库与动态库的区别 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Lib ...
- Makefile常用万能模板(包括静态链接库、动态链接库、可执行文件)
本文把makefile 分成了三份:生成可执行文件的makefile,生成静态链接库的makefile,生成动态链接库的makefile. 这些makefile都很简单,一般都是一看就会用,用法也很容 ...
- 介绍静态链接库和动态链接库的差别,及在VC++6.0中的建立和使用
首先介绍一下链接库:链接库分为动态链接库和静态链接库两种 LIB是静态链接库,在程序编译连接的时候是静态链接,其相应的文件格式是.lib. 即当程序採用静态链接库的时候..lib文件里的函数被链接到终 ...
随机推荐
- 【UOJ 79】 一般图最大匹配 (✿带花树开花)
从前一个和谐的班级,所有人都是搞OI的.有 n 个是男生,有 0 个是女生.男生编号分别为 1,…,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽.每个人至多属于 ...
- [HNOI2008]玩具装箱TOY --- DP + 斜率优化 / 决策单调性
[HNOI2008]玩具装箱TOY 题目描述: P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京. 他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器 ...
- 【MPI】矩阵向量乘法
输入作乘法的次数K 然后输入矩阵和向量的维度n 然后输入一个n维向量 然后输入K个n阶方阵 程序会给出该向量连续与此K个方阵做乘法后的结果 主要用了MPI_Gather, MPI_Allgather, ...
- 【最大独立集】BZOJ3175- [Tjoi2013]攻击装置
[题目大意] 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2, ...
- mac安装redis拓展
安装 下载源码 编译安装 添加拓展 添加权限重启 安装 在mac上安装了php7.1.7 php -m 查看安装的拓展,没有redis,以前可以brew install php71-redis简单命令 ...
- SpringBoot 解决时区问题
SpringBoot 解决时区问题 1.在启动类加上 @PostConstruct void setDefaultTimezone() { TimeZone.setDefault(TimeZone.g ...
- bzoj 1433: [ZJOI2009]假期的宿舍 -- 最大流
1433: [ZJOI2009]假期的宿舍 Time Limit: 10 Sec Memory Limit: 162 MB Description Input Output Sample Input ...
- redis实现简单延时队列(转)
继之前用rabbitMQ实现延时队列,Redis由于其自身的Zset数据结构,也同样可以实现延时的操作 Zset本质就是Set结构上加了个排序的功能,除了添加数据value之外,还提供另一属性scor ...
- python 3.x和2.x不同和改动
参考于http://www.runoob.com/python/python-2x-3x.html 因为这几天换了电脑,之前电脑里装的是python2.x,因为那时候刚学的时候,很多教程都是用2.x. ...
- 人脸检测:微软 VS Face++
近些年国内的人脸技术已经得到了很大的发展,今天网上无意看到了微软和face++两家公司的人脸检测,Face++号称国际顶尖的技术,也用过他们的接口感觉确实很不错,而微软则不再话下了.于是想对比微软和F ...