C++中Boost库裁剪与其应用详解

前言

Boost 库涵盖的范围极广,有字符串和文本处理相关子库比如 format 库和 regexp 库,有容器相关子库比如 variant 库(和 Qt 的 QVariant 有得一拼),有迭代器子库比如 tokenizer 库(可以把字符进行 tokenize),还有算法、函数对象和高阶编程相关子库如functional 库、lambda 库和 signal 库,还有泛型编程、模板编程子库如 call traits、mpl,还有并发编程相关的 thread 库,等等等等。

Boost 是如此强大,毫无疑问它也很大。Windows 上安装 boost 需要占用 2G+ 的空间,编译配置起来也十分麻烦。

本文讨论的是如何不配置 boost 库而使用 boost 库。

解决方案用一句话说就是:

裁剪 boost 库,并在项目中内嵌 boost 源码,使项目脱离对 boost 库的依赖。

通过一个例子说明 boost 库裁剪的意义

或许你还是不明白 boost 库裁剪到底是啥意思,那我们一起来跑一个例子。以我的 cmake-templates 里面的一个 boost 代码为例,源码只有一个 main.cpp,里面只有如下几行:

#include <cstdio>
#include <boost/date_time/posix_time/posix_time_types.hpp>

int main( void )
{
 namespace pt = boost::posix_time;
 pt::ptime now = pt::second_clock::local_time();

 printf( "%s\t->\t%04d-%02d-%02d %02d:%02d:%02d\n","date '+%Y-%m-%d %H:%M:%S'",(int)now.date().year(),(int)now.date().month(),(int)now.date().day(),(int)now.time_of_day().hours(),(int)now.time_of_day().minutes(),(int)now.time_of_day().seconds() );

 return 0;
}

程序运行输出大概是:

date '+%Y-%m-%d %H:%M:%S' -> 2016-07-11 19:33:19

这 20 行不到的代码,展示了 Linux 系统下一个常用指令 date 输出当前时间的效果(相当于命令行下输入 date '+%Y-%m-%d %H:%M:%S')。

如果你的系统配置了 Boost,那就到上面的链接下载源码,进入 boost 文件夹,这里一共有三个文件:一个 main.cpp、一个 CMakeLists.txt,一个 README 说明文档。

但要运行这个程序并不容易,尤其是在一切都要手工的 Windows 系统上:你必须自己去下载合适的 boost 版本,设定一些环境变量。

在 Linux 下则比较简单,只要三步(先下载源码,并 cd 到源码目录):

sudo apt-get install -y libboost-all-dev cmake
mkdir build && cd build
cmake .. && make && ./BOOST

你不禁感慨,为了运行一个 20 行不到的小程序,居然要手工安装两三个 G 的 boost 库!

这时候 boost 库的裁剪,就显得尤为重要了。我们不希望拿到代码的人还要费时间去配置 boost 库,我们也不希望自己的代码要十分小心地,才能跑起来。我们要让自己的代码不论什么情况都能迅速地跑起来!

我们裁剪后的 boost 库,头文件大概有 3.18 MB,cpp 文件有两个约 11 KB。看上去挺大,但是压缩完其实就 213 KB!拿到这份代码,首先解压 include.zip 到当前文件夹,然后运行 cmake 生成 VS 工程(或者 Linux 上的 makefile 工程),然后编译、运行。完全不需要再管那烦心的 boost 库的配置了!

我想你一定能把这个程序跑起来的。无论你用什么操作系统,用什么编译器。

运行起来更省心,这就是 boost 库裁剪的意义。

我要怎么裁剪出自己需要的部分?

我们来深究一下怎么拿到上面那 3.18 MB 的头文件,11 KB 的 cpp 文件。

首先,下载 Boost 库源码,你可以去 官网。我们只需要官方 release 的源码里的 boost 和 libs 文件夹下的东西,所以我建议你下载我的备份。因为它真的小很多,下载起来也很快。而且里面还打包了用于提取 boost 源码的工具 bcp1。

然后,解压下载到的压缩包,进入源码文件夹,新建一个文件夹,比如叫 output,然后在当前窗口打开命令行,输入 ./bcp.exe boost/date_time/posix_time/posix_time_types.hpp output,这里 "./bcp.exe" 是我们的裁剪工具,"boost/date_time/posix_time/posix_time_types.hpp" 是我们自己项目中用到的 boost 头文件,如果有多个头文件,用空格隔开,把它们都敲进命令行。2最后的 "output" 是输出文件夹。

在 cmake 里,这个过程大概是

1)在源码根目录新建 include 文件夹,在根目录的 CMakeLists.txt 加上 include_directories( ${CMAKE_SOURCE_DIR} );

2)新建 libs 文件夹,把裁剪出来的 cpp 文件放到这个文件下的 MiniBoost 文件加下,然后参考 district10/bcp-example-1/libs 写好 CMakeLists 文件,再到根目录的 CMakeLists 文件加上 add_subdirectory( libs);3)将裁剪出来的 miniboost 链接到我们的二进制:target_link_libraries( ${PROJECT_NAME} MiniBoost )

