当前位置: 首页 > 编程日记 > 正文

程序员的自我修养--链接、装载与库笔记:Windows PE/COFF

1. Windows的二进制文件格式PE/COFF

在32位Windows平台下,微软引入了一种叫PE(Portable Executable)的可执行格式。作为Win32平台的标准可执行文件格式,PE有着跟ELF一样良好的平台扩展性和灵活性。PE文件格式事实上与ELF同根同源,它们都是由COFF(Common Object File Format)格式发展而来的,更加具体地讲是来源于当时著名的DEC(Digital Equipment Corporation)的VAX/VMS上的COFF文件格式。微软将它的可执行文件格式命名为”Portable Executable”,从字面意义上讲是希望这个可执行文件格式能够在不同版本的Windows平台上使用,并且可以支持各种CPU。

在Windows平台,VISUAL C++编译器产生的目标文件仍然使用COFF格式,而可执行文件为PE格式

随着64位Windows的发布,微软对64位Windows平台上的PE文件结构稍微做了一些修改,这个新的文件格式叫做PE32+。新的PE32+并没有添加任何结构,最大的变化就是把那些原来32位的字段变成了64位。绝大部分情况下,PE32+与PE的格式一致,我们可以将它看作是一般的PE文件。

与ELF文件相同,PE/COFF格式也是采用了那种基于段的格式。一个段可以包含代码、数据或其它信息,在PE/COFF文件中,至少包含一个代码段,这个代码段的名字往往叫做”.code”,数据段叫做”.data”。不同的编译器产生的目标文件的段名不同,VISUAL C++使用”.code”和”.data”,而Borland的编译器使用”CODE”, “DATA”。也就是说跟ELF一样,段名只有提示性作用,并没有实际意义。

跟ELF一样,PE中也允许程序员将变量或函数放到自定义的段。在GCC中我们使用”__attribute__((section(“name”)))”扩展属性,在VISUAL C++中可以使用”#pragma”编译器指示,如”#pragma data_set(“name”)”。

2. PE的前身----COFF

SimpleSection.c内容如下:

int printf(const char* format, ...);int global_init_var = 84;
int global_uninit_var;void func1(int i)
{printf("%d\n", i);
}int main(void)
{static int static_var = 85;static int static_var2;int a = 1;int b;func1(static_var + static_var2 + a + b);return a;
}

以管理员身份打开cmd.exe,然后在C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64目录下,先执行vcvars64.bat,然后定位到SimpleSection.c所在的目录E:\test\下,执行”cl.exe /c /Za SimpleSection.c”,会生成目标文件SimpleSection.obj,执行结果如下图所示:

“cl.exe”是VISUAL C++的编译器,即”Compiler”的缩写。”/c”参数表示只编译,不链接,即将.c文件编译成.obj文件,而不调用链接器生成.exe文件。如果不加这个参数,cl.exe会在编译”SimpleSection.c”文件以后,再调用link.exe链接器将该产生的SimpleSection.obj文件与默认的C运行库链接,产生可执行文件SimpleSection.exe。

VISUAL C++有一些C和C++语言的专有扩展,这些扩展并没有定义ANSI C标准或ANSI C++标准。”/Za”参数禁用这些扩展,使得我们的程序跟标准的C/C++兼容。使用”/Za”参数时,编译器自动定义了__STDC__这个宏,我们可以在程序里通过判断这个宏是否被定义而确定编译器是否禁用了Microsoft C/C++语法扩展。

跟GNU的工具链中的”objdump”一样,Visual C++也提供了一个用于查看目标文件和可执行文件的工具,就是”dumpbin.exe”。通过这个命令可以查看SimpleSection.obj的结构,”/ALL”参数是将打印输出目标文件的所有相关信息,包括文件头、每个段的属性和段的原始数据及符号表。也可以用”/SUMMARY”选项来查看整个文件的基本信息,它只输出所有段的段名和长度,执行结果如下图所示:

