当前课程知识点:基于Linux的C++ >  第十二讲 Linux系统编程基础 >  12.11 库(二) >  LinuxCPP1211

返回《基于Linux的C++》慕课在线视频课程列表

LinuxCPP1211在线视频

LinuxCPP1211

下一节:LinuxCPP1212

返回《基于Linux的C++》慕课在线视频列表

LinuxCPP1211课程教案、知识点、字幕

当我们需要使用动态库的时候

可以调用 dlopen() 函数

把这个动态库装载到内存里

dlopen() 这个函数

它所对应的头文件是 “dlfcn.h”

dlopen() 这个函数带两个参数

一个参数是 filename 一个参数是 flag

返回值类型是一个 void * 哑型指针

filename 表示的就是动态库的名字

flag 就是这个动态库的装载标志

典型的两个值是 RTLD_LAZY 和 RTLD_NOW

典型的两个值是 RTLD_LAZY 和 RTLD_NOW

RTLD_LAZY 就表示动态库的装载是惰性装载

RTLD_LAZY 就表示动态库的装载是惰性装载

就是需要的时候

才会把这个动态库装载到内存里

RTLD_NOW 是马上装载

立即装载的意思

就是 dlopen() 这个函数一执行完

就把这个动态库装载到内存里面了

一般情况下面

我们写一个程序要装载一个动态库

总是希望什么呢

就是希望这个动态库

在需要的时候才装载在内存里

我们并不需要一开始

就把这个程序需要使用到的所有动态库

都装载到内存里

所以我们参数往往给的是 RTLD_LAZY

返回值呢

就是装载完成以后这个动态库的句柄

相当于我们前面谈到的那个文件描述符

你比如讲

如果我有一个库名叫 “libtest.so”

我想把它装载进去

这是个动态库了

所以我要装载的话

我就调用 dlopen() 这个函数

传这个库的名字

传装载的标志 RTLD_LAZY

我就把它装载进去了

这个函数就会返回一个哑型指针

我们要用一个量

来记录这个函数的返回值

然后每次使用这个动态库里的函数的时候

然后每次使用这个动态库里的函数的时候

就可以使用这个动态库的句柄来去查询的

就可以使用这个动态库的句柄来去查询的

那么具体怎么查询动态库里边的某一个函数呢

那么具体怎么查询动态库里边的某一个函数呢

这里边就有一个查找和装载

动态库里的函数用的函数

叫 dlsym() 它带两个参数

一个参数是哑型指针 handle

一个参数是字符串 symbol

第一个参数 handle

就表示你要装载的那个动态库

返回的那个哑型指针

你不是要查一个函数吗

这个函数不是在这个动态库里吗

好吧 你就在那个动态库里查

那哪一个动态库呢

当然就用这个哑型指针表示的那个动态库

当然就用这个哑型指针表示的那个动态库

所以 handle 传过来的那个值

那个参数 就是 dlopen() 返回值

第二个呢 就是那个函数的名字

你想调用哪个函数

那么你就用这个名字去查找它

就完了 它的返回值呢

就是那个函数所对应的入口地址

所以你别看它返回值写的是一个 void *

它事实上是一个函数指针

这个地方是需要特别注意的

当动态库用完以后你不想用了

那你就可以 dlclose()

就关闭这个动态库

传递动态库的句柄给它

它就负责把这个动态库

给关闭或卸载

当在动态库的装载、函数的查询、

关闭的过程中出现了问题

就可以使用 dlerror() 这个函数来处理它的错误

就可以使用 dlerror() 这个函数来处理它的错误

我们看具体的例子

假设我有一个动态库

我想调用动态库中的某一个函数

我们设这个函数的名字是 g

那么我们怎么去装载这个函数呢

代码就在这里

定义一个哑型指针 handle

把它初始化成

dlopen( "libtest.so", RTLD_LAZY )

我们会动态装载 “libtest.so” 这个动态库

打开它 得到这个动态库的句柄

初始化给 handle

然后我们会调用 dlsym()

在这个动态库里查找函数 g

传参数 handle 传字符串 “g”

g 就是函数的名字

我们得到的就是指向 g 这个函数的函数指针

我们得到的就是指向 g 这个函数的函数指针

假设我们这个函数指针

它是这个样子 void ( *test )

