1. 程式人生 > 實用技巧 >C/C++ 開源庫及示例程式碼

C/C++ 開源庫及示例程式碼

Table of Contents

說明

本頁面彙總俺收集的各種 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:http://www.cse.wustl.edu/~schmidt/ACE.html

Wikipedia:英文中文

這是一個跨平臺的 C++ 庫,提供了一套網路通訊的框架;另外還支援執行緒、程序和 IPC。

POCO

Home:http://pocoproject.org/

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:http://boost.org/libs/multi_array

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:http://boost.org/libs/graph

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,簡稱 BGL(Boost Graph Library),封裝了“圖”這種資料結構。

它提供了與 STL 類似的泛型程式設計風格。

Dlib

Docs:http://dlib.net/graph_tools.html

Dlib 前面已經介紹過。它提供了2個類(graph & directed_graph)封裝“圖”。

2.2 對容器的操作

(STL 標準庫裡面已經實現了很多演算法用來操作容器,考慮到本頁面已經很長,這裡只列舉第三方庫實現的演算法)

Boost.Foreach

Docs:http://boost.org/libs/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:http://boost.org/libs/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:http://pocoproject.org/docs/package-Foundation.Text.html

POCO 前面已經介紹過。它提供了 UTF8/UTF16/UTF32 的轉換。

2.3.2 字串格式化

Boost.Format

Docs:http://boost.org/libs/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:http://boost.org/libs/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:http://pocoproject.org/docs/package-Foundation.DateTime.html

POCO 前面已經介紹過。它提供了若干個日期和時間的封裝類(時區轉換、格式化字串、解析時間字串)。

2.6 編碼 & 解碼

2.6.1 序列化

Boost.Serialization

Docs:http://boost.org/libs/serialization

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,提供了【可定製的】“序列化”功能。

2.6.2 Base64

Base64是一組編碼演算法的總稱。用於把二進位制資料編碼為文字。

Boost.Serialization

Docs:http://boost.org/libs/serialization

Boost 前面已經介紹過。使用前面提到的“Boost.Serialization”,你可以定製採用 Base64 方式進行編碼和解碼。

Crypto++

Docs:http://www.cryptopp.com/docs/ref/annotated.html

Crypto++ 前面已經介紹過。它提供了6個類,分別用於 Base64、Base32、Base16 的編碼/解碼。

POCO.Streams

Docs:http://pocoproject.org/docs/package-Foundation.Streams.html

POCO 前面已經介紹過。它提供了 Base64 和 Base32 的編碼/解碼。

2.7 (其它)

2.7.1 隨機數

std

ANSI C 在 stdlib.h 中提供了隨機數生成函式 rand()。使用前記得先用 srand() 函式播種,否則就傻了。

Boost.Random

Docs:http://boost.org/libs/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:http://www.cryptopp.com/docs/ref/class_random_number_generator.html

Crypto++ 前面已經介紹過。它提供了好幾個類,用於隨機數生成。

2.7.2 UUID

Boost.UUID

Docs:http://boost.org/libs/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/grouplog.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] << " path\n";
        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/groupfile.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/groupthreading.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 %c\n", c);
                break;
            case 'a':
                printf("option a\n");
                aopt = 1;
                break;
            case 'b':
                printf("option b\n");
                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: %s\n", 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: %s\n", 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: %s\n", 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: %s\n", filter_exp, pcap_geterr(handle));
        return 2;
    }
    if(pcap_setfilter(handle, &fp) == -1)
    {
        fprintf(stderr, "Couldn't install filter %s: %s\n", 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,俺前幾年寫過一篇博文推薦它(在“這裡”)。

程式碼示例——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: %s\n",
                    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%s\n", msg);
        nn_freemsg(msg);
    }
}

int request(const char* url, const char* msg)
{
    int sz_msg = strlen(msg) + 1; // '\0'
    int sock = nn_socket(AF_SP, NN_PUSH);
    assert(sock >= 0);
    assert(nn_connect(sock, url) >= 0);
    printf("SENDING:\n%s\n", msg);
    int bytes = nn_send(sock, msg, sz_msg, 0);
    assert(bytes == sz_msg);
    return nn_shutdown(sock, 0);
}

ICE(Internet Communications Engine)

Home:https://zeroc.com/

Wikipedia:英文中文

這是一個面向物件的通訊中介軟體,誕生於2002年。支援不同程式語言的通訊。

它的設計借鑑了 CORBA,好在沒有 CORBA 那麼複雜。

libevent

Home:http://libevent.org/

Wikipedia:英文中文

它提供了非同步事件處理機制。在網路開發中,可以用它替代傳統的“event loop”,有助於簡化程式碼。

它被一些知名的開源專案使用(比如:Tormemcached)。

程式碼示例——HTTP Server(本示例基於 ANSI C)

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <event.h>
#include <evhttp.h>

void generic_request_handler(struct evhttp_request* req, void* arg)
{
    struct evbuffer* return_buffer = evbuffer_new();

    evbuffer_add_printf(return_buffer, "Thanks for the request!");
    evhttp_send_reply(req, HTTP_OK, "Client", return_buffer);
    evbuffer_free(return_buffer);
}

int main(int argc, char** argv)
{
    short          http_port = 8080;
    char*          http_addr = "127.0.0.1";
    struct evhttp* http_server = NULL;

    event_init();
    http_server = evhttp_start(http_addr, http_port);
    evhttp_set_gencb(http_server, generic_request_handler, NULL);

    fprintf(stderr, "Server started on port %d\n", http_port);
    event_dispatch();

    return 0;
}

程式碼示例——HTTP Server(本示例基於 C++ 11 標準)

#include <memory>
#include <cstdint>
#include <iostream>
#include <evhttp.h>

