Linux拓展:链接库

这篇具有很好参考价值的文章主要介绍了Linux拓展:链接库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.说明

本篇博客介绍Linux操作系统下的链接库相关知识,由于相关概念已在Windows下链接库一文中介绍,本篇博客直接上操作。

二.静态链接库的创建和使用

1.提前看

这里主要介绍的是C语言的链接库技术,而在Linux下实现C语言程序,需要你的虚拟机的WSL具有GCC编译器,如果你不了解,可以看Linux下实现C语言程序

2.静态链接库的创建

前提:准备好要编译的 .c 库文件和 .h 头文件,具体是是什么,请查看Windows下链接库

基本步骤:

  • 1.执行gcc -c myMath.c -o myMath.o 文件
  • 2.使用ls命令查看上一步是否成功
  • 3.使用ar rcs libmyMath.a myMath.o 将所有目标文件打包为一个静态链接库(这里是以一个为例,命令下面介绍)
  • 4.使用ls命令查看上一步是否成功

没错,就这几步,你就简单的实现 静态链接库的建立了。

3.静态链接库的使用

静态链接库的用法很简单,就是和其它目标文件一起参与链接,最终生成一个可执行文件。

基本步骤:

  • 1.同目录下再创建一个 main.c 文件
  • 2.利用vim编辑器正常编写代码
  • 3.利用gcc编译命令实现编译成.o文件
  • 4.开始链接

第四步的链接命令有两种:

 gcc -static main.o libmyMath.a -o main                       <-- 第 1 种
 gcc main.o -o main -static -lmyMath -L /home/test/myMath     <-- 第 2

上面两种如果不行,可以使用:

 gcc -L /usr/lib main.o libmymath.a -o main

注意:里面的文件名和路径都要改成你自己文件名和路径,即不变色部分需要修改。

4.演示

Linux拓展:链接库

三.动态链接库的创建与使用

1.提前看

Windows 平台上生成动态链接库时,需要用__declspec(dllexport)显式地“告诉”编译器哪些函数和变量能被外界调用,这些函数和变量的信息(名称、存储位置)保存在引入库文件(.lib)中,而它们的定义保存在动态链接库文件(.dll)中。

与前者不同,Linux 平台上不再需要生成引入库文件,原因很简单,默认情况下动态链接库中定义的所有函数和变量都允许被外界调用。或者说,动态链接库中不仅保存了所有函数和变量的定义,还保存了能被外界调用的所有函数和变量的信息,所以不需要生成引入库文件。

2.动态链接库的建立

前提和静态链接库一样,需要一个.h文件和.c文件

基本步骤:

  • 1.执行命令 gcc -shared -fPIC myMath.c -o libmyMath.so
  • 2.使用ls命令查看上一步结果

有libmyMath.so文件即成功建立

3.动态链接库的使用

基本步骤:

  • 1 将 main.c 与 myMath.h 放在同一目录,向 main.c 文件中引入 myMath.h 头文件
  • 2.执行gcc main.c libmymath.so -o main.exe命令
  • 3.使用ls命令查看上一步结果结果

4.补充注意

相比之下,你是不是以为和windows相比,Linux下动态链接库既然比静态链接库如此简单,那么你可以试着运行静态链接库和动态链接库最后的可执行文件,你会发现报错:./main.exe: error while loading shared libraries: libmyMath.so: cannot open shared object file: No such file or directory

这是因为执行main.exe文件时,需要调动所有动态链接库及其存储位置,而其中 libmyMath.so 文件的存储位置系统并不直到,有下面几种解决方式:

  • 将链接库文件移动到标准库目录下(例如 /usr/lib、/usr/lib64、/lib、/lib64);
  • 在终端输入export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx,其中xxx为动态链接库文件的绝对存储路径(此方式仅在当前终端有效,关闭终端后无效);
  • 修改~/.bashrc~/.bash_profile文件,即在文件最后一行添加export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxxxxx为动态库文件的绝对存储路径)。保存之后,执行source .bashrc指令(此方式仅对当前登陆用户有效)。

接下来你重新运行即可成功。

5.演示

Linux拓展:链接库

四.补充知识点

1.建立动态链接库

使用gcc -shared -fPIC myMath.c -o libmyMath.so命令

gcc 命令中,各个选项的含义是:

  • -shared:表示生成动态链接库;
  • -fPIC:也可以写成 -fpic,功能是令 GCC 编译器生成动态链接库时,用相对地址表示库中各个函数和变量的存储位置。这样做的好处是,无论动态链接库被加载到内存的什么位置,都可以被多个程序(进程)同时调用;(无论怎样,你都加上)
  • -o libmyMath.so:-o 选项用于指定生成文件的名称,此命令最终生成的动态链接库文件的文件名为 libmyMath.so。