就是没有参数 没有返回值

那么你就可以定义这样的一个函数指针变量 test

那么你就可以定义这样的一个函数指针变量 test

然后把它初始化成 dlsym() 的返回值

单独定义一个函数类型

然后根据函数类型定义我们的函数指针变量

然后根据函数类型定义我们的函数指针变量

再把那个函数指针变量赋值或初始化为 dlsym() 的结果也可以

再把那个函数指针变量赋值或初始化为 dlsym() 的结果也可以

有了这个函数指针

指向 g 函数的函数指针

我们就可以在 test 上

调用 g 函数 ( *test )

我们就调用那个 g 函数

通过函数指针调用 g 函数

调用完了 这库不就用完了

我们就 dlclose( handle )

就可以关闭这个动态库

动态库里的函数

都是按照这样的方式处理的

但同学们要注意

因为动态库的链接

需要使用 “-ldl” 选项

确保它能够被链接进去

还需要注意的是

动态库代码的实现

其中的很多函数 它都是 C 的格式

所以当你进行混合 C/C++ 代码编程的时候

所以当你进行混合 C/C++ 代码编程的时候

就需要特别注意

凡是那些 C 函数

都应该用 extern "C"{}的格式

把它的函数的原型、函数的实现都封装起来

把它的函数的原型、函数的实现都封装起来

表示它是一个 C 格式

而不是 C++ 的格式

为啥 就是因为在 C++ 代码下边

C 格式的函数和 C++ 格式的函数

函数签名是不一样的

因为 C 不支持函数重载

而 C++ 是支持函数重载的

支持重载的 C++ 函数签名

和不支持重载的 C 函数签名

是不一样的 所以为了保证

能够正确解析到 C 的函数

那么你的 C 的函数

必须封装在 extern "C"{}里

那么如果你本质上

写的基本上是 C 的代码

而不是 C++ 的代码

那么你也可以倒过来

把 C++ 的代码封装到 extern "C++"{}里

也可以

就是混合 C/C++ 编程的时候

需要特别注意的一个问题

就在这个地方

同学们一定要记住了

因为我们动态库里面的相当多的代码

都是 C 实现 而不是 C++ 实现

基于Linux的C++课程列表:

第一讲 C/C++基本语法元素

-1.1 提纲

--LinuxCPP0101

-1.2 程序设计的基本概念

--LinuxCPP0102

-1.3 简单C/C++程序介绍

--LinuxCPP0103

-1.4 程序设计的基本流程

--LinuxCPP0104

-1.5 基本语法元素

--LinuxCPP0105

-1.6 程序设计风格

--LinuxCPP0106

-1.7 编程实践

--LinuxCPP0107

-第一讲 C/C++基本语法元素--编程实践提交入口

第二讲 程序控制结构

-2.1 提纲

--LinuxCPP0201

-2.2 结构化程序设计基础

--LinuxCPP0202

-2.3 布尔数据

--LinuxCPP0203

-2.4 分支结构

--LinuxCPP0204

-2.5 break语句

--LinuxCPP0205

-2.6 循环结构

--LinuxCPP0206

-2.7 编程实践

--LinuxCPP0207

-第二讲 程序控制结构--编程实践提交入口

第三讲 函数

-3.1 提纲

--LinuxCPP0301

-3.2 函数声明、调用与定义

--LinuxCPP0302

-3.3 函数调用栈框架

--LinuxCPP0303

-3.4 编程实践

--LinuxCPP0304

-第三讲 函数--编程实践提交入口

第四讲 算法

-4.1 提纲

--LinuxCPP0401

-4.2 算法概念与特征

--LinuxCPP0402

-4.3 算法描述

--LinuxCPP0403

-4.4 算法设计与实现

--LinuxCPP0404

-4.5 递归算法(一)

--LinuxCPP0405

-4.6 递归算法(二)

--LinuxCPP0406

-4.7 容错与计算复杂度

--LinuxCPP0407

-4.8 编程实践

--LinuxCPP0408

-第四讲 算法--编程实践提交入口

第五讲 程序组织与开发方法

-5.1 提纲

--LinuxCPP0501

-5.2 库与接口

--LinuxCPP0502

-5.3 随机数库(一)

--LinuxCPP0503

-5.4 随机数库(二)