int main()
{
    if(!event_init())
    {
        std::cerr << "Failed to init libevent." << std::endl;
        return -1;
    }
    char const SrvAddress[] = "127.0.0.1";
    std::uint16_t SrvPort = 8080;
    std::unique_ptr<evhttp, decltype(&evhttp_free)> Server(evhttp_start(SrvAddress, SrvPort), &evhttp_free);
    if(!Server)
    {
        std::cerr << "Failed to init http server." << std::endl;
        return -1;
    }

    void (*OnReq)(evhttp_request* req, void*) = [] (evhttp_request* req, void*)
    {
        auto* OutBuf = evhttp_request_get_output_buffer(req);
        if(!OutBuf)
        {
            return;
        }
        evbuffer_add_printf(OutBuf, "<html><body><h1>Hello, World!</h1></body></html>");
        evhttp_send_reply(req, HTTP_OK, "", OutBuf);
    };

    evhttp_set_gencb(Server.get(), OnReq, nullptr);
    if(event_dispatch() == -1)
    {
        std::cerr << "Failed to run messahe loop." << std::endl;
        return -1;
    }
    return 0;
}

libev

Home:http://libev.schmorp.de/

看名稱就能猜到它跟 libevent 很像。實際上,你可以把 libev 視為 libevent 的競爭性替代品。

gevent官方部落格的一篇文章對比了這倆庫的優缺點。

libuv

Home:https://github.com/libuv/libuv

Wikipedia:英文

它提供了跨平臺的非同步 I/O 機制。主要是為了提供給Node.js使用。

除了支援網路通訊,還支援:執行緒池、Windows 命名管道、Unix domain sockets、檔案系統事件通知 ......

Dlib

Docs:http://dlib.net/network.html

Dlib 前面已經介紹過。它針對網路通訊,提供了比較高的抽象層。


9 資料庫

9.1 開源資料庫

MySQL

Home:https://www.mysql.com/

Wikipedia:英文中文

名氣最大的開源資料庫,誕生於1995年,採用 C 和 C++ 語言開發。如今隸屬於 Oracle 公司。

PostgreSQL

Home:http://postgresql.org/

Wikipedia:英文中文

名氣僅次於 MySQL 的開源資料庫,誕生於1996年。採用 C 語言開發。

SQLite

Home:http://sqlite.org/

Wikipedia:英文中文

它是一個很優秀的嵌入式(程序內)資料庫,非常輕量級,支援各種作系統平臺。採用 C 語言開發。

俺前幾年寫過一篇博文推薦它(在“這裡”)。

MongoDB

Home:https://www.mongodb.org/

Wikipedia:英文

這是近幾年興起的 NoSQL 資料庫的一員。它本身是基於 C++ 和 C 開發的。

Redis

Home:http://redis.io/

Wikipedia:中文英文

誕生於2009年,是目前(2014~2015)最流行的鍵值儲存資料庫,基於 C 語言開發。

以效能高而著稱,很多大型網站用到它(Twitter、GitHub、Flickr、Instagram、百度、新浪、騰訊、搜狐)

Berkeley DB(BDB)

Home:http://www.oracle.com/us/products/database/berkeley-db/

Wikipedia:英文中文

誕生於1994年,是一個很老牌的嵌入式(程序內)資料庫,提供“鍵值儲存”的功能,基於 C 語言開發。

開發 BDB 的公司於2006年被 Oracle 收購。

很多開源專案用到它。甚至 MySQL 也包含了一個基於 BDB 的儲存後端。

LevelDB

Home:https://github.com/google/leveldb

Wikipedia:英文中文

它是 Google 基於 C++ 開發的 NoSQL 資料庫,提供“鍵值儲存”的功能。

號稱速度很快,內建資料壓縮(基於Snappy庫)。

比特幣專案用到它。Facebook 基於它開發出 RocksDB 資料庫。

Firebird

Home:http://www.firebirdsql.org/

Wikipedia:英文中文

它是2000年的時候,從Borland公司的 InterBase 資料庫派生出來的。

基於 C++ 開發,支援多種作業系統平臺。

關於它有個插曲:Firefox 瀏覽器曾經用過“Firebird”這個名稱,因為跟 Firebird 資料庫同名,後來才改用 Firefox 這個名稱。

ScyllaDB

Home:http://www.scylladb.com/

這是2015年新興的 NoSQL 資料庫,相當於是用 C++ 重寫了(Java 開發的)Cassandra。

號稱效能提高10倍,並且延遲極低。

9.2 資料庫 API 的封裝庫

9.2.1 綜合性的封裝庫

OTL

Home:http://otl.sourceforge.net/

Wikipedia:英文

原生支援的資料庫:Oracle、SQL Server、DB2、Informix、TimesTen, MAX/DB;另支援 ODBC。

它的特色是:全部程式碼都在一個頭檔案中。

程式碼示例——操作 Oracle 資料庫

#include <stdio.h>
#include <iostream>

#define OTL_ORA8  // Compile OTL 4.0/OCI8
#include <otlv4.h>  // include the OTL 4.0 header file

int main()
{
    otl_connect::otl_initialize();
    try
    {
        otl_connect db;
        db.rlogon("scott/tiger");  // connect to Oracle
        otl_cursor::direct_exec(
            db,
            "drop table test_tab",
            otl_exception::disabled  // disable OTL exceptions
        );

        otl_cursor::direct_exec(
            db,
            "create table test_tab(f1 number, f2 varchar2(30))"
        );
    }
    catch(otl_exception& err)
    {
        using namespace std;
        // intercept OTL exceptions
        cerr << err.msg << endl;  // print error message
        cerr << err.stm_text << endl;  // print SQL that caused the error
        cerr << err.var_info << endl;  // print variable that caused the error
    }

    db.logoff();  // disconnect from Oracle
    return 0;
}

9.2.2 MySQL 封裝庫

MySQL Connector C++

Home:http://dev.mysql.com/doc/connector-cpp/en/

這是 MySQL 官方提供的 C++ 封裝。

程式碼示例——執行 SQL 語句

sql::mysql::MySQL_Driver* driver = sql::mysql::MySQL_Driver::get_mysql_driver_instance();
sql::Connection* conn = driver->connect("tcp://127.0.0.1:3306", "user", "password");
sql::Statement* stmt = conn->createStatement();

stmt->execute("USE EXAMPLE_DB");
stmt->execute("DROP TABLE IF EXISTS test");
stmt->execute("CREATE TABLE test(id INT, label CHAR(1))");
stmt->execute("INSERT INTO test(id, label) VALUES (1, 'a')");