COFF文件结构:几乎跟ELF文件一样,COFF也是由文件头及后面的若干个段组成,再加上文件末尾的符号表、调试信息的内容,就构成了COFF文件的基本结构。COFF文件的文件头部包括了两部分,一个是描述文件总体结构和属性的映像头(Image Header),另外一个是描述该文件中包含的段属性的段表(Section Table)。文件头后面紧跟着的就是文件的段,包括代码段、数据段等,最后还有符号表等。

映像(Image):因为PE文件在装载时被直接映射到进程的虚拟空间中运行,它是进程的虚拟空间的映像。所以PE可执行文件很多时候被叫做映像文件(Image File)。

文件头里描述COFF文件总体属性的映像头是一个”IMAGE_FILE_HEADER”的结构,它跟ELF中的”Elf64_Ehdr”结构的作用相同。这个结构及相关常数被定义在” C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include”里面:

//
// File header format.
//typedef struct _IMAGE_FILE_HEADER {WORD    Machine;WORD    NumberOfSections;DWORD   TimeDateStamp;DWORD   PointerToSymbolTable;DWORD   NumberOfSymbols;WORD    SizeOfOptionalHeader;WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;#define IMAGE_SIZEOF_FILE_HEADER             20

对照前面”SimpleSection.txt”中的输出信息,我们可以看到输出的信息里面最开始一段”FILE HEADER VALUES”中的内容跟COFF映像头中的成员是一一对应的,如下图所示:

可以看到这个目标文件的文件类型是”COFF OBJECT”,也就是COFF目标文件格式。文件头里面还包含了目标机器类型,例子里的类型是0x8664。按照微软的预想,PE/COFF结构的可执行文件应该可以在不同类型的硬件平台上使用,所以预留了该字段。在WinNT.h里面可以找到相应的以”IMAGE_FILE_MACHINE_”开头的目标机器类型的定义。文件头里面的”Number of Sections”是指该PE所包含的”段”的数量。”Time date stamp”是指PE文件的创建时间。“File pointer to symbol table”是符号表在PE中的位置。”Size of optional header”是指Optional Header的大小,这个结构只存在于PE可执行文件,COFF目标文件中该结构不存在,所以为0.

映像头后面紧跟着的就是COFF文件的段表,它是一个类型为”IMAGE_SECTION_HEADER”结构的数组,数组里面每个元素代表一个段,这个结构跟ELF文件中的”Elf64_Shdr”很相似。这个数组元素的个数刚好是该COFF文件所包含的段的数量,也就是映像头里面的”number of sections”。这个结构是用来描述每个段的属性的,它也被定义在WinNT.h里面:

//
// Section header format.
//#define IMAGE_SIZEOF_SHORT_NAME              8typedef struct _IMAGE_SECTION_HEADER {BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];union {DWORD   PhysicalAddress;DWORD   VirtualSize;} Misc;DWORD   VirtualAddress;DWORD   SizeOfRawData;DWORD   PointerToRawData;DWORD   PointerToRelocations;DWORD   PointerToLinenumbers;WORD    NumberOfRelocations;WORD    NumberOfLinenumbers;DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;#define IMAGE_SIZEOF_SECTION_HEADER          40

可以看到每个段所拥有的属性包括段名(Section Name)、物理地址(Physical address)、虚拟地址(Virtual address)、原始数据大小(Size of raw data)、段在文件中的位置(File pointer ro raw data)、该段的重定位表在文件中的位置(File pointer to relocation table)、该段的行号表在文件中的位置(File pointer to line numbers)、标志位(Characteristics)等。VirtualSize:该段被加载至内存后的大小;VirtualAddress:该段被加载至内存后的虚拟地址;SizeOfRawData:该段在文件中的大小。注意:这个值有可能跟VirtualSize的值不一样,比如.bss段的SizeOfRawData是0,而VirtualSize值是.bss段的大小。另外涉及一些内存对齐等问题,这个值往往比VirtualSize小。Characteristics:段的属性,属性里包含的主要是段的类型(代码、数据、bss)、对齐方式及可读可写可执行等权限。段的属性是一些标志位的组合,这些标志位被定义在WinNT.h里,比如IMAGE_SCN_CNF_CODE(0x00000020)表示该段里面包含的是代码,等等。

段表以后就是一个个的段的实际内容了。COFF中的代码段、数据段、BSS段的内容及它们的存储方式与ELF中几乎一样。