--LinuxCPP0504

-5.5 作用域与生存期

--LinuxCPP0505

-5.6 典型软件开发流程(一)

--LinuxCPP0506

-5.7 典型软件开发流程(二)

--LinuxCPP0507

-5.8 编程实践

--LinuxCPP0508

-第五讲 程序组织与开发方法--编程实践提交入口

第六讲 复合数据类型

-6.1 提纲

--LinuxCPP0601

-6.2 字符

--LinuxCPP0602

-6.3 数组(一)

--LinuxCPP0603

-6.4 数组(二)

--LinuxCPP0604

-6.5 结构体

--LinuxCPP0605

-6.6 编程实践

--LinuxCPP0606

-第六讲 复合数据类型--编程实践提交入口

第七讲 指针与引用

-7.1 提纲

--LinuxCPP0701

-7.2 指针基本概念

--LinuxCPP0702

-7.3 指针与函数

--LinuxCPP0703

-7.4 指针与复合数据类型(一)

--LinuxCPP0704

-7.5 指针与复合数据类型(二)

--LinuxCPP0705

-7.6 字符串

--LinuxCPP0706

-7.7 动态存储管理(一)

--LinuxCPP0707

-7.8 动态存储管理(二)

--LinuxCPP0708

-7.9 引用

--LinuxCPP0709

-7.10 编程实践

--LinuxCPP0710

-第七讲 指针与引用--编程实践提交入口

第八讲 链表与程序抽象

-8.1 提纲

--LinuxCPP0801

-8.2 数据抽象(一)

--LinuxCPP0802

-8.3 数据抽象(二)

--LinuxCPP0803

-8.4 链表(一)

--LinuxCPP0804

-8.5 链表(二)

--LinuxCPP0805

-8.6 链表(三)

--LinuxCPP0806

-8.7 链表(四)

--LinuxCPP0807

-8.8 函数指针(一)

--LinuxCPP0808

-8.9 函数指针(二)

--LinuxCPP0809

-8.10 抽象链表(一)

--LinuxCPP0810

-8.11 抽象链表(二)

--LinuxCPP0811

-8.12 编程实践

--LinuxCPP0812

-第八讲 链表与程序抽象--编程实践提交入口

第九讲 类与对象

-9.1 提纲

--LinuxCPP0901

-9.2 程序抽象与面向对象

--LinuxCPP0902

-9.3 类类型

--LinuxCPP0903

-9.4 对象(一)

--LinuxCPP0904

-9.5 对象(二)

--LinuxCPP0905

-9.6 类与对象的成员(一)

--LinuxCPP0906

-9.7 类与对象的成员(二)

--LinuxCPP0907

-9.8 类与对象的成员(三)

--LinuxCPP0908

-9.9 继承(一)

--LinuxCPP0909

-9.10 继承(二)

--LinuxCPP0910

-9.11 继承(三)

--LinuxCPP0911

-9.12 多态(一)

--LinuxCPP0912

-9.13 多态(二)

--LinuxCPP0913

-9.14 编程实践

--LinuxCPP0914

-第九讲 类与对象--编程实践提交入口

第十讲 操作符重载

-10.1 提纲

--LinuxCPP1001

-10.2 四则运算符重载(一)

--LinuxCPP1002

-10.3 四则运算符重载(二)

--LinuxCPP1003

-10.4 关系与下标操作符重载

--LinuxCPP1004

-10.5 赋值操作符重载(一)

--LinuxCPP1005

-10.6 赋值操作符重载(二)

--LinuxCPP1006

-10.7 赋值操作符重载(三)

--LinuxCPP1007

-10.8 赋值操作符重载(四)

--LinuxCPP1008

-10.9 赋值操作符重载(五)

--LinuxCPP1009

-10.10 流操作符重载(一)

--LinuxCPP1010

-10.11 流操作符重载(二)

--LinuxCPP1011

-10.12 流操作符重载(三)

--LinuxCPP1012

-10.13 操作符重载总结

--LinuxCPP1013

-10.14 编程实践

--LinuxCPP1014

-第十讲 操作符重载--编程实践提交入口

第十一讲 泛型编程

-11.1 提纲

--LinuxCPP1101

-11.2 泛型编程概览

--LinuxCPP1102

-11.3 异常处理机制(一)