delete stmt;
stmt = NULL;
delete conn;
conn = NULL;

MySQL++

Home:http://www.tangentsoft.net/mysql%2B%2B/

這是個老牌的庫,誕生於1998年,提供了 MySQL API 的 C++ 封裝。

程式碼示例——執行 SQL 語句

#include <iostream>
#include <mysql++.h>

void query(db_name, server_name, user, password)
{
    using namespace std;

    mysqlpp::Connection conn(false);
    if(!conn.connect(db_name, server_name, user, password))
    {
        cerr << "DB connection failed: " << conn.error() << endl;
        return;
    }

    mysqlpp::Query query = conn.query("select item from table1");
    mysqlpp::StoreQueryResult sqr = query.store()
    if(!sqr)
    {
        cerr << "Failed to get item list: " << query.error() << endl;
        return;
    }

    mysqlpp::StoreQueryResult::const_iterator iter;
    for(iter=sqr.begin(); iter!=sqr.end(); ++iter)
    {
        mysqlpp::Row row = *iter;
        cout << '\t' << row[0] << endl;
    }
}

POCO::Data::MySQL

Docs:http://pocoproject.org/docs/package-MySQL.MySQL.html

POCO 前面已經介紹過。它提供了 MySQL 的封裝類

9.2.3 PostgreSQL 封裝庫

libpq

Home:http://www.postgresql.org/docs/9.4/static/libpq.html

這是由 PostgreSQL 官方提供的 C 封裝類庫。

libpqxx

Home:http://pqxx.org/development/libpqxx/

這是由 PostgreSQL 官方提供的 C++ 封裝類庫。

程式碼示例

#include <iostream>
#include <pqxx/pqxx>

void update(const std::string& name)
{
    pqxx::connection conn("dbname=company user=accounting");
    pqxx::work txn(conn);

    pqxx::result r = txn.exec("SELECT id FROM Employee WHERE name =" + name);
    if(r.size() != 1)
    {
        std::cerr << "Expected 1 employee with name " << name << ", "
                  << "but found " << r.size() << std::endl;
        return 1;
    }

    int employee_id = r[0][0].as<int>();
    std::cout << "Updating employee #" << employee_id << std::endl;

    txn.exec(
        "UPDATE EMPLOYEE SET salary = salary + 1 "
        "WHERE id = " + txn.quote(employee_id)
    );

    txn.commit();
}

9.2.4 Oracle 封裝庫

OCILIB

Home:http://vrogier.github.io/ocilib/

這是一個跨平臺的 C 開源庫。如其名,它封裝了 Oracle 官方的 OCI(Oracle Call Interface)。

它同時還提供了 C++ 的 API。

程式碼示例

#include <ocilib.hpp>
using namespace ocilib;

int main()
{
    try
    {
        Environment::Initialize();
        Connection conn("db", "user", "password");
        Statement stmt(conn);
        stmt.Execute("select intcol, strcol from table");

        Resultset rs = stmt.GetResultset();
        while(rs.Next())
        {
            std::cout << rs.Get<int>(1) << " - " << rs.Get<ostring>(2) << std::endl;
        }
    }
    catch(std::exception& err)
    {
        std::cout << err.what() << std::endl;
    }

    Environment::Cleanup();
    return 0;
}

9.2.5 DB2 封裝庫

9.2.6 SQLite 封裝庫

官方的 C API

Docs:http://sqlite.org/c3ref/intro.html

SQLite 前面已經介紹過。由於 SQLite 本身就是用 C 語言開發的,因此它直接提供了基於 C 的 API 介面。

程式碼示例

#include <stdio.h>
#include <sqlite3.h>

static int callback(void* NotUsed, int argc, char** argv, char** azColName)
{
    for(int i=0; i<argc; i++)
    {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
        return 1;
    }

    sqlite3* db = NULL;
    int rc = sqlite3_open(argv[1], &db);
    if(rc)
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }

    char* szErrMsg = NULL;
    rc = sqlite3_exec(db, argv[2], callback, 0, &szErrMsg);
    if(rc != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", szErrMsg);
        sqlite3_free(szErrMsg);
    }

    sqlite3_close(db);
    return 0;
}

POCO::Data::SQLite

Docs:http://pocoproject.org/docs/package-SQLite.SQLite.html

POCO 前面已經介紹過。它提供了 sqlite 的封裝類

9.2.7 Redis 封裝庫

Hiredis

Home:https://github.com/redis/hiredis

這是 Redis 官方提供的 C 客戶端,很輕量級,支援“非同步 API”。

程式碼示例——結合 libev 進行非同步呼叫

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <hiredis.h>
#include <async.h>
#include <adapters/libev.h>

void getCallback(redisAsyncContext* context, void* r, void* privdata)
{
    redisReply* reply = r;
    if(reply == NULL)
    {
        return;
    }
    printf("argv[%s]: %s\n", (char*)privdata, reply->str);
    redisAsyncDisconnect(context);  /* Disconnect after receiv reply */
}

void connectCallback(const redisAsyncContext* context, int status)
{
    if(status != REDIS_OK)
    {
        printf("Error: %s\n", context->errstr);
        return;
    }
    printf("Connected...\n");
}

void disconnectCallback(const redisAsyncContext* context, int status)
{
    if(status != REDIS_OK)
    {
        printf("Error: %s\n", context->errstr);
        return;
    }
    printf("Disconnected...\n");
}

int main(int argc, char* argv[])
{
    signal(SIGPIPE, SIG_IGN);

    redisAsyncContext* context = redisAsyncConnect("127.0.0.1", 6379);
    if(context->err)
    {
        printf("Error: %s\n", context->errstr);
        return 1;  /* Let *context leak for now... */
    }

    redisLibevAttach(EV_DEFAULT_ context);
    redisAsyncSetConnectCallback(context, connectCallback);
    redisAsyncSetDisconnectCallback(context, disconnectCallback);
    redisAsyncCommand(context, NULL, NULL,
                        "SET key %b", argv[argc-1], strlen(argv[argc-1]));
    redisAsyncCommand(context, getCallback, (char*)"end-1", "GET key");
    ev_loop(EV_DEFAULT_ 0);
    return 0;
}

