Linux下动态库的使用

【简介】

linux环境下的动态库一般名为libxxx.so, 用ldd命令分析某个可执行程序,可以看到该程序依赖哪些动态库,以及路径。 如 ldd ./test

linux-vdso.so.1 =>  (0x00007fffaab52000)

libc.so.6 => /lib64/libc.so.6 (0x0000003c4c800000)

/lib64/ld-linux-x86-64.so.2 (0x0000003c4c000000)

如果有依赖库找不到,程序会无法正常运行。

【创建一个动态库】

util.cpp


1

2

3

4

extern "C" int InsertSubStr(char* pszBuf, int nPos, char* pValue)

{

     return 1;

}

代码为cpp时,函数可以重载,在symbol里生成的函数名会带上修饰,如_ZwqInsertSubStrBstl. 加上extern "C"之后在symbol里就是原名,当然也就不能有同名函数了。如果函数体使用了该修饰后,头文件定义也必须加上,否则调用者编译时会找不到函数名。

makefile


1

2

3

4

5

libmyutil.so : util.o

  g++ -shared -o libmyutil.so util.o

util.o : util.cpp

  g++ -fPIC -c util.cpp -o util.o

如果没有编译错误,则会生成libmyutil.so文件。因为使用了-shared编译选项,如果在代码里引用了其他库libabc.so,在编译时不会报错(不像windows下那样会报unresolve external,或者我还没找到设置方法)。如果调用者也没有引用该库libabc.so,则加载或运行时会报错。所以知道引用了哪些库,最好在makefile里加上,如g++ -shared -labc -o libmyutil.so util.o

QT创建动态库时,会生成libxx.so.1.0.0等几个带版本号的符号链接,可以加上 CONFIG += plugin 这样就不带版本号了。

【使用动态库】

像windows一样,也有直接编译链接和动态加载两种方式

1.直接编译链接

include头文件的函数定义后,在程序中调用函数,再在makefile中加上-lmyutil即可。用ldd命令分析执行程序,可以看到引用了libmyutil.so QT编译时,需要在pro文件里指定路径 LIB += -L../lib -lmymodule

2.动态加载


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#include <dlfcn.h>

typedef int (*fnTestFoo)(char* pszBuf, int nPos, char* pValue);

  void *hso = dlopen("./libmyutil.so", RTLD_NOW);//RTLD_LAZY);//

  if(!hso)

  {

    printf("dlopen failed:%s\n", dlerror());

    return;

  }

  fnTestFoo fnTest = (fnTestFoo)dlsym(hso, "InsertSubStr");

  char *perr = dlerror();

  if(perr)

  {

    printf("load symbol failed:%s\n", perr);

    return;

  }

  char szText[256]="abcdef";

  fnTestFoo(szText, 2, "xyz");

  printf("%s\n", szText);

  dlclose(hso);

可以看出与windows函数的对应:dlopen=LoadLibrary,dlsym=GetProcAddress. 这几个函数在libdl.so中,编译时在makefile中加上-ldl dlopen

可以有选项RTLD_NOW/RTLD_LAZY,前者为加载时解析依赖关系,失败则报错停止运行;后者为先不解析,运行到相应的代码时,如果有依赖关系错误再报错。

动态加载C++类

如果想要使用动态库中的C++类,直接使用肯定不行,因为编译时会找不到构造函数。其实只要在动态库中输出一个函数,创建类对象

CTest *GetClass_DL(void)

{

return (new CTest());

}

这样就可以了,析构函数也一样。

【依赖关系和路径】

在windows下可以用depends来查看库的依赖关系,在Linux下有好几个工具可以达到类似效果,如上面提到的文件依赖关系的ldd. 如果要查看函数依赖关系,可以用nm命令,如nm test


1

2

3

4

5

6

7

8

0000000000601170 d _DYNAMIC

                 w _Jv_RegisterClasses

00000000004008e4 T _Z8callFunciPPcPFiS_zE

                 U [email protected]@GLIBC_2.2.5

                 U [email protected]@GLIBC_2.2.5

                 U [email protected]@GLIBC_2.2.5

                 U [email protected]@GLIBC_2.2.5

0000000000400da2 T main

其中T(text)前面是在本程序中的地址;U(unresolved)表示引用的外部库函数,以及对应的库名称。另外还有w(weak),A(absolute)不了解。 另外还有objdump命令,更详细的显示程序内的内容。

动态加载dlopen时,最好是指定全路径,否则当前路径可能发生变化。当编译链接库文件时,有时运行程序会找不到库文件报错:error while loading shared libraries: libxxx.so.1: cannot open shared object file: No such file or directory.很多时候是未指定路径。

与windows不同,把dll放在exe一起就行了,加载时会先从当前路径查找。linux下的库文件的路径配置在/etc/ld.so.conf 中,内容如下一行

