前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux下库文件制作方法详解

Linux下库文件制作方法详解

作者头像
Linux兵工厂
发布2023-02-28 13:44:40
2.1K0
发布2023-02-28 13:44:40
举报
文章被收录于专栏:Linux兵工厂

大家好,继上节<Linux库详解>,这节我们继续讲解如何在Linux系统上创建我们需要的库文件

  • 在创建程序库之前,需要先来了解GCC的一些参数,因为静态库和共享库需要GCC工具产生,并且两者的GCC参数不同。

参数

含义

-c

激活预处理、编译和汇编,把程序做成目标文件(.o文件)

-g

在编译的时候产生调试信息

-Wall

生成警告信息

-l

指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称

-L

表示要连接的库目录

-fPIC

表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码,概念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方

-shared

生成动态链接库

我们编写两个函数并将文件制作成库文件,用下面相同的代码分别制作静态库和共享库

Test.h文件

代码语言:javascript
复制
#ifndef _TEST_H_ 
#define _TEST_H_  

int add(int a, int b);
int sub(int a, int b);

#endif

Test.c文件

代码语言:javascript
复制
#include <stdio.h>
#include "Test.h"

int add(int a, int b)
{
    return (a+b);
}

int sub(int a, int b)
{
    return (a - b);
}

制作静态库

    1. 首先生成.o目标文件
代码语言:javascript
复制
gcc -c Test.c
    1. ar命令将目标文件生成.a静态库文件
代码语言:javascript
复制
ar -cr libTest.a Test.o // 遵循静态库命名的规则 lib + 名字 + .a

-c create的意思 -r replace的意思,表示当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。

    1. 静态库调用
代码语言:javascript
复制
#include <stdio.h>

#include "Test.h"

int main(int argc, char const *argv[])
{
    int nAdd = add(1, 2);
    printf("nAdd: %d\n", nAdd);

    int nSub = sub(2, 1);
    printf("nSub: %d\n", nSub);

    return 0;
}
代码语言:javascript
复制
gcc -o main main.c -lTest -L.

-l 指定了静态函数库名,由于静态函数库的命名方式是lib***.a,其中的lib和.a忽略 -L 指定静态函数库的查找目录,L后面'.',表示静态函数库在本目录下查找

制作共享库

  • 生成共享库
代码语言:javascript
复制
// 用下面两个命令
gcc -fPIC -o libTest.o -c Test.c
gcc -shared -o libTest.so libTest.o

// 或用下面一个命令
gcc -shared -fpic -o libTest.so Test.c

-fpic:产生位置无关代码 -shared:生成共享库

  • 共享库调用
代码语言:javascript
复制
#include <stdio.h>

#include "Test.h"

int main(int argc, char const *argv[])
{
    int nAdd = add(1, 2);
    printf("nAdd: %d\n", nAdd);

    int nSub = sub(2, 1);
    printf("nSub: %d\n", nSub);

    return 0;
}

代码语言:javascript
复制
gcc -o main-so main-so.c -lTest -L.
  • 执行可执行程序

在执行可执行程序时,出现以下错误,说找不到库文件,在继续往下看之前大家想想这是为什么?

因为在动态函数库使用时,会查找/usr/lib、/lib目录下的动态函数库,而此时我们生成的库不在里边。我们可以通过以下方法解决此问题,其实这个问题在上一节中我们提到过,小伙伴可以回看一下。

1.最直接最简单的方法就是把libTest.so拷贝到/usr/lib或/lib中去。

2.设置环境变量,假设libTest.so在/home/ubuntu/workspace_ex/lib/static目录下

代码语言:javascript
复制
export LD_LIBRARY_PATH=/home/linux/addsub:$LD_LIBRARY_PATH

3.另外还可以在/etc/ld.so.conf文件里加入我们生成的库的目录,然后/sbin/ldconfig /etc/ld.so.conf是非常重要的一个目录,里面存放的是链接器和加载器搜索共享库时要检查的目录,默认是从/usr/lib /lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig

动态加载库

上面共享库的调用属于动态链接方法,此外我们还可以动态加载,在上一节中我们讲过二者的区别,此处不做过多讲解。动态加载需要用到系统API函数

接口

描述

dlopen

打开对象文件,可被程序访问

dlsym

获取执行了dlopen函数的对象文件中的符号的地址

dlerror

返回上一次出现的错误

dlclose

关闭目标文件

调用过程

代码语言:javascript
复制
#include <stdio.h>
#include <dlfcn.h>

#include"Test.h"

int main(int argc, char const *argv[])
{
    void *dlHandler = NULL;
    int(*Func)(int,int);
    char *Error;
    int  nAdd;

    dlHandler = dlopen("libTest.so", RTLD_LAZY);
    if(!dlHandler)
    {
        printf("dlopen:%s\n", dlerror());
        return 0;
    }

    Func = dlsym(dlHandler, "add");

    Error = dlerror();
    if(Error != NULL)
    {
        printf("find:%s\n",Error);
        return 0;
    }

    nAdd = (*Func)(1, 2);
    printf("add = %d\n",nAdd);

    dlclose(dlHandler);
    return 0;
}
代码语言:javascript
复制
gcc -o main-dl main-dl.c -ldl

-ldl 表明将 dllib 链接于该程序,即可调用DL的API

共享库文件放置与共享库调用时操作一样

结束语

到目前为止,我们详细讲解了Linux下制作静态库、共享库、以及动态加载库,希望通过此文对你在Linux库的认识有所帮助,那么目的就达到了

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linux兵工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 制作静态库
  • 制作共享库
  • 动态加载库
  • 结束语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档