C语言库相关知识及简单库的制作

库即二进制形式的目标模块,使用库可以很方便对程序进行模块化设计,

方便对某些固定功能的重复使用,方便对某些功能进行更新。

库与.c文件关系如下图:

库分为两种类型,即静态库和动态库;

静态库扩展名.a ,库中封装的二进制代码,在链接阶段被复制到调用模块中,

调用模块运行时不再需要静态库的支持;

动态库扩展名.so ,库中封装的二进制代码,在链接阶段不会复制到调用模块,

被嵌入到调用模块中的仅仅是被调用函数在库中的相对地址,

因此,调用模块在运行时需要动态库的支持。

动态库和静态库相比,使用更为灵活,更常见。

库的制作:

静态库的制作:

第一步:编辑源程序,包括a.c a.h . . .

第二步:源程序编译成目标文件,gcc -c a.c  --->a.o . . .

第三步:打包目标文件,即把他们做成库,ar -r libxxx.a a.o b.o c.o . . .

ar命令解释:

格式:ar   [选项]    静态库名    目标文件列表

选项如下:

-r:将目标文件插入到静态库,若目标文件已存在,则更新

-q:将目标文件追加到静态库的末尾

-d:从静态库中删除指定的目标文件

-t:列表形式显示静态库中的目标文件

-x:将静态库展开为目标文件

动态库的制作:

第一步:编辑源程序,包括xxx.c xxx.h

第二步:编译成目标模块,gcc -fpic -c a.c . . .

-fpic:小模式,代码量小,速度快,只支持一部分平台,比如Linux

-fPIC:大模式,代码量较大,速度较慢,支持所有平台

第三步:链接成库,gcc -shared a.o . . . -o libxxx.so

库的使用:

1、直接调用法

gcc main.c libmath.a / gcc main.c libmath.so

2、参数调用法

gcc main.c -lmath -L. //-l库名    -L库所在路径

3、设置环境变量法

静态库设置方法:export LIBRARY_PATH=$LIBRARY_PATH:.

动态库设置方法:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

为了永久设置环境变量,可将上述语句写入~/.bashrc

gcc main.c -lmath

动态库的使用还可以利用Linux中的dl库实现动态加载

简单实例如下:

其中add和show是库中的函数,add 的功能是将两个数相加,返回结果;show 的功能是 printf 传进来的数

#include <stdio.h>
#include <dlfcn.h>
#include "math.h"  //动态库里的头文件
#include "show.h"  //动态库里的头文件

typedef int (*operation)(int,int);  //给函数类型 int (*) (int,int) 起别名operation
typedef void (*d_show)(int);

int main()
{
    int a,b;

    void *handle = dlopen("./libmath.so",RTLD_LAZY);  //获取库的句柄
    if(handle == NULL)
    {
        printf("%s\n",dlerror());
        return;
    }

    operation add = (operation)dlsym(handle,"add");  //“add”为库里面的函数,执行加法运算,该语句的作用是获取add函数在库里面的地址
    if(add == NULL)
    {
        printf("%s\n",dlerror());
        return;
    }

    d_show show = (d_show)dlsym(handle,"show");
    if(show == NULL)
    {
        printf("%s\n",dlerror());
        return;
    }

    printf("请输入两个整数:");
    scanf("%d %d",&a,&b);
    printf("%d + %d = ",a,b);
    show(add(a,b));  //show,add为本文件的变量,不是库里面的函数名

    dlclose(handle);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章