Linux动态链接库的生成和使用
目录
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库文件。
解决办法有几个:
将
libmyfunc.so放到gcc默认搜索目录,比如/usr/lib/x86_64-linux-gnu或者/lib/x86_64-linux-gnu都可以,这样做简单粗暴。但要是这样做的话,需要root权限来完成,除此之外,我感觉污染了整个系统。在
/etc/ld.so.conf.d目录下新建一个.conf文件,比如mylib.conf,在里面添加第三方库(libmyfunc.so)目录路径设置
LD_LIBRARY_PATH环境变量,比如export LD_LIBRARY_PATH=.。设置这个环境变量之后,操作系统将在先在LD_LIBRARY_PATH下搜索库文件,再到默认路径中搜索文件。这样,可执行文件就可以在LD_LIBRARY_PATH中找到第三方库(libmyfunc.so)的位置。编译的时候添加
-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. 参考资料
Linux动态链接库的生成和使用的更多相关文章
- 【ARM-Linux开发】linux下Eclipse进行C编程时动态链接库的生成和使用
linux下Eclipse进行C编程时动态链接库的生成和使用 引用 http://linux.chinaitlab.com/soft/864157.html 欢迎进入Linux社区论坛,与200万技术 ...
- Linux动态链接库的创建与使用
Linux动态链接库的创建与使用1. 介绍 使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数 ...
- Linux静态库生成指南
Linux静态库生成指南 Linux上的静态库,其实是目标文件的归档文件.在Linux上创建静态库的步骤如下: 写源文件,通过 gcc -c xxx.c 生成目标文件. 用 ar 归档目标文件,生 ...
- Linux Makefile自动生成--config.h
Linux Makefile自动生成--config.h http://blog.csdn.net/spch2008/article/details/12510805
- 在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序
在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序 本贴首发于: http://xuekaiyuan.com/forum.php?mod=vie ...
- Linux下随机生成密码的命令总结
有时候经常为如何设置一个安全.符合密码复杂度的密码而绞尽脑汁,说实话,这实在是一个体力活而且浪费时间,更重要的是设置密码的时候经常纠结.终于有一天实在忍不住了,于是学习.整理了一下如何使用Linux下 ...
- 使用linux perf工具生成java程序火焰图
pre.cjk { font-family: "Nimbus Mono L", monospace } p { margin-bottom: 0.1in; line-height: ...
- VS2010动态链接库的生成及调用(C++)
一.动态链接库的生成 首先利用VS2010新建一个空的工程或者win32工程 2.在工程中添加头文件和源文件 3.工程属性配置 3.1 可以在解决方案目录下新建以下几个文件夹 bin (用于存放Rel ...
- Linux动态库生成与使用指南
相关阅读: Linux静态库生成指南 Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件. 在链接动态库生成可执行文件时,并不 ...
随机推荐
- sql Server 2008 数据库自动备份维护计划
数据库中右键-‘管理’-新建维护计划 创建执行计划,设置备份时间 点击保存 完成 执行后报 ‘’错误5:拒绝访问 ’,时需到文件目录‘属性’→‘安全’设置用户的 ‘写入’ 权限
- 解释型语言VS编译型语言
前言 计算机不能直接理解除机器语言以外的语言,所以只有把程序员编写的程序翻译成机器语言,计算机才能够执行程序. 将其他语言翻译成机器语言的工具,被称之为:编译器. 编译器的翻译方式有两种:编译和解释. ...
- WPF的架构分析
首先,在这里我要说明的是:这里的例子,都是通过控制台程序来创建WPF应用,而非使用现成的WPF模版.因为WPF模版封装了创建WPF应用所需要的各种基本元素,并不利于我们学习. 创建一个WPF需要引用的 ...
- kvm虚拟化
1.kvm虚拟化介绍 什么是虚拟化 虚拟化就是通过模拟计算机硬件(cpu,内存,硬盘,网卡)来实现在一台物理服务器上运行同时多个不同的操作系统,并且使每个操作系统之间都是互相隔离的 为什么要学习虚拟化 ...
- ASP.NET Core 2.1与2.2 SignalR CORS 跨域问题
将 SignalR 集成到 ASP.NET Core api 程序的时候,按照官方 DEMO 配置完成,本地访问没有问题,但是发布之后一直报跨域问题,本地是这样设置的: Asp.net core 2. ...
- Pytorch实现UNet例子学习
参考:https://github.com/milesial/Pytorch-UNet 实现的是二值汽车图像语义分割,包括 dense CRF 后处理. 使用python3,我的环境是python3. ...
- Spring boot读取application.properties中文乱码
解决方案 在IDEA环境下: File -> Settings -> Editor -> File Encodings 将Properties Files (*.properties ...
- openstack第二章:glance
第二篇glance— 镜像服务 一.glance介绍: Glance是Openstack项目中负责镜像管理的模块,其功能包括虚拟机镜像的查找.注册和检索等. Glance提供 ...
- RB-Tree插入过程详解
红黑树具有很优秀的特性,其自平衡性特性,局部调整特性使得红黑树插入,删除,以查找,以及这些过程的内存资源的占用,的综合性能是非常高的(通常我们会拿红黑树和AVL树进行对比). 对于红黑树的这些特性,在 ...
- 微信小程序-表单笔记2
本地添加4张图片并显示至页面——组件位置.设置样式.列表渲染 Q.button是一张图片,需要实现点击这张图片后选择本地图片后显示至页面,不知道怎么让本地图片将button挤到右边 S.在wxml中 ...