概述
C/C++ 开源库及示例代码
说明
本页面汇总俺收集的各种 C 和 C++ 的开源代码库,不定期更新。
如果你发现本页面的开源库有错漏之处,非常欢迎给俺提供反馈——有 GitHub 帐号的同学,可以给俺发 issue;没帐号的同学,可以去俺博客留言。
1 综合性的库
Boost
Home:http://boost.org/
Wikipedia: 英文、 中文
Boost 大概是最重要的第三方 C++ 库。其作者有很多是 C++ 标准委员会的成员。Boost 的很多子库后来都成为 C++ 的标准库。
本页面的其它章节还会继续提及 Boost 在各种领域的应用。
wxWidgets
Home:https://wxwidgets.org/
Wikipedia: 英文、 中文
这是一个非常老牌的 C++ 开源 GUI 框架,诞生于1992年。原先叫做 wxWindows,后来因为微软的法律纠纷,改为现名。
它支持的操作系统平台很多(包括嵌入式系统)。
很多开源项目用到它,比如:BitTorrent、aMule、FileZilla、Code::Blocks、Dolphin……
虽然它以 GUI 为主,但是也提供了其它一些辅助功能(比如:进程间通讯、网络、数据库、多媒体……)
Qt
Home:http://www.qt-project.org/
Wikipedia: 英文、 中文
这是一个非常老牌的 C++ 开源 GUI 框架,于1995年发布 1.0 版本。原先由 Trolltech 公司维护,后来该公司被 Nokia 收购。
它支持的操作系统平台很多(包括嵌入式系统)。
虽然它以 GUI 为主,但是也提供了其它一些辅助功能(比如:网络、数据库、多媒体、3D引擎……)
APR(Apache Portable Runtime)
Home:https://apr.apache.org/
Wikipedia: 英文、 中文
这是由 Apache 社区维护的 C 开源库,主要提供操作系统相关的功能(文件系统、进程、线程、用户、IPC)。此外还提供了一些网络相关的功能。
APR 原先是 Apache Web 服务器的一个组成部分,后来独立出来,成为一个单独的开源项目。
ACE(Adaptive Communication Environment)
Home:ACE
Wikipedia:英文、 中文
这是一个跨平台的 C++ 库,提供了一套网络通讯的框架;另外还支持线程、进程和 IPC。
POCO
Home:POCO
Wikipedia: 英文
它的名称源自“POrtable COmponents”,是一个基于 C++ 的开源库。
它的功能以网络通讯为主,同时也提供一些其它功能(比如:多线程、进程间通讯、数据库、XML、JSON……)
Dlib
Home:[http://dlib.net/]
Wikipedia:英文
诞生于2002年的 C++ 开源库,提供了非常多的功能(网络、多线程、GUI、数值计算、图像处理、数据挖掘……)。
它还有一个特色是:同时提供了 Python API :)
Crypto++
Home:http://www.cryptopp.com/
Wikipedia: 英文
它也叫“CryptoPP”或“libcrypto++”,是非常著名的开源加密库,诞生于1995年。基于 C++ 开发,大量用到模板语法。
虽然它以加密为主,但是也提供了其它一些辅助功能(比如:数据压缩、编码解码、计时器…)
2 数据结构 & 算法 =
2.1 容器
2.1.1 标准容器
std
C++ 98 标准内置的 STL 提供了如下容器:
数组:vector(动态数组)、valarray(针对数值类型特化的 vector)、bitset(储存比特的【固定】数组)
链表:list(双向)
队列:queue、deque(双端队列)
栈:stack
映射:map(键值无重复)、multimap(键值可重复)
集合:set(元素无重复)、multiset(元素可重复)
C++ 11 标准新增了如下容器:
数组:array(相比 vector,它的 size 是编译时【固定】的)
链表:forward_list(相比 list,它是【单向】的)
映射:unordered_map、unordered_multimap(相比 map 和 multimap,这俩采用 hash 实现)
集合:unordered_set、unordered_multiset(相比 set 和 multiset,这俩采用 hash 实现)
下面几个容器,C++ 标准【没有】包含,但包含在某些知名的 STL 第三方库中(比如 SGI 的 STL):
映射:hash_map、hash_multimap(与 unordered_map、unordered_multimap 相同)
集合:hash_set、hash_multiset(与 unordered_set、unordered_multiset 相同)
2.1.2 Lockfree 的容器
(“lock-free”翻译成“锁无关”会引发歧义,所以俺直接用洋文)
Boost.Lockfree
Docs:http://boost.org/libs/lockfree
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了三种 lock-free 的容器(queue、stack、spsc_queue)。最后这种是“环形缓冲”。
libcds(Concurrent Data Structures)
Home:http://libcds.sourceforge.net/
这是一个跨平台的 C++ 开源库,提供了若干 lock-free 的容器。它的 2.0.0 版本,代码重写以支持 C++ 11 标准。
2.1.3 环形缓冲
Boost.CircularBuffer
Docs:http://boost.org/libs/circular_buffer
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“环形缓冲区”的模板。
“环形缓冲区”可以降低内存分配的开销。俺曾经写过一篇博文推荐环形缓冲区(在“这里”)。
代码示例
include <boost/circular_buffer.hpp>
boost::circular_buffer<int> cb(3); // Create with capacity for 3 integers
cb.push_back(1);
cb.push_back(2);
cb.push_back(3);
// The buffer is full now
// pushing subsequent elements will overwrite front-most elements.
cb.push_back(4); // Overwrite 1 with 4.
cb.push_back(5); // Overwrite 2 with 5.
// The buffer now contains 3, 4 and 5.
// Elements can be popped from either the front or the back.
cb.pop_back(); // 5 is removed.
cb.pop_front(); // 3 is removed.
// Leaving only one element with value = 4.
assert(cb[0] == 4);
2.1.4 多维数组
Boost.MultiArray
Docs:MultiArray
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了任意维的数组。
代码示例——3维数组
include <boost/multi_array.hpp>
typedef boost::multi_array<double, 3> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
int values = 0;
for(index i=0; i!=3; ++i)
for(index j=0; j!=4; ++j)
for(index k=0; k!=2; ++k)
A[i][j][k] = values++;
2.1.5 图
Boost.Graph
Docs:Graph
Boost 前面已经介绍过。这是 Boost 的其中一个子库,简称 BGL(Boost Graph Library),封装了“图”这种数据结构。
它提供了与 STL 类似的泛型编程风格。
Dlib
Docs:DLib
Dlib 前面已经介绍过。它提供了2个类(graph & directed_graph)封装“图”。
2.2 对容器的操作
(STL 标准库里面已经实现了很多算法用来操作容器,考虑到本页面已经很长,这里只列举第三方库实现的算法)
Boost.Foreach
Docs:Foreach
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了通用的遍历,其效果类似于 Python 的 for 循环语法。
有了它,你在遍历时无需声明迭代器变量,也无需关心遍历的容器是何种类型。
代码示例——遍历字符串
include <string>
include <iostream>
include <boost/foreach.hpp>
std::string test("Hello, world!"); // string 可以视为 char 的容器
BOOST_FOREACH(char ch, test)
{
std::cout << ch;
}
2.3 字符串处理
2.3.1 字符集
Boost.Locale
Docs:locale
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了各种“本地化”的功能。其中就包括字符集编码转换。
代码示例
include <fstream>
include <boost/locale.hpp>
using namespace boost::locale;
std::locale loc = generator().generate("he_IL.UTF-8");
std::wofstream file.
file.imbue(loc);
file.open("hello.txt");
file << L"שלום!";
POCO.Text
Docs:Text
POCO 前面已经介绍过。它提供了 UTF8/UTF16/UTF32 的转换。
2.3.2 字符串格式化
Boost.Format
Docs:Format
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“格式化字符串”的功能。相比 ANSI C 的 sprintf() 和 snprintf(),它的格式化功能更强并且更安全。
代码示例
include <iostream>
include <boost/format.hpp>
using std::cout;
using boost::format;
// 基于“位置指示符”的格式串语法
cout << format("%1% %2% %3% %2% %1%") % "11" % "22" % "333";
// 输出如下:
// 11 22 333 22 11
// 兼容 printf() 的格式串语法
cout << format("%s %d") % "price" % 1234;
// 输出如下:
// price 1234
fmt
Home:https://github.com/fmtlib/fmt
这是一个轻量级、类型安全、高性能的字符串格式化库。它也可以用来替代 C++ 标准库中的 IOStreams。
代码示例
include <string>
include <fmt/format.h>
// 使用 Python 的格式化语法
fmt::print("Hello, {}!", "world");
// 使用 printf 的格式化语法
fmt::printf("Hello, %s!", "world");
// 使用序号参数,
std::string s = fmt::format("{0} {1} {0}", "Hello", "world");
// 使用命名参数
fmt::print("Hello, {name}! The answer is {number}. Goodbye, {name}.",
fmt::arg("name", "World"), fmt::arg("number", 42));
2.3.3 正则表达式
PCRE(Perl Compatible Regular Expressions)
Home:http://www.pcre.org/
Wikipedia:英文
这是一个很老牌的正则表达式的库,诞生于1997年。很多知名的开源项目(Apache、PHP、KDE)用到了它。
Boost.Regex
Docs:Regex
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“正则式”的功能。
注:Boost 的这个子库已经进入 C++ 11 标准。
代码示例——基于正则式进行匹配和替换
include <boost/regex.hpp>
using std::string;
using namespace boost;
// 正则式匹配的例子
bool validate_card_format(const string& s)
{
const regex e("(\d{4}[- ]){3}\d{4}");
return regex_match(s, e);
}
// 正则式替换的例子
const regex e("\A(\d{3,4})[- ]?(\d{4})[- ]?(\d{4})[- ]?(\d{4})\z");
const string machine_format("\1\2\3\4");
const string human_format("\1-\2-\3-\4");
string machine_readable_card_number(const string& s)
{
return regex_replace(s, e, machine_format, match_default|format_sed);
}
string human_readable_card_number(const string& s)
{
return regex_replace(s, e, human_format, match_default|format_sed);
}
re2
Home:https://github.com/google/re2
这是 Google 提供的正则式库,基于 C++。其 API 使用起来很简洁。
有多种脚本语言(Python、Ruby、Perl、Node.js、Erlang、OCaml)提供了对它的封装。
代码示例——基于正则式进行匹配
include <re2/re2.h>
int i;
string s;
assert(RE2::FullMatch("test:1234", "(\w+):(\d+)", &s, &i));
assert(s == "test");
assert(i == 1234);
Oniguruma(鬼车)
Home:http://www.geocities.jp/kosako3/oniguruma/
Wikipedia: 英文
来自日本的正则式库,基于 C 语言。据说性能很高。
它被用在 Ruby、TextMate、Sublime Text、SubEthaEdit 等软件上。
POCO.RegExp
Docs:http://pocoproject.org/docs/package-Foundation.RegExp.html
POCO 前面已经介绍过。它提供了正则表达式的封装类。
Qt.QRegExp
Docs:http://doc.qt.io/qt-4.8/qregexp.html
Qt 前面已经介绍过。这是 Qt 中的一个类,提供了“正则式”的功能。
2.3.4 (其它)
Boost.StringAlgorithms
Docs:http://boost.org/libs/algorithm/string
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了各种字符串的算法(替换、合并、拆分、大小写转换、trim……)。
代码示例——字符串合并
include <string>
include <vector>
include <iostream>
include <boost/algorithm/string.hpp>
std::vector<std::string> v;
// 此处填充 v
std::cout << boost::algorithm::join(v, " ") << 'n';
Boost.Lexical_Cast
Docs:http://boost.org/libs/lexical_cast
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了各种字符串与其它类型的转换。
注:Boost 的这个子库已经进入 C++ 11 标准。
代码示例
include <string>
include <iostream>
include <boost/lexical_cast.hpp>
std::string s = boost::lexical_cast<std::string>(123);
std::cout << s << 'n';
double d = boost::lexical_cast<double>(s);
std::cout << d << 'n';
2.4 内存相关
2.4.1 智能指针
Boost.SmartPointers
Docs:http://boost.org/libs/smart_ptr
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了几种智能指针。最常用的是“shared_ptr”。
有了智能指针,你就无需操心 new 之后的 delete 了。
注:Boost 的这个子库已经进入 C++ 11 标准。
2.4.2 内存池
Boost.Pool
Docs:http://boost.org/libs/pool
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“内存池”的功能。
Dlib
Docs:http://dlib.net/other.html
Dlib 前面已经介绍过。它提供了内存池(参见文档中以“memory_manager”开头的类)。
APR
Docs:https://apr.apache.org/docs/apr/trunk/modules.html
APR 前面已经介绍过。它提供了内存池的功能。
2.5 时间 & 日期
Boost.Date_Time
Docs:http://boost.org/libs/date_time
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了针对“日期 和 时间”的各种处理。
POCO.DateTime
Docs:DateTime
POCO 前面已经介绍过。它提供了若干个日期和时间的封装类(时区转换、格式化字符串、解析时间字符串)。
2.6 编码 & 解码
2.6.1 序列化
Boost.Serialization
Docs:serialization
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了【可定制的】“序列化”功能。
2.6.2 Base64
Base64 是一组编码算法的总称。用于把二进制数据编码为文本。
Boost.Serialization
Docs:serialization
Boost 前面已经介绍过。使用前面提到的“Boost.Serialization”,你可以定制采用 Base64 方式进行编码和解码。
Crypto++
Docs:Crypto++
Crypto++ 前面已经介绍过。它提供了6个类,分别用于 Base64、Base32、Base16 的编码/解码。
POCO.Streams
Docs:Streams
POCO 前面已经介绍过。它提供了 Base64 和 Base32 的编码/解码。
2.7 (其它)
2.7.1 随机数
std
ANSI C 在 stdlib.h 中提供了随机数生成函数 rand()。使用前记得先用 srand() 函数播种,否则就傻了。
Boost.Random
Docs:Random
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“随机数生成”的功能。
相比 ANSI C 的随机数函数,它提供的功能更丰富。
代码示例
include <ctime>
include <boost/random.hpp>
double SampleNormal(double mean, double sigma)
{
using namespace boost;
// 建立一个 Mersenne twister 随机数产生器,使用当前时间播种
static mt19937 rng(static_cast<unsigned>(std::time(NULL)));
// 选择高斯机率分布
normal_distribution<double> norm_dist(mean, sigma);
// 使用 function 的形式,生成随机数据产生器
variate_generator<mt19937&, normal_distribution<double> > normal_sampler(rng, norm_dist);
// 传回样本分布结果
return normal_sampler();
}
Crypto++
Docs:Crypto++
Crypto++ 前面已经介绍过。它提供了好几个类,用于随机数生成。
2.7.2 UUID
Boost.UUID
Docs:UUID
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了 UUID 的生成。
代码示例——生成 UUID
include <boost/uuid/uuid.hpp>
include <boost/uuid/uuid_generators.hpp>
// uuid 类以 POD 方式实现,可以直接用在 memcpy()
unsigned char uuid_data[16];
boost::uuids::uuid u;
memcpy(&u, uuid_data, 16);
APR
Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
APR 前面已经介绍过。它提供了 UUID 的生成、格式化成字符串、解析 UUID 字符串。
POCO.UUID
Docs:[http://pocoproject.org/docs/package-Foundation.UUID.html]
POCO 前面已经介绍过。它提供了 UUID 的生成、格式转换。
3 编程范式
(这一章节主要针对 C++——“支持多范式”是 C++ 的一大特色)
3.1 面向对象编程(OOP)
fruit
Home:[https://github.com/google/fruit]
它是 Google 开发的 C++ 库,提供了“依赖注入”(dependency injection)的框架。
代码示例——一个简单的例子
include <iostream>
include <fruit/fruit.h>
using fruit::Component;
using fruit::Injector;
class Writer
{
public:
virtual void write(std::string str) = 0;
};
class StdoutWriter : public Writer
{
public:
// Like "StdoutWriter() = default;" but also marks this constructor as the
// one to use for injection.
INJECT(StdoutWriter()) = default;
virtual void write(std::string str) override
{
std::cout << str;
}
};
class Greeter
{
public:
virtual void greet() = 0;
};
class GreeterImpl : public Greeter
{
private:
Writer* writer;
public:
// Like "GreeterImpl(Writer* writer) {...}"
// but also marks this constructor as the one to use for injection.
INJECT(GreeterImpl(Writer* writer))
: writer(writer)
{
}
virtual void greet() override
{
writer->write("Hello world!n");
}
};
Component<Greeter> getGreeterComponent()
{
return fruit::createComponent()
.bind<Writer, StdoutWriter>()
.bind<Greeter, GreeterImpl>();
}
int main()
{
Injector<Greeter> injector(getGreeterComponent());
Greeter* greeter = injector.get<Greeter*>();
greeter->greet();
return 0;
}
3.2 泛型编程(GP)
Boost.TypeTraits
Docs:http://boost.org/libs/type_traits
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“类型特化”相关的辅助功能。
3.3 函数式编程(FP)
(不了解“函数式编程”的同学,可以先看维基百科)
Boost.Function
Docs:http://boost.org/libs/function
Boost 前面已经介绍过。这是 Boost 的其中一个子库,用来辅助封装函数对象(仿函式)。
注:Boost 的这个子库已经进入 C++ 11 标准。
代码示例——封装标准 C 的函数
include <cstdlib>
include <cstring>
include <iostream>
include <boost/function.hpp>
boost::function<int(const char*)> f = std::atoi;
std::cout << f("42") << 'n';
f = std::strlen;
std::cout << f("42") << 'n';
Boost.Lambda
Docs:http://boost.org/libs/lambda
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“匿名函数/无名函数”的功能。
注:Boost 的这个子库已经进入 C++ 11 标准。
代码示例
include <vector>
include <algorithm>
include <iostream>
include <boost/lambda/lambda.hpp>
std::vector<int> v;
// 此处填充 v
std::for_each(v.begin(), v.end(),
std::cout << boost::lambda::_1 << "n");
3.4 元编程(Metaprogramming)
(不知道何为“元编程”,可以先看维基百科
Boost.MPL
Docs:http://boost.org/libs/mpl
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“模板元编程”的框架。
Dlib
Docs:http://dlib.net/metaprogramming.html
Dlib 前面已经介绍过。它提供了“模板元编程”的辅助类。
4 调试 & 测试
4.1 调试日志
Boost.Log
Docs:http://boost.org/libs/log
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了记录日志的机制。
下面给出的示例是最简单的版本,其实它还提供了很丰富的扩展机制。
代码示例
include <boost/log/trivial.hpp>
BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
BOOST_LOG_TRIVIAL(info) << "An informational severity message";
POCO.Logging
Docs:http://pocoproject.org/docs/package-Foundation.Logging.html
POCO 前面已经介绍过。它提供了好几个用于调试日志的封装类(包括特定于 Windows 平台和特定于 POSIX 平台的类)。
它还支持日志文件的循环存储。
Dlib
Docs:http://dlib.net/other.html#logger
Dlib 前面已经介绍过。它提供了风格类似 log4j 的日志记录机制。
代码示例
include <dlib/logger.h>
include <dlib/misc_api.h>
using namespace dlib;
logger dlog("example");
dlog.set_level(LALL);
dlog << LINFO << "This is an informational message.";
int variable = 8;
dlog << LDEBUG << "The integer variable is set to " << variable;
wxWidgets
Docs:http://docs.wxwidgets.org/trunk/group__group__funcmacro__log.html
wxWidgets 前面已经介绍过。它提供了记录日志的函数和宏。
log4cpp
Home:http://log4cpp.sourceforge.net/
如其名,这是一个模仿 log4j 的 C++ 库。支持多种操作系统(包括 Windows)。
4.2 单元测试
Boost.Test
Docs:http://boost.org/libs/test
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了与测试相关的各种辅助工具(包括单元测试)。
Google Test
Home:https://github.com/google/googletest
Wikipedia: 英文
这是 Google 提供的单元测试框架。从 Google Code 迁移到 GitHub 之后,又整合了 GoogleMock 项目。
一些知名的开源项目(Chromium、LLVM、OpenCV)用到了它。
CppUnit
Home:http://freedesktop.org/wiki/Software/cppunit/
Wikipedia:英文
如其名,这是一个 C++ 的单元测试框架。该项目起先是作为 JUnit 的 C++ 移植而创建的。
Check
Home:http://check.sourceforge.net/
Wikipedia: 英文
这是针对 C 的单元测试框架。
代码示例
include <check.h>
/* The basic unit test looks as follows: */
START_TEST (test_name)
{
/* unit test code */
}
END_TEST
/* The "START_TEST/END_TEST" pair are macros that setup basic structures to permit testing.
It is a mistake to leave off the END_TEST marker;
doing so produces all sorts of strange errors when the check is compiled. */
4.3 健壮性测试
Boost.Test.ExecutionMonitor
Docs:http://boost.org/libs/test/doc/html/execution-monitor.html
Boost 前面已经介绍过。这是 Boost 的其中一个子库,它除了提供“单元测试”,还提供“内存泄漏的检测”。
4.4 性能测试
benchmark
Home:https://github.com/google/benchmark
这是 Google 提供的性能测试辅助工具,用来测试指定函数的执行时间。
它可以把测试结果导出为 CSV 或 JSON 格式。
5 操作系统
5.1 跨操作系统
5.1.1 文件系统
Boost.Filesystem
Docs:http://boost.org/libs/filesystem
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了对“文件系统”的操作。
代码示例——获取文件大小
include <iostream>
include <boost/filesystem.hpp>
int main(int argc, char* argv[])
{
using namespace boost::filesystem;
if(argc != 2)
{
std::cout << "Usage: n" << argv[0] << " pathn";
return 1;
}
std::cout << argv[1] << " " << file_size(argv[1]) << 'n';
return 0;
}
POCO.Filesystem
Docs:http://pocoproject.org/docs/package-Foundation.Filesystem.html
POCO 前面已经介绍过。它提供了文件系统相关的封装类(遍历目录和文件、通配符匹配、临时文件、文件变化通知…)。
wxWidgets
Docs:http://docs.wxwidgets.org/trunk/group__group__class__file.html
wxWidgets 前面已经介绍过。它提供了文件系统相关的封装类(遍历目录和文件、临时文件、文件变化通知…)。
APR
Docs:https://apr.apache.org/docs/apr/trunk/modules.html
APR 前面已经介绍过。它提供了“文件信息、文件名匹配”等功能。
5.1.2 线程
Boost.Thread
Docs:http://boost.org/libs/thread
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“多线程”的功能。
代码示例
include <iostream>
include <boost/thread/thread.hpp>
void hello_world()
{
std::cout << "Hello world, I'm a thread!n";
}
int main()
{
boost::thread my_thread(&hello_world); // 启动一个线程
my_thread.join(); // 等待该线程结束
return 0;
}
ACE
Docs:http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html
ACE 前面已经介绍过。它提供了“多线程”的功能(参见文档中以“ACE_Thread”开头的类)
APR
Docs:https://apr.apache.org/docs/apr/trunk/modules.html
APR 前面已经介绍过。它提供了“线程池、线程同步/互斥”等功能,以及一些线程安全的数据结构。
POCO.Threading
Docs:http://pocoproject.org/docs/package-Foundation.Threading.html
POCO 前面已经介绍过。它提供了线程、线程池以及线程同步/互斥的封装类。
wxWidgets
Docs:http://docs.wxwidgets.org/trunk/group__group__class__threading.html
wxWidgets 前面已经介绍过。它提供了线程以及线程同步/互斥的封装类。
GNU Common C++
Home:http://www.gnu.org/software/commoncpp/
由 GNU 提供的一套跨平台的线程并发框架。
5.1.3 进程
ACE
Docs:http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html
ACE 前面已经介绍过。它提供了“进程管理”的功能(参见文档中以“ACE_Process”开头的类)。
APR
Docs:https://apr.apache.org/docs/apr/trunk/modules.html
APR 前面已经介绍过。它提供了“进程管理”的功能。
POCO.Processes
Docs:http://pocoproject.org/docs/Poco.Process.html
POCO 前面已经介绍过。它提供了“进程”的封装类。
5.1.4 本地进程间通信(IPC)
(本章节列举的是【本地】IPC,跨主机的网络通讯,参见本页面后续的章节)
Boost.Interprocess
Docs:http://boost.org/libs/interprocess
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了共享内存和几种同步机制(Mutexes、Condition variables、Semaphores、Upgradable mutexes、File locks)。
ACE
Docs:http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html
ACE 前面已经介绍过。它提供了许多种 IPC 机制(有些不是跨平台的)。
APR
Docs:https://apr.apache.org/docs/apr/trunk/modules.html
APR 前面已经介绍过。它提供了“进程同步、共享内存、信号处理”等功能。
POCO.Processes
Docs:http://pocoproject.org/docs/package-Foundation.Processes.html
POCO 前面已经介绍过。它提供了 IPC 相关的封装类(“共享内存”和“管道”)。
5.2 特定于 Windows 系统
5.2.1 注册表
wxWidgets
Docs:http://docs.wxwidgets.org/trunk/classwx_reg_key.html
wxWidgets 前面已经介绍过。它提供了操作 Windows 注册表的封装类。
POCO::Util
Docs:http://pocoproject.org/docs/Poco.Util.html
POCO 前面已经介绍过。它提供了操作 Windows 注册表的封装类(WinRegistryKey)。
5.2.2 Windows 服务(Service)
POCO::Util
Docs:http://pocoproject.org/docs/Poco.Util.html
POCO 前面已经介绍过。它提供了相应的封装类(WinService),可以用来操作 Service(注册、删除、启动、停止)。
5.3 特定于 Linux & Unix 系统
6 图形用户界面(GUI)
6.1 GUI 框架
6.1.1 跨平台的 GUI 框架
wxWidgets
Docs:http://docs.wxwidgets.org/trunk/modules.html
wxWidgets 前面已经介绍过。用 wxWidgets 开发 GUI 应用,其代码结构类似 MFC。熟悉 MFC 的程序员应该很容易上手。
代码示例——Hello world
include <wx/wxprec.h>
ifndef WX_PRECOMP
include <wx/wx.h>
endif
class MyApp: public wxApp
{
public:
virtual bool OnInit();
};
wxIMPLEMENT_APP(MyApp);
class MyFrame: public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
private:
void OnExit(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
wxEND_EVENT_TABLE()
bool MyApp::OnInit()
{
MyFrame* frame = new MyFrame("Hello, World", wxPoint(50, 50), wxSize(450, 340));
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{
wxMenu* menuFile = new wxMenu();
menuFile->Append(wxID_EXIT);
wxMenuBar* menuBar = new wxMenuBar();
menuBar->Append(menuFile, "&File");
SetMenuBar(menuBar);
}
void MyFrame::OnExit(wxCommandEvent& event)
{
Close(true);
}
Qt
Qt 前面已经介绍过。下面给出一个 Hello world 的示例,让你看看 Qt 的风格。
代码示例——Hello world
include <QtWidgets/QApplication>
include <QtWidgets/QLabel>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QLabel label("Hello, world!");
label.show();
return app.exec();
}
GTK+
Home:http://www.gtk.org/
Wikipedia:英文、中文
老牌的 GUI 框架,诞生于1998年。原先叫做“GIMP Toolkit”,是基于 C 开发的跨平台界面组件库。
代码示例——Hello world
include <gtk/gtk.h>
int main(int argc, char* argv[])
{
gtk_init(&argc, &argv);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Hello, world!");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 200, 100);
/*
** Map the destroy signal of the window to gtk_main_quit;
** When the window is about to be destroyed, we get a notification and
** stop the main GTK+ loop by returning 0
*/
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
/* Start the main loop, do nothing until the application is closed */
gtk_main();
return 0;
}
FLTK
Home:http://www.fltk.org/
Wikipedia: 英文、 中文
它的全称是“Fast, Light Toolkit”。如其名,它非常轻量级。用它写一个“Hello World 应用”,静态链接后大约才 100KB
代码示例——Hello world
include <FL/Fl.H>
include <FL/Fl_Window.H>
include <FL/Fl_Box.H>
int main(int argc, char **argv)
{
Fl_Window* window = new Fl_Window(300, 180);
Fl_Box* box = new Fl_Box(20, 40, 260, 100, "Hello, World!");
box->box(FL_UP_BOX);
box->labelsize(36);
box->labelfont(FL_BOLD+FL_ITALIC);
box->labeltype(FL_SHADOW_LABEL);
window->end();
window->show(argc, argv);
return Fl::run();
}
6.1.2 特定于 Windows 的 GUI 框架
WTL(Windows Template Library)
Home:http://sourceforge.net/projects/wtl/
Wikipedia: 英文、中文
这是微软雇员 Nenad Stefanovic 开发的开源 GUI 框架。开发 WTL 是为了提供一个轻量级的 MFC 替代品。
6.2 图表(Chart)
Qt
Docs:http://doc.qt.io/QtCharts/
Qt 前面已经介绍过。它内置了一套 Chart 的封装类。
代码示例——饼图
include <QtWidgets/QApplication>
include <QtWidgets/QMainWindow>
include <QtCharts/QChartView>
include <QtCharts/QPieSeries>
include <QtCharts/QPieSlice>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QPieSeries* series = new QPieSeries();
series->append("Jane", 1);
series->append("Joe", 2);
series->append("Andy", 3);
series->append("Barbara", 4);
series->append("Axel", 5);
QPieSlice* slice = series->slices().at(1);
slice->setExploded();
slice->setLabelVisible();
slice->setPen(QPen(Qt::darkGreen, 2));
slice->setBrush(Qt::green);
QChart* chart = new QChart();
chart->addSeries(series);
chart->setTitle("Simple piechart example");
chart->legend()->hide();
QChartView* chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 300);
window.show();
return app.exec();
}
wxCode
Home:http://wxcode.sourceforge.net/
该项目专门提供组件来扩展 wxWidgets 的功能。它里面提供了好几种图表的组件(wxChart、wxFreeChart、wxPlotCtrl)。
wxMathPlot
Home:http://wxmathplot.sourceforge.net/
看名称就知道它是跟 wxWidgets 搭配的。效果图参见“ 这里”
7 文本用户界面(TUI)
7.1 命令行参数
getopt
Home:https://www.gnu.org/software/libc/manual/html_node/Getopt.html
Wikipedia:英文
这是标准C用来处理命令行参数的老牌函数,诞生于上世纪80年代初期。
它有很多种不同的实现,如今用得最多的是 GNU C Library 的实现。GNU 还实现了一个增强版 getopt_long。
代码示例
include <stdio.h> /* for printf */
include <stdlib.h> /* for exit */
include <unistd.h> /* for getopt */
int main(int argc, char** argv)
{
int digit_optind = 0;
int aopt = 0, bopt = 0;
char* copt = NULL;
char* dopt = NULL;
int c;
while( (c = getopt(argc, argv, "abc:d:012")) != -1)
{
int this_option_optind = optind ? optind : 1;
switch(c)
{
case '0':
case '1':
case '2':
if(digit_optind != 0 && digit_optind != this_option_optind)
{
printf("digits occur in two different argv-elements.n");
}
digit_optind = this_option_optind;
printf("option %cn", c);
break;
case 'a':
printf("option an");
aopt = 1;
break;
case 'b':
printf("option bn");
bopt = 1;
break;
case 'c':
printf("option c with value '%s'n", optarg);
copt = optarg;
break;
case 'd':
printf("option d with value '%s'n", optarg);
dopt = optarg;
break;
case '?':
break;
default:
printf("?? getopt returned character code 0%o ??n", c);
}
}
if(optind < argc)
{
printf("non-option ARGV-elements: ");
while(optind < argc)
{
printf("%s ", argv[optind++]);
}
printf("n");
}
exit (0);
}
Boost.Program_options
Docs:http://boost.org/libs/program_options
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“处理命令行参数”的功能。
它的功能很丰富,但是比较重型。
7.2 文本终端
ncurses
Home:https://www.gnu.org/software/ncurses/
Wikipedia: 英文、 中文
ncurses 是“new curses”的缩略词,它是 curses 库的自由软件克隆,诞生于1993年。
大名鼎鼎的 Eric S. Raymond 曾参与早期版本的开发。
8 网络
8.1 链路层 & 网络层
libpcap
Home:http://www.tcpdump.org/
Wikipedia: 英文
很著名的 Sniffer 抓包库,基于 C 语言开发。
代码示例——一个简单的抓包示例
include <stdio.h>
include <pcap.h>
int main(int argc, char* argv[])
{
pcap_t* handle; /* Session handle */
char* dev; /* The device to sniff on */
char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
struct bpf_program fp; /* The compiled filter */
char filter_exp[] = "port 23"; /* The filter expression */
bpf_u_int32 mask; /* Our netmask */
bpf_u_int32 net; /* Our IP */
struct pcap_pkthdr header; /* The header that pcap gives us */
const u_char* packet; /* The actual packet */
/* Define the device */
dev = pcap_lookupdev(errbuf);
if(dev == NULL)
{
fprintf(stderr, "Couldn't find default device: %sn", errbuf);
return 2;
}
/* Find the properties for the device */
if(pcap_lookupnet(dev, &net, &mask, errbuf) == -1)
{
fprintf(stderr, "Couldn't get netmask for device %s: %sn", dev, errbuf);
net = 0;
mask = 0;
}
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if(handle == NULL)
{
fprintf(stderr, "Couldn't open device %s: %sn", dev, errbuf);
return 2;
}
/* Compile and apply the filter */
if(pcap_compile(handle, &fp, filter_exp, 0, net) == -1)
{
fprintf(stderr, "Couldn't parse filter %s: %sn", filter_exp, pcap_geterr(handle));
return 2;
}
if(pcap_setfilter(handle, &fp) == -1)
{
fprintf(stderr, "Couldn't install filter %s: %sn", filter_exp, pcap_geterr(handle));
return 2;
}
packet = pcap_next(handle, &header); /* Grab a packet */
printf("Jacked a packet with length of [%d]n", header.len);
pcap_close(handle); /* Close the session */
return 0;
}
WinPcap
Home:http://www.winpcap.org/
Wikipedia:英文
它是 libpcap 在 Windows 系统下的移植。
8.2 传输层
socket
socket 最早源自 BSD 系统,有时候也称“伯克利套接字”。
它已成了传输层网络编程的标准,主流的操作系统平台都支持,主流的 C/C++ 编译器也都内置了相关的库文件。
ACE
Docs:http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html
ACE 前面已经介绍过。它提供了针对 socket 的更高层封装。
APR
Docs:https://apr.apache.org/docs/apr/trunk/modules.html
APR 前面已经介绍过。它提供了对 socket 的封装和增强。
POCO::Net
Docs:http://pocoproject.org/docs/Poco.Net.html
POCO 前面已经介绍过。它提供了针对 TCP 服务端的封装类。
8.3 标准的应用层
8.3.1 综合性的库
cURL & libcurl
Home:http://curl.haxx.se/libcurl/
Wikipedia: 英文、 中文
cURL 是一个功能很强的网络库/网络工具,支持 N 多应用层协议。下面是支持协议的列表(从它官网抄袭的)
DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, HTTP/2
它采用 C 语言开发,开发很活跃,支持非常多的操作系统平台。
关于 cURL,俺前几年写过一篇博文推荐它(在“[http://program-think.blogspot.com/2009/03/opensource-review-curl-library.html 这里]”)。
代码示例——IMAP 协议(邮件)
include <stdio.h>
include <curl/curl.h>
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL* curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
// This will list the folders within the user's mailbox. If you want to
// list the folders within a specific folder, for example the inbox,
// then specify the folder as a path in the URL such as /INBOX
curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com");
CURLcode res = curl_easy_perform(curl);
if(res != CURLE_OK) // Check for errors
{
fprintf(stderr, "curl_easy_perform() failed: %sn",
curl_easy_strerror(res));
}
curl_easy_cleanup(curl); // Always cleanup
}
curl_global_cleanup();
return 0;
}
cURLpp
Home:http://www.curlpp.org/
看名字就知道这是 cURL 的 C++ 封装。
POCO::Net
Docs:http://pocoproject.org/docs/Poco.Net.html
POCO 前面已经介绍过。它提供了几种常见应用层协议(HTTP、SMTP、POP3、FTP、NTP …)的封装类。
8.3.2 HTTP
(关于“HTTP 协议”,请参见另一个大类:“Web 相关”)
8.3.3 DNS
c-ares
Home:http://c-ares.haxx.se/
这是一个 C 语言开发的 DNS 封装库,支持异步 DNS 请求,跨多种操作系统。
对比官网域名可知,它跟 cURL 是一家子。除了 cURL/libcurl 用到它,还有一些知名开源项目(比如:Wireshark、node.js …)用到它。
8.3.4 XMPP
( XMPP 的洋文全称是“Extensible Messaging and Presence Protocol”。这是一个标准化的 IM 交互协议)
Swiften
Home:http://swift.im/swiften.html
这是一个 C++ 语言开发的 XMPP 封装库。它同时也是 Swift 聊天客户端所用的后端。
它大量使用了 Boost 的子库(Signal、Bind、Optional、Smart Pointers …)。
QXmpp
Home:https://github.com/qxmpp-project/qxmpp
这是一个 C++ 语言开发的 XMPP 封装库。从它的名称可以看出——依赖了 Qt 框架(需要 Qt 4.5 或更高版本)。
8.4 自定义的应用层
Protocol Buffers
Home:https://developers.google.com/protocol-buffers/
Wikipedia: 英文
它是 Google 开发的一个跨语言的库,用于传输业务数据时的“编码/解码”。其优点是:跨多种语言、高性能、向前兼容、向后兼容。
具体的使用,可以参考俺前几年写过的一篇博文(在“ 这里”)。
作为 Protocol Buffers 的发明者,Google 默认实现了三种编程语言(C++、Java、Python)对它的支持。除了 Google 官方提供的这三种语言,它还支持很多其它的编程语言(由第三方提供)。
Apache Thrift
Home:https://thrift.apache.org/
Wikipedia: 英文
来自于 Apache 社区,提供了一种跨语言的通讯机制。
程序员通过 Thrift 的“接口定义语言”定义通讯协议格式,然后 Thrift 根据协议格式自动帮你生成服务端和客户端代码。
(在这个方面,它有点类似于 Google 的 Protocol Buffers)
8.5 网络库、框架、中间件
Boost.Asio
Docs:http://boost.org/libs/asio
Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了异步网络通讯和异步 I/O。
代码示例——TCP Server
include <string>
include <iostream>
include <boost/asio.hpp>
int main()
{
using boost::asio::ip::tcp;
try
{
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));
while(true)
{
tcp::socket socket(io_service);
acceptor.accept(socket);
std::string msg = "Hello, world";
boost::system::error_code ignored_err;
boost::asio::write(socket, boost::asio::buffer(msg), ignored_err);
}
}
catch(std::exception& err)
{
std::cerr << err.what() << std::endl;
}
return 0;
}
ACE
Docs:http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html
ACE 前面已经介绍过。它提供了很多种用于网络通讯的设计模式。
ZeroMQ(ØMQ)
Home:http://www.zeromq.org/
Wikipedia: 英文、 中文
ZeroMQ 是一个轻量级、跨平台的开源库,提供了高性能、异步的消息队列。采用 C++ 开发,提供了多种语言的绑定。
与传统的消息中间件不同,使用 ZeroMQ 不需要额外的“消息代理(message broker)”。
俺曾经写过一篇博文推荐它(在“ 这里”)。
代码示例——TCP Server
include <zhelpers.hpp>
int main(int argc, char* argv[])
{
zmq::context_t context(1);
zmq::socket_t responder(context, ZMQ_REP);
responder.connect("tcp://localhost:5560");
while(true)
{
// Wait for next request from client
std::string request = s_recv(responder);
std::cout << "Received request: " << request << std::endl;
// Do some 'work'
sleep(1);
// Send reply back to client
s_send(responder, "Hello, world");
}
}
nanomsg
Home:http://nanomsg.org/
很类似 ZeroMQ 的库,比 ZMQ 更加轻量级。采用 C 开发,提供了多种语言的绑定。
API 完全参照 BSD socket 的风格和语义。
代码示例——Request/Reply
include <assert.h>
include <libc.h>
include <stdio.h>
include <nanomsg/nn.h>
include <nanomsg/pipeline.h>
int reply(const char* url)
{
int sock = nn_socket(AF_SP, NN_PULL);
assert(sock >= 0);
assert(nn_bind(sock, url) >= 0);
while(1)
{
char* msg = NULL;
int bytes = nn_recv(sock, &msg, NN_MSG, 0);
assert(bytes >= 0);
printf("RECEIVED:n%sn", msg);
nn_freemsg(msg);
}
}
int request(const char* url, const char* msg)
{
int sz_msg = strlen(msg) + 1; // '