你可以仔细对比看看链接系统安装的 Boost 库和使用自带的裁剪后的 Boost 库(我把它称为 MiniBoost)两者的区别和联系

注意:一个需要注意的地方是,提取出来的头文件里,boost/config/auto_link.hpp 里的内容最好删掉,不然在 Windows 平台上,boost 会尝试自动链接。所以我通常把这个文件内容清空。

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作能有所帮助,如果有疑问大家可以留言交流。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数。在不同的情况下static的作用不尽相同。 (1)修饰局部变量 一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组的一些区别,然而在某些情况下,指针和数组是等同的,下面讨论一下什么时候指针和数组是相同的。C语言标准对此作了说明:规则1:表达式中的数组名被编译器当做一个指向该数组第一个元素的指针; 注:下面几种情况例外 1)数组名作为sizeof的操作数
浅谈C/C++中的指针和数组(一)指针是C/C++的精华,而指针和数组又是一对欢喜冤家,很多时候我们并不能很好的区分指针和数组,对于刚毕业的计算机系的本科生很少有人能够熟练掌握指针以及数组的用法和区别。造成这种原因可能跟现在大学教学以及现在市面上流行的很多C或者C++教程有关,这些教程虽然通俗易懂,
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时,书中谈到C语言的声明问题,《C专家编程》这本书只有两百多页,却花了一章的内容去阐述这个问题,足以看出这个问题的重要性,要想透彻理解C语言的声明问题仅仅看书是远远不够的,需要平时多实践并大量阅读别人写的代码。下面借鉴《C专家编程》书中的两个
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下与文件相关的东西。一.文本文件和二进制文件 文本文件的定义:由若干行字符构成的计算机文件,存在于计算机系统中。文本文件只能存储文件中的有效字符信息,不能存储图像、声音等信息。狭义上的二进制文件则指除开文本文件之外的文件,如图片、DOC文档。
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面说一下文件的读写操作。文件的读写操作主要有4种,字符读写、字符串读写、块读写以及格式化读写。一.字符读写 字符读写主要使用两个函数fputc和fgetc,两个函数的原型是: int fputc(int ch,FILE *fp);若写入成功则
浅谈C语言中的位段 位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。 位段的定义格式为: type [var]:digits 其中type只能为int,unsigned int,s
C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符。但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特别是在判断文件是否到达文件末尾时,常常出错。1.EOF是什么? 在VC中查看EOF的定义可知: #def
关于VC+ʶ.0中getline函数的一个bug 最近在调试程序时,发现getline函数在VC+ʶ.0和其他编译器上运行结果不一样,比如有如下这段程序:#include &lt;iostream&gt;#include &lt;string&gt;using namespace std;int
C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100。则在Intel CPU架构的系统中,存放方式为 10000100(低地址单元) 00000100(高地址单元),因为Intel CPU
浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp#includeusing namespace std;int main(int argc, char *argv[]){ int a =0; switch(a) { case ...
浅谈C/C++中的typedef和#define 在C/C++中,我们平时写程序可能经常会用到typedef关键字和#define宏定义命令,在某些情况下使用它们会达到相同的效果,但是它们是有实质性的区别,一个是C/C++的关键字,一个是C/C++的宏定义命令,typedef用来为一个已有的数据类型
看下面一道面试题:#include&lt;stdio.h&gt;#include&lt;stdlib.h&gt;int main(void) { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&amp;aʱ); printf(&quot;%d,%d&quot;,*(
联合体union 当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的: 1)联合体是一个结构; 2)它的所有成员相对于基地址的偏移量都为0; 3)此结构空间要大到足够容纳最&quot;宽&quo
从一个程序的Bug解析C语言的类型转换 先看下面一段程序,这段程序摘自《C 专家编程》:#include&lt;stdio.h&gt;int array[]={23,34,12,17,204,99,16};#define TOTAL_ELEMENTS (sizeof(array)/sizeof(ar
大端和小端 嵌入式开发者应该对大端和小端很熟悉。在内存单元中数据是以字节为存储单位的,对于多字节数据,在小端模式中,低字节数据存放在低地址单元,而在大端模式中,低字节数据存放在高地址单元。比如一个定义一个short型的变量a,赋值为1,由于short型数据占2字节。在小端模式中,其存放方式为0X40
位运算和sizeof运算符 C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的。位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果。位运算主要有6种:与(&amp;),或(|),取反(~),异或(^),左移(&gt;)。1.位运算中的类型转换位
C语言文件操作解析(四)在文件操作中除了打开操作以及读写操作,还有几种比较常见的操作。下面介绍一下这些操作中涉及到的函数。一.移动位置指针的函数 rewind函数和fseek函数,这两个函数的原型是:void rewind(FILE *fp); 将位置指针移动到文件首 int fseek(FILE
结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排
C语言文件操作解析(二)C语言中对文件进行操作必须首先打开文件,打开文件主要涉及到fopen函数。fopen函数的原型为 FILE* fopen(const char *path,const char *mode) 其中path为文件路径,mode为打开方式 1)对于文件路径,只需注意若未明确给出绝