9.2.8 MongoDB 封裝庫

官方的 C API

Docs:https://api.mongodb.org/c/current/

MongoDB 前面已經介紹過。這是其官方提供的 API。

程式碼示例

#include <stdio.h>
#include <bson.h>
#include <mongoc.h>

int main(int argc, char* argv[])
{
    mongoc_init();

    mongoc_client_t* client = mongoc_client_new("mongodb://localhost:27017/");
    mongoc_collection_t* collection = mongoc_client_get_collection(client, "test", "test");

    bson_t* doc = bson_new();

    bson_oid_t oid;
    bson_oid_init(&oid, NULL);
    BSON_APPEND_OID(doc, "_id", &oid);
    BSON_APPEND_UTF8(doc, "hello", "world");

    bson_error_t error;
    if(!mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error))
    {
        printf("%s\n", error.message);
    }

    bson_destroy(doc);
    mongoc_collection_destroy(collection);
    mongoc_client_destroy(client);

    return 0;
}

POCO::MongoDB

Docs:http://pocoproject.org/docs/package-MongoDB.MongoDB.html

POCO 前面已經介紹過。它提供了 MongoDB 的封裝類

9.3 ODBC 相關

unixODBC

Home:http://www.unixodbc.org/

Wikipedia:英文

誕生於1999年,實現了全套的 ODBC 架構,包括:驅動管理器、相關的 GUI 介面和命令列介面。支援多種作業系統。

Libodbc++

Home:http://libodbcxx.sourceforge.net/

如其名,這是專門封裝 ODBC 的 C++ 類庫,支援多種作業系統。它提供的 API 類似於 JDBC 的 API

POCO::Data::ODBC

Docs:http://pocoproject.org/docs/package-ODBC.ODBC.html

POCO 前面已經介紹過。它提供了操作 ODBC 的封裝類。

9.4 ORM(Object-Relational Mapping)

ODB

Home:http://www.codesynthesis.com/products/odb

Wikipedia:英文

它的特色是:可以根據 C++ 類定義自動生成資料庫的表結構。

為了獲得高效能,它直接呼叫具體資料庫的原生 API。支援的資料庫包括:MySQL、PostgreSQL、Oracle、SQL Server、SQLite

程式碼示例——宣告一個可持久化的類

// 通過預處理語句“#pragma”來進行某些定製

#pragma db object table("people")
class person
{
public:
    // ......

private:
    friend class odb::access;
    person();

    #pragma db id auto
    unsigned long id_;

    string first_;
    string last_;

    #pragma type("INT UNSIGNED")
    unsigned short age_;
};

程式碼示例——查詢

typedef odb::query<person> query;
typedef odb::result<person> result;

transaction trans(db.begin());
result r(db.query<person>(query::last == "Doe" && query::age < 30));

for(result::iterator i(r.begin()); i!=r.end(); ++i)
{
    cout << "Hello, " << i->first() << endl;
}

trans.commit();

hiberlite

Home:https://github.com/paulftw/hiberlite

專門提供給 Sqlite 的 ORM 封裝庫。基於 C++ 開發,其 API 採用類似 Boost.Serialization 的風格。


10 Web

10.1 HTTP Server

Apache HTTP Server

Home:https://httpd.apache.org/

Wikipedia:英文中文

大名鼎鼎的 Apache,誕生於1995年,採用 C 和 C++ 開發。長期作為 Web Server 市場份額的老大。

Nginx

Home:http://nginx.org/

Wikipedia:英文中文

Web Server 的後起之秀,誕生於2002年,採用 C 語言開發。其市場份額如今排名第二。

POCO::Net

Docs:http://pocoproject.org/docs/package-Net.HTTPServer.html

POCO 前面已經介紹過。它提供了 HTTP Server 的封裝類

Dlib::server_http

Docs:http://dlib.net/network.html#server_http

Dlib 前面已經介紹過。它提供了一個簡單的 HTTP Server 的類(server_http)。

10.2 HTTP Client

cURL & libcurl

Docs:http://curl.haxx.se/libcurl/c/

libcurl 前面已經介紹過。它提供了【完整的】HTTP 協議支援。另,HTTP 2.0 標準剛出來不久,它就已經支援了。

程式碼示例——HTTP POST

#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_URL, "http://post.example.com/foo.cgi");
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");

        CURLcode res = curl_easy_perform(curl);
        if(res != CURLE_OK)  // Check for errors
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                    curl_easy_strerror(res));
        }
        curl_easy_cleanup(curl);  // always cleanup
    }

    curl_global_cleanup();
    return 0;
}

POCO::Net

Docs:http://pocoproject.org/docs/package-Net.HTTPClient.html

POCO 前面已經介紹過。它提供了 HTTP Client 的封裝類。

10.3 瀏覽器引擎

WebKit

Home:https://www.webkit.org/

Wikipedia:英文中文

它是很多瀏覽器使用的渲染引擎,基於 C++ 開發。

Gecko

Home:https://developer.mozilla.org/

Wikipedia:英文中文

它是 Firefox 的渲染引擎,基於 C++ 開發,由 Mozilla 社群維護。

10.4 瀏覽器整合

CEF(Chromium Embedded Framework)

Home:https://bitbucket.org/chromiumembedded/cef

Wikipedia:英文

如其名,它提供了嵌入 Chrome 瀏覽器的框架。採用 C++ 開發。好幾個商業公司(Google、Adobe、Facebook、Evernote...)的產品用到它。

以下是其它開源專案針對 CEF 的擴充套件,提供了其它程式語言的繫結。

PhantomJS

Home:http://phantomjs.org/

Wikipedia:英文

2011年才誕生的。基於 C++ 開發,整合了 WebKit。

它本身沒有提供 GUI 介面。但是提供了 JavaScript 的 API,讓你可以操縱 WebKit 引擎。可以利用它進行 Web 介面的單元測試。

10.5 (其它)

WebSocket++

