库有动态与静态两种,动态通常用.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语言静态链接库和动态链接库创建和使用相关推荐

  1. C语言静态链接库和动态链接库讲解及制作使用

    C语言静态链接库和动态链接库讲解及制作使用 1. 引言 静态链接库和动态库均为函数库 函数库:不是C语言的一部分,是一些事先写好的函数的集合,给别人复用 就像scanf和printf函数一样,通过#i ...

  2. c语言Linux用线程创建文件,Linux环境下C语言线程创建---简单代码

    在Linux环境下用C语言编写线程创建. //file name: pthreadtext.c #include #include //线程头文件 //pthread不是linux下的默认的库,也就是 ...

  3. 静态链接库与动态链接库详解

    以下内容源于C语言中文网相关内容的学习整理,如有侵权请告知删除. 一.库文件的简介 库文件,其等价为压缩包文件.该文件内部通常包含不止一个目标文件(也就是二进制文件),每个目标文件存储的代码,并非完整 ...

  4. 静态链接库、动态链接库和动态加载库

    前言 静态库是obj文件的一个集合(目标文件中通常仅解析了文件内部的变量和函数,对于引用的函数和变量还没有解析,这需要将其他已经编写好的目标文件引用进来,将没有解析的函数和变量进行解析,通常引用的目标 ...

  5. Linux下的静态链接库和动态链接库编程

    Linux下的静态链接库和动态链接库编程 参考: Linux下的静态链接库和动态链接库编程 - Histring - 博客园 Mac下静态库和动态库的创建和使用_C/C++_vincent2610的专 ...

  6. Linux下的静态链接库和动态链接库

    Linux下的静态链接库和动态链接库 零.链接库概述 Linux下得库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀.面对比一下两者: 静态链接库:当要使用时,连接器会找出程序所需的函数, ...

  7. linux下静态链接库和动态链接库

    关于链接库的知识,网上太多资料了,但是并不代表我很熟悉.今天遇到了 一个问题,就是由于静态链接库和ubuntu系统不兼容导致的,虽然花了点时间才搞定 但是,其中暴露的问题也不少. 没有区分好静态链接库 ...

  8. cnsl是什么意思_VS2010下创建静态链接库和动态链接库

    VS2010下创建静态链接库和动态链接库 类封装成dll如果你的工作长期与某个领域相关,比如说长期做直接体绘制 (DVR)方面的开发,那么你可能经常使用自己的传递函数类,如果每一个工程你都把传递函数类 ...

  9. UNIX环境高级编程(三)—— 静态链接库与动态链接库

    动态链接库一般不开放源码,需要建工程才能使用(其中提供的接口和 API): 0. .a/.o/.so What are .a and .so files? .o 就相当于 windows 里的 obj ...

最新文章

  1. 【Android View基础】View中几个容易混淆的距离及坐标量
  2. 深度学习arm cache系列--一篇就够了
  3. 关于oracle数据库的操作的命令
  4. 软件与软件工程的概念
  5. (已解决)wamp + Apache报错:出现403Forbidden You don't have permission to access / on this server.
  6. 十字链表 java_十字链表法,十字链表压缩存储稀疏矩阵详解
  7. linux离线安装mysql8
  8. VB基础知识整理——没干货哪敢打扰你
  9. vscode 历史版本1.68.1
  10. 栈的应用(三)之C语言实现逆波兰表达式
  11. 怎样设置CCProxy
  12. 独家 | 维信金科申请消费金融牌照未果
  13. codewars练习(javascript)-2021/1/24
  14. There is no getter for property named ‘pCode‘ in ‘classXXX‘
  15. 《你不懂我,我不怪你》 作者:余秋雨
  16. 关机时候计算机更新,电脑关机时提示更新,能否强制关机?
  17. SAP HANA基本数据类型
  18. 023货仓选址(绝对值不等式)
  19. 快速入门 | 篇十三:正运动技术运动控制器ZDevelop 编程软件的使用
  20. uniapp开发使用uni-icons添加自定义图标

热门文章

  1. sql 相加_SQL-多表查询
  2. linux 的ss看进程号,linux ss命令详解
  3. mysql 事务id_[转]MySQL 5.6 全局事务 ID(GTID)实现原理(一)
  4. 常用的linux命令与示例,linux常用命令及用法示例
  5. 智能视觉组参赛总结及体会- 西安邮电大学 - AI小布丁
  6. 2020年全国大学生智能汽车竞赛山东赛区比赛专家组工作方案
  7. 基于STC8G1K17的信号转换方案
  8. mysql使用中遇到的问题吗_MySQL使用中遇到的问题及解决办法
  9. win10 Linux子系统 交叉编译器注意事项
  10. 随机抽样java_Reservoir Sampling 蓄水池抽样算法,经典抽样