- 浏览: 369767 次
- 性别:
- 来自: 苏州
文章分类
- 全部博客 (335)
- C++ (190)
- 设计模式 (43)
- 数据库技术 (5)
- 网络编程 (11)
- 自动化测试 (6)
- Linux (13)
- OpenSSL (10)
- MS Crypt API (5)
- SCM (2)
- English (4)
- Android (10)
- EMV规范 (1)
- Saturn Platform (0)
- C (10)
- SQL (2)
- ASP.NET (3)
- 英语口语学习 (3)
- 调试工具 (21)
- 编译技术 (5)
- UML (1)
- 项目管理 (5)
- 敏捷开发 (2)
- Http Server (6)
- 代码审查、代码分析 (5)
- 面试基础 (10)
- 重点知识 (16)
- STL (6)
- Efficient C++资料 (8)
- 数据结构和算法 (7)
- 读书笔记 (0)
- 开源项目 (4)
- 多线程 (2)
- Console App (6)
- 个人开源项目 (4)
- IBM DevelopWorks (4)
- Java (16)
- 内存泄漏相关调试和检测 (13)
- 软件测试相关技术 (2)
- C# (11)
- Apple Related (1)
- 软件测试和管理 (2)
- EMV (1)
- Python (1)
- Node.js (6)
- JavaScript (5)
- VUE (1)
- Frontend (1)
- Backend (4)
- RESTful API (3)
- Firebase (3)
最新评论
-
u013189503:
来个密码吧
[C++][Logging] 项目中写日志模块的实现 -
wyf_vc:
来个密码啊!!
[C++][Logging] 项目中写日志模块的实现
Linux下静态、动态库(隐式、显式调用)的创建和使用及区别
转自http://blog.csdn.net/star_xiong/article/details/17301191
一、静态链接库的创建与使用:
1、编写add.c 及main.c代码:
/**************************************************************************/
/*add.c*/
int add(int x, int y)
{
return x + y;
return 0;
}
/*************************************************************************/
然后add.h代码为:
/*add.h*/
#ifndef _ADD_H_
#define _ADD_H_
int add(int, int);
#endif
/***************************************************************************/
main函数代码:
/*main.c*/
#include <stdio.h>
int main(void)
{
printf("2+3= %d\n", add(2,3));
return 0;
}
/**********************************************************************************/
2、现在首先要明确我们目的是将add.c做成静态链接库,然后main.c调用生成的静态链接库中的add()
(1)将add.c做成静态链接库(创建静态库):
首先将add.c编译成目标文件(add.o文件),如下:
#gcc -c add.c //生成add.o
然后将生成的目标文件(add.o)生成静态库libadd.a:
#ar crv libadd.a add.o //生成libadd.a
(2)静态库做好了,就可以在编译main.c时将静态库链接进去了,接下来就编译生成可执行文件(静态库的使用):
#gcc -o exe main.c
-I. -L. -ladd
//或者 #gcc -o exe main.c ./libadd.a
//再或者#gcc -o exe main.c -L. libadd.a
(注:这里的-I/路径, -L/路径, 是通过-I和-L指定对应的库文件名和库文件的路径,这里就是当前目录,
libadd.a就是要用的静态库,这样对应的静态库已经编译到对应的可执行程序中。执行对应的可执行文件
便可以得到对应函数调用的结果。在main.c中不需要包含导出文件的头文件。
上面的(2)分开就是:
1)编译生成对应的目标文件:
#gcc -c -I/home/hcj/xxxxxxxx main.c
2)生成可执行文件:
#gcc -o exe -L/home/hcj/xxxxxxxx main.o libstr.a
还有若主函数是C++程序(即.cpp),则需要在main.cpp中用extern "C"{}包含被调用函数(add.c)的
头文件,编译时用g++编译或者还用gcc编译但需加上一个链接c++库的参数(-lstdc++)
)
(3)最后执行可执行程序:
#./exe
二、动态链接库的创建与使用:
1、把add.c编译生成动态库(创建动态库):
#gcc -fPIC -c add.c //生成add.o
#gcc -shared -o libadd.so add.o /* 或者 #ar crv libadd.so add.o */
(上面两行可以整合成一行:#gcc -fPIC -shared -o libadd.so add.c)
注:-fpic 使输出的对象模块是按照可重定位地址方式生成的(即与位置无关)。
-shared指定把对应的源文件生成对应的动态链接库文件libstr.so文件
2、动态库的使用(动态链接库分:隐式调用和显式调用2种):
(1)隐式调用:
动态链接库(隐式调用)在代码上与写静态链接库没什么区别,主要是在编译时。
代码编写与静态库一样,不需要包含导出函数的头文件,若主函数是C++程序(即.cpp),则需要在main.cpp中用
extern "C"{}包含被调用函数(add.c)的头文件(这里需要包含头文件是与.cpp和.c混合编译有关,同静态\动态库
无关),编译时用g++编译或者还用gcc编译但需加上一个链接c++库的参数(-lstdc++)
1)代码编写: 与静态库一样
2)编译main.c生成可执行程序(动态库隐式调用的使用):
#gcc -o exe main.c ./libadd.so
(或者 #gcc -o exe main.c -L. libadd.so
再或者将libadd.so copy到目录 /usr/lib或/lib中,然后执行:
#gcc -o exe main.c libadd.so //此时不需要指定搜索路径
)
注: 最直接最简单的方法就是把libadd.so拉到/usr/lib或/lib中去。 、
还有一种方法 export LD_LIBRARY_PATH=$(pwd)
另外还可以在/etc/ld.so.conf文件里加入我们生成的库的目录,然后执行#/sbin/ldconfig。
/etc/ld.so.conf是非常重要的一个目录,里面存放的是链接器和加载器搜索共享库时要检查的目录,
默认是从/usr/lib /lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中
并执行/sbin/ldconfig 。另外还有个文件需要了解/etc/ld.so.cache,里面保存了常用的动态函数
库,且会先把他们加载到内存中,因为内存的访问速度远远大于硬盘的访问速度,这样可以提高软件加载
动态函数库的速度了。
3)#./exe
(2)显式调用:
显式调用的动态库的创建与隐式调用相同。(隐式调用与静态库的使用方法一样,不需要包含导出函数的头文件(显式调用
也不用包含头文件),只需要在编译可执行程序时指定库文件的路径)
显式调用和隐式调用的区别在于:编译可执行程序时需要指定库文件的搜索路径,而显式调用编译可执行程序时不用加上
动态库的搜索路径(因为已经在主函数中包含了库文件的路径),但是需要增加几个系统调用:
(#include <dlfcn.h>, //头文件
1)dlopen()
第一个参数:指定共享库的名称,将会在下面位置查找指定的共享库。
-环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。
-文件/etc/ld.so.cache中找到的库的列表,用ldconfig维护。
-目录usr/lib。
-目录/lib。
-当前目录。
第二个参数:指定如何打开共享库。
-RTLD_NOW:将共享库中的所有函数加载到内存
-RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数
返回值:返回动态库的句柄
2)dlsym()
调用dlsym时,利用dlopen()返回的共享库的句柄以及函数名称作为参数,返回要加载函数的入口地址。
3)dlclose()
关闭动态链接库
4)dlerror()
该函数用于检查调用共享库的相关函数出现的错误。
如果dlerror返回值不为空,则dlsym执行出错
)
1、编写add.c 及main.c代码:
/**************************************************************************/
/*add.c*/
int add(int x, int y)
{
return x + y;
return 0;
}
/*************************************************************************/
然后add.h代码为:
/*add.h*/
#ifndef _ADD_H_
#define _ADD_H_
int add(int, int);
#endif
/***************************************************************************/
main函数代码:
/*main.c*/
#include <stdio.h>
#include <dlfcn.h> //显式加载需要用到的头文件
#define LIB "./libadd.so" //指定动态库路径
int main(void)
{
void *dl;
char *error;
int (*func)();
dl = dlopen(LIB, RTLD_LAZY); /*打开动态链接库*/
if(dl == NULL)
{
printf("Failed load libary\n");
}
error = dlerror(); /*检测错误*/
if(error != NULL)
{
printf("%s\n", error);
return -1;
}
func = dlsym(dl, "test"); /*获取函数的地址*/
error = dlerror(); /*检测错误*/
if(error != NULL)
{
printf("%s\n", error);
return -1;
}
func(); /*调用动态库中函数*/
dlclose(dl); /*关闭共享库*/
error = dlerror(); /*检测错误*/
if(error != NULL)
{
printf("%s\n", error);
return -1;
}
return 0;
}
/**********************************************************************************/
2、编译main.c生成可执行程序,动态库的创建已经在上面讲了(动态库显式调用):
1)#gcc -ldl -o exe mian.c
注意要添加-ldl选项,以使用显式调用相关的函数调用。
可以看到,显式调用的代码看上去要复杂很多,但是却比隐式调用要灵活,我们不必在编译时就确定要加载哪个
动态链接库,可以在运行时再确定,甚至重新加载。
2)#./exe
发表评论
-
FreeRTOS
2022-03-05 16:31 248Ref https://blog.csdn.net/weix ... -
串口通讯相关
2018-11-02 13:44 411https://bbs.csdn.net/wap/topics ... -
[转]C++验证IP是否可以PING通
2018-10-30 17:54 1325https://www.cnblogs.com/guoyz13 ... -
C++/MFC 換皮膚
2018-10-20 11:05 477https://blog.csdn.net/u01123991 ... -
WinCE 截屏 - C++ 代碼
2018-08-31 09:45 574// this function create a bmp ... -
Android NDK搭建環境
2017-11-27 13:25 580https://www.cnblogs.com/ut2016- ... -
8583协议相关
2017-10-17 13:38 5738583相关资料,整理中... -
Java高级应用之JNI
2017-06-19 09:00 600参考link http://www.cnblogs.com/l ... -
2017 Google hosts
2017-06-08 08:30 14参考link https://laod.cn/hosts/20 ... -
BeagleBone Black安装mono开发环境
2017-05-17 08:49 673Installing Mono and C# on the B ... -
在linux 下怎么进入 /dev/sda1
2017-05-12 13:18 2148https://zhidao.baidu.com/questi ... -
[Ubuntu] 安装开发环境
2017-05-03 10:03 399安装gcc/g++ http://www.cnblogs.co ... -
C++实现ping功能
2017-04-18 11:21 2155基础知识 ping的过程是向目的IP发送一个type=8的I ... -
OpenSSL 编译环境搭建
2017-03-27 15:01 9061 安裝VS2008到 c:\Program Files (x ... -
最优非对称加密填充(OAEP)
2017-03-25 14:53 1582OpenSSL命令---rsautl http://blog. ... -
[Platform Builder] 设置SVM OS build Env
2016-11-10 11:39 01 copy one OSDesign Project to ... -
[Windows] System Error Codes(GetLastError )0-----5999
2016-10-26 13:28 1881ERROR_SUCCESS 0 (0x0) T ... -
开源Windows驱动程序框架
2016-09-17 21:35 871转自 http://code.csdn.net/news/28 ... -
c/c++代码中执行cmd命令
2016-09-14 14:50 1908转自 http://blog.csdn.net/slixinx ... -
C#使用C++标准DLL实例(包含callback)
2016-09-11 19:44 1086C++编写标准Win32DLL如下 头文件 /***** ...
相关推荐
### Linux静态和动态链接库创建和使用 #### 概述 在软件开发过程中,经常会遇到相同功能模块在多个项目中重复出现的情况。例如,多个项目可能都需要实现用户验证功能。为了避免代码重复,提高代码的可维护性和重用...
Linux下,动态库的调用也是静态和动态两种方式: - 静态调用:编译时通过-L和-l选项指定库路径和库名称,链接器将库函数链接到可执行文件。 - 动态调用:运行时使用dlopen、dlsym和dlclose等函数动态加载、查找和...
Windows动态库的调用方式分为静态调用(隐式调用)和动态调用(显式调用)。静态调用通过将.LIB文件加入工程,使得DLL在程序启动时自动加载;而动态调用则需要程序员使用API函数如LoadLibrary、GetProcAddress和...
在Linux操作系统中,库是程序员共享代码和功能的机制,分为静态库和动态库。静态库(.a文件)在编译时会被直接链接到可执行文件中,而动态库(.so文件)则在运行时被加载。理解这两种库的生成和调用对于Linux系统下...
### LINUX系统中动态链接库的创建与使用 #### 一、引言 在现代软件开发领域,无论是Windows还是Linux系统,动态链接库(Dynamic Link Library,简称DLL)都是提高程序性能和灵活性的重要手段之一。在Linux环境下,...
QT库是C++开发的一个强大的跨平台应用框架,支持多种操作系统,包括Windows、Linux和macOS等。在QT中,动态链接库(DLL)的使用是实现代码复用和模块化设计的重要手段。本Demo主要涵盖了DLL的两种加载方式:显示加载...
- 创建Linux下的Makefile或CMake配置,编译和链接动态库。 - 在Linux环境中测试移植后的库,确保功能完整且无错误。 5. 总结 Windows到Linux的动态库移植是一项复杂的工作,涉及多种技术和工具。理解两个平台间...
而在Linux环境下,对应的机制是共享对象(.so文件),使用dlopen、dlsym和dlclose等函数实现动态加载和调用。 总的来说,DLL和LIB(尤其是静态库与动态库)的选择主要取决于软件的需求,如内存效率、更新频率、跨...
总结,"dll-so-libload-master.zip" 文件集可能包含的是一系列关于如何在Windows和Linux系统下编写、管理和加载动态链接库的示例代码和教程。通过学习这些内容,开发者可以提升在多平台环境下的编程能力,更好地理解...
3. 类型转换:C++支持多种类型转换操作,包括隐式类型转换和显式类型转换。C++11后引入了static_cast、dynamic_cast、const_cast、reinterpret_cast等四种转换操作符,以提高类型转换的安全性和灵活性。 4. 内存...
- Intent机制:如何使用Intent进行组件间的通信,包括显式和隐式Intent的区别。 - Layouts和View:熟悉各种布局管理器(如LinearLayout、RelativeLayout、ConstraintLayout)以及自定义View的实现。 2. **Android...
3. Intent机制:了解Intent的作用,如何通过Intent启动Activity和Service,理解显式Intent与隐式Intent的区别。 4. 数据存储:熟悉SharedPreferences、SQLite数据库、文件存储、ContentProvider和内部/外部存储的...
- 显式Intent指定目标组件,隐式Intent基于行动(Action)和数据(Data)匹配。 7. **服务** - 服务在后台长时间运行,不提供用户界面。 - 启动服务和绑定服务的区别及其应用场景。 8. **广播接收器** - 广播...
C#支持隐式类型转换和显式类型转换,前者自动完成,后者需要开发者明确指定。 #### 三、面向对象的C# ##### 第九章 面向对象的程序设计 面向对象编程(OOP)是一种软件工程方法,它将代码和数据组织成对象,对象...