Home:http://www.zaphoyd.com/websocketpp/

顧名思義,它提供了WebSocket的 C++ 封裝,基於 Boost Asio 構建。

支援多種作業系統平臺,支援 TLS、proxy、IPv6。


11 資訊保安

11.1 密碼學

Crypto++

Docs:http://www.cryptopp.com/docs/ref/annotated.html

Crypto++ 前面已經介紹過。它提供了常見的對稱加密演算法(DES、AES、IDEA 等)、公鑰加密演算法(RSA、DSA 等)、雜湊演算法(MD5、SHA1、RIPEMD 等)。

程式碼示例——計算 SHA256 雜湊值

#include <cryptopp/sha.h>
using namespace CryptoPP;

const byte* pbData = ...;  // 要計算的資料的地址
unsigned int nDataLen = ...;  // 位元組數
byte abDigest[SHA256::DIGESTSIZE];
SHA256().CalculateDigest(abDigest, pbData, nDataLen);
// 注:abDigest 中通常會包含不可見字元,要輸出為可見字串需要做一下 Hex 編碼

OpenSSL

Home:https://www.openssl.org/

Wikipedia:英文中文

OpenSSL 基於 C 語言開發,在加密領域那可是大名鼎鼎。大部分常用的加密演算法(對稱、非對稱)和雜湊演算法,它都支援。

很多知名的軟體(包括 Web Server)用到它,所以2014年的“心臟滴血漏洞”讓好多網站中招。

LibreSSL

Home:http://www.libressl.org/

Wikipedia:英文中文

OpenSSL 爆出“心臟滴血漏洞”之後,OpenBSD 社群的程式設計師複製了 OpenSSL 版本 1.0.1g 的程式碼,然後另起爐灶。

LibreSSL 的主要目標是“安全性”,其維護人員刪除了原 OpenSSL 中大量過時的程式碼,替換了相關的記憶體管理函式(規避緩衝區溢位),增強了隨機數生成演算法....

GnuTLS

Home:http://gnutls.org/

Wikipedia:英文

採用 C 語言開發,名氣也挺大。如其名,主要提供 TLS/SSL 的相關功能。

NaCl

Home:http://nacl.cr.yp.to/

Wikipedia:英文

這個名稱是“Networking and Cryptography library”的縮寫。

它採用 C 語言開發,另有其它程式語言(Python、Ruby、PHP)的 API 繫結。

它的作者同時也是qmailCurve25519的作者。

libsodium

Home:https://github.com/jedisct1/libsodium

它派生自 NaCl,提供了跟 NaCl 相容的 API。支援的作業系統平臺更多。

ssss-h-a-d-o-w-s-o-c-k-s 和 dnscrypt-proxy 用到它。

Keyczar

Home:https://github.com/google/keyczar

這是 Google 提供的加密庫,同時提供 C++、Java、Python 三種語言的實現。

它提供了比較高層的 API, 使用者無需關心太多的細節。

程式碼示例——加密/解密文字

#include <cassert>
#include <iostream>
#include <string>
#include <keyczar/keyczar.h>

void test(const std::string& key_location)
{
    keyczar::Keyczar* crypter = keyczar::Crypter::Read(key_location);
    if(!crypter)
    {
        return;
    }

    std::string plain = "Secret message";
    std::cout << "Plain text: " << plain << std::endl;

    std::string cipher;
    if(crypter->Encrypt(plain, &cipher))
    {
        std::cout << "Cipher text (Base64w): " << cipher << std::endl;
        std::string decrypted;
        if(crypter->Decrypt(cipher, &decrypted))
        {
            assert(plain == decrypted);
        }
    }
    delete crypter;
}

POCO::Crypto

Docs:http://pocoproject.org/docs/Poco.Crypto.html

POCO 前面已經介紹過。它提供了常見的加密演算法和雜湊演算法。


12 處理檔案格式

12.1 結構化資料格式

12.1.1 CSV

CSV是一種歷史悠久的結構化資料儲存格式。其效果類似於一張資料庫二維表。

Boost.Tokenizer

Docs:http://boost.org/libs/tokenizer

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,用來靈活地切割字串。使用它,可以幫你提取 CSV 的行和列。

12.1.2 JSON

JSON 格式源自 JavaScript,如今在 Web 開發中廣為應用。

Boost.PropertyTree

Docs:http://boost.org/libs/property_tree

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,封裝了某種特殊的“樹”結構(property_tree)。它支援對 JSON 的讀寫。

程式碼示例——讀寫 JSON 字串

#include <sstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;

// Write json
ptree pt1;
pt1.put("foo", "bar");
std::ostringstream oss; 
write_json(oss, pt1, false);
std::string json = oss.str(); // {"foo":"bar"}

// Read json
std::istringstream iss(json);
ptree pt2;
read_json(iss, pt2);
std::string value = pt2.get<std::string>("foo");

POCO::JSON

Docs:http://pocoproject.org/docs/package-JSON.JSON.html

POCO 前面已經介紹過。它提供了 JSON 的封裝類

rapidjson

Home:https://github.com/miloyip/rapidjson

這是一個 C++ 的 JSON 庫。提供了 SAX 和 DOM 風格的 API。

(另,作者是香港同胞)

jsoncpp

Home:https://github.com/open-source-parsers/jsoncpp

如其名,這是個 C++ 的 JSON 封裝庫。

12.1.3 YAML

YAML是一種類似於 json 的結構化資料格式。它在確保可讀性的基礎上,提供了超越 json 的靈活性和擴充套件性。

yaml-cpp

Home:https://github.com/jbeder/yaml-cpp

C++ 實現的 YAML 解析器。

LibYAML

Home:http://pyyaml.org/wiki/LibYAML

C 語言實現的 YAML 解析器。

12.2 壓縮檔案 & 打包檔案

12.2.1 綜合性的庫

libarchive

Home:http://www.libarchive.org/

C 語言實現,支援的格式:

可讀寫的格式:zip、gzip、bzip2、xz、lzma、tar、ISO、cpio、ar、pax、mtree;

只讀的格式:7z、rar、cab、rpm、lzh、lzop、raw、xar