3. 链接指示信息

SimpleSection.txt中”.drectve”段相关的内容如下图所示:

“.drectve”段实际上是”Directive”的缩写,它的内容是编译器传递给链接器的指令(Directive),即编译器希望告诉链接器应该怎样链接这个目标文件。段名后面就是段的属性,包括地址、长度、位置等与ELF中存在的相同的属性,最后一个属性是标志位”flags”,即IMAGE_SECTION_HEADERS里面的Characteristics成员。”.drectve”段的标志位为”0x100A00”,它是下表中标志位的组合:

“dumpbin”已经为我们打印出了标志位的三个组合属性:Inof、Remove、1 byte align。即该段是信息段,并非程序数据;该段可以在最后链接成可执行文件的时候被抛弃;该段在文件中的对齐方式是1个字节对齐。

输出信息中紧随其后的是该段在文件中的原始数据(RAW DATA #1,用十六进制显示的原始数据及相应的ASCII字符)。”dumpbin”知道该段是个”.drectve”段,并且对段的内容进行了解析,解析结果为一个”/DEFAULTLIB:’LIBCMT’”的链接指令(Linker Directives),实际上它就是”cl.exe”编译器希望传给”link.exe”链接器的参数。这个参数表示编译器希望告诉链接器,该目标文件需要LIBCMT这个默认库。LIBCMT的全称是Library C Multithread,它表示VC的静态链接的多线程C库,对应的文件在VC安装目录下的lib/libcmt.lib。我们可以在cl.exe编译器里面加入/Zl来关闭默认C库的链接指令。

4. 调试信息

COFF文件中所有以”.debug”开始的段都包含着调试信息。比如”.debug$S”表示包含的是符号(Symbol)相关的调试信息段;”.debug$P”表示包含预编译头文件(Precompiled Header Files)相关的调试信息段;”.debug$T”表示包含类型(Type)相关的调试信息段。在”SimpleSection.obj”中,我们只看到了”.debug$S”段,也就是只有调试时的相关信息。我们可以从该段的文本信息中看到目标文件的原始路径,编译器信息等。调试信息段的具体格式被定义在PE格式文件标准中。调试段相关信息在”SimpleSection.txt”中的内容如下:

5. 大家都有符号表

“SimpleSection.txt”的最后部分是COFF符号表(Symbol table),COFF文件的符号表包含的内容几乎跟ELF文件的符号表一样,主要就是符号名、符号的类型、所在的位置。”SimpleSection.txt”关于符号表的输出如下所示:

在输出结果的最左列是符号的编号,也就是符号在符号表中的下标。接着是符号的大小,即符号所表示的对象所占用的空间。第三列是符号所在的位置,ABS(Absolute)表示符号是个绝对值,即一个常量,它不存在于任何段中;SECT1(Section #1)表示符号所表示的对象定义在本COFF文件的第一个段中,即本例中的”.drectve”段;UNDEF(Undefined)表示符号是未定义的,即这个符号被定义在其它目标文件中。第四列是符号类型,可以看到对于C语言的符号,COFF只区分了两种,一种是变量和其它符号,类型为notype,另外一种是函数,类型为notype (),这个符号类型值可以用于其它一些需要强符号类型的语言或系统中,可以给链接器更多的信息来识别符号的类型。第五列是符号的可见范围,Static表示符号是局部变量,只有目标文件内部是可见的;External表示符号是全局变量,可以被其它目标文件引用。最后一列是符号名,对于不需要修饰的符号名,”dumpbin”直接输出原始的符号名;对于那些经过修饰的符号名,它会把修饰前和修饰后的名字都打印出来,后面括号里面的就是未修饰的符号名。

从符号表的dump输出信息中,我们可以看到”global_init_var”这个符号位于Section #3,即”.data”段。另外还有一个$SG1326的符号,其实它表示的是程序中的那个”%d\n”字符串常量。因为程序中要引用到这个字符串常量,而该字符串常量又没有名字,所以编译器自动为它生成了一个名字,并且作为符号放在符号表里面,可以看到这个符号对外都是不可见的。ELF文件中并没有为字符串常量自动生成的符号,另外所有的段名都是一个符号,”dumpbin”如果碰到某个符号是一个段的段名,那么它还会解析该符号所表示的段的基本属性,每个段名符号后面紧跟着一行就是段的基本属性,分别是段长度、重定位数、行号数和校验和。

6. Windows下的ELF----PE

PE文件是基于COFF的扩展,它比COFF文件多了几个结构。最主要的变化有两个:第一个是文件最开始的部分不是COFF文件头,而是DOS MZ可执行文件格式的文件头和桩代码(DOS MZ File Header and Stub);第二个变化是原来的COFF文件头中的”IMAGE_FILE_HEADER”部分扩展成了PE文件文件头结构”IMAGE_NT_HEADERS”,这个结构包括了原来的”Image Header”及新增的PE扩展头部结构(PE Optional Header)。PE文件的结构如下图所示:

DOS下的可执行文件的扩展名与Windows下的可执行文件扩展名一样,都是”.exe”,但是DOS下的可执行文件格式是”MZ”格式,与Windows下的PE格式完全不同,虽然它们使用相同的扩展名。PE文件中的”Image DOS Header”和”DOS Stub”这两个结构就是为了兼容DOS系统而设计的,其中”IMAGE_DOS_HEADER”结构其实跟DOS的”MZ”可执行结构的头部完全一样,所以从某个角度看,PE文件其实也是一个”MZ”文件。”IMAGE_DOS_HEADER”的结构中有的前两个字节是”e_magic”结构,它是里面包含了”MZ”这两个字母的ASCII码;”e_cs”和”e_ip”两个成员指向程序的入口地址。

当PE可执行映像在DOS下被加载的时候,DOS系统检测该文件,发现最开始两个字节是”MZ”,于是认为它是一个”MZ”可执行文件。然后DOS系统就将PE文件当作正常的”MZ”文件开始执行。DOS系统会读取”e_cs”和”e_ip”这两个成员的值,以跳转到程序的入口地址。然而PE文件中,”e_cs”和”e_ip”这两个成员并不指向程序真正的入口地址,而是指向文件中的”DOS Stub”。”DOS Stub”是一段可以在DOS下运行的一小段代码,这段代码的唯一作用是向终端输出一行字:”This program cannot be run in DOS”,然后退出程序,表示该程序不能在DOS下运行。所以我们如果在DOS系统下运行Windows的程序就可以看到上面这句话,这是因为PE文件结构兼容DOS “MZ”可执行文件结构的缘故。

“IMAGE_DOS_HEADER”结构也被定义在WinNT.h里面,里面的”e_lfanew”成员表明了PE文件头(IMAGE_NT_HEADERS)在PE文件中的偏移,我们需要使用这个值来定位PE文件头。这个成员在DOS的”MZ”文件格式中它的值永远为0,所以当Windows开始执行一个后缀名为”.exe”的文件时,它会判断”e_lfanew”成员是否为0。如果为0,则该”.exe”文件是一个DOS  “MZ”可执行文件,Windows会启动DOS子系统来执行它;如果不为0,那么它就是一个Windows的PE可执行文件,”e_lfanew”的值表示”IMAGE_NT_HEADERS”在文件中的偏移。

“IMAGE_NT_HEADERS”是PE真正的文件头,它包含了一个标记(Signature)和两个结构体。标记是一个常量。文件头包含的两个结构分别是映像头(Image Header)、PE扩展头部结构(Image Optional Header)。

Windows中把32位的PE文件格式叫做PE32,把64位的PE文件格式叫做PE32+。这两种格式就是ELF32和ELF64一样,都大同小异,只不过关于地址和长度的一些成员从32位扩展成了64位,还增加了若干个额外的成员之外,没有其它区别。

我们平时可以使用”IMAGE_OPTIONAL_HEADER”作为”Optional Image Header”的定义。它是一个宏,在64位的Windows下,Visual C++在编译时会定义”_WIN64”这个宏,那么”IMAGE_OPTIONAL_HEADER”就被定义成”IMAGE_OPTIONAL_HEADER64”;32位Windows下没有定义”_WIN64”这个宏,那么它就是”IMAGE_OPTIONAL_HEADER32”。

PE数据目录:在Windows系统装载PE可执行文件时,往往需要很快地找到一些装载所需要的数据结构,比如导入表、导出表、资源、重定位表等。这些常用的数据的位置和长度都被保存在了一个叫做数据目录(Data Directory)的结构里面,其实它就是”IMAGE_OPTIONAL_HEADER”结构里面的”DataDirectory”成员。这个成员是一个”IMAGE_DATA_DIRECTORY”的结构数组,相关的定义如下:

//
// Directory format.
//typedef struct _IMAGE_DATA_DIRECTORY {DWORD   VirtualAddress;DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

可以看到这个数组的大小为16,IMAGE_DATA_DIRECTORY结构有两个成员,分别是虚拟地址以及长度。DataDirectory数组里面每一个元素都对应一个包含一定含义的表。”WinNT.h”里面定义了一些以”IMAGE_DIRECTORY_ENTRY_”开头的宏,数值从0到14,它们实际上就是相关的表的宏定义在数组中的下标。比如”IMAGE_DIRECTORY_ENTRY_EXPORT”被定义为0,所以这个数组的第一个元素所包含的地址和长度就是导出表(Export Table)所在的地址和长度。这个数组中还包含其它的表,不如导入表、资源表、异常表、重定位表、调试信息表、线程私有存储(TLS)等的地址和长度。这些表多数跟装载和DLL动态链接有关,与静态链接没什么关系。

GitHub: https://github.com/fengbingchun/Messy_Test

相关文章:

神州数码与神州控股、神州信息共同主办首届技术年会,透露出什么信号?

11 月 8 日,神州控股、神州数码集团、神州信息共同主办“数字中国 2019 技术年会”,聚焦云计算、大数据、人工智能、区块链、5G 等前沿技术创新与应用实践,众多领域的技术专家展开了深度交流,共同探讨数字时代的技术创新与协同发展…

osi七层协议和tcp/ip四层协议

(大部分内容为转载)OSI(Open System Interconnection)是一个开放性的通行系统互连参考模型,他是一个定义的非常好的协议规范,共包含七层协议。OSI七层协议是由ISO (International Standards Organization)在…

Swift中页面跳转与传值:

1.简单方式 首先,Swift的跳转可分为利用xib文件跳转与storyboard跳转两种方法,我这里选择使用storyboard的界面跳转方法。 1、通过在storyboard中拉button控件建立segue跳转。 2、通过presentViewController方法进行界面跳转。 这里需要注意presentV…

知乎热议!学完Python之后,我的编程能力竟然退化了!

在知乎上有一个特别火的问题:如何学Python?你会看到很多高赞回答是:我一天就学完了。在大家群嘲的背后,我们来分析一下,为什么在已经学过的人眼里,Python这么容易学,甚至简单到被某些人鄙视呢&a…

libjpeg-turbo介绍及测试代码

很多年之前在https://blog.csdn.net/fengbingchun/article/details/10171583 中简单介绍过libjpeg-turbo的安装,因为libjpeg-turbo一直在维护更新,较之前有了些变化,这里再次整理下,并增加更多的测试代码。 libjpeg-turbo的主页为…

高级特性-多线程,GUI

2019独角兽企业重金招聘Python工程师标准>>> 创建线程两种方式第一种,导入improt thread 模块,thread.start_new_thread(功能函数名称,(参数1,参数2...)) 后面参数为功能函数的参数第二个方式类似于java,导…

Hulu视频如何提升推荐多样性?

作者 | 余沾 整理 | 深度传送门(ID: deep_deliver)导读:本文主要介绍Hulu在NIPS 2018上发表的《Fast Greedy MAP Inference for Determinantal Point Process to Improve Recommendation Diversity》中,提出的DPP算法解决视频推荐…

UITextField长度限制的写法

1.遵循代理 UITextFieldDelegate 2.点击响应方法 userNameText.addTarget(self, action: "tappedOne:", forControlEvents: UIControlEvents.EditingChanged) 3.方法的实现 func tappedOne(textField: UITextField) { textField.text textField.text?.uppercaseS…

通过Python在Windows或Linux上快速搭建HTTP服务器

在Windows 7/10或Ubuntu上可以通过python2.x或python3.x来快速搭建一个简单的HTTP服务器。 如果python为2.x,则可执行:$ python -m SimpleHTTPServer 或 $ python2 -m SimpleHTTPServer 如果python为3.x,则可执行:$ python -m h…

NAND FLASH

NAND Flash 以Micron公司的MT29F2G08为例介绍NAND Flash原理和使用。 1. 概述 MT29F2G08使用一个高度复用的8-bit总线(I/O[7:0])来数据传输、地址、指令。5个命令脚(CLE、ALE、CE#、WE#)实现NAND命令总线接口规程。3个…

swift 中跳转web view的两种方法

首先 遵循代理 引入头文件 #import <WebKit/WebKit.h> 第一种情况 直接跳转 了解不含特殊字符的 import UIKit class NewsViewController: UIViewController,WKNavigationDelegate,UIScrollViewDelegate { var webView : WKWebView WKWebView() override func viewW…

YAML开源库yaml-cpp简介及使用

关于YAML的介绍可以参考&#xff1a;https://blog.csdn.net/fengbingchun/article/details/88090609 yaml-cpp是用c实现的用来解析和生成yaml文件的&#xff0c;源码地址在https://github.com/jbeder/yaml-cpp &#xff0c;这里使用的是最新发布的稳定版0.6.2. 解析和产生yam…

数据安全引担忧?get它,让你吃一颗“定心丸”

网络购物、在线外卖、远程教育、共享单车……如今&#xff0c;这些数字化的消费场景在个人生活中早已司空见惯。同时&#xff0c;在数字化浪潮下&#xff0c;越来越多的企业意识到大数据资产的价值&#xff0c;并试图推动其数字化转型。数据经济飞速发展&#xff0c;带来便捷和…

ETL数据抽取策略

ETL的抽取策略本文所提到的数据加载策略为OLTP系统作为源系统&#xff0c;并进行ETL数据加载到OLAP系统中所采用的一般数据加载策略。依循数据仓库的工作方式&#xff0c;原始资料由源数据库被抽取出来后&#xff0c;将在中间过程被写入到”Operational Data Store”(ODS)&…

iOS下拉tableView实现上面的图片放大效果

#import "ViewController.h" #define kScreenbounds [UIScreen mainScreen].bounds #define kScreenWidth [UIScreen mainScreen].bounds.size.width #define kScreenHeight [UIScreen mainScreen].bounds.size.height // 宏定义一个高度 #define pictureHeight 200…

在Windows7/10上通过VS2013编译FFmpeg 4.1.3源码操作步骤

多年前在https://blog.csdn.net/fengbingchun/article/details/40951403 中对FFmpeg在windows下的编译过程做过说明&#xff0c;那时FFmpeg版本用的2.4.3, VS是2010&#xff0c;现在FFmpeg最新稳定版为4.1.3&#xff0c;通过VS2013进行编译&#xff0c;较之前有了些不同&#x…

GitHub标星近1万:只需5秒音源,这个网络就能实时“克隆”你的声音

作者 | Google团队 译者 | 凯隐 编辑 | Jane 出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;本文中&#xff0c;Google 团队提出了一种文本语音合成&#xff08;text to speech&#xff09;神经系统&#xff0c;能通过少量样本学习到多个不同说话者&…

entity framework 使用Mysql配置文件

2019独角兽企业重金招聘Python工程师标准>>> <?xml version"1.0" encoding"utf-8"?> <configuration><configSections><section name"entityFramework" type"System.Data.Entity.Internal.ConfigFile.En…

UIWebView、WKWebView使用详解及性能分析

一、整体介绍 UIWebView自iOS2就有&#xff0c;WKWebView从iOS8才有&#xff0c;毫无疑问WKWebView将逐步取代笨重的UIWebView。通过简单的测试即可发现UIWebView占用过多内存&#xff0c;且内存峰值更是夸张。WKWebView网页加载速度也有提升&#xff0c;但是并不像内存那样提…

FFmpeg中libavutil库简介及测试代码

libavutil是一个实用库&#xff0c;用于辅助多媒体编程。此库包含安全的可移植字符串函数、随机数生成器、数据结构、附加数学函数、加密和多媒体相关功能(如像素和样本格式的枚举)。libavcodec和libavformat并不依赖此库。 以下是测试代码&#xff0c;包括base64, aes, des, …

区块链人才月均薪酬1.6万元?

在上周&#xff0c;我国宣布将重点推动区块链技术的发展&#xff0c;这个消息无疑是为区块链开发者们打了一直强心剂&#xff0c;简直是喜大普奔啊 &#xff01; 因为之前区块链这个技术虽然一直在圈内很火&#xff0c;但是却没有得到国家的全面认可和推广&#xff0c;所以很多…

用最少的时间学最多的数据挖掘知识(附教程数据源)| CSDN博文精选

作者 | 宋莹来源 | 数据派THU&#xff08;ID:DatapiTHU&#xff09;本文为你介绍数据挖掘的知识及应用。引言最近笔者学到了一个新词&#xff0c;叫做“认知折叠”。就是将复杂的事物包装成最简单的样子&#xff0c;让大家不用关心里面的细节就能方便使用。作为数据科学领域从业…

WKWebView 的使用简介

1. navigationDelegate [objc] view plaincopy print?- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { // 类似UIWebView的 -webViewDidStartLoad: NSLog("didStartProvisionalNavigation"); [UIAppli…

FFmpeg中libswscale库简介及测试代码

libswscale库功能主要包括高度优化的图像缩放、颜色空间和像素格式转换操作。 以下是测试代码(test_ffmpeg_libswscale.cpp)&#xff1a; #include "funset.hpp" #include <string.h> #include <iostream> #include <string> #include <memor…

FFmpeg中libswresample库简介及测试代码

libswresample库功能主要包括高度优化的音频重采样、rematrixing和样本格式转换操作。 以下是测试代码(test_ffmpeg_libswresample.cpp)&#xff0c;对音频了解较少&#xff0c;测试代码是参考examples中的&#xff1a; #include "funset.hpp" #include <iostre…

高德地图POI搜索,附近地图搜索,类似附近的人搜索

效果图&#xff1a; 首先导入道德地图的SDK&#xff0c;导入步骤不在这里介绍 2&#xff1a;包含头文件&#xff1a; [objc] view plaincopy #import <AMapSearchKit/AMapSearchAPI.h> 3&#xff1a;代码 [javascript] view plaincopy property(nonatomic,strong)AMap…

手把手教你实现PySpark机器学习项目——回归算法

作者 | hecongqing 来源 | AI算法之心&#xff08;ID:AIHeartForYou&#xff09;【导读】PySpark作为工业界常用于处理大数据以及分布式计算的工具&#xff0c;特别是在算法建模时起到了非常大的作用。PySpark如何建模呢&#xff1f;这篇文章手把手带你入门PySpark&#xff0c;…

mcDropdown使用方法

最近使用了mcDropdown插件&#xff0c;百度一查&#xff0c;资料较少&#xff0c;只看到了mcDropdown官网的英文说明文档&#xff0c;所以今天就写点&#xff0c;以便以后使用。 第一步&#xff1a;引用jquery库和css jQuery v1.2.6 (or higher)*jquery.mcdropdown.js Plug-inj…

Windows上通过VLC播放器搭建rtsp流媒体测试地址操作步骤

1. 从https://www.videolan.org/index.zh.html 下载最新的windows 64bit 3.0.6版本并安装&#xff1b; 2. 打开VLC media player&#xff0c;依次点击按钮&#xff1a;”媒体” --> “流”&#xff0c;如下图所示&#xff1a; 3. 点击”添加”按钮&#xff0c;选择一个视频…

Swift - AppDelegate.swift类中默认方法的介绍

项目创建后&#xff0c;AppDelegate类中默认带有如下几个方法&#xff0c;具体功能如下&#xff1a; 1&#xff0c;应用程序第一次运行时执行这个方法只有在App第一次运行的时候被执行过一次&#xff0c;每次App从后台激活时都不会再执行该方法。&#xff08;注&#xff1a;所有…