Linux 平台上,动态链接库文件的命名格式为 libxxx.so,其中 xxx 部分可以自定义。

2.ar

ar 是一个用于创建静态库的命令行工具。

语法:ar rcs libname.a file1.o file2.o file3.o

其中 libname.a 是要创建的库的名称,.a 表示这是一个静态库文件。

file1.o, file2.o, file3.o 是包含目标代码的文件,你可以指定任意数量的文件来创建库。

r, c, 和 s 选项都是必须的,表示:

  • r: 将新的目标文件添加到库中或者替换库中已有的同名文件。
  • c: 如果库不存在则创建它。
  • s: 在库中为每个成员生成符号表。

需要注意的是,Linux 平台上静态链接库的名称不是随意的,通常遵循 libxxx.a 格式,xxx 部分可以自定义。

五.动态链接库的显示调用

Linux 平台下,动态加载库的装载、使用、卸载等操作需要借助以下 4 个函数来完成,使用它们时需要引入<dlfcn.h>头文件。

1.dlopen():打开库文件

语法:void *dlopen(const char *filename, int flag);

其中,filename 参数是共享库文件的路径名,可以是绝对路径或相对路径;flag 参数是一个标志位,用于指定 dlopen() 的行为,可以是以下值之一:

  • RTLD_LAZY:表示在 dlopen() 返回句柄后,只有在需要时才解析符号。
  • RTLD_NOW:表示在 dlopen() 返回句柄前,解析所有符号。
  • RTLD_GLOBAL:表示将库中的符号添加到全局符号表中,以便其他库可以使用这些符号。
  • RTLD_LOCAL:表示不将库中的符号添加到全局符号表中,而是将其限制在当前库中。

成功调用 dlopen() 函数将返回一个非空的句柄,失败则返回 NULL。通过句柄可以使用 dlsym() 函数获取共享库中的符号地址,使用 dlclose() 函数关闭句柄并卸载共享库。

2. dlsym():从库文件中找到要调用的资源

语法:void *dlsym(void *handle, const char *symbol);

其中,handle 参数是由 dlopen() 返回的共享库句柄,symbol 参数是要查找的符号名称(字符串类型),可以是函数名、变量名或其他标识符。

如果成功找到该符号,则 dlsym() 将返回该符号的地址(指向函数或变量的指针)。否则,dlsym() 将返回 NULL。

3. dlclose():关闭打开的库文件

语法:int dlclose(void *handle);

其中,handle 参数是由 dlopen() 返回的共享库句柄。成功调用 dlclose() 函数将返回零,表示函数调用成功。失败则返回非零值,表示出现错误。

4.例子

#include <stdio.h>
#include <dlfcn.h>

int main() {
    // 打开共享库
    void *handle = dlopen("libmylib.so", RTLD_NOW);

    if (handle == NULL) {
        fprintf(stderr, "Error: %s\n", dlerror());
        return 1;
    }

    // 查找符号
    int (*my_func)(int) = (int (*)(int))dlsym(handle, "my_func");

    if (my_func == NULL) {
        fprintf(stderr, "Error: %s\n", dlerror());
        dlclose(handle);
        return 1;
    }

    // 调用函数
    int result = my_func(42);
    printf("Result: %d\n", result);

    // 关闭共享库
    int close_result = dlclose(handle);

    if (close_result != 0) {
        fprintf(stderr, "Error: %s\n", dlerror());
        return 1;
    }

    return 0;
}

上面的代码打开名为 libmylib.so 的共享库,查找其中名为 my_func 的函数,并调用该函数,最后关闭共享库。这里假设 libmylib.so 中包含一个名为 my_func 的函数,它接受一个 int 类型的参数并返回一个 int 类型的值。

需要注意的是,上面的代码中使用了 dlerror() 函数来获取错误信息。当 dlopen()、dlsym() 或 dlclose() 发生错误时,可以通过调用 dlerror() 函数来获取具体的错误信息。

六.总结

这就是Linux下链接库的知识了,为后面介绍makefile做基础,可以结合windows下链接库一起观看。文章来源地址https://www.toymoban.com/news/detail-440357.html