LZMA SDK

Home:http://www.7-zip.org/sdk.html

這是由 7-zip 官方提供的。7-zip 就是用它進行壓縮/解壓縮。

支援的格式:7z、LZMA、LZMA2、XZ

PhysicsFS

Home:http://icculus.org/physfs/

Wikipedia:英文

針對不同的壓縮/歸檔格式,提供了類似 VFS 的抽象封裝層。主要用於遊戲開發中。

支援的格式:zip、7z、GRP、PAK、HOG、MVL、WAD...

zopfli

Home:https://github.com/google/zopfli

這是由 Google 開發的 C 庫,提供對 zip 和 gzip 格式的壓縮(不提供解壓)。

壓縮的速度比較慢,但是可以得到更高的壓縮率。

12.2.2 zip

格式說明

libzip

Home:http://www.nih.at/libzip/

Wikipedia:英文

用 C 語言開發的庫,基於 zlib 庫。

Poco::Zip

Docs:http://pocoproject.org/docs/Poco.Zip.html

POCO 前面已經介紹過。它提供了若干封裝類,用於 zip 格式的壓縮和解壓。

12.2.3 bzip2(bz2)

格式說明

libbzip2

Home:http://bzip.org/

這是 bzip2 官方提供的庫,C 語言實現。

12.2.4 gzip(gz)

zlib

Home:http://zlib.net/

Wikipedia:英文中文

C 語言實現,誕生於1995年,被大量的開源專案使用(OpenSSL、OpenSSH、Apache、PostgreSQL、Git、libpng......)。

12.2.5 tar

libtar

Home:http://www.feep.net/libtar/

基於 C 語言開發,可以對 tar 格式新增內容或讀取內容。

12.2.6 rar

unrarlib

Home:http://www.unrarlib.org/

該專案的開發已經停止。只支援對 RAR2 格式的解壓縮。

12.2.7 snappy

snappy

Home:https://google.github.io/snappy/

由 Google 開發的壓縮格式,特點是非常快(不論是壓縮還是解壓);但是壓縮率不如 gzip。

起先被用於 Google 內部的 BigTable,如今被用於多種 NoSQL 資料庫(比如:Cassandra、Hadoop、LevelDB、MongoDB、RocksDB...)

支援多種語言的繫結(C#、Common Lisp、Erlang、Go、Haskell、Lua、Java、Node.js、Perl、PHP、Python、R、Ruby、Smalltalk)

12.2.8 Brotli

Brotli

Home:https://github.com/google/brotli

Wikipedia:英文

由 Google 開發的壓縮格式,壓縮率很高(據說高於 LZMA 和 bz2)。

該演算法很新,是2015年9月才釋出的。

12.3 標記語言

12.3.1 XML

Expat

Home:http://www.libexpat.org/

Wikipedia:英文

基於 C 語言實現,誕生於1998年。很多知名的開源專案(Apache Server、Firefox、Python、PHP、Perl)用到它。

libxml2

Home:http://xmlsoft.org/

Wikipedia:英文

基於 C 語言實現,誕生於1999年。提供了多種語言(C++、Python、Ruby、Common Lisp、PHP、Perl)的 API 繫結。

wxWidgets

Docs:http://docs.wxwidgets.org/trunk/groupxml.html

wxWidgets 前面已經介紹過。它提供了 XML 的封裝類,其內部是基於 Expat 進行解析。

POCO::XML

Docs:http://pocoproject.org/docs/package-XML.XML.html

POCO 前面已經介紹過。它提供了 XML 的封裝類。

libxml++

Home:http://libxmlplusplus.sourceforge.net/

如其名,它是針對前面提到的 libxml2 的 C++ 封裝。

12.3.2 HTML

htmlcxx

Home:http://htmlcxx.sourceforge.net/

如其名,是基於 C++ 開發的。支援 HTML 和 CSS 的解析。

12.4 PDF

PoDoFo

Home:http://podofo.sourceforge.net/

基於 C++ 開發的跨平臺庫,名稱取自“Portable Document Format”每個單詞的頭兩個字母 :)

它既支援 PDF 檔案的生成,也支援 PDF 內容的提取。它同時還提供一堆命令列的小工具,用來操作 PDF 檔案。

LibHaru

Home:http://libharu.org/

Wikipedia:英文

它是基於 C 語言開發的跨平臺庫,可以用來生成 PDF 檔案格式。

程式碼示例

#include <hpdf.h>

// 建立文件物件
HPDF_Doc doc = HPDF_New(error_handler, NULL);
if(!doc)
{
    printf("ERROR: cannot create pdf object.\n");
    return 1;
}

// 設定文件屬性
HPDF_SetCompressionMode(doc, HPDF_COMP_ALL);
HPDF_SetPageMode(doc, HPDF_PAGE_MODE_USE_OUTLINE);
HPDF_SetPassword(doc, "owner pwd", "user pwd");

// 新增一頁
HPDF_Page page_1 = HPDF_AddPage(doc);
// 設定頁屬性
HPDF_Page_SetSize(page_1, HPDF_PAGE_SIZE_B5, HPDF_PAGE_LANDSCAPE);

// 儲存到檔案
HPDF_SaveToFile(doc, "test.pdf");

// 結束
HPDF_Free(doc);

12.5 MS Office 文件

wvWare

Home:http://wvware.sourceforge.net/

它能夠讀取 Word 文件的內容,支援的 Word 版本是(2000、97、95、6)。

AbiWord 和 KWord 用到它。

12.6 RTF

LibRTF

Home:http://sourceforge.net/projects/librtf/

C 語言實現的庫,可以解析 RTF 檔案格式。

12.7 CHM

CHMLIB

Home:http://www.jedrea.com/chmlib/

這是一個輕量級的庫,基於 C 語言開發,可以用來提取 CHM 格式檔案的內容。

它提供了多種程式語言(C++、Python、Perl、Common Lisp)的 API 繫結。

libCHMxx

Home:http://www.mare.ee/indrek/libchmxx/

它就是基於 CHMLIB 的 C++ 封裝庫。


13 影象

13.1 影象處理

ImageMagick