--LinuxCPP1103

-11.4 异常处理机制(二)

--LinuxCPP1104

-11.5 运行期型式信息(一)

--LinuxCPP1105

-11.6 运行期型式信息(二)

--LinuxCPP1106

-11.7 模板与型式参数化

--LinuxCPP1107

-11.8 题外话:术语翻译

--LinuxCPP1108

-11.9 泛型编程实践(一)

--LinuxCPP1109

-11.10 泛型编程实践(二)

--LinuxCPP1110

-11.11 泛型编程实践(三)

--LinuxCPP1111

-11.12 泛型编程实践(四)

--LinuxCPP1112

-11.13 泛型编程实践(五)

--LinuxCPP1113

-11.14 泛型编程实践(六)

--LinuxCPP1114

-11.15 泛型编程实践(七)

--LinuxCPP1115

-11.16 泛型编程实践(八)

--LinuxCPP1116

-11.17 泛型编程实践(九)

--LinuxCPP1117

-11.18 泛型编程实践(十)

--LinuxCPP1118

-11.19 编程实践

--LinuxCPP1119

-第十一讲 泛型编程--编程实践提交入口

第十二讲 Linux系统编程基础

-12.1 提纲

--LinuxCPP1201

-12.2 程序执行环境(一)

--LinuxCPP1202

-12.3 程序执行环境(二)

--LinuxCPP1203

-12.4 程序执行环境(三)

--LinuxCPP1204

-12.5 程序执行环境(四)

--LinuxCPP1205

-12.6 输入输出(一)

--LinuxCPP1206

-12.7 输入输出(二)

--LinuxCPP1207

-12.8 文件系统

--LinuxCPP1208

-12.9 设备

--LinuxCPP1209

-12.10 库(一)

--LinuxCPP1210

-12.11 库(二)

--LinuxCPP1211

-12.12 makefile文件(一)

--LinuxCPP1212

-12.13 makefile文件(二)

--LinuxCPP1213

-12.14 makefile文件(三)

--LinuxCPP1214

-12.15 编程实践

--LinuxCPP1215

-第十二讲 Linux系统编程基础--编程实践提交入口

第十三讲 进程编程

-13.01 提纲

--LinuxCPP1301

-13.02 进程基本概念

--LinuxCPP1302

-13.03 信号

--LinuxCPP1303

-13.04 进程管理(一)

--LinuxCPP1304

-13.05 进程管理(二)

--LinuxCPP1305

-13.06 进程管理(三)

--LinuxCPP1306

-13.07 进程间通信(一)

--LinuxCPP1307

-13.08 进程间通信(二)

--LinuxCPP1308

-13.09 进程间通信(三)

--LinuxCPP1309

-13.10 进程间通信(四)

--LinuxCPP1310

-13.11 进程池

--LinuxCPP1311

-13.12 编程实践

--LinuxCPP1312

-第十三讲 进程编程--编程实践提交入口

第十四讲 线程编程

-14.1 提纲

--LinuxCPP1401

-14.2 线程基本概念

--LinuxCPP1402

-14.3 线程管理(一)

--LinuxCPP1403

-14.4 线程管理(二)

--LinuxCPP1404

-14.5 线程管理(三)

--LinuxCPP1405

-14.6 线程管理(四)

--LinuxCPP1406

-14.7 线程同步机制(一)

--LinuxCPP1407

-14.8 线程同步机制(二)

--LinuxCPP1408

-14.9 C++11线程库(一)

--LinuxCPP1409

-14.10 C++11线程库(二)

--LinuxCPP1410

-14.11 C++11线程库(三)

--LinuxCPP1411

-14.12 C++11线程库(四)

--LinuxCPP1412

-14.13 C++11线程库(五)

--LinuxCPP1413

-14.14 编程实践

--LinuxCPP1414

-第十四讲 线程编程--编程实践提交入口

第十五讲 网络编程

-15.1 提纲

--LinuxCPP1501

-15.2 Internet网络协议

--LinuxCPP1502

-15.3 套接字(一)

--LinuxCPP1503

-15.4 套接字(二)

--LinuxCPP1504

-15.5 编程实践

--LinuxCPP1505

-第十五讲 网络编程--编程实践提交入口

课程文档

-课程PDF文件

LinuxCPP1211笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。