linux 调用动态库so文件
linux找不到动态链接库.so文件的解决方法
linux找不到动态链接库.so⽂件的解决⽅法
如果使⽤⾃⼰⼿动⽣成的动态链接库.so⽂件,但是这个.so⽂件,没有加⼊库⽂件搜索路劲中,程序运⾏时可能会出现找不到动态链接库的情形。
可以通过ldd命名来查看可执⾏⽂件依赖的动态链接库,如下(其中D为可执⾏程序):
其中的libjson_linux-gcc-4.6_libmt.so cannot found。
解决这个问题:
(1)在系统中查找这个⽂件(当然要保证系统中已经有这个.so⽂件,只是查找路径没有设置正确⽽已):
sudo find / -name libjson_linux-gcc-4.6_libmt.so
结果:/home/liu/Desktop/jsoncpp-src-0.5.0/libs/linux-gcc-4.6/libjson_linux-gcc-4.6_libmt.so
(2)将.so⽂件路径的⽬录添加到/etc/ld.so.conf
sudo vim /etc/ld.so.conf
⽂件末尾新添加⼀⾏,/home/liu/Desktop/jsoncpp-src-0.5.0/libs/linux-gcc-4.6
(3)使得修改⽣效
sudo /sbin/ldconfig
这样就不会有那个找不对.so⽂件的错误啦。
linux中.so用法
linux中.so用法
.so(Shared Object) 是Linux中的动态库文件,用于实现共享库的加载和运行,主要用于动态加载程序的运行环境和资源,减少程序的重复代码量。
主要用法有:
- 链接时加载:程序在链接时将需要的共享库文件.so通过程序链接器命令ld时指定加载,运行时可以直接使用。
- 惰性加载:程序运行时,当调用惰性加载库时,程序就会查找库文件,如有就加载库文件,没有就报错。
该方式可以动态加载不同的共享库,以满足需求。
- dlopen()函数:使用该函数可以指定路径加载指定库,可以将dlopen()和她的几个相关函数使用起来,实现更复杂的加载功能。
- 共享语义:.so文件可以实现函数共享,多个程序可以调用同一函数库,当程序修改函数库时,多个程序都可以同时使用,这可以减少程序的重复代码量。
ubuntu 程序读取本地so原理
Ubuntu 程序读取本地so原理一、概述在 Ubuntu 系统中,程序读取本地 .so 文件(共享库文件)是非常常见的操作。
共享库文件是一组可以被多个程序共享的预编译的目标文件,它包含了一些函数、符号和数据。
当一个程序需要使用共享库文件中的函数时,它会通过一定的机制来读取共享库文件,并将其中的函数信息到程序中,从而实现对共享库文件中函数的调用。
二、程序读取本地 .so 文件的原理程序读取共享库文件的原理是通过动态信息的方式来实现的。
动态信息是在程序运行时才进行的信息操作,而静态信息是在程序编译时就进行的信息操作。
Linux 中的程序默认会在系统指定的路径中搜索共享库文件,然后通过动态信息的方式将共享库文件中的函数信息到程序中。
具体来说,当程序需要使用共享库文件中的函数时,它会首先从程序自身的内部符号表中查找,如果找不到,就会去系统指定的路径中查找共享库文件。
程序会按照一定的规则来搜索共享库文件,这些规则包括环境变量 LD_LIBRARY_PATH 的设置、/etc/ld.so.conf 文件的内容等。
一旦找到了需要的共享库文件,程序就会将共享库文件中的函数信息到程序中,使得程序能够正常调用共享库文件中的函数。
在 Ubuntu 系统中,程序还能够通过调用 dl.h 头文件中定义的函数来动态加载和卸载共享库文件,从而实现对共享库文件的读取和使用。
三、程序读取本地 .so 文件的实现方式在 Ubuntu 系统中,程序可以通过多种方式来读取本地 .so 文件。
下面将介绍一些常见的实现方式:1. 静态信息静态信息是一种最简单的程序读取 .so 文件的方法。
在静态信息中,程序在编译时就会将共享库文件中的函数信息到程序中,从而形成一个单独的可执行文件。
这种方式的优点是程序的运行速度比较快,但缺点是程序的体积比较大,且无法动态加载新的共享库文件。
2. 动态信息动态信息是一种常见的程序读取 .so 文件的方法。
linux动态库和静态库调用方法
linux动态库和静态库调用方法
在Linux操作系统中,动态库和静态库的调用方法如下:
1. 动态库(Shared Library):动态库在程序运行时被载入内存,可以被多个程序同时使用,节省内存空间。
在Linux中,动态库一般存放在/usr/lib或/lib目录下。
调用方法:在程序中使用extern "C"来声明函数接口,然后通过dlopen(), dlsym()等函数来动态调用动态库中的函数。
2. 静态库(Static Library):静态库在程序编译时被包含进可执行程序中,每个程序都有一份自己的库副本。
静态库一般存放在/usr/lib或/lib目录下。
调用方法:在程序中直接使用静态库中的函数,不需要额外的调用方法。
只需要在编译时使用"-l"选项指定要链接的库名,例如"gcc -o test test.c -lmylib"。
需要注意的是,对于动态库和静态库的使用,一般建议优先使用动态库,因为这样可以节省内存空间,并且可以在不停止程序运行的情况下更新库文件。
第1页/ 共1页。
dlopen方式调用Linux的动态链接库
dlopen⽅式调⽤Linux的动态链接库在dlopen()函数以指定模式打开指定的动态链接库⽂件。
并返回⼀个句柄给()的调⽤进程。
使⽤()来打开的库。
功能:打开⼀个动态链接库,并返回动态链接库的句柄包括头⽂件:#include <dlfcn.h>函数定义:void * dlopen( const char * pathname, int mode);函数描写叙述:mode是打开⽅式,其值有多个,不同操作系统上实现的功能有所不同,在linux下,按功能可分为三类:1、解析⽅式RTLD_LAZY:在dlopen返回前,对于动态库中的没有定义的符号不运⾏解析(仅仅对函数引⽤有效。
对于变量引⽤总是马上解析)。
RTLD_NOW:须要在dlopen返回前。
解析出全部没有定义符号,假设解析不出来。
在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......2、作⽤范围,可与解析⽅式通过“|”组合使⽤。
RTLD_GLOBAL:动态库中定义的符号可被其后打开的其他库解析。
RTLD_LOCAL:与RTLD_GLOBAL作⽤相反,动态库中定义的符号不能被其后打开的其他库重定位。
假设没有指明是RTLD_GLOBAL还是RTLD_LOCAL。
则缺省为RTLD_LOCAL。
3、作⽤⽅式RTLD_NODELETE:在dlclose()期间不卸载库,⽽且在以后使⽤dlopen()⼜⼀次载⼊库时不初始化库中的静态变量。
这个flag不是POSIX-2001标准。
RTLD_NOLOAD:不载⼊库。
可⽤于測试库是否已载⼊(dlopen()返回NULL说明未载⼊,否则说明已载⼊),也可⽤于改变已载⼊库的flag,如:先前载⼊库的flag为RTLD_LOCAL,⽤dlopen(RTLD_NOLOAD|RTLD_GLOBAL)后flag将变成RTLD_GLOBAL。
这个flag不是POSIX-20 RTLD_DEEPBIND:在搜索全局符号前先搜索库内的符号。
ld-linux.so 原理
ld-linux.so 原理
ld-linux.so是Linux系统中的动态链接器,它的主要作用是
在程序运行时加载动态链接库,并解析程序所需的符号。
动态链接
器的工作原理涉及到动态链接库的加载、符号解析、重定位等方面。
首先,当一个程序启动时,操作系统会加载可执行文件到内存中,并调用动态链接器ld-linux.so来处理动态链接库的加载。
动
态链接器会根据可执行文件中的动态链接库依赖信息,找到这些动
态链接库的位置,并将它们加载到内存中。
其次,动态链接器会进行符号解析,即找到程序中调用的函数
或变量对应的地址。
这个过程涉及到符号表的查找和匹配,确保程
序能够正确调用动态链接库中的函数和变量。
另外,动态链接器还会进行重定位操作,将动态链接库中的地
址引用重定位到正确的地址上,以确保程序能够正确地访问动态链
接库中的函数和变量。
总的来说,ld-linux.so的原理就是在程序运行时负责加载动
态链接库,并进行符号解析和重定位操作,以确保程序能够正常地
调用动态链接库中的函数和变量。
这样可以实现代码的共享和复用,提高程序的灵活性和可维护性。
shell调用so方法
shell调用so方法在Shell脚本中调用共享库(.so文件)中的方法需要使用动态链接库加载器,如`dlopen`、`dlsym`等函数。
这些函数在Linux系统中的动态链接库中提供,可以在Shell脚本中使用。
以下是一个简单的示例,演示如何在Shell脚本中调用共享库中的方法:假设我们有一个名为``的共享库,其中包含一个名为`example_func`的函数,该函数接受一个字符串参数并返回一个整数。
```c//include <>int example_func(const char str) {printf("Received string: %s\n", str);return strlen(str);}```编译共享库:```shellgcc -shared -o```现在我们创建一个Shell脚本,调用`example_func`函数:```shell!/bin/bash加载共享库dlopen获取函数的地址example_func_ptr=$(dlsym $(dlinfo --dli-handle) -- example_func)调用函数并传递参数result=$($example_func_ptr "Hello, World!")打印结果echo "Result: $result"```在脚本中,我们首先使用`dlopen`函数加载共享库。
然后,使用`dlsym`函数获取函数的地址,并将其存储在变量`example_func_ptr`中。
最后,我们使用`$()`语法调用函数并传递参数,将结果存储在变量`result`中,并打印出来。
注意:使用动态链接库需要在脚本中添加适当的错误处理和检查,以确保加载和调用成功。
Linux缺少动态连接库.so--cannotopensharedobjectfile:N。。。
Linux缺少动态连接库.so--cannotopensharedobjectfile:N。
1 Liunx安装报错时,缺少动态链接库时,形式如下:
/usr/local/libexec/gcc/x86_64-unknown-liunx-gnu/4.8.2/cc1: error while loading shared libraries: libmpc.so.2: cannot open shared object file: No such file or directory
那就表⽰Linux系統不知道libmpc.so.2放在哪个⽬录下。
2 ⼀般⽽⾔,有很多so⽂件会在/usr/local/lib or /usr/lib ⽬录下,现在改⽬录找到libmpc.so.2。
3 在 /etc/ld.so.conf 中加⼊/usr/local/lib 这⼀⾏,将 /etc/ld.so.conf 保存后;
4 执⾏【/sbin/ldconfig –v 】命⾥更新⼀下才⽣效,然后在执⾏其他按装命令;
PS 若没有看到 libmpc.so.2的⽂件,说明这是个链接⽂件,需要创建⼀个,于是进⼊libmpc.so.2.0.0所在⽬录i386-linux-gnu创建链接⽂件;root@Nikola :/usr/lib# ln -s libmpc.so.2.0.0 libmpc.so.2
创建成功,然后重新编译zlib,OK
也可以参考:。
Linux动态链接(2)so初始化执行
Linux动态链接(2)so初始化执⾏⼀、so⽂件和exe⽂件这两种⽂件其实具有很多相似⾃出,或者说so⽂件是介于obj⽂件和exe⽂件的⼀种中间过渡形式,它虽然不能直接运⾏(但是经过特殊编写的so⽂件内核是⽀持加载运⾏的,例如ld.so),但是具有了⾃⼰的⼀些更为⾼级的内容,例如⼀些初始化节,got表等内容,虽然孱弱,但是它具有了更加完善的⽣物形态。
但是⼤家不要⽤进化论的观点来认为so⽂件⽐exe⽂件出现的早,事实上so是⽐较新的⼀个概念。
我们看⼀下这些⽂件类型的标识类型说明#define ET_NONE 0#define ET_REL 1#define ET_EXEC 2#define ET_DYN 3可以看到动态so⽂件的数值要⽐exe数值⼤。
这⾥说明这么多,就是so可以被通⽤的动态链接器识别和加载,由于so已经是⼀个exe的雏形,所以在加载⼀个so⽂件的时候可能除了完成动态链接之外还需要进⾏⼀些额外的操作,其中我们最为关⼼的就是个个so中定义的⼀些全局变量的初始化。
这个概念对于通常的C⽂件⽣成的so没有直接意义,但是对于包含了全局变量的C++⽂件可能⽐较有⽤,也就是在这个so⽂件被加载之后、该⽂件中任何代码执⾏之前需要执⾏so中所有的初始化函数。
⼆、测试⼯程代码//总共包含四个源⽂件,三个dep??.c⽣成各⾃的libdep??.so,main.c⽣成主程序。
其中main.exe依赖dep11.so 和 dep12.so,⽽dep11.so进⽽依赖dep21.so,主要看这些⽂件的打开顺序以及初始化函数的执⾏顺序。
[tsecer@Harry soinit]$ lsdep11.c dep12.c dep21.c main.c Makefile[tsecer@Harry soinit]$ cat dep11.c#include <stdio.h>int __attribute__((constructor)) dep11(void){return printf("In %s\n",__FUNCTION__);}[tsecer@Harry soinit]$ cat dep12.c#include <stdio.h>int __attribute__((constructor)) dep12(void){return printf("In %s\n",__FUNCTION__);}[tsecer@Harry soinit]$ cat dep21.c#include <stdio.h>int __attribute__((constructor)) dep21(void){return printf("In %s\n",__FUNCTION__);}[tsecer@Harry soinit]$ cat Makefilemain.exe:main.c libdep11.so libdep12.sogcc -fPIC main.c -o $@ -L. -ldep11 -ldep12LD_LIBRARY_PATH=. ./main.exelibdep12.so libdep21.so:lib%.so:%.cgcc -fPIC -shared -o $@ $<libdep11.so:libdep21.sogcc -fPIC -shared -o $@ -L. -ldep21 dep11.cclean:rm -f *.so *.exe *.o//执⾏make之后输出的执⾏顺序,这个顺序我们稍后解释。
QTCreator调用动态库实例
在linux中,qt里面已经集成了最新的开发平台QT Creator,下面是我练习调用动态库(.so文件)的例程:1、打开QT Creator,点击File-》New...菜单,选择C++ Libarary工程,点击下一步,输入工程名称(本例为zsz)即可,这没什么可说的。
工程文件(.pro)程序清单# -------------------------------------------------# Project created by QtCreator 2009-03-02T10:09:35# -------------------------------------------------TARGET = zszTEMPLATE = libCONFIG += pluginDEPENDPATH += .INCLUDEPATH += .SOURCES += mylib.cppHEADERS += mylib.hmylib.h文件程序清单:#ifndef MYLIB_H#define MYLIB_H#ifdef Q_WS_WIN //表示在windows环境#define MY_EXPORT __declspec(dllexport)#else#define MY_EXPORT#endifclass mylib {public:int mymax(int i, int j);int add(int i, int j);};extern "C" MY_EXPORT int diff(int i, int j);#endif // MYLIB_Hmylib.cpp文件程序清单:#include "mylib.h"extern "C" MY_EXPORT int mylib::mymax(int i,int j){if(i>=j)return i;elsereturn j;}extern "C" MY_EXPORT int mylib::add(int i,int j){return i+j;}extern "C" MY_EXPORT int diff(int i, int j){if(i>=j)return i-j;elsereturn j-i;}对该工程进行编译,生成libzsz.so文件。
linux.o,.a,.so文件解析
linux.o,.a,.so⽂件解析linux下⽂件的类型是不依赖于其后缀名的,但⼀般来讲:.o,是⽬标⽂件,相当于windows中的.obj⽂件.so 为共享库,是shared object,⽤于动态连接的,和dll差不多.a为静态库,是好多个.o合在⼀起,⽤于静态连接.la为libtool⾃动⽣成的⼀些共享库,vi编辑查看,主要记录了⼀些配置信息。
可以⽤如下命令查看*.la⽂件的格式 $file *.la*.la: ASCII English text所以可以⽤vi来查看其内容。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@创建.a库⽂件和.o库⽂件:[yufei@localhost perl_c2]$ pwd/home/yufei/perl_c2[yufei@localhost perl_c2]$ cat mylib.c#include#includevoid hello(){printf("success call from perl to c library\n");}[yufei@localhost perl_c2]$ cat mylib.hextern void hello();[yufei@localhost perl_c2]$ gcc -c mylib.c[yufei@localhost perl_c2]$ dirmylib.c mylib.h mylib.o[yufei@localhost perl_c2]$ ar -r mylib.a mylib.oar: 正在创建 mylib.a[yufei@localhost perl_c2]$ dirmylib.a mylib.c mylib.h mylib.o@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111动态链接库*.so的编译与使⽤- -动态库*.so在linux下⽤c和c++编程时经常会碰到,最近在⽹站找了⼏篇⽂章介绍动态库的编译和链接,总算搞懂了这个之前⼀直不太了解得东东,这⾥做个笔记,也为其它正为动态库链接库⽽苦恼的兄弟们提供⼀点帮助。
Linux和Windows平台动态库.so和.dll文件的生成
Linux和Windows平台动态库.so和.dll⽂件的⽣成Linux动态库的⽣成1、纯cpp⽂件打包动态库将所有cpp⽂件和所需要的头⽂件放在同⼀⽂件夹,然后执⾏下⾯命令gcc -shared - fpic *.c -o xxx.so;g++ -std=c++17 - fpic *.cpp -o xxx.so;[C++17标准,需要⾼版本gcc,本⼈采⽤gcc 8.2.0]其中*.c代表所有的c⽂件,xxx.so中的xxx代表so动态库的名字, -std=c++17代表采⽤C++17标准编译。
2、多个cpp⽂件和so库⼀起打包成⼀个sog++ -std=c++17 -fpic AFClassifier.cpp -shared -L. -lRandom -o test.so3、多个so打包为⼀个so如果有两个so,分别为 libRandom.so和libAF.so,并且在当前⽬录下⾯,则执⾏下⾯命令:g++ -std=c++17 -fpic -shared -L. -lAF -lRandom -o test.so如果libRandom.so和libAF.so不在当前⽬录,-L 后⾯要加上⽬录,⽐如在当前⽬录的下⼀层⽬录,则:g++ -std=c++17 -fpic -shared -L ./ -lAF -lRandom -o test.so===========================================================Windows动态库的打包(dll)1、打开⼯程,在解决⽅案中打开属性—》配置属性:做以下修改:“⽬标⽂件扩展名”:由默认的exe修改为dll“配置类型”:选择动态库dll同时注意配置和平台的版本。
最好把release和debug下⾯的配置属性都做上⾯的修改。
2、在接⼝⽂件(也就是最重要的头⽂件)添加两处代码:1)#ifdef LIBRARY_EXPORTS# define LIBRARY_API __declspec(dllexport)#else# define LIBRARY_API __declspec(dllimport)#endif2)在调⽤函数前⾯加上“LIBRARY_AP”当然如果在接⼝函数前⾯直接写上__declspec(dllimport)有时也可以,但是当遇到静态变量或者静态函数时,就不⾏了,我⾃⼰没有真实测试过,看的博⽂这样介绍的,博⽂连接如下:3、点击⽣成解决⽅案,即可⽣成.dll⽂件。
so文件格式解析 -回复
so文件格式解析-回复SO文件格式解析SO文件是一种可执行文件格式,通常在Linux和其他Unix-like操作系统中使用。
它是一种用于共享库的文件格式,也被称为共享目标文件。
SO文件的格式非常重要,因为它确定了操作系统如何加载和运行这些共享库。
SO文件的结构是按照特定的规范来定义的,以下是SO文件格式的解析过程。
1. ELF格式SO文件采用的是ELF(Executable and Linkable Format)格式,它是一种通用的可执行文件格式。
ELF格式定义了SO文件的头部(header)、段(section)和符号表(symbol table)等重要部分。
2. 头部信息SO文件的头部包含了与文件相关的一些基本信息,比如ELF文件的魔数、文件类型、机器体系结构、入口地址等。
通过读取头部信息,操作系统可以判断文件格式,并且正确加载和执行共享库。
3. 段信息SO文件由多个段组成,每个段具有不同的作用。
常见的段包括.text(代码段)、.data(数据段)、.bss(未初始化数据段)以及各种重要的元数据段。
- .text段:包含共享库的实际机器代码。
- .data段:存储已初始化的全局和静态变量。
- .bss段:存储未初始化的全局和静态变量。
4. 符号表符号表是SO文件中的重要组成部分,它记录了共享库中定义和引用的符号。
符号可以是函数、变量、常量等。
操作系统通过符号表可以获取共享库中的各种符号信息,以便正确解析和运行共享库。
5. 节与节头表ELF格式中的节(section)是段的子集,它们存储着文件的各种额外信息。
节头表是一个记录节信息的表格,每个表项对应一个节的描述,包括节名、大小、偏移等。
6. 动态符号解析共享库可能会引用其他共享库中定义的符号,为了正确解析这些符号,操作系统采用了动态符号解析的机制。
当SO文件被加载到内存时,操作系统会根据符号表的信息,依次解析和链接其他共享库,确保符号的正确解析和调用。
linux下编译动态链接库(.so文件)的步骤和示例代码
在Linux下,我们可以使用GCC编译器来编译动态链接库(.so文件)。
以下是一个简单的示例,演示了如何创建一个动态链接库。
假设我们有一个简单的C程序,它定义了一个函数add,该函数接受两个整数并返回它们的和。
c// add.c#include<stdio.h>int add(int a, int b) {return a + b;}接下来,我们需要编写一个头文件add.h,以供其他程序使用。
c// add.h#ifndef ADD_H#define ADD_Hint add(int a, int b);#endif// ADD_H现在,我们编写一个动态链接库程序libadd.c。
该程序包含了上面定义的头文件和函数。
c// libadd.c#include"add.h"int add(int a, int b) {return a + b;}编译动态链接库的步骤如下:1.使用gcc编译器将C源文件编译为共享对象文件。
使用-shared选项指定输出为共享对象文件。
例如:2.shellgcc -shared -o libadd.so add.c libadd.c这将生成一个名为libadd.so的共享对象文件。
2. 将生成的共享对象文件复制到适当的位置。
例如,您可以将文件复制到系统的库目录中:shellsudo cp libadd.so /usr/local/lib/这将将共享对象文件复制到/usr/local/lib/目录下,这样其他程序就可以找到并链接它。
请注意,可能需要使用超级用户权限来执行此操作。
【linux】程序找不到动态库.so的解决办法查看.so动态库信息.so动态库加载顺序
【linux】程序找不到动态库.so的解决办法查看.so动态库信息.so动态库加载顺序⽬录找不到.so解决⽅法Linux 动态库的默认搜索路径是 /lib 和 /usr/lib,除了默认的搜索路径外,还可以通过以下⼏种⽅法来指定。
⽅法⼀:添加环境变量添加环境变量三种⽅式1. 添加当前⽤户当前终端的环境变量(临时)export LD_LIBRARY_PATH=/home/czd/... #.so file path2. 添加当前⽤户的环境变量修改~/.bashrc⽂件,在其末尾,添加环境变量vim ~/.bashrcexport LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/czd/... #.so file path使其⽣效,source ~/.bashrc如不能⽣效,请重启3. 添加所有⽤户的环境变量修改profile⽂件,在其末尾添加环境变量vim /etc/profileexport LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/czd/... #.so file path使其⽣效source /etc/profile如不能⽣效,请重启⽅法⼆:复制so⽂件到lib路径linux系统的so库⼀般存储与“/usr/lib/”路径中,可将动态库复制到该路径中。
sudo cp liblibtest.so /usr/lib/即时⽣效⽅法三:(推荐)添加ldconfig寻找路径步骤1. 编辑链接配置⽂件vim /etc/ld.so.conf,确认内容是否为如下,不是则修改为如下:include /etc/ld.so.conf.d/*.conf步骤2. 进⼊/etc/ld.so.conf.d⽬录内,创建*.conf⽂件,⽂件名随意,扩展名必须为.confcd /etc/ld.so.conf/vim libmy.conf步骤4. 在⽂件内部,添加so的路径,保存并退出/home/czd/eclipse-workspacee/calllib/Debug步骤5. 执⾏命令时期⽣效sudo ldconfig程序在运⾏时寻找so库就会到添加的⽬录中寻找。
动态链接库及静态链接库(windows下的.dll.lib和linux下的.so.a)
动态链接库及静态链接库(window s下的.dll .lib和li nux下的.so .a)库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。
例如:libhel lo.so libhel lo.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如:libhel lo.so.1.0,由于程序连接默认以.so为文件后缀名。
所以为了使用这些库,通常使用建立符号连接的方式。
ln -s libhel lo.so.1.0 libhel lo.so.1ln -s libhel lo.so.1 libhel lo.so使用库当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。
然而,对动态库而言,就不是这样。
动态库会在执行程序内留下一个标记…指明当程序执行时,首先必须载入这个库。
由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。
现在假设有一个叫hel lo的程序开发包,它提供一个静态库lib hello.a 一个动态库l ibhel lo.so,一个头文件h ello.h,头文件中提供sayhe llo()这个函数/* hello.h */void sayhel lo();另外还有一些说明文档。
这一个典型的程序开发包结构1.与动态库连接linux默认的就是与动态库连接,下面这段程序testl ib.c使用hel lo库中的sayhe llo()函数/*testli b.c*/#includ e#includ eint main(){sayhel lo();return 0;}使用如下命令进行编译$gcc -c testli b.c -o testli b.o用如下命令连接:$gcc testli b.o -lhello -o testli b在连接时要注意,假设libh ello.o 和libhe llo.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数与与静态库连接麻烦一些,主要是参数问题。
linux 提取so库函数的参数类型
linux 提取so库函数的参数类型(原创实用版)目录1.介绍 Linux 系统中的 so 库2.探讨如何在 Linux 系统中提取 so 库函数的参数类型3.总结提取参数类型的方法及应用场景正文一、Linux 系统中的 so 库在 Linux 系统中,so 库(共享对象库)是一种可重用的动态链接库,包含了许多可执行文件和共享库所需的函数和数据。
so 库文件的后缀名为.so,它们可以在不同的程序之间共享,从而减少了内存占用和提高了程序的执行效率。
当一个程序需要调用某个函数时,操作系统会加载相应的 so 库,并将其中的函数映射到程序的地址空间。
二、如何在 Linux 系统中提取 so 库函数的参数类型要提取 so 库函数的参数类型,我们可以使用一些工具和命令来完成。
下面介绍两种常用的方法:1.使用 nm 工具m(name mangling)是一个用于解析符号和函数名称的工具,它可以帮助我们查看 so 库中的函数名称及其参数类型。
使用 nm 命令的基本格式如下:```m -D -f so 库文件名```例如,要查看名为 libexample.so 中的函数参数类型,可以使用以下命令:```m -D -f libexample.so```在输出结果中,我们可以看到函数名称以及括号内的参数类型。
需要注意的是,nm 命令输出的结果可能会较为繁琐,需要仔细阅读和分析。
2.使用 cdecl 工具cdecl是一个用于解析C/C++函数原型和参数类型的工具,它可以帮助我们以更直观的方式查看so库函数的参数类型。
使用cdecl命令的基本格式如下:```cdecl -I -M so 库文件名```例如,要查看名为 libexample.so 中的函数参数类型,可以使用以下命令:```cdecl -I -M libexample.so```在输出结果中,我们可以看到以“prototype:”开头的函数原型,其后的括号内就是函数的参数类型。
Linux的so文件到底是干嘛的?浅析Linux的动态链接库
Linux的so⽂件到底是⼲嘛的?浅析Linux的动态链接库我们分析了Hello World是如何编译的,即使⼀个⾮常简单的程序,也需要依赖C标准库和系统库,链接其实就是把其他第三⽅库和⾃⼰源代码⽣成的⼆进制⽬标⽂件融合在⼀起的过程。
经过链接之后,那些第三⽅库中定义的函数就能被调⽤执⾏了。
早期的⼀些操作系统⼀般使⽤静态链接的⽅式,现在基本上都在使⽤动态链接的⽅式。
静态链接和动态链接虽然静态链接和动态链接都能⽣成可执⾏⽂件,但两者的代价差异很⼤。
下⾯这张图可以很形象地演⽰了动态链接和静态链接的区别:左侧的⼈就像是⼀个动态链接的可执⾏⽂件,右侧的海象是⼀个静态链接的可执⾏⽂件。
⽐起⼈,海象臃肿得多,那是因为静态链接在链接的时候,就把所依赖的第三⽅库函数都打包到了⼀起,导致最终的可执⾏⽂件⾮常⼤。
⽽动态链接在链接的时候并不将那些库⽂件直接拿过来,⽽是在运⾏时,发现⽤到某些库中的某些函数时,再从这些第三⽅库中读取⾃⼰所需的⽅法。
我们把编译后但是还未链接的⼆进制机器码⽂件称为⽬标⽂件(Object File),那些第三⽅库是其他⼈编译打包好的⽬标⽂件,这些库⾥⾯包含了⼀些函数,我们可以直接调⽤⽽不⽤⾃⼰动⼿写⼀遍。
在编译构建⾃⼰的可执⾏⽂件时,使⽤静态链接的⽅式,其实就是将所需的静态库与⽬标⽂件打包到⼀起。
最终的可执⾏⽂件除了有⾃⼰的程序外,还包含了这些第三⽅的静态库,可执⾏⽂件⽐较臃肿。
相⽐⽽⾔,动态链接不将所有的第三⽅库都打包到最终的可执⾏⽂件上,⽽是只记录⽤到了哪些动态链接库,在运⾏时才将那些第三⽅库装载(Load)进来。
装载是指将磁盘上的程序和数据加载到内存上。
例如下图中的Program 1,系统⾸先加载Program 1,发现它依赖libx.so后才去加载libx.so。
所以,静态链接就像GIF图中的海象,把所需的东西都带在了⾝上。
动态链接只把精简后的内容带在⾃⼰⾝上,需要什么,运⾏的时候再去拿。
linux编译so
return a + b; } 然后将它编译成.so文件: $ gcc -O -c -fPIC -o hello.o hello.c $ gcc -shared -o libhello.so hello.o 放到系统库中: # cp libhello.so /usr/local/lib # sudo ldconfig 在这里说明一下,之前的linux系统的用户动态库目录设置好像是在/etc/ld.so.conf.d/local.conf文件中,而在我使用的ubuntu12.04中是 在/etc/ld.so.conf.d/libc.conf这个文件中,而且默认已设置为/usr/local/lib这个目录,将我们的so文件放到这个目录后,需用ldconfig命令使其 生效。 下面我们写个test程序来验证一下:
unexpectedendofjsoninput请尝试刷新页面或更换浏览器重试
linux编译 so
开发中通常需要模块化设计,因此通常独立的功能会在单独的模块中实现,在widnows下通常实现为dll,而在linux下则封装成so库,我们来 看一下在ubuntu下怎么调用so库。以下代码与操作在ubuntu12.04上实现。 首先编写一个简单的so:
#include <stdio.h> int main() {
int a = 3, b = 4; printf("%d + %d = %d\n", a, b, hello_add(a,b)); return 0; } 编译并执行: $ gcc -o helllotest 3+4=7
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
pf(); //通过指针 pf 的调用来调用动态库中的 test 函数 dlclose(handle); //关闭调用动态库句柄 return 0; }
////////////////////////////////makefile////////////////////////////////////////////////////// .SUFFIXES: .c .cpp .o CC=g++ -shared -fPIC GCC=g++
功能描述:在 dlopen 之后,库被装载到内存。dlsym 可以获得指定函数(symbol)在内存中 的位置(指针)。如果找不到指定函数,则 dlsym 会返回 NULL 值。但判断函数是否存在最好 的方法是使用 dlerror 函数,
4) dlclose 函数原型:int dlclose(void *);
#include <stdio.h>
#include <stdlib.h> extern "C" { int test(void); }
////////////////////////////////ttest_so1.cpp////////////////////////////////////////////////////// #include "test_so1.h" int test(void) {
下面对这些接口函数逐一介绍(调用这些接口时,需引用头文件#include <dlfcn.h>): 1) dlopen 函数原型:void *dlopen(const char *libname,int flag); 功能描述:dlopen 必须在 dlerror,dlsym 和 dlclose 之前调用,表示要将库装载到内存,准 备使用。如果要装载的库依赖于其它库,必须首先装载依赖库。如果 dlopen 操作失败,返 回 NULL 值;如果库已经被装载过,则 dlopen 会返回同样的句柄。 参数中的 libname 一般是库的全路径,这样 dlopen 会直接装载该文件;如果只是指定了库 名称,在 dlopen 会按照下面的机制去搜寻: a.根据环境变量 LD_LIBRARY_PATH 查找 b.根据/etc/ld.so.cache 查找 c.查找依次在/lib 和/usr/lib 目录查找。
linux 调用动态库 so 文件
分类: c++那些事 2012-05-02 14:55 4831 人阅读 评论(0) 收藏 举报 linuxdlliostreamclass 编译器 winapi
关于动态调用动态库方法说明 一、 动态库概述 1、 动态库的概念 日常编程中,常有一些函数不需要进行编译或者可以在多个文件中使用(如数据库输入/输 出操作或屏幕控制等标准任务函数)。可以事先对这些函数进行编译,然后将它们放置在一 些特殊的目标代码文件中,这些目标代码文件就称为库。库文件中的函数可以通过连接程序 与应用程序进行链接,这样就不必在每次开发程序时都对这些通用的函数进行编译了。
int main(int argc, char **argv) {
if(argc!=2) {
printf("Argument Error! You must enter like this:\n"); printf("./test_dl test_so1.so\n"); exit(1);
}
void *handle; char *error; typedef void (*pf_t)(); //声明函数指针类型
flag 参数表示处理未定义函数的方式,可以使用 RTLD_LAZY 或 RTLD_NOW。RTLD_LAZY 表示暂时不去处理未定义函数,先把库装载到内存,等用到没定义的函数再说;RTLD_NOW 表示马上检查是否存在未定义的函数,若存在,则 dlopen 以失败告终。
2) dlerror 函数原型:char *dlerror(void);
功能描述:dlerror 可以获得最近一次 dlopen,dlsym 或 dlclose 操作的错误信息,返回 NULL 表示无错误。dlerror 在返回错误信息的同时,也会清除错误信息。
3) dlsym 函数原型:void *dlsym(void *handle,const char *symbol);
3、 动态库与静态库之间的区别 静态库是指编译连接时,把库文件的代码全部加入到可执行文件中,所以生成的文件较大, 但运行时,就不再需要库文件了。即,程序与静态库编译链接后,即使删除静态库文件,程 序也可正常执行。
动态库正好相反,在编译链接时,没有把库文件的代码加入到可执行文件中,所以生成的文 件较小,但运行时,仍需要加载库文件。即,程序只在执行启动时才加载动态库,如果删除 动态库文件,程序将会因为无法读取动态库而产生异常。
////////////////////////////////ttest_so2.cpp////////////////////////////////////////////////////// #include "test_so2.h" int test(void) {
printf("USING TEST_SO2.SO NOW!\n");//注意此处与 test_so1.cpp 中的 //test 函数的不同
g++ -g -o test test.cpp –L/root/src/lib –ltest_so1 (此处,我们重点讲解动态库的动态调用的方法,关于静态的通过 g++编译命令调用的方式 不作详细讲解,具体相关内容可上网查询)
Linux 下,提供专门的一组 API 用于完成打开动态库,查找符号,处理出错,关闭动态库等 功能。
动态库是一种在已经编译完毕的程序开始启动运行时,才被加载来调用其中函数的库。 其加载方式与静态库截然不同。
2、 动态库的命名 Linux 下,动态库通常以.so(share object)结尾。(通常/lib 和/usr/lib 等目录下存在大量系统 提供的以.so 结尾的动态库文件)
Windows 下,动态库常以.dll 结尾。(通常 C:\windows\System32 等目录下存在大量系统提 供的以.dll 结尾的动态库文件)
二、 Linux 下动态调用动态库 备注:以下 linux 实例说明都是在 RedHat 5.1 系统+ gcc 版本 4.1.2 20080704 (Red Hat 4.1.2-46)上实现。
1、 .so 动态库的生成 可使用 gcc 或者 g++编译器生成动态库文件(此处以 g++编译器为例)
g++ -shared -fPIC -c XXX.cpp g++ -shared -fPIC -o XXX.so XXX.o 2、 .so 动态库的动态调用接口函数说明 动态库的调用关系可以在需要调用动态库的程序编译时,通过 g++的-L 和-l 命令来指定。例 如:程序 test 启动时需要加载目录/root/src/lib 中的 libtest_so1.so 动态库,编译命令可照如 下编写执行:
printf("USING TEST_SO1.SO NOW!\n");//注意此处与 test_so2.cpp 中的 //test 函数的不同
return 1; }
//////////////////////////////// test_so2.h ////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> extern "C" { int test(void); }
test_dl.cpp 生成 test_dl 可执行程序,dl 通过 dlopen 系列等 API 函数,并使用函数指 针以到达动态调用不同 so 库中 test 函数的目的。
////////////////////////////////test_so1.h//////////////////////////////////////////////////////
handle = dlopen (argv[1], RTLD_NOW); //打开 argv[1]指定的动态库
if (!handle) {
fprintf (stderr, "%s\n", dlerror()); exit(1); }
dlerror(); pf_t pf=(pf_t)dlsym(handle,"test" ); //指针 pf 指向 test 在当前内存中的地址 if ((error = dlerror()) != NULL) {
all:test_so1.so test_so2.so test_dl clean
OBJ1=test_so1.o OBJ2=test_so2.o OBJ3=test_dl.o
test_so1.so:$(OBJ1) $(CC) -o $@ $? cp $@ /usr/lib
test_so2.so:$(OBJ2)
而 C++允许重载(不同的函数有相同的名字但不同的参数),并且有很多 C 所没有的特性 ──比如类、成员函数、异常说明──几乎不可能直接用函数名作符号名。为了解决这个问题, C++采用了所谓的 name mangling。它把函数名和一些信息(如参数数量和大小)杂糅在一 起,改造成奇形怪状,只有编译器才懂的符号名。例如,被 mangle 后的 foo 可能看起来像 foo@4%6^,或者,符号名里头甚至不包括“foo”。