Home:http://imagemagick.org/

Wikipedia:英文中文

ImageMagick 可說是最強大的開源圖片處理工具集,採用 C 語言編寫。誕生於1990年,其開發至今依然非常活躍。支援非常多的作業系統平臺。

它提供許多程式語言的 API,對於 C++ 是Magick++,對於 C 是MagickWand

Boost.GIL(Generic Image Library)

Docs:http://boost.org/libs/gil

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,實現了影象處理功能。

程式碼示例——調整影象尺寸

#include <boost/gil/image.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/gil/extension/io/jpeg_io.hpp>
#include <boost/gil/extension/numeric/sampler.hpp>
#include <boost/gil/extension/numeric/resample.hpp>

using namespace boost::gil;

rgb8_image_t img;
jpeg_read_image("input.jpg", img);

// Scale the image to 100x100 pixels using bilinear resampling
rgb8_image_t square(100, 100);
resize_view(const_view(img), view(square), bilinear_sampler());
jpeg_write_view("output.jpg", const_view(square));

Dlib

Docs:http://dlib.net/imaging.html

Dlib 前面已經介紹過。它提供了常見的影象處理功能(旋轉、剪下、拉伸、過濾)。

13.2 影象格式轉換

ImageMagick

ImageMagick 前面已經介紹過。它支援非常多的圖片格式(清單),基本上你聽說過的,它都支援。甚至包括 Postscript 和 PDF。

在支援的格式中,它可以實現其中幾十種格式的相互轉換。

13.3 影象渲染

Cairo

Home:http://cairographics.org/

Wikipedia:英文中文

它提供了向量影象的渲染功能。支援多種後端輸出(Win32 GDI、OpenGL、Xlib、XCB、PDF、PNG、SVG ......)。