include ld.so.conf.d/*.conf

在conf.d目录,可以看到其他软件所需的库文件路径,如mysql-x86_64.conf 里面也只有一行:/usr/lib64/mysql

所以如果自己的库文件不放在系统的库路径如/usr/lib64下的话,也可以照此方法增加myapp.conf文件,写上/mylib, 放在这里即可。

sudo ldconfig更新配置(注意较慢),用ldconfig -p|grep libmyxxx可以查看自己的库是否在系统的路径里。当在路径里新增so文件时,配置不会自动更新。

如果不想更改系统的库文件路径,也可以在运行时修改环境变量LD_LIBRARY_PATH,如 $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/my_library_path $ ./my_app

原文: https://www.cnblogs.com/chaos77/p/6874378.html

原文地址:https://www.cnblogs.com/jiftle/p/8401776.html

时间: 2024-07-28 15:22:38

Linux下动态库的使用的相关文章

谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH

谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH  PKG_CONFIG_PATH 转载自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=23069658&id=4028681 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里那真叫一个难受.那时候脑袋里曾经

linux下动态库的编写和调用

linux下动态库的编写和调用 linux下编写和调用一个简单的动态库大概分为以下几个步骤: - 创建动态库程序文件 add.c int add(int a,int b) { return a+b; } 创建引用头文件 head.c #ifndef _HEAD_ #define _HEAD_ int add(int a,int b); #endif 生成目标文件 生成要加编译器选项 -fpic gcc -fpic -c add.c 然后生成动态库 注意使用链接器选项 -shared gcc -s

Linux下动态库生成和使用

Linux下动态库生成和使用 一.动态库的基本概念 1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序.动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的.库中函数和变量的地址是相对地址,不是绝对地址,其真实地址在调用动态库的程序加载时形成. 2.动态链接库的名称有别名(soname), 真名(realname)和链接名(linker name).别名由一个前缀lib,然后是库的名字,再加上一个后缀“.so”构成.真名是

[转]谈谈Linux下动态库查找路径的问题

http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里那真叫一个难受.那时候脑袋里曾经也犯过嘀咕,为啥Linux不弄成windows那样呢,装个软件那个麻烦不说,连运行软件都这么恼火呢?如果那样的话就不叫Linux了.借用小米公司CEO雷军一句话:小米,为发烧而生

转:谈谈Linux下动态库查找路径的问题

http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续"上路".回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里那真叫一个难受.那时候脑袋里曾经也犯过嘀咕,为啥Linux不弄成windows那样呢,装个软件那个麻烦不说,连运行软件都这么恼火呢?如果那样的话就不叫Linux了.借用小米公司CEO雷军一句话:小米,

Linux下动态库和静态库的编译和链接

1.动态库:Linux中动态库的后缀名为.so 第二步:gcc -shared (C文件名.c) -o (lib动态库名.so) 创建一个.so文件,因为是64位的系统,不兼容,会报错 应该在指令前加-fpic 即gcc -fpic -shared (C文件名.c) -o (lib动态库名.so) 第三步:gcc () -(l库文件名无后缀) -L. -o (编译后的c文件名) -L.告诉系统文件库为当前目录 第四步:进入root模式,export LD_LIBRARY_PATH=.:$LD_L

LINUX总结第13篇:LINUX下动态库及版本号控制

感觉讲得挺详细 注: ln 命令用法 ln –s 源文件 目标文件 (目标文件即为软链接文件) 可用ls -l查看软链接文件具体指向哪个文件 目录[-] 1. File libhello.c 2. File libhello.h 3. File main.c 前言 针对同一动态组件的不同版本链接和加载. 一.概念                  DLL HELL字面意思是DLL"灾难",是由于com组件(动态库)升级引起的程序不能运行的情况.        原因         有三

Linux 下动态库 / 静态库(依赖)

一. 依赖动态库的动态库 libfun.so依赖动态库libtest.so(libfun.so动态库里的函数intnothing()调用了libtest.so里的intmytest()函数),而main.exe又调用了libfun.so的函数int nothing(). 下面两种方式都能工作: 1> 常用的方式 g++ -shared -fPIC -o libtest.so test.cpp g++ -shared -fPIC -o libfun.so function.cpp  -L./ -I

【linux】linux下动态库so文件的一些认识

来源:http://mypyg.iteye.com/blog/845915 so其实就是shared object的意思.今天看了上面的博客,感觉好吃力.赶紧做个笔记记录一下.下面的内容大多都是连接中的,穿插我自己的笔记 牵扯到ELF格式,gcc编译选项待补,简单实用的说明一下,对Linux下的so文件有个实际性的认识. 1.so文件是什么? 2.怎么生成以及使用一个so动态库文件? 3.地址空间,以及线程安全. 4.库的初始化,解析: 5.使用我们自己库里的函数替换系统函数: 1.so文件是什