到了这里,关于Linux拓展:链接库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AXI_UART调试说明-PS使用AXI_Uartlite拓展PL端串口资源

    ** ** 注:本例程是在xc7z010clg400_1实现,若导入至复旦微电子需更改为xc7z045iffg900-2L (目录中带*号的可略过) 背景:PS端UART资源有限,难以满足实际运用中多串口的需求。 具体方法:PS通过AXI总线调用PL的资源进行UART的拓展,本说明采用vivado自带的IP核AXI Uartlite完成,属于AX

    2024年02月05日
    浏览(111)
  • 基于.NetCore开发博客项目 StarBlog - (28) 开发友情链接相关接口

    之前介绍的友情链接功能,只实现了友情链接的展示和管理接口。 还缺失友情链接申请、审核管理、通知,现在把这块功能补全。 Model 什么的之前那篇文章都有,本文直接补全逻辑代码~ 详见: 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能 友情链接申请页面 实现一

    2024年02月06日
    浏览(50)
  • 使用SSM框架基于SpringBoot的个人博客+源代码+文档说明

    点击这里下载源码 项目介绍 通过从零开始搭建整个项目,了解整个开发流程,如何设计,如何实现,一步步发现,一步步解决。系统的运用SpringBoot与它集成的各种框架,对于学习了SpringBoot却没有实际运用的人是一个很好的练手项目。 主要技术与框架 项目构建:Maven web框架

    2024年02月03日
    浏览(57)
  • static、extern、inline 说明符和链接属性

    在我初学 C++ 时, static 、 inline 、 extern 可能是最令我迷惑的 C++ 说明符,原因是它们在不同的语境下会发挥不同的作用,而且某些说明符的含义已经和以前不同,这加剧了我在查询资料时的困扰。所以今天决定好好总结一下。 首先要介绍 C++ 的两个概念: 存储期 和 链接 。

    2024年02月05日
    浏览(78)
  • 【Linux】常见指令收官&&拓展

    Linux下find命令在目录结构中搜索文件,并执行指定的操作。 Linux下find命令提供了相当多的查找条件,功能很强大。由于find具有强大的功能,所以它的选项也很多。这里我们只说了-name选项 在运行一个非常消耗资源的find命令时,很多人都倾向于把它放在后台执行,因为遍历一

    2024年02月12日
    浏览(41)
  • 初入公司用不好git ?-- 本篇针对GitLab

    本篇并不涉及git的所有知识,内容包括工作中每天用到的以及需要知道的 一、从远程仓库拉取指定分支到本地仓库,并创建个人分支  二、(补充)基于以上补充几点基础知识点以便你更好理解并实践 1. 主分支:通常是master分支 2. 开发分支:基于主分支派生,你通常在这个

    2024年02月05日
    浏览(48)
  • TF060N03M规格书|TF060N03M 参数说明|用于Type-C转HDMI拓展坞转换器N-MOS

    TF060N03M规格书|TF060N03M 参数说明|用于Type-C转HDMI拓展坞转换器N-MOS TF060N03M是一款专门用于USB TYPEC转换器的MOS。TF060N03M采用先进的沟槽技术,提供出色的RDS(ON)、低栅极电荷和低至2.5V的栅极电压。该装置适用于电池保护或其他开关应用。 TF060N03M产品形态: TF060N03M特征 先进的器

    2023年04月08日
    浏览(38)
  • 微信小程序web-view使用说明,及链接打不开问题

             开发微信小程序时,有时会需要在小程序内打开网页链接,这时就需要用到 web-view 标签。web-view 是小程序上用来承载网页的容器,且每个页面只能有一个 web-view,它会自动铺满整个页面,并覆盖其他组件。目前个人类型的小程序上不支持使用。         在小程

    2024年02月09日
    浏览(91)
  • MySQL笔记——MySQL数据库介绍以及在Linux里面安装MySQL数据库,对MySQL数据库的简单操作,MySQL的外接应用程序使用说明

    MySQL笔记——MySQL数据库介绍以及在Linux里面安装MySQL数据库,对MySQL数据库的简单操作,MySQL的外接应用程序使用说明 MySQL笔记——表的分组查询、表的分页查询、表的约束、数据库设计 MySQL案例——多表查询以及嵌套查询 MySQL笔记——数据库当中的事务以及Java实现对数据库进

    2024年01月16日
    浏览(75)
  • Visual Studio(2022)生成链接过程的.map映射文件以及.map映射文件的内容说明

    /MAP(生成映射文件) | Microsoft Learn         1. 右键项目属性, 连接器 - 常规 - 启用增量链接,设置为否。如下图:         2. 连接器 - 调试                 生成调试信息  设置为  生成调试信息 (/DEBUG)                 生成程序数据库文件  设置为 指定路径文件名,

    2024年02月10日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包