基於 C 語言開發,提供多種語言繫結(C++、Java、C#、Python、Ruby、Perl、Scheme、Smalltalk)。

cairomm

Home:http://cairographics.org/cairomm/

這是針對 Cairo 的 C++ 封裝庫。

Skia

Home:https://github.com/google/skia

Wikipedia:英文中文

它是 Google 基於 C++ 開發的影象渲染庫。支援多種後端輸出(rasterization、OpenGL、PDF、SVG、SWF ......)。

原先由 Skia 公司開發,後來該公司被 Google 收購。被用於 Android、Chrome、Chrome OS、Firefox 等知名開源專案。

PBRT(Physically Based Rendering Toolkit)

Home:http://pbrt.org/

基於光線追蹤的物理渲染系統,採用 C++ 開發。

13.4 計算機視覺

OpenCV

Home:http://opencv.org/

Wikipedia:英文中文

它是一個跨平臺的計算機視覺庫,由 Intel 發起並參與開發。開發語言是 C 和 C++。

提供其它程式語言(Python、Java、MATLAB/OCTAVE ...)的 API 繫結。


14 多媒體

14.1 多媒體框架

FFmpeg

Home:http://ffmpeg.org/

Wikipedia:英文中文

名氣非常大的開源多媒體框架,基於 C 和彙編開發,支援多種作業系統。

另外,該開源專案還提供了若干命令列工具,包含了一些輔助功能。

  • ffmpeg 格式轉換工具
  • ffplay 簡化版的播放器
  • ffserver 流媒體伺服器
  • ffprobe 顯示多媒體檔案資訊

幾個知名的開源播放器(VLC、MPC-HC、xine)用到它,Google Chrome 也用到它。

Libav

Home:http://libav.org/

Wikipedia:英文

它是2011年從 FFmpeg 派生出來的。基於 C 語言開發,支援多種作業系統。

14.2 視訊庫

libavcodec

Home:http://ffmpeg.org/

它來自於 FFmpeg 社群,基於 C 語言實現,提供了多種視訊格式和音訊格式的編碼/解碼功能。

由於 Libav 從 FFmpeg 分裂出來,Libav 下也帶有一個同名的庫。

14.3 音訊庫

PortMedia & PortAudio

Home:http://www.portaudio.com/

Wikipedia:英文

PortAudio 是 PortMedia 的組成部分,提供了音訊的播放和錄製功能。支援多種底層 API(ALSA、DirectSound、WASAPI、ASIO...)

OpenAL

Home:http://www.openal.org/

Wikipedia:英文中文

C 語言開發的 3D 音效庫,跨平臺。最初由 Loki Software 開發。Loki 倒閉以後,這個專案由開源社群繼續維護。


15 遊戲

15.1 綜合性的遊戲引擎

id Tech 系列

Wikipedia:英文

這個系列來自於大名鼎鼎的id Software 公司,由同樣大名鼎鼎約翰·卡馬克打造。

第一代誕生於1993年,是 DOS 時代的經典。

原先基於 C 和 彙編開發,從 id Tech 4 開始改用 C++ 開發。

  • id Tech 1——俗稱:Doom 引擎
  • id Tech 2(Quake)——俗稱:Quake 引擎
  • id Tech 2(Quake II)——俗稱:Quake II 引擎
  • id Tech 3——俗稱:Quake III 引擎
  • id Tech 4——俗稱:Doom 3 引擎

Crystal Space

Home:http://www.crystalspace3d.org/

Wikipedia:英文

以 C++ 編寫,功能包括:2D 和 3D 渲染、音效、AI... 它的物理引擎基於 ODE 和 Bullet

Blender Game Engine

Home:http://www.blender.org/

Wikipedia:英文中文

它是Blender的組成部分,以 C++ 編寫,使用 Python 指令碼擴充套件。功能包括:3D 渲染、碰撞檢測、角色編輯器、音效、網路通訊、AI、...

Panda3D

Home:http://www.panda3d.org/

Wikipedia:英文

以 C++ 編寫,用 Python 指令碼擴充套件。雖然它的名字有“3D”,但它不僅僅是 3D 引擎,還包括了其它功能(碰撞檢測、音效、關卡編輯器...)。

15.2 3D 渲染引擎

OGRE

Home:http://www.ogre3d.org/

Wikipedia:英文中文

著名的 3D 渲染引擎,C++ 開發,誕生於2005年。支援很多作業系統(包括兩大手機作業系統)。很多商業遊戲用到它。

支援其它程式語言(Python、Ruby、Perl)的 API 繫結。支援 JVM 和 dotNet 平臺。

Mesa 3D

Home:http://mesa3d.org/

Wikipedia:英文中文

使用 C 語言開發,它是針對 OpenGL 規範的【純軟體】實現(大部分 OpenGL 的實現都用到了顯示卡硬體)。

15.3 物理引擎

Bullet

Home:http://www.bulletphysics.org/

Wikipedia:英文中文

採用 C 和 C++ 開發。電影《2012》用到它,遊戲“俠盜獵車手”、“荒野大鏢客”用到它。

Box2D

Home:http://www.box2d.org/

Wikipedia:英文中文

基於 C++ 開發的2維物理引擎。“憤怒的小鳥”用到它。

ODE(Open Dynamics Engine)

Home:http://www.ode.org/

Wikipedia:英文中文

誕生於2001年,採用 C 和 C++ 開發。

Newton Game Dynamics

Home:http://www.newtondynamics.com/

Wikipedia:英文

基於 C++ 開發。


16 數值運算 & 科學計算

16.1 綜合性的庫

GSL(GNU Scientific Library)

Home:https://www.gnu.org/software/gsl/

Wikipedia:英文

由 GNU 官方提供,包括:複數、多項式、矩陣、線性代數、特徵向量、快速傅立葉變換、統計、模擬退火......

程式碼示例——貝塞爾函式

#include <stdio.h>
#include <gsl/gsl_sf_bessel.h>

double x = 5.0;
double y = gsl_sf_bessel_J0(x);
printf("J0(%g) = %.18e\n", x, y);

16.2 有理數

Boost.Rational

Docs:http://boost.org/libs/rational

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,提供了“有理數”的功能。

16.3 高精度數值運算

GMP(GNU Multiple Precision)

Home:https://gmplib.org/

Wikipedia:英文中文

基於 C 語言的高精度數值運算庫,誕生於1991年,非常老牌。

程式碼示例——大整數相乘

#include <stdio.h>
#include <gmp.h>

mpz_t x,y,result;

mpz_init_set_str(x, "7612058254738945", 10);
mpz_init_set_str(y, "9263591128439081", 10);
mpz_init(result);

mpz_mul(result, x, y);
gmp_printf("%Zd\n", result);

/* free used memory */
mpz_clear(x);
mpz_clear(y);
mpz_clear(result);

Boost.Multiprecision

Docs:http://boost.org/libs/multiprecision

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,實現了高精度數值運算。它還提供了針對 GMP 的資料型別的封裝。

16.4 矩陣

Boost.uBLAS.Matrix

Docs:http://boost.org/libs/numeric/ublas/doc/matrix.html

Boost 前面已經介紹過。這是 Boost 提供的矩陣模板類。

程式碼示例

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

using namespace boost::numeric::ublas;

matrix<double> m(3, 3);
for(unsigned i=0; i<m.size1(); i++)
    for(unsigned j=0; j<m.size2(); j++)
        m(i, j) = 3 * i + j;

std::cout << m << std::endl;

Dlib

Docs:http://dlib.net/linear_algebra.html#matrix

Dlib 前面已經介紹過。它提供了一個矩陣類。

16.5 線性代數

Boost.uBLAS

Docs:http://boost.org/libs/numeric/ublas

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,實現了 BLAS 的1、2、3級。

程式碼示例——計算矩陣與向量的乘積

#include <iostream>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

using namespace boost::numeric::ublas;
vector<double> v(2);
v(0) = 1; v(1) = 2;

matrix<double> m(2,2);
m(0,0) = 0; m(0,1) = 1;
m(1,0) = 2; m(1,1) = 3;

vector<double> v2 = prod(m, v);
std::cout << v2 << std::endl;

Blitz++

Home:http://blitz.sourceforge.net/

Wikipedia:英文

它是基於 C++ 實現的。其特色是:採用“模板超程式設計”的技術進行編譯時計算,從而優化了效能。

Armadillo

Home:http://arma.sourceforge.net/

Wikipedia:英文

類似 Blitz++,Armadillo 也用了“模板超程式設計”的技術。

程式碼示例

#include <iostream>
#include <armadillo>

using namespace std;
using namespace arma;

vec v;
v << 2.0 << 5.0 << 2.0;

// endr represents the end of a row in a matrix
mat m;
m << 1.0 << 2.0 << endr
  << 2.0 << 3.0 << endr
  << 1.0 << 3.0 << endr;

cout << "Least squares solution:" << endl << solve(m,v) << endl;

Dlib

Docs:http://dlib.net/linear_algebra.html

Dlib 前面已經介紹過。它提供了線性代數相關的封裝類。


17 跨語言程式設計

17.1 整合多種語言的庫

SWIG

Home:http://swig.org/

Wikipedia:英文

這是一個很老牌的、有名氣的工具,它可以把多種語言(Java、Python、C#、Ruby、PHP、Perl、Lua、Go ......)整合到 C/C++ 中。

整合之後,你的 C/C++ 程式就可以享受到其它這些語言的特性啦,非常爽!

17.2 整合單一語言的庫

17.2.1 整合 Python 語言

Boost.Python

Docs:http://boost.org/libs/python

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,實現了 C++ 程式碼和 Python 程式碼的互操作。

程式碼示例——Hello world

// 這是一個標準的 C 函式
const char* greet()
{
    return "Hello, world";
}

// 使用如下程式碼對上述函式進行包裝
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(hello_ext)
{
    using namespace boost::python;
    def("greet", greet);
}

// 以下是呼叫該模組的 Python 程式碼
// import hello_ext
// print(hello_ext.greet())


18 (其它)

一些不方便歸類的,暫時放到這裡。

18.1 詞法分析 & 語法分析

Boost.Spirit

Docs:http://boost.org/libs/spirit

Boost 前面已經介紹過。這是 Boost 的其中一個子庫,提供了“基於 EBNF 的解析器框架”。

https://github.com/programthink/opensource/blob/master/libs/cpp.wiki