目录

1. 编写C程序

  • 比如编写myfunc.c文件,里面包含两个函数,一个是say_hello,另一个是cal_sum
#include "myfunc.h"

void say_hello()
{
printf("hello world\n");
} int cal_sum(int x, int y)
{
return x + y;
}
  • myfunc.c编写接口文件
#ifndef __MY_FUNC_H
#define __MY_FUNC_H #include <stdio.h>
#include <stdlib.h> void say_hello();
int cal_sum(int x, int y); #endif

2. 编译动态链接库

  • 首先编译myfunc.c
gcc -c -fPIC -o myfunc.o myfunc.c

-c 表示只编译(compile),而不链接,输出目标文(obj文件)。

-o 表示输出文件的文件名。

-fPIC PIC指Position Independent Code, 生成适合在共享库中使用的与位置无关的代码。编译成共享库要求此选项。适用于动态链接并避免对全局偏移表大小的任何限制。

  • 生成共享库文件libmyfunc.so
gcc -shared myfunc.o -o libmyfunc.so

-share 生成一个共享对象,然后可以与其他对象链接以形成可执行文件。

两条命令合成一条就是:

gcc -fPIC -shared myfunc.c -o libmyfunc.so

3. 使用共享库

接下来我们使用test.c来调用共享库。test.c内容如下:

#include "myfunc.h"

int main(int argc, char const *argv[])
{
int result = 0; say_hello();
result = cal_sum(2, 3);
printf("%d\n", result); return 0;
}

编译上述包含.h头文件的程序,GCC编译器需要知道头文件的位置

  • 对于#include <...>,GCC编译器会在默认include搜索路径中寻找。
  • 对于#include "...",GCC编译器会在当前路径搜索.h文件。你也可以使用-I选项提供额外的搜索路径,比如-I /home/test/

除此之外,GCC编译器还需要知道我们用了哪个库文件,库文件在哪里

  • 使用-l选项说明库文件的名字。这里,我们使用的是libmyfunc.so库文件,所以选项是这样写的:-l myfunc
  • 使用-L选项说明库文件的路径。这里,我们的库文件是在当前路径,所以选项是这样写的:-L .(.表示当前路径)。

所以,最终我们链接库文件生成的可执行文件命令是这样的:

gcc -o test test.c -l myfunc -L .

附加:

可以使用下面的命令,来获知系统的include默认搜索路径:

$ gcc -print-prog-name=cc1 -v

获知库默认搜索路径:

$ gcc -print-search-dirs

4. 执行程序

$ ./test

执行程序后发现出现这样的情况:

./test: error while loading shared libraries: libmyfunc.so: cannot open shared object file: No such file or directory

这是因为执行程序的时候,操作系统不知道libmyfunc.so的位置,系统无法找到libmyfunc.so库文件。尽管我们用GCC编译的时候,用-L选项提供了libmyfunc.so文件的位置,但是这个信息并没有被写入到可执行程序里面。下面用命令ldd命令测试(ldd命令是用于显示可执行文件所依赖的库):

$ ldd test

    linux-vdso.so.1 =>  (0x00007ffccc9fe000)
libmyfunc.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0d31a44000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0d31e0e000)

可以看出可执行文件test无法找到libmyfunc.so库文件。

解决办法有几个:

  1. libmyfunc.so放到gcc默认搜索目录,比如/usr/lib/x86_64-linux-gnu或者/lib/x86_64-linux-gnu都可以,这样做简单粗暴。但要是这样做的话,需要root权限来完成,除此之外,我感觉污染了整个系统。

  2. /etc/ld.so.conf.d目录下新建一个.conf文件,比如mylib.conf,在里面添加第三方库(libmyfunc.so)目录路径

  3. 设置LD_LIBRARY_PATH环境变量,比如export LD_LIBRARY_PATH=.。设置这个环境变量之后,操作系统将在先在LD_LIBRARY_PATH下搜索库文件,再到默认路径中搜索文件。这样,可执行文件就可以在LD_LIBRARY_PATH中找到第三方库(libmyfunc.so)的位置。

  4. 编译的时候添加-Wl,-rpath选项,比如gcc -o test test.c -l myfunc -L . -Wl,-rpath=.-Wl选项告诉编译器将后面的参数传递给链接器

最后运行可执行文件test的结果:

$ gcc -o test test.c -l myfunc -L . -Wl,-rpath=.
$ ./test
hello world
5

5. 参考资料

  1. C编译: 动态连接库 (.so文件)
  2. Linux动态库生成与使用指南
  3. Linux 动态库剖析
  4. Linux动态链接
  5. 运行时动态库:not found 及介绍-linux的-Wl,-rpath命令

