Linux 动态链接库(.so)的使用

1. 背景

库:就是已经编写好的,后续可以直接使用的代码。

c++静态库:会合入到最终生成的程序,使得结果文件比较大。优点是不再有任何依赖。

c++动态库:动态库,一个文件可以多个代码同时使用内存中只有一份,节省内存,可以随主代码一起编译。缺点是需要头文件。

网友说:库就是除了main函数之外的其他代码,都可以组成库。

2. 只介绍动态库(工作中主要用动态库)

C++使用动态库比C语言使用动态库稍微麻烦点。

因为C++支持函数重载(参数变量个数不同、参数类型不同、类型修饰符不同const/not const等),都会使得C++对函数名进行重写,不方便根据函数名查找对应函数

C++中可以使用extern关键字修饰对应的函数,表示函数名按照C言语分隔编译,不进行改写。(extern关键字另一个关键字修饰变量,表示变量在其他文件中已经定义。通常见于修饰全局变量)

3. 使用so文件需要的api

头文件 #include <dlfcn.h>

dlopen以指定的模式打开共享链接库。使用可以参考: http://man7.org/linux/man-pages/man3/dlopen.3.html

4. C++使用动态链接库实例

4.1 test.h

1 class Test{
2 public:
3     virtual int get();
4     virtual void set(const int num);
5 };

4.2 test.cpp

 1 #include <iostream>
 2 #include "test.h"
 3
 4 int g_num = 0;   ///全局变量
 5
 6 int Test::get() { return g_num; }
 7 void Test::set(const int num){ g_num = num; }
 8
 9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12
13 Test* create(){ return new Test; }
14
15 #ifdef __cplusplus
16 }
17 #endif

4.3 main.cpp

 1 #include <iostream>
 2 #include <dlfcn.h>
 3 #include "test.h"
 4 using namespace std;
 5
 6 //声明函数指针
 7 typedef Test* (*so_init)();
 8
 9 //定义插件类来封装,句柄用完后需要释放
10 struct Plugin{
11     void *handle;
12     Test *t;
13
14     Plugin():handle(NULL), t(NULL) { }
15     ~Plugin(){
16         if(t) { delete t; }
17         if (handle) { dlclose(handle); }
18     }
19 };
20
21 int create_instance(const char *so_file, Plugin &p){
22     //根据特定的模式打开so文件, 获取so文件句柄
23     //RTLD_NOW:需要在dlopen返回前,解析出所有未定义符号
24     //RTLD_DEEPBIND:在搜索全局符号前先搜索库内的符号,避免同名符号的冲突
25     p.handle = dlopen(so_file, RTLD_NOW | RTLD_DEEPBIND);
26     if (!p.handle) {
27         cout << "Cannot open library: " << dlerror() << endl;
28         return -1;
29     }
30
31     //根据字符串"create"读取库中对应到函数, 并返回函数地址,可以理解为一种间接的“反射机制”
32     so_init create_fun = (so_init) dlsym(p.handle, "create");
33     if (!create_fun) {
34         cout << "Cannot load symbol" << endl;
35         dlclose(p.handle);
36         return -1;
37     }
38
39     //调用方法, 获取类实例
40     p.t = create_fun();
41
42     return 0;
43 }
44
45 int main(){
46     Plugin p1;
47     Plugin p2;
48
49     if (0 != create_instance("./libtest_1.so", p1)
50             || 0 != create_instance("./libtest_2.so", p2)){
51         cout << "create_instance failed" << endl;
52         return 0;
53     }
54
55     p1.t->set(1);   //对库1中到全局变量进行设置
56     p2.t->set(2);   //对库2中到全局变量进行设置
57
58     //输出两个库中的全局变量
59     cout << "t1 g_num is " << p1.t->get() << endl;
60     cout << "t2 g_num is " << p2.t->get() << endl;
61     return 0;
62 }

执行:

g++ -fPIC -shared test.cpp -o libtest_1.so

g++ -fPIC -shared test.cpp -o libtest_2.so