Linux动态链接库的生成和使用的更多相关文章

  1. 【ARM-Linux开发】linux下Eclipse进行C编程时动态链接库的生成和使用

    linux下Eclipse进行C编程时动态链接库的生成和使用 引用 http://linux.chinaitlab.com/soft/864157.html 欢迎进入Linux社区论坛,与200万技术 ...

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

    Linux动态链接库的创建与使用1. 介绍     使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数 ...

  3. Linux静态库生成指南

    Linux静态库生成指南   Linux上的静态库,其实是目标文件的归档文件.在Linux上创建静态库的步骤如下: 写源文件,通过 gcc -c xxx.c 生成目标文件. 用 ar 归档目标文件,生 ...

  4. Linux Makefile自动生成--config.h

    Linux Makefile自动生成--config.h http://blog.csdn.net/spch2008/article/details/12510805

  5. 在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序

    在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序 本贴首发于: http://xuekaiyuan.com/forum.php?mod=vie ...

  6. Linux下随机生成密码的命令总结

    有时候经常为如何设置一个安全.符合密码复杂度的密码而绞尽脑汁,说实话,这实在是一个体力活而且浪费时间,更重要的是设置密码的时候经常纠结.终于有一天实在忍不住了,于是学习.整理了一下如何使用Linux下 ...

  7. 使用linux perf工具生成java程序火焰图

    pre.cjk { font-family: "Nimbus Mono L", monospace } p { margin-bottom: 0.1in; line-height: ...

  8. VS2010动态链接库的生成及调用(C++)

    一.动态链接库的生成 首先利用VS2010新建一个空的工程或者win32工程 2.在工程中添加头文件和源文件 3.工程属性配置 3.1 可以在解决方案目录下新建以下几个文件夹 bin (用于存放Rel ...

  9. Linux动态库生成与使用指南

    相关阅读: Linux静态库生成指南 Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件. 在链接动态库生成可执行文件时,并不 ...

随机推荐

  1. SQL Server中将多行数据拼接为一行数据(一个字符串)

    表A中id与表B中aid为一对多的关系 例如: 表A: id name a1 tom a2 lily a3 lucy 表B: id aid value b1 a1 B1 b2 a1 B2 b3 a2 ...

  2. 一个特殊的SQL Server阻塞案例分析

    上周,在SQL Server数据库下面遇到了一个有意思的SQL阻塞(SQL Blocking)案例.其实个人对SQL Server的阻塞还是颇有研究的.写过好几篇相关文章. 至于这里为什么要总结一下这 ...

  3. Vcenter 账户密码过期设置修改

    Vcenter 安装完后,账户的密码过期时间是90天,如果不进行修改90天后就会过期,不能登录,这样对日常的定时任务影响比较大. 如何进行修改呢? 对于Vcenter 6.0 ,修改密码过期设置只能使 ...

  4. Python 爬虫基础Selenium

    https://blog.csdn.net/weixin_36279318/article/details/79475388

  5. WPF效果(GIS三维续篇)

    去年这个时候简单的摸索了一下三维的GIS相关的东西,也就是仅仅玩耍了一把,这次来点真正用的上的干货效果效果: 1.加载自定义百度样式的瓦片效果 2.加载自定义百度样式的缩放效果 3.快速手动进去咱的大 ...

  6. 我用Python爬取了李沧最近一年多的二手房成交数据得出以下结论

    前言 去年年底,博主有购房的意愿,本来是打算在青岛市北购房,怎奈工作变动,意向转移到了李沧,坐等了半年以后,最终选择在红岛附近购置了期房. 也许一些知道青岛红岛的小伙伴会问我,为什么会跑到那鸟不拉屎的 ...

  7. filebeat-6.4.3-windows-x86_64输出Kafka

    配置filebeat.yml文件 filebeat.prospectors: - type: log encoding: utf- enabled: true paths: - e:\log.log ...

  8. mysql-笔记-类型转化

    1 concat() 隐式转化为字符串 2 cast( 1 as char) 显示转化 3 比较中的隐式转化 null 与任何值比例都是null : 除了使用 null-safe <=> ...

  9. 初始ajax技术

    一.AJAX是啥? 1.页面无需刷新,异步请求. 2.为什么使用ajax? 原因: 1传统模式  需要将请求发送到服务器,服务器经过业务处理,返回一个页面给客户端.这样做,会很浪费资源. 2.ajax ...

  10. 快速搭建一个vue开发环境

    常规的搭建就是从npm到vue到webpack这样一个一个的来,这样一套下来说不上复杂但是也不简单.之前公司的vue后台项目 我还是写的轻车熟路的,因为前端同事已经把架子搭好了,环境配置的丝般顺滑,你 ...