g++ -g -Wl,--no-as-needed -ldl main.cpp -rdynamic

可见两个全局变量也互不干扰。

时间: 2024-10-05 02:44:55

Linux 动态链接库(.so)的使用的相关文章

Linux动态链接库.so文件的创建与使用

1. 介绍         使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个"程序函数库"简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他的程序使用.程序函数库可以使整个程序更加模块化,更容易重新编译,而且更方便升级.  程序函数库可分为3种类型:静态函数库(static libraries).共享函数库(shared libraries).动态加载函数库(dynamically loaded libraries): 1.静态函数

Linux 动态链接库

如何使用动态链接库 Linux下打开使用动态链接库需要三步(实际上和windows下基本一样):1.加载动态链接库,通过调用库函数dlopen()获得链接库的句柄,对应于windows下的 AfxLoadLibrary函数 //参数一filename是.so文件路径 //参数二flag指定解析符号的时间点等 //返回值是链接库的句柄 void *dlopen(const char *filename, int flag); 2.从句柄中获取函数符号加载的内存地址,通过调用dlsym函数返回函数地

Linux动态链接库

[重要资料]http://www.ibm.com/developerworks/cn/linux/l-dynamic-libraries/#list2 动态链接库的生成: 代码上与写静态链接库没什么区别,主要是在编译时,以两个文件举例: /*mylib.h*/void Print(); /*mylib.c*/#include#include "mylib.h" void Print(){printf("This is in mylibn");}编译方法如下: gcc

Linux动态链接库的使用

定义add.h和add.c两个文件   add.h #ifndef ADD_H_ #define ADD_H_ int add(int,int); #endif add.c #include "add.h" int add(int a,int b) { return (a+b); } 编译生成so文件 gcc -shared -fPIC add.c -o libadd.so 编写测试程序 demo.c #include <stdio.h> #include "ad

Linux 动态链接库学习笔记

参考资料: 1. -fpic Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entr

Linux 动态链接库包含静态链接库的方法

今天老司机们在讨论一个编译问题  A是一个静态库  C是一个动态库  B是运行程序,能不能将A打包到C 然后B只需要链接C 就可以了. 这个问题我以前在出来zlib库版本冲突的时候有点印象,所以写了个测试例子,放在了 github 上,地址: https://github.com/raoshaoquan/a https://github.com/raoshaoquan/b https://github.com/raoshaoquan/c 结论是: 可以 记得包含编译选项 -fPIC

Linux下的动态链接库包含漏洞

说明 Nebula是一个用于Linux下提权漏洞练习的虚拟机,其第15关Level15提供了这样一个有漏洞的程序flag15 sh-4.2$ ls -l total 7 -rwsr-x--- 1 flag15 level15 7161 2011-11-20 21:22 flag15 sh-4.2$ whoami level15 要求利用该setuid程序的漏洞,从用户level15提权到用户flag15,执行/bin/getflag. 2. 漏洞挖掘 这道题是一个经典的动态链接库劫持题目,首先用

程序的链接和装入及Linux下动态链接的实现

http://www.ibm.com/developerworks/cn/linux/l-dynlink/ 程序的链接和装入及Linux下动态链接的实现 程序的链接和装入存在着多种方法,而如今最为流行的当属动态链接.动态装入方法.本文首先回顾了链接器和装入器的基本工作原理及这一技术的发展历史,然后通过实际的例子剖析了Linux系统下动态链接的实现.了解底层关键技术的实现细节对系统分析和设计人员无疑是必须的,尤其当我们在面对实时系统,需要对程序执行时的时空效率有着精确的度量和把握时,这种知识更显重

linux库文件编写入门(笔记)

linux库文件的编写 作者: laomai地址: http://blog.csdn.net/laomai 本文主要参考了如下资料⑴hcj写的"Linux静态/动态链接库的创建和使用"地址 http://fanqiang.chinaunix.net/system/linux/2006-05-08/4126.shtml⑵雨亦奇的文章"LINUX动态链接库高级应用"地址http://www.ccw.com.cn/htm/center/prog/02_3_13_3_2.a