├── LICENSE
├── README.wiki
└── libs
├── README.wiki
├── cpp.wiki
└── python.wiki
/LICENSE:
--------------------------------------------------------------------------------
1 | CC0 1.0 Universal
2 |
3 | Statement of Purpose
4 |
5 | The laws of most jurisdictions throughout the world automatically confer
6 | exclusive Copyright and Related Rights (defined below) upon the creator and
7 | subsequent owner(s) (each and all, an "owner") of an original work of
8 | authorship and/or a database (each, a "Work").
9 |
10 | Certain owners wish to permanently relinquish those rights to a Work for the
11 | purpose of contributing to a commons of creative, cultural and scientific
12 | works ("Commons") that the public can reliably and without fear of later
13 | claims of infringement build upon, modify, incorporate in other works, reuse
14 | and redistribute as freely as possible in any form whatsoever and for any
15 | purposes, including without limitation commercial purposes. These owners may
16 | contribute to the Commons to promote the ideal of a free culture and the
17 | further production of creative, cultural and scientific works, or to gain
18 | reputation or greater distribution for their Work in part through the use and
19 | efforts of others.
20 |
21 | For these and/or other purposes and motivations, and without any expectation
22 | of additional consideration or compensation, the person associating CC0 with a
23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
25 | and publicly distribute the Work under its terms, with knowledge of his or her
26 | Copyright and Related Rights in the Work and the meaning and intended legal
27 | effect of CC0 on those rights.
28 |
29 | 1. Copyright and Related Rights. A Work made available under CC0 may be
30 | protected by copyright and related or neighboring rights ("Copyright and
31 | Related Rights"). Copyright and Related Rights include, but are not limited
32 | to, the following:
33 |
34 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
35 | and translate a Work;
36 |
37 | ii. moral rights retained by the original author(s) and/or performer(s);
38 |
39 | iii. publicity and privacy rights pertaining to a person's image or likeness
40 | depicted in a Work;
41 |
42 | iv. rights protecting against unfair competition in regards to a Work,
43 | subject to the limitations in paragraph 4(a), below;
44 |
45 | v. rights protecting the extraction, dissemination, use and reuse of data in
46 | a Work;
47 |
48 | vi. database rights (such as those arising under Directive 96/9/EC of the
49 | European Parliament and of the Council of 11 March 1996 on the legal
50 | protection of databases, and under any national implementation thereof,
51 | including any amended or successor version of such directive); and
52 |
53 | vii. other similar, equivalent or corresponding rights throughout the world
54 | based on applicable law or treaty, and any national implementations thereof.
55 |
56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of,
57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
59 | and Related Rights and associated claims and causes of action, whether now
60 | known or unknown (including existing as well as future claims and causes of
61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
62 | duration provided by applicable law or treaty (including future time
63 | extensions), (iii) in any current or future medium and for any number of
64 | copies, and (iv) for any purpose whatsoever, including without limitation
65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
66 | the Waiver for the benefit of each member of the public at large and to the
67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
68 | shall not be subject to revocation, rescission, cancellation, termination, or
69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
70 | by the public as contemplated by Affirmer's express Statement of Purpose.
71 |
72 | 3. Public License Fallback. Should any part of the Waiver for any reason be
73 | judged legally invalid or ineffective under applicable law, then the Waiver
74 | shall be preserved to the maximum extent permitted taking into account
75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
76 | is so judged Affirmer hereby grants to each affected person a royalty-free,
77 | non transferable, non sublicensable, non exclusive, irrevocable and
78 | unconditional license to exercise Affirmer's Copyright and Related Rights in
79 | the Work (i) in all territories worldwide, (ii) for the maximum duration
80 | provided by applicable law or treaty (including future time extensions), (iii)
81 | in any current or future medium and for any number of copies, and (iv) for any
82 | purpose whatsoever, including without limitation commercial, advertising or
83 | promotional purposes (the "License"). The License shall be deemed effective as
84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
85 | License for any reason be judged legally invalid or ineffective under
86 | applicable law, such partial invalidity or ineffectiveness shall not
87 | invalidate the remainder of the License, and in such case Affirmer hereby
88 | affirms that he or she will not (i) exercise any of his or her remaining
89 | Copyright and Related Rights in the Work or (ii) assert any associated claims
90 | and causes of action with respect to the Work, in either case contrary to
91 | Affirmer's express Statement of Purpose.
92 |
93 | 4. Limitations and Disclaimers.
94 |
95 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
96 | surrendered, licensed or otherwise affected by this document.
97 |
98 | b. Affirmer offers the Work as-is and makes no representations or warranties
99 | of any kind concerning the Work, express, implied, statutory or otherwise,
100 | including without limitation warranties of title, merchantability, fitness
101 | for a particular purpose, non infringement, or the absence of latent or
102 | other defects, accuracy, or the present or absence of errors, whether or not
103 | discoverable, all to the greatest extent permissible under applicable law.
104 |
105 | c. Affirmer disclaims responsibility for clearing rights of other persons
106 | that may apply to the Work or any use thereof, including without limitation
107 | any person's Copyright and Related Rights in the Work. Further, Affirmer
108 | disclaims responsibility for obtaining any necessary consents, permissions
109 | or other rights required for any use of the Work.
110 |
111 | d. Affirmer understands and acknowledges that Creative Commons is not a
112 | party to this document and has no duty or obligation with respect to this
113 | CC0 or use of the Work.
114 |
115 | For more information, please see
116 |
117 |
--------------------------------------------------------------------------------
/README.wiki:
--------------------------------------------------------------------------------
1 | = 俺收藏的开源项目 =
2 |
3 | == 开源库及示例代码 ==
4 |
5 | 本目录放置:面向程序员的开源代码库清单(含示例代码)。
6 |
7 | 为了方便查找,根据“编程语言”归类。(目前先整理两个编程语言,今后有空再补充其它语言)
8 |
9 | * [/libs/cpp.wiki C/C++]
10 | * [/libs/python.wiki Python]
11 |
12 | == 开源软件 ==
13 |
14 | (俺会抽空整理)
15 |
--------------------------------------------------------------------------------
/libs/README.wiki:
--------------------------------------------------------------------------------
1 | = 开源库及示例代码 =
2 |
3 | 本目录放置:面向程序员的开源代码库清单(含示例代码)。
4 |
5 | 为了方便查找,根据“编程语言”归类。(目前先整理两个编程语言,今后有空再补充其它语言)
6 |
7 | * [/libs/cpp.wiki C/C++]
8 | * [/libs/python.wiki Python]
9 |
--------------------------------------------------------------------------------
/libs/cpp.wiki:
--------------------------------------------------------------------------------
1 |
C/C++ 开源库及示例代码
2 |
3 | = =
4 |
5 | = 说明 =
6 |
7 | 本页面汇总俺收集的各种 C 和 C++ 的开源代码库,不定期更新。
8 |
9 | 如果你发现本页面的开源库有错漏之处,非常欢迎给俺提供反馈——有 GitHub 帐号的同学,可以[https://github.com/programthink/opensource/issues 给俺发 issue];没帐号的同学,可以去[http://program-think.blogspot.com/ 俺博客]留言。
10 |
11 | ----
12 |
13 | = 1 综合性的库 =
14 |
15 | Boost
16 |
17 | Home:[http://boost.org/]
18 |
19 | Links:[https://en.wikipedia.org/wiki/Boost_%28C%2B%2B_libraries%29 Wikipedia] [https://zh.wikipedia.org/wiki/Boost_C%2B%2B_Libraries 维基百科]
20 |
21 | Boost 大概是最重要的第三方 C++ 库。其作者有很多是 C++ 标准委员会的成员。Boost 的很多子库后来都成为 C++ 的标准库。
22 |
23 | 本页面的其它章节还会继续提及 Boost 在各种领域的应用。
24 |
25 | wxWidgets
26 |
27 | Home:[https://wxwidgets.org/]
28 |
29 | Links:[https://en.wikipedia.org/wiki/WxWidgets Wikipedia] [https://zh.wikipedia.org/wiki/WxWidgets 维基百科]
30 |
31 | 这是一个非常老牌的 C++ 开源 GUI 框架,诞生于1992年。原先叫做 wxWindows,后来因为微软的法律纠纷,改为现名。
32 |
33 | 它支持的操作系统平台很多(包括嵌入式系统)。
34 |
35 | 很多开源项目用到它,比如:BitTorrent、aMule、FileZilla、Code::Blocks、Dolphin......
36 |
37 | 虽然它以 GUI 为主,但是也提供了其它一些辅助功能(比如:进程间通讯、网络、数据库、多媒体......)
38 |
39 | Qt
40 |
41 | Home:[http://www.qt-project.org/]
42 |
43 | Links:[https://en.wikipedia.org/wiki/Qt_(toolkit) Wikipedia] [https://zh.wikipedia.org/wiki/Qt 维基百科]
44 |
45 | 这是一个非常老牌的 C++ 开源 GUI 框架,于1995年发布 1.0 版本。原先由 Trolltech 公司维护,后来该公司被 Nokia 收购。
46 |
47 | 它支持的操作系统平台很多(包括嵌入式系统)。
48 |
49 | 虽然它以 GUI 为主,但是也提供了其它一些辅助功能(比如:网络、数据库、多媒体、3D引擎......)
50 |
51 | APR(Apache Portable Runtime)
52 |
53 | Home:[https://apr.apache.org/]
54 |
55 | Links:[https://en.wikipedia.org/wiki/Apache_Portable_Runtime Wikipedia] [https://zh.wikipedia.org/wiki/Apache%E5%8F%AF%E7%A7%BB%E6%A4%8D%E8%BF%90%E8%A1%8C%E6%97%B6 维基百科]
56 |
57 | 这是由 Apache 社区维护的 C 开源库,主要提供操作系统相关的功能(文件系统、进程、线程、用户、IPC)。此外还提供了一些网络相关的功能。
58 |
59 | APR 原先是 Apache Web 服务器的一个组成部分,后来独立出来,成为一个单独的开源项目。
60 |
61 | ACE(Adaptive Communication Environment)
62 |
63 | Home:[http://www.cse.wustl.edu/~schmidt/ACE.html]
64 |
65 | Links:[https://en.wikipedia.org/wiki/Adaptive_Communication_Environment Wikipedia] [https://zh.wikipedia.org/wiki/ACE%E8%87%AA%E9%80%82%E9%85%8D%E9%80%9A%E4%BF%A1%E7%8E%AF%E5%A2%83 维基百科]
66 |
67 | 这是一个跨平台的 C++ 库,提供了一套网络通讯的框架;另外还支持线程、进程和 IPC。
68 |
69 | POCO
70 |
71 | Home:[http://pocoproject.org/]
72 |
73 | Links:[https://en.wikipedia.org/wiki/POCO_C%2B%2B_Libraries Wikipedia]
74 |
75 | 它的名称源自“POrtable COmponents”,是一个基于 C++ 的开源库。
76 |
77 | 它的功能以网络通讯为主,同时也提供一些其它功能(比如:多线程、进程间通讯、数据库、XML、JSON......)
78 |
79 | Dlib
80 |
81 | Home:[http://dlib.net/]
82 |
83 | Links:[https://en.wikipedia.org/wiki/Dlib Wikipedia]
84 |
85 | 诞生于2002年的 C++ 开源库,提供了非常多的功能(网络、多线程、GUI、数值计算、图像处理、数据挖掘......)。
86 |
87 | 它还有一个特色是:同时提供了 Python API :)
88 |
89 | Crypto++
90 |
91 | Home:[http://www.cryptopp.com/]
92 |
93 | Links:[https://en.wikipedia.org/wiki/Crypto%2B%2B Wikipedia]
94 |
95 | 它也叫“CryptoPP”或“libcrypto++”,是非常著名的开源加密库,诞生于1995年。基于 C++ 开发,大量用到模板语法。
96 |
97 | 虽然它以加密为主,但是也提供了其它一些辅助功能(比如:数据压缩、编码解码、计时器...)
98 |
99 | ----
100 |
101 | = 2 数据结构 & 算法 =
102 |
103 | == 2.1 容器 ==
104 |
105 | === 2.1.1 标准容器 ===
106 |
107 | std
108 |
109 | C++ 98 标准内置的 STL 提供了如下容器:
110 |
111 | * 数组:vector(动态数组)、valarray(针对数值类型特化的 vector)、bitset(储存比特的【固定】数组)
112 |
113 | * 链表:list(双向)
114 |
115 | * 队列:queue、deque(双端队列)
116 |
117 | * 栈:stack
118 |
119 | * 映射:map(键值无重复)、multimap(键值可重复)
120 |
121 | * 集合:set(元素无重复)、multiset(元素可重复)
122 |
123 | [https://en.wikipedia.org/wiki/C%2B%2B11 C++ 11 标准]新增了如下容器:
124 |
125 | * 数组:array(相比 vector,它的 size 是编译时【固定】的)
126 |
127 | * 链表:forward_list(相比 list,它是【单向】的)
128 |
129 | * 映射:unordered_map、unordered_multimap(相比 map 和 multimap,这俩采用 hash 实现)
130 |
131 | * 集合:unordered_set、unordered_multiset(相比 set 和 multiset,这俩采用 hash 实现)
132 |
133 | 下面几个容器,C++ 标准【没有】包含,但包含在某些知名的 STL 第三方库中(比如 SGI 的 STL):
134 |
135 | * 映射:hash_map、hash_multimap(与 unordered_map、unordered_multimap 相同)
136 |
137 | * 集合:hash_set、hash_multiset(与 unordered_set、unordered_multiset 相同)
138 |
139 | === 2.1.2 Lockfree 的容器 ===
140 |
141 | (“lock-free”翻译成“锁无关”会引发歧义,所以俺直接用洋文)
142 |
143 | Boost.Lockfree
144 |
145 | Docs:[http://boost.org/libs/lockfree]
146 |
147 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了三种 lock-free 的容器(queue、stack、spsc_queue)。最后这种是“环形缓冲”。
148 |
149 | libcds(Concurrent Data Structures)
150 |
151 | Home:[http://libcds.sourceforge.net/]
152 |
153 | 这是一个跨平台的 C++ 开源库,提供了若干 lock-free 的容器。它的 2.0.0 版本,代码重写以支持 C++ 11 标准。
154 |
155 | === 2.1.3 环形缓冲 ===
156 |
157 | Boost.CircularBuffer
158 |
159 | Docs:[http://boost.org/libs/circular_buffer]
160 |
161 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“环形缓冲区”的模板。
162 |
163 | “环形缓冲区”可以降低内存分配的开销。俺曾经写过一篇博文推荐环形缓冲区(在“[http://program-think.blogspot.com/2009/04/producer-consumer-pattern-3-circle.html 这里]”)。
164 |
165 | 代码示例
166 |
167 | #include
168 |
169 | boost::circular_buffer cb(3); // Create with capacity for 3 integers
170 | cb.push_back(1);
171 | cb.push_back(2);
172 | cb.push_back(3);
173 |
174 | // The buffer is full now
175 | // pushing subsequent elements will overwrite front-most elements.
176 |
177 | cb.push_back(4); // Overwrite 1 with 4.
178 | cb.push_back(5); // Overwrite 2 with 5.
179 | // The buffer now contains 3, 4 and 5.
180 |
181 | // Elements can be popped from either the front or the back.
182 | cb.pop_back(); // 5 is removed.
183 | cb.pop_front(); // 3 is removed.
184 |
185 | // Leaving only one element with value = 4.
186 | assert(cb[0] == 4);
187 |
188 |
189 | === 2.1.4 多维数组 ===
190 |
191 | Boost.MultiArray
192 |
193 | Docs:[http://boost.org/libs/multi_array]
194 |
195 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了任意维的数组。
196 |
197 | 代码示例——3维数组
198 |
199 | #include
200 |
201 | typedef boost::multi_array array_type;
202 | typedef array_type::index index;
203 | array_type A(boost::extents[3][4][2]);
204 |
205 | int values = 0;
206 | for(index i=0; i!=3; ++i)
207 | for(index j=0; j!=4; ++j)
208 | for(index k=0; k!=2; ++k)
209 | A[i][j][k] = values++;
210 |
211 |
212 | === 2.1.5 图 ===
213 |
214 | Boost.Graph
215 |
216 | Docs:[http://boost.org/libs/graph]
217 |
218 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,简称 BGL(Boost Graph Library),封装了“图”这种数据结构。
219 |
220 | 它提供了与 STL 类似的泛型编程风格。
221 |
222 | Dlib
223 |
224 | Docs:[http://dlib.net/graph_tools.html]
225 |
226 | Dlib 前面已经介绍过。它提供了2个类(graph & directed_graph)封装“图”。
227 |
228 | == 2.2 对容器的操作 ==
229 |
230 | (STL 标准库里面已经实现了很多算法用来操作容器,考虑到本页面已经很长,这里只列举第三方库实现的算法)
231 | Boost.Foreach
232 |
233 | Docs:[http://boost.org/libs/foreach]
234 |
235 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了通用的遍历,其效果类似于 Python 的 for 循环语法。
236 |
237 | 有了它,你在遍历时无需声明迭代器变量,也无需关心遍历的容器是何种类型。
238 |
239 | 代码示例——遍历字符串
240 |
241 | #include
242 | #include
243 | #include
244 |
245 | std::string test("Hello, world!"); // string 可以视为 char 的容器
246 | BOOST_FOREACH(char ch, test)
247 | {
248 | std::cout << ch;
249 | }
250 |
251 |
252 | == 2.3 字符串处理 ==
253 |
254 | === 2.3.1 字符集 ===
255 |
256 | Boost.Locale
257 |
258 | Docs:[http://boost.org/libs/locale]
259 |
260 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了各种“本地化”的功能。其中就包括字符集编码转换。
261 |
262 | 代码示例
263 |
264 | #include
265 | #include
266 |
267 | using namespace boost::locale;
268 | std::locale loc = generator().generate("he_IL.UTF-8");
269 | std::wofstream file.
270 | file.imbue(loc);
271 | file.open("hello.txt");
272 | file << L"שלום!";
273 |
274 |
275 | POCO.Text
276 |
277 | Docs:[http://pocoproject.org/docs/package-Foundation.Text.html]
278 |
279 | POCO 前面已经介绍过。它提供了 UTF8/UTF16/UTF32 的转换。
280 |
281 | === 2.3.2 字符串格式化 ===
282 |
283 | Boost.Format
284 |
285 | Docs:[http://boost.org/libs/format]
286 |
287 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“格式化字符串”的功能。相比 ANSI C 的 sprintf() 和 snprintf(),它的格式化功能更强并且更安全。
288 |
289 | 代码示例
290 |
291 | #include
292 | #include
293 |
294 | using std::cout;
295 | using boost::format;
296 |
297 | // 基于“位置指示符”的格式串语法
298 | cout << format("%1% %2% %3% %2% %1%") % "11" % "22" % "333";
299 | // 输出如下:
300 | // 11 22 333 22 11
301 |
302 | // 兼容 printf() 的格式串语法
303 | cout << format("%s %d") % "price" % 1234;
304 | // 输出如下:
305 | // price 1234
306 |
307 |
308 | fmt
309 |
310 | Home:[https://github.com/fmtlib/fmt]
311 |
312 | 这是一个轻量级、类型安全、高性能的字符串格式化库。它也可以用来替代 C++ 标准库中的 IOStreams。
313 |
314 | 代码示例
315 |
316 | #include
317 | #include
318 |
319 | // 使用 Python 的格式化语法
320 | fmt::print("Hello, {}!", "world");
321 | // 使用 printf 的格式化语法
322 | fmt::printf("Hello, %s!", "world");
323 | // 使用序号参数,
324 | std::string s = fmt::format("{0} {1} {0}", "Hello", "world");
325 | // 使用命名参数
326 | fmt::print("Hello, {name}! The answer is {number}. Goodbye, {name}.",
327 | fmt::arg("name", "World"), fmt::arg("number", 42));
328 |
329 |
330 | === 2.3.3 正则表达式 ===
331 |
332 | PCRE(Perl Compatible Regular Expressions)
333 |
334 | Home:[http://www.pcre.org/]
335 |
336 | Links:[https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions Wikipedia]
337 |
338 | 这是一个很老牌的正则表达式的库,诞生于1997年。很多知名的开源项目(Apache、PHP、KDE)用到了它。
339 |
340 | Boost.Regex
341 |
342 | Docs:[http://boost.org/libs/regex]
343 |
344 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“正则式”的功能。
345 |
346 | 注:Boost 的这个子库已经进入 C++ 11 标准。
347 |
348 | 代码示例——基于正则式进行匹配和替换
349 |
350 | #include
351 |
352 | using std::string;
353 | using namespace boost;
354 |
355 | // 正则式匹配的例子
356 | bool validate_card_format(const string& s)
357 | {
358 | const regex e("(\\d{4}[- ]){3}\\d{4}");
359 | return regex_match(s, e);
360 | }
361 |
362 | // 正则式替换的例子
363 | const regex e("\\A(\\d{3,4})[- ]?(\\d{4})[- ]?(\\d{4})[- ]?(\\d{4})\\z");
364 | const string machine_format("\\1\\2\\3\\4");
365 | const string human_format("\\1-\\2-\\3-\\4");
366 |
367 | string machine_readable_card_number(const string& s)
368 | {
369 | return regex_replace(s, e, machine_format, match_default|format_sed);
370 | }
371 |
372 | string human_readable_card_number(const string& s)
373 | {
374 | return regex_replace(s, e, human_format, match_default|format_sed);
375 | }
376 |
377 |
378 | re2
379 |
380 | Home:[https://github.com/google/re2]
381 |
382 | 这是 Google 提供的正则式库,基于 C++。其 API 使用起来很简洁。
383 |
384 | 有多种脚本语言(Python、Ruby、Perl、Node.js、Erlang、OCaml)提供了对它的封装。
385 |
386 | 代码示例——基于正则式进行匹配
387 |
388 | #include
389 |
390 | int i;
391 | string s;
392 | assert(RE2::FullMatch("test:1234", "(\\w+):(\\d+)", &s, &i));
393 | assert(s == "test");
394 | assert(i == 1234);
395 |
396 |
397 | Oniguruma(鬼车)
398 |
399 | Home:[http://www.geocities.jp/kosako3/oniguruma/]
400 |
401 | Links:[https://en.wikipedia.org/wiki/Oniguruma Wikipedia]
402 |
403 | 来自日本的正则式库,基于 C 语言。据说性能很高。
404 |
405 | 它被用在 Ruby、TextMate、Sublime Text、SubEthaEdit 等软件上。
406 |
407 | POCO.RegExp
408 |
409 | Docs:[http://pocoproject.org/docs/package-Foundation.RegExp.html]
410 |
411 | POCO 前面已经介绍过。它提供了正则表达式的封装类。
412 |
413 | Qt.QRegExp
414 |
415 | Docs:[http://doc.qt.io/qt-4.8/qregexp.html]
416 |
417 | Qt 前面已经介绍过。这是 Qt 中的一个类,提供了“正则式”的功能。
418 |
419 | === 2.3.4 (其它) ===
420 |
421 | Boost.StringAlgorithms
422 |
423 | Docs:[http://boost.org/libs/algorithm/string]
424 |
425 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了各种字符串的算法(替换、合并、拆分、大小写转换、trim......)。
426 |
427 | 代码示例——字符串合并
428 |
429 | #include
430 | #include
431 | #include
432 | #include
433 |
434 | std::vector v;
435 | // 此处填充 v
436 | std::cout << boost::algorithm::join(v, " ") << '\n';
437 |
438 |
439 | Boost.Lexical_Cast
440 |
441 | Docs:[http://boost.org/libs/lexical_cast]
442 |
443 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了各种字符串与其它类型的转换。
444 |
445 | 注:Boost 的这个子库已经进入 C++ 11 标准。
446 |
447 | 代码示例
448 |
449 | #include
450 | #include
451 | #include
452 |
453 | std::string s = boost::lexical_cast(123);
454 | std::cout << s << '\n';
455 |
456 | double d = boost::lexical_cast(s);
457 | std::cout << d << '\n';
458 |
459 |
460 | == 2.4 内存相关 ==
461 |
462 | === 2.4.1 智能指针 ===
463 |
464 | Boost.SmartPointers
465 |
466 | Docs:[http://boost.org/libs/smart_ptr]
467 |
468 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了几种智能指针。最常用的是“shared_ptr”。
469 |
470 | 有了智能指针,你就无需操心 new 之后的 delete 了。
471 |
472 | 注:Boost 的这个子库已经进入 C++ 11 标准。
473 |
474 | === 2.4.2 内存池 ===
475 |
476 | Boost.Pool
477 |
478 | Docs:[http://boost.org/libs/pool]
479 |
480 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“内存池”的功能。
481 |
482 | Dlib
483 |
484 | Docs:[http://dlib.net/other.html]
485 |
486 | Dlib 前面已经介绍过。它提供了内存池(参见文档中以“memory_manager”开头的类)。
487 |
488 | APR
489 |
490 | Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
491 |
492 | APR 前面已经介绍过。它提供了内存池的功能。
493 |
494 | == 2.5 时间 & 日期 ==
495 |
496 | Boost.Date_Time
497 |
498 | Docs:[http://boost.org/libs/date_time]
499 |
500 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了针对“日期 和 时间”的各种处理。
501 |
502 | POCO.DateTime
503 |
504 | Docs:[http://pocoproject.org/docs/package-Foundation.DateTime.html]
505 |
506 | POCO 前面已经介绍过。它提供了若干个日期和时间的封装类(时区转换、格式化字符串、解析时间字符串)。
507 |
508 | == 2.6 编码 & 解码 ==
509 |
510 | === 2.6.1 序列化 ===
511 |
512 | Boost.Serialization
513 |
514 | Docs:[http://boost.org/libs/serialization]
515 |
516 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了【可定制的】“序列化”功能。
517 |
518 | === 2.6.2 Base64 ===
519 |
520 | [https://en.wikipedia.org/wiki/Base64 Base64] 是一组编码算法的总称。用于把二进制数据编码为文本。
521 |
522 | Boost.Serialization
523 |
524 | Docs:[http://boost.org/libs/serialization]
525 |
526 | Boost 前面已经介绍过。使用前面提到的“Boost.Serialization”,你可以定制采用 Base64 方式进行编码和解码。
527 |
528 | Crypto++
529 |
530 | Docs:[http://www.cryptopp.com/docs/ref/annotated.html]
531 |
532 | Crypto++ 前面已经介绍过。它提供了6个类,分别用于 Base64、Base32、Base16 的编码/解码。
533 |
534 | POCO.Streams
535 |
536 | Docs:[http://pocoproject.org/docs/package-Foundation.Streams.html]
537 |
538 | POCO 前面已经介绍过。它提供了 Base64 和 Base32 的编码/解码。
539 |
540 | == 2.7 (其它) ==
541 |
542 | === 2.7.1 随机数 ===
543 |
544 | std
545 |
546 | ANSI C 在 stdlib.h 中提供了随机数生成函数 rand()。使用前记得先用 srand() 函数播种,否则就傻了。
547 |
548 | Boost.Random
549 |
550 | Docs:[http://boost.org/libs/random]
551 |
552 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“随机数生成”的功能。
553 |
554 | 相比 ANSI C 的随机数函数,它提供的功能更丰富。
555 |
556 | 代码示例
557 |
558 | #include
559 | #include
560 |
561 | double SampleNormal(double mean, double sigma)
562 | {
563 | using namespace boost;
564 |
565 | // 建立一个 Mersenne twister 随机数产生器,使用当前时间播种
566 | static mt19937 rng(static_cast(std::time(NULL)));
567 |
568 | // 选择高斯机率分布
569 | normal_distribution norm_dist(mean, sigma);
570 |
571 | // 使用 function 的形式,生成随机数据产生器
572 | variate_generator > normal_sampler(rng, norm_dist);
573 |
574 | // 传回样本分布结果
575 | return normal_sampler();
576 | }
577 |
578 |
579 | Crypto++
580 |
581 | Docs:[http://www.cryptopp.com/docs/ref/class_random_number_generator.html]
582 |
583 | Crypto++ 前面已经介绍过。它提供了好几个类,用于随机数生成。
584 |
585 | === 2.7.2 UUID ===
586 |
587 | Boost.UUID
588 |
589 | Docs:[http://boost.org/libs/uuid]
590 |
591 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了 UUID 的生成。
592 |
593 | 代码示例——生成 UUID
594 |
595 | #include
596 | #include
597 |
598 | // uuid 类以 POD 方式实现,可以直接用在 memcpy()
599 | unsigned char uuid_data[16];
600 | boost::uuids::uuid u;
601 | memcpy(&u, uuid_data, 16);
602 |
603 |
604 | APR
605 |
606 | Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
607 |
608 | APR 前面已经介绍过。它提供了 UUID 的生成、格式化成字符串、解析 UUID 字符串。
609 |
610 | POCO.UUID
611 |
612 | Docs:[http://pocoproject.org/docs/package-Foundation.UUID.html]
613 |
614 | POCO 前面已经介绍过。它提供了 UUID 的生成、格式转换。
615 |
616 | ----
617 |
618 | = 3 编程范式 =
619 |
620 | (这一章节主要针对 C++——“支持多范式”是 C++ 的一大特色)
621 |
622 | == 3.1 面向对象编程(OOP) ==
623 |
624 | fruit
625 |
626 | Home:[https://github.com/google/fruit]
627 |
628 | 它是 Google 开发的 C++ 库,提供了“依赖注入”([https://en.wikipedia.org/wiki/Dependency_injection dependency injection])的框架。
629 |
630 | 代码示例——一个简单的例子
631 |
632 | #include
633 | #include
634 |
635 | using fruit::Component;
636 | using fruit::Injector;
637 |
638 | class Writer
639 | {
640 | public:
641 | virtual void write(std::string str) = 0;
642 | };
643 |
644 | class StdoutWriter : public Writer
645 | {
646 | public:
647 | // Like "StdoutWriter() = default;" but also marks this constructor as the
648 | // one to use for injection.
649 | INJECT(StdoutWriter()) = default;
650 |
651 | virtual void write(std::string str) override
652 | {
653 | std::cout << str;
654 | }
655 | };
656 |
657 | class Greeter
658 | {
659 | public:
660 | virtual void greet() = 0;
661 | };
662 |
663 | class GreeterImpl : public Greeter
664 | {
665 | private:
666 | Writer* writer;
667 |
668 | public:
669 | // Like "GreeterImpl(Writer* writer) {...}"
670 | // but also marks this constructor as the one to use for injection.
671 | INJECT(GreeterImpl(Writer* writer))
672 | : writer(writer)
673 | {
674 | }
675 |
676 | virtual void greet() override
677 | {
678 | writer->write("Hello world!\n");
679 | }
680 | };
681 |
682 | Component getGreeterComponent()
683 | {
684 | return fruit::createComponent()
685 | .bind()
686 | .bind();
687 | }
688 |
689 | int main()
690 | {
691 | Injector injector(getGreeterComponent());
692 | Greeter* greeter = injector.get();
693 | greeter->greet();
694 | return 0;
695 | }
696 |
697 |
698 | == 3.2 泛型编程(GP) ==
699 |
700 | Boost.TypeTraits
701 |
702 | Docs:[http://boost.org/libs/type_traits]
703 |
704 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“类型特化”相关的辅助功能。
705 |
706 | == 3.3 函数式编程(FP) ==
707 |
708 | (不了解“函数式编程”的同学,可以先看[https://zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B8%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80 维基百科])
709 |
710 | Boost.Function
711 |
712 | Docs:[http://boost.org/libs/function]
713 |
714 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,用来辅助封装函数对象(仿函式)。
715 |
716 | 注:Boost 的这个子库已经进入 C++ 11 标准。
717 |
718 | 代码示例——封装标准 C 的函数
719 |
720 | #include
721 | #include
722 | #include
723 | #include
724 |
725 | using namespace std;
726 |
727 | boost::function f = atoi;
728 | cout << f("42") << '\n';
729 |
730 | f = strlen;
731 | cout << f("42") << '\n';
732 |
733 |
734 | Boost.Lambda
735 |
736 | Docs:[http://boost.org/libs/lambda]
737 |
738 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“匿名函数/无名函数”的功能。
739 |
740 | 注:Boost 的这个子库已经进入 C++ 11 标准。
741 |
742 | 代码示例
743 |
744 | #include
745 | #include
746 | #include
747 | #include
748 |
749 | using namespace std;
750 |
751 | vector v;
752 | // 此处填充 v
753 | for_each(v.begin(), v.end(), cout << boost::lambda::_1 << "\n");
754 |
755 |
756 | simple_match
757 |
758 | Home:[https://github.com/jbandela/simple_match]
759 |
760 | 这个库是为了提供类似 Rust 语言中的 match 语法。
761 |
762 | (不懂 Rust 的同学,可以把 match 语法视作增强版的 switch/case)
763 |
764 | 代码示例
765 |
766 | #include
767 | #include
768 | using namespace simple_match;
769 | using namespace simple_match::placeholders;
770 |
771 | int x = 0;
772 | while (true)
773 | {
774 | std::cin >> x;
775 | match(x,
776 | 1, []() { std::cout << "one\n"; },
777 | 2, []() { std::cout << "two\n"; },
778 | _x < 10, [](auto&& n) { std::cout << n << " is less than 10\n"; },
779 | 10 < _x < 20, [](auto&& n) { std::cout << n << " is between 10 and 20 exclusive\n"; },
780 | _, []() { std::cout << "NOT match\n"; }
781 | );
782 | }
783 |
784 |
785 | == 3.4 元编程(Metaprogramming) ==
786 |
787 | (不知道何为“元编程”,可以先看[https://zh.wikipedia.org/wiki/%E5%85%83%E7%BC%96%E7%A8%8B 维基百科])
788 |
789 | Boost.MPL
790 |
791 | Docs:[http://boost.org/libs/mpl]
792 |
793 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“模板元编程”的框架。
794 |
795 | Dlib
796 |
797 | Docs:[http://dlib.net/metaprogramming.html]
798 |
799 | Dlib 前面已经介绍过。它提供了“模板元编程”的辅助类。
800 |
801 | ----
802 |
803 | = 4 调试 & 测试 =
804 |
805 | == 4.1 调试日志 ==
806 |
807 | Boost.Log
808 |
809 | Docs:[http://boost.org/libs/log]
810 |
811 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了记录日志的机制。
812 |
813 | 下面给出的示例是最简单的版本,其实它还提供了很丰富的扩展机制。
814 |
815 | 代码示例
816 |
817 | #include
818 |
819 | BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
820 | BOOST_LOG_TRIVIAL(info) << "An informational severity message";
821 |
822 |
823 | POCO.Logging
824 |
825 | Docs:[http://pocoproject.org/docs/package-Foundation.Logging.html]
826 |
827 | POCO 前面已经介绍过。它提供了好几个用于调试日志的封装类(包括特定于 Windows 平台和特定于 POSIX 平台的类)。
828 |
829 | 它还支持日志文件的循环存储。
830 |
831 | Dlib
832 |
833 | Docs:[http://dlib.net/other.html#logger]
834 |
835 | Dlib 前面已经介绍过。它提供了风格类似 log4j 的日志记录机制。
836 |
837 | 代码示例
838 |
839 | #include
840 | #include
841 |
842 | using namespace dlib;
843 |
844 | logger dlog("example");
845 | dlog.set_level(LALL);
846 |
847 | dlog << LINFO << "This is an informational message.";
848 |
849 | int variable = 8;
850 | dlog << LDEBUG << "The integer variable is set to " << variable;
851 |
852 |
853 | wxWidgets
854 |
855 | Docs:[http://docs.wxwidgets.org/trunk/group__group__funcmacro__log.html]
856 |
857 | wxWidgets 前面已经介绍过。它提供了记录日志的函数和宏。
858 |
859 | log4cpp
860 |
861 | Home:[http://log4cpp.sourceforge.net/]
862 |
863 | 如其名,这是一个模仿 log4j 的 C++ 库。支持多种操作系统(包括 Windows)。
864 |
865 | == 4.2 单元测试 ==
866 |
867 | Boost.Test
868 |
869 | Docs:[http://boost.org/libs/test]
870 |
871 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了与测试相关的各种辅助工具(包括单元测试)。
872 |
873 | Google Test
874 |
875 | Home:[https://github.com/google/googletest]
876 |
877 | Links:[https://en.wikipedia.org/wiki/Google_Test Wikipedia]
878 |
879 | 这是 Google 提供的单元测试框架。从 Google Code 迁移到 GitHub 之后,又整合了 GoogleMock 项目。
880 |
881 | 一些知名的开源项目(Chromium、LLVM、OpenCV)用到了它。
882 |
883 | CppUnit
884 |
885 | Home:[http://freedesktop.org/wiki/Software/cppunit/]
886 |
887 | Links:[https://en.wikipedia.org/wiki/CppUnit Wikipedia]
888 |
889 | 如其名,这是一个 C++ 的单元测试框架。该项目起先是作为 JUnit 的 C++ 移植而创建的。
890 |
891 | Check
892 |
893 | Home:[http://check.sourceforge.net/]
894 |
895 | Links:[https://en.wikipedia.org/wiki/Check_%28unit_testing_framework%29 Wikipedia]
896 |
897 | 这是针对 C 的单元测试框架。
898 |
899 | 代码示例
900 |
901 | #include
902 |
903 | /* The basic unit test looks as follows: */
904 | START_TEST (test_name)
905 | {
906 | /* unit test code */
907 | }
908 | END_TEST
909 | /* The "START_TEST/END_TEST" pair are macros that setup basic structures to permit testing.
910 | It is a mistake to leave off the END_TEST marker;
911 | doing so produces all sorts of strange errors when the check is compiled. */
912 |
913 |
914 | == 4.3 健壮性测试 ==
915 |
916 | Boost.Test.ExecutionMonitor
917 |
918 | Docs:[http://boost.org/libs/test/doc/html/execution-monitor.html]
919 |
920 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,它除了提供“单元测试”,还提供“内存泄漏的检测”。
921 |
922 | == 4.4 性能测试 ==
923 |
924 | benchmark
925 |
926 | Home:[https://github.com/google/benchmark]
927 |
928 | 这是 Google 提供的性能测试辅助工具,用来测试指定函数的执行时间。
929 |
930 | 它可以把测试结果导出为 CSV 或 JSON 格式。
931 |
932 | ----
933 |
934 | = 5 操作系统 =
935 |
936 | == 5.1 跨操作系统 ==
937 |
938 | === 5.1.1 文件系统 ===
939 |
940 | Boost.Filesystem
941 |
942 | Docs:[http://boost.org/libs/filesystem]
943 |
944 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了对“文件系统”的操作。
945 |
946 | 代码示例——获取文件大小
947 |
948 | #include
949 | #include
950 |
951 | int main(int argc, char* argv[])
952 | {
953 | using namespace boost::filesystem;
954 | if(argc != 2)
955 | {
956 | std::cout << "Usage: \n" << argv[0] << " path\n";
957 | return 1;
958 | }
959 | std::cout << argv[1] << " " << file_size(argv[1]) << '\n';
960 | return 0;
961 | }
962 |
963 |
964 | POCO.Filesystem
965 |
966 | Docs:[http://pocoproject.org/docs/package-Foundation.Filesystem.html]
967 |
968 | POCO 前面已经介绍过。它提供了文件系统相关的封装类(遍历目录和文件、通配符匹配、临时文件、文件变化通知...)。
969 |
970 | wxWidgets
971 |
972 | Docs:[http://docs.wxwidgets.org/trunk/group__group__class__file.html]
973 |
974 | wxWidgets 前面已经介绍过。它提供了文件系统相关的封装类(遍历目录和文件、临时文件、文件变化通知...)。
975 |
976 | APR
977 |
978 | Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
979 |
980 | APR 前面已经介绍过。它提供了“文件信息、文件名匹配”等功能。
981 |
982 | === 5.1.2 线程 ===
983 |
984 | Boost.Thread
985 |
986 | Docs:[http://boost.org/libs/thread]
987 |
988 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“多线程”的功能。
989 |
990 | 代码示例
991 |
992 | #include
993 | #include
994 |
995 | void hello_world()
996 | {
997 | std::cout << "Hello world, I'm a thread!\n";
998 | }
999 |
1000 | int main()
1001 | {
1002 | boost::thread my_thread(&hello_world); // 启动一个线程
1003 | my_thread.join(); // 等待该线程结束
1004 | return 0;
1005 | }
1006 |
1007 |
1008 | ACE
1009 |
1010 | Docs:[http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html]
1011 |
1012 | ACE 前面已经介绍过。它提供了“多线程”的功能(参见文档中以“ACE_Thread”开头的类)
1013 |
1014 | APR
1015 |
1016 | Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
1017 |
1018 | APR 前面已经介绍过。它提供了“线程池、线程同步/互斥”等功能,以及一些线程安全的数据结构。
1019 |
1020 | POCO.Threading
1021 |
1022 | Docs:[http://pocoproject.org/docs/package-Foundation.Threading.html]
1023 |
1024 | POCO 前面已经介绍过。它提供了线程、线程池以及线程同步/互斥的封装类。
1025 |
1026 | wxWidgets
1027 |
1028 | Docs:[http://docs.wxwidgets.org/trunk/group__group__class__threading.html]
1029 |
1030 | wxWidgets 前面已经介绍过。它提供了线程以及线程同步/互斥的封装类。
1031 |
1032 | GNU Common C++
1033 |
1034 | Home:[http://www.gnu.org/software/commoncpp/]
1035 |
1036 | 由 GNU 提供的一套跨平台的线程并发框架。
1037 |
1038 | === 5.1.3 进程 ===
1039 |
1040 | ACE
1041 |
1042 | Docs:[http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html]
1043 |
1044 | ACE 前面已经介绍过。它提供了“进程管理”的功能(参见文档中以“ACE_Process”开头的类)。
1045 |
1046 | APR
1047 |
1048 | Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
1049 |
1050 | APR 前面已经介绍过。它提供了“进程管理”的功能。
1051 |
1052 | POCO.Processes
1053 |
1054 | Docs:[http://pocoproject.org/docs/Poco.Process.html]
1055 |
1056 | POCO 前面已经介绍过。它提供了“进程”的封装类。
1057 |
1058 | === 5.1.4 本地进程间通信(IPC) ===
1059 |
1060 | (本章节列举的是【本地】IPC,跨主机的网络通讯,参见本页面后续的章节)
1061 |
1062 | Boost.Interprocess
1063 |
1064 | Docs:[http://boost.org/libs/interprocess]
1065 |
1066 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了共享内存和几种同步机制(Mutexes、Condition variables、Semaphores、Upgradable mutexes、File locks)。
1067 |
1068 | ACE
1069 |
1070 | Docs:[http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html]
1071 |
1072 | ACE 前面已经介绍过。它提供了许多种 IPC 机制(有些不是跨平台的)。
1073 |
1074 | APR
1075 |
1076 | Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
1077 |
1078 | APR 前面已经介绍过。它提供了“进程同步、共享内存、信号处理”等功能。
1079 |
1080 | POCO.Processes
1081 |
1082 | Docs:[http://pocoproject.org/docs/package-Foundation.Processes.html]
1083 |
1084 | POCO 前面已经介绍过。它提供了 IPC 相关的封装类(“共享内存”和“管道”)。
1085 |
1086 | == 5.2 特定于 Windows 系统 ==
1087 |
1088 | === 5.2.1 注册表 ===
1089 |
1090 | wxWidgets
1091 |
1092 | Docs:[http://docs.wxwidgets.org/trunk/classwx_reg_key.html]
1093 |
1094 | wxWidgets 前面已经介绍过。它提供了操作 Windows 注册表的封装类。
1095 |
1096 | POCO::Util
1097 |
1098 | Docs:[http://pocoproject.org/docs/Poco.Util.html]
1099 |
1100 | POCO 前面已经介绍过。它提供了操作 Windows 注册表的封装类(WinRegistryKey)。
1101 |
1102 | === 5.2.2 Windows 服务(Service) ===
1103 |
1104 | POCO::Util
1105 |
1106 | Docs:[http://pocoproject.org/docs/Poco.Util.html]
1107 |
1108 | POCO 前面已经介绍过。它提供了相应的封装类(WinService),可以用来操作 Service(注册、删除、启动、停止)。
1109 |
1110 | == 5.3 特定于 Linux & Unix 系统 ==
1111 |
1112 | ----
1113 |
1114 | = 6 图形用户界面(GUI) =
1115 |
1116 | == 6.1 GUI 框架 ==
1117 |
1118 | === 6.1.1 跨平台的 GUI 框架 ===
1119 |
1120 | wxWidgets
1121 |
1122 | Docs:[http://docs.wxwidgets.org/trunk/modules.html]
1123 |
1124 | wxWidgets 前面已经介绍过。用 wxWidgets 开发 GUI 应用,其代码结构类似 MFC。熟悉 MFC 的程序员应该很容易上手。
1125 |
1126 | 代码示例——Hello world
1127 |
1128 | #include
1129 | #ifndef WX_PRECOMP
1130 | # include
1131 | #endif
1132 |
1133 | class MyApp: public wxApp
1134 | {
1135 | public:
1136 | virtual bool OnInit();
1137 | };
1138 | wxIMPLEMENT_APP(MyApp);
1139 |
1140 | class MyFrame: public wxFrame
1141 | {
1142 | public:
1143 | MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
1144 | private:
1145 | void OnExit(wxCommandEvent& event);
1146 | wxDECLARE_EVENT_TABLE();
1147 | };
1148 | wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
1149 | EVT_MENU(wxID_EXIT, MyFrame::OnExit)
1150 | wxEND_EVENT_TABLE()
1151 |
1152 | bool MyApp::OnInit()
1153 | {
1154 | MyFrame* frame = new MyFrame("Hello, World", wxPoint(50, 50), wxSize(450, 340));
1155 | frame->Show(true);
1156 | return true;
1157 | }
1158 |
1159 | MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
1160 | : wxFrame(NULL, wxID_ANY, title, pos, size)
1161 | {
1162 | wxMenu* menuFile = new wxMenu();
1163 | menuFile->Append(wxID_EXIT);
1164 | wxMenuBar* menuBar = new wxMenuBar();
1165 | menuBar->Append(menuFile, "&File");
1166 | SetMenuBar(menuBar);
1167 | }
1168 |
1169 | void MyFrame::OnExit(wxCommandEvent& event)
1170 | {
1171 | Close(true);
1172 | }
1173 |
1174 |
1175 | Qt
1176 |
1177 | Qt 前面已经介绍过。下面给出一个 Hello world 的示例,让你看看 Qt 的风格。
1178 |
1179 | 代码示例——Hello world
1180 |
1181 | #include
1182 | #include
1183 |
1184 | int main(int argc, char* argv[])
1185 | {
1186 | QApplication app(argc, argv);
1187 | QLabel label("Hello, world!");
1188 | label.show();
1189 | return app.exec();
1190 | }
1191 |
1192 |
1193 | GTK+
1194 |
1195 | Home:[http://www.gtk.org/]
1196 |
1197 | Links:[https://en.wikipedia.org/wiki/GTK%2B Wikipedia] [https://zh.wikipedia.org/wiki/GTK%2B 维基百科]
1198 |
1199 | 老牌的 GUI 框架,诞生于1998年。原先叫做“GIMP Toolkit”,是基于 C 开发的跨平台界面组件库。
1200 |
1201 | 代码示例——Hello world
1202 |
1203 | #include
1204 |
1205 | int main(int argc, char* argv[])
1206 | {
1207 | gtk_init(&argc, &argv);
1208 |
1209 | GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1210 | gtk_window_set_title(GTK_WINDOW(window), "Hello, world!");
1211 | gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
1212 | gtk_window_set_default_size(GTK_WINDOW(window), 200, 100);
1213 |
1214 | /*
1215 | ** Map the destroy signal of the window to gtk_main_quit;
1216 | ** When the window is about to be destroyed, we get a notification and
1217 | ** stop the main GTK+ loop by returning 0
1218 | */
1219 | g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
1220 |
1221 | gtk_widget_show_all(window);
1222 |
1223 | /* Start the main loop, do nothing until the application is closed */
1224 | gtk_main();
1225 |
1226 | return 0;
1227 | }
1228 |
1229 |
1230 | FLTK
1231 |
1232 | Home:[http://www.fltk.org/]
1233 |
1234 | Links:[https://en.wikipedia.org/wiki/FLTK Wikipedia] [https://zh.wikipedia.org/wiki/FLTK 维基百科]
1235 |
1236 | 它的全称是“Fast, Light Toolkit”。如其名,它非常轻量级。用它写一个“Hello World 应用”,静态链接后大约才 100KB
1237 |
1238 | 代码示例——Hello world
1239 |
1240 | #include
1241 | #include
1242 | #include
1243 |
1244 | int main(int argc, char **argv)
1245 | {
1246 | Fl_Window* window = new Fl_Window(300, 180);
1247 | Fl_Box* box = new Fl_Box(20, 40, 260, 100, "Hello, World!");
1248 | box->box(FL_UP_BOX);
1249 | box->labelsize(36);
1250 | box->labelfont(FL_BOLD+FL_ITALIC);
1251 | box->labeltype(FL_SHADOW_LABEL);
1252 |
1253 | window->end();
1254 | window->show(argc, argv);
1255 | return Fl::run();
1256 | }
1257 |
1258 |
1259 | === 6.1.2 特定于 Windows 的 GUI 框架 ===
1260 |
1261 | WTL(Windows Template Library)
1262 |
1263 | Home:[http://sourceforge.net/projects/wtl/]
1264 |
1265 | Links:[https://en.wikipedia.org/wiki/Windows_Template_Library Wikipedia] [https://zh.wikipedia.org/wiki/Windows_Template_Library 维基百科]
1266 |
1267 | 这是微软雇员 Nenad Stefanovic 开发的开源 GUI 框架。开发 WTL 是为了提供一个轻量级的 MFC 替代品。
1268 |
1269 | == 6.2 图表(Chart) ==
1270 |
1271 | Qt
1272 |
1273 | Docs:[http://doc.qt.io/QtCharts/]
1274 |
1275 | Qt 前面已经介绍过。它内置了一套 Chart 的封装类。
1276 |
1277 | 代码示例——饼图
1278 |
1279 | #include
1280 | #include
1281 | #include
1282 | #include
1283 | #include
1284 |
1285 | QT_CHARTS_USE_NAMESPACE
1286 |
1287 | int main(int argc, char* argv[])
1288 | {
1289 | QApplication app(argc, argv);
1290 |
1291 | QPieSeries* series = new QPieSeries();
1292 | series->append("Jane", 1);
1293 | series->append("Joe", 2);
1294 | series->append("Andy", 3);
1295 | series->append("Barbara", 4);
1296 | series->append("Axel", 5);
1297 |
1298 | QPieSlice* slice = series->slices().at(1);
1299 | slice->setExploded();
1300 | slice->setLabelVisible();
1301 | slice->setPen(QPen(Qt::darkGreen, 2));
1302 | slice->setBrush(Qt::green);
1303 |
1304 | QChart* chart = new QChart();
1305 | chart->addSeries(series);
1306 | chart->setTitle("Simple piechart example");
1307 | chart->legend()->hide();
1308 |
1309 | QChartView* chartView = new QChartView(chart);
1310 | chartView->setRenderHint(QPainter::Antialiasing);
1311 |
1312 | QMainWindow window;
1313 | window.setCentralWidget(chartView);
1314 | window.resize(400, 300);
1315 | window.show();
1316 |
1317 | return app.exec();
1318 | }
1319 |
1320 |
1321 | wxCode
1322 |
1323 | Home:[http://wxcode.sourceforge.net/]
1324 |
1325 | 该项目专门提供组件来扩展 wxWidgets 的功能。它里面提供了好几种图表的组件(wxChart、wxFreeChart、wxPlotCtrl)。
1326 |
1327 | wxMathPlot
1328 |
1329 | Home:[http://wxmathplot.sourceforge.net/]
1330 |
1331 | 看名称就知道它是跟 wxWidgets 搭配的。效果图参见“[http://wxmathplot.sourceforge.net/screenshot.shtml 这里]”
1332 |
1333 | == 6.3 文本编辑 ==
1334 |
1335 | Scintilla
1336 |
1337 | Home:[https://scintilla.org/]
1338 |
1339 | Links:[https://en.wikipedia.org/wiki/Scintilla_(software) Wikipedia]
1340 |
1341 | 功能【超强】的文本编辑组件,支持:词法高亮、代码折叠、自动补全、动态提示......(基本上你能想到的,它都已经有了)
1342 |
1343 | 不光功能齐全,还支持各种主流的操作系统平台。很多编辑器/IDE 用到它。
1344 |
1345 | ----
1346 |
1347 | = 7 文本用户界面(TUI) =
1348 |
1349 | == 7.1 命令行参数 ==
1350 |
1351 | getopt
1352 |
1353 | Home:[https://www.gnu.org/software/libc/manual/html_node/Getopt.html]
1354 |
1355 | Links:[https://en.wikipedia.org/wiki/Getopt Wikipedia]
1356 |
1357 | 这是标准C用来处理命令行参数的老牌函数,诞生于上世纪80年代初期。
1358 |
1359 | 它有很多种不同的实现,如今用得最多的是 GNU C Library 的实现。GNU 还实现了一个增强版 getopt_long。
1360 |
1361 | 代码示例
1362 |
1363 | #include /* for printf */
1364 | #include /* for exit */
1365 | #include /* for getopt */
1366 |
1367 | int main(int argc, char* argv[])
1368 | {
1369 | int digit_optind = 0;
1370 | int aopt = 0, bopt = 0;
1371 | char* copt = NULL;
1372 | char* dopt = NULL;
1373 | int c;
1374 | while( (c = getopt(argc, argv, "abc:d:012")) != -1)
1375 | {
1376 | int this_option_optind = optind ? optind : 1;
1377 | switch(c)
1378 | {
1379 | case '0':
1380 | case '1':
1381 | case '2':
1382 | if(digit_optind != 0 && digit_optind != this_option_optind)
1383 | {
1384 | printf("digits occur in two different argv-elements.\n");
1385 | }
1386 | digit_optind = this_option_optind;
1387 | printf("option %c\n", c);
1388 | break;
1389 | case 'a':
1390 | printf("option a\n");
1391 | aopt = 1;
1392 | break;
1393 | case 'b':
1394 | printf("option b\n");
1395 | bopt = 1;
1396 | break;
1397 | case 'c':
1398 | printf("option c with value '%s'\n", optarg);
1399 | copt = optarg;
1400 | break;
1401 | case 'd':
1402 | printf("option d with value '%s'\n", optarg);
1403 | dopt = optarg;
1404 | break;
1405 | case '?':
1406 | break;
1407 | default:
1408 | printf("?? getopt returned character code 0%o ??\n", c);
1409 | }
1410 | }
1411 | if(optind < argc)
1412 | {
1413 | printf("non-option ARGV-elements: ");
1414 | while(optind < argc)
1415 | {
1416 | printf("%s ", argv[optind++]);
1417 | }
1418 | printf("\n");
1419 | }
1420 | exit (0);
1421 | }
1422 |
1423 |
1424 | Boost.Program_options
1425 |
1426 | Docs:[http://boost.org/libs/program_options]
1427 |
1428 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“处理命令行参数”的功能。
1429 |
1430 | 它的功能很丰富,但是比较重型。
1431 |
1432 | docopt
1433 |
1434 | Home:[https://github.com/docopt/docopt.cpp]
1435 |
1436 | 这是一个很有创意的库,提供了一种【全新】的方式来处理命令行参数。
1437 |
1438 | 你只需定义好命令行的帮助文本(usage),该库会根据 usage 文本自动分析出命令行参数的定义。
1439 |
1440 | 也就是说:用了这个库,就无需再写一大堆 parse 命令行参数的代码 :)
1441 |
1442 | 代码示例
1443 |
1444 | #include
1445 | #include
1446 |
1447 | static const char USAGE[] =
1448 | R"(Naval Fate.
1449 |
1450 | Usage:
1451 | naval_fate ship new ...
1452 | naval_fate ship move [--speed=]
1453 | naval_fate ship shoot
1454 | naval_fate mine (set|remove) [--moored | --drifting]
1455 | naval_fate (-h | --help)
1456 | naval_fate --version
1457 |
1458 | Options:
1459 | -h --help Show this screen.
1460 | --version Show version.
1461 | --speed= Speed in knots [default: 10].
1462 | --moored Moored (anchored) mine.
1463 | --drifting Drifting mine.
1464 | )";
1465 |
1466 | int main(int argc, const char* argv[])
1467 | {
1468 | std::map args
1469 | = docopt::docopt(USAGE,
1470 | { argv + 1, argv + argc },
1471 | true, // 是否显示帮助
1472 | "Naval Fate 2.0"); // 版本号
1473 |
1474 | for(auto const& arg : args)
1475 | {
1476 | std::cout << arg.first << arg.second << std::endl;
1477 | }
1478 |
1479 | return 0;
1480 | }
1481 |
1482 |
1483 | == 7.2 文本终端 ==
1484 |
1485 | ncurses
1486 |
1487 | Home:[https://www.gnu.org/software/ncurses/]
1488 |
1489 | Links:[https://en.wikipedia.org/wiki/Ncurses Wikipedia] [https://zh.wikipedia.org/wiki/Ncurses 维基百科]
1490 |
1491 | ncurses 是“new curses”的缩略词,它是 [https://en.wikipedia.org/wiki/Curses_(programming_library) curses] 库的自由软件克隆,诞生于1993年。
1492 |
1493 | 大名鼎鼎的 [https://en.wikipedia.org/wiki/Eric_S._Raymond Eric S. Raymond] 曾参与早期版本的开发。
1494 |
1495 | = 8 网络 =
1496 |
1497 | == 8.1 链路层 & 网络层 ==
1498 |
1499 | libpcap
1500 |
1501 | Home:[http://www.tcpdump.org/]
1502 |
1503 | Links:[https://en.wikipedia.org/wiki/Pcap Wikipedia]
1504 |
1505 | 很著名的 Sniffer 抓包库,基于 C 语言开发。
1506 |
1507 | 代码示例——一个简单的抓包示例
1508 |
1509 | #include
1510 | #include
1511 |
1512 | int main()
1513 | {
1514 | pcap_t* handle; /* Session handle */
1515 | char* dev; /* The device to sniff on */
1516 | char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
1517 | struct bpf_program fp; /* The compiled filter */
1518 | char filter_exp[] = "port 23"; /* The filter expression */
1519 | bpf_u_int32 mask; /* Our netmask */
1520 | bpf_u_int32 net; /* Our IP */
1521 | struct pcap_pkthdr header; /* The header that pcap gives us */
1522 | const u_char* packet; /* The actual packet */
1523 |
1524 | /* Define the device */
1525 | dev = pcap_lookupdev(errbuf);
1526 | if(dev == NULL)
1527 | {
1528 | fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
1529 | return 2;
1530 | }
1531 | /* Find the properties for the device */
1532 | if(pcap_lookupnet(dev, &net, &mask, errbuf) == -1)
1533 | {
1534 | fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
1535 | net = 0;
1536 | mask = 0;
1537 | }
1538 | /* Open the session in promiscuous mode */
1539 | handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
1540 | if(handle == NULL)
1541 | {
1542 | fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
1543 | return 2;
1544 | }
1545 | /* Compile and apply the filter */
1546 | if(pcap_compile(handle, &fp, filter_exp, 0, net) == -1)
1547 | {
1548 | fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
1549 | return 2;
1550 | }
1551 | if(pcap_setfilter(handle, &fp) == -1)
1552 | {
1553 | fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
1554 | return 2;
1555 | }
1556 |
1557 | packet = pcap_next(handle, &header); /* Grab a packet */
1558 | printf("Jacked a packet with length of [%d]\n", header.len);
1559 | pcap_close(handle); /* Close the session */
1560 | return 0;
1561 | }
1562 |
1563 |
1564 | WinPcap
1565 |
1566 | Home:[http://www.winpcap.org/]
1567 |
1568 | Links:[https://en.wikipedia.org/wiki/Pcap Wikipedia]
1569 |
1570 | 它是 libpcap 在 Windows 系统下的移植。
1571 |
1572 | == 8.2 传输层 ==
1573 |
1574 | socket
1575 |
1576 | socket 最早源自 BSD 系统,有时候也称“伯克利套接字”。
1577 |
1578 | 它已成了传输层网络编程的标准,主流的操作系统平台都支持,主流的 C/C++ 编译器也都内置了相关的库文件。
1579 |
1580 | ACE
1581 |
1582 | Docs:[http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html]
1583 |
1584 | ACE 前面已经介绍过。它提供了针对 socket 的更高层封装。
1585 |
1586 | APR
1587 |
1588 | Docs:[https://apr.apache.org/docs/apr/trunk/modules.html]
1589 |
1590 | APR 前面已经介绍过。它提供了对 socket 的封装和增强。
1591 |
1592 | POCO::Net
1593 |
1594 | Docs:[http://pocoproject.org/docs/Poco.Net.html]
1595 |
1596 | POCO 前面已经介绍过。它提供了针对 TCP 服务端的封装类。
1597 |
1598 | == 8.3 标准的应用层 ==
1599 |
1600 | === 8.3.1 综合性的库 ===
1601 |
1602 | cURL & libcurl
1603 |
1604 | Home:[http://curl.haxx.se/libcurl/]
1605 |
1606 | Links:[https://en.wikipedia.org/wiki/CURL Wikipedia] [https://zh.wikipedia.org/wiki/CURL 维基百科]
1607 |
1608 | cURL 是一个功能很强的网络库/网络工具,支持 N 多应用层协议。下面是支持协议的列表(从它官网抄袭的)
1609 |
1610 | 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
1611 |
1612 | 它采用 C 语言开发,开发很活跃,支持非常多的操作系统平台。
1613 |
1614 | 关于 cURL,俺前几年写过一篇博文推荐它(在“[http://program-think.blogspot.com/2009/03/opensource-review-curl-library.html 这里]”)。
1615 |
1616 | 代码示例——IMAP 协议(邮件)
1617 |
1618 | #include
1619 | #include
1620 |
1621 | int main()
1622 | {
1623 | curl_global_init(CURL_GLOBAL_ALL);
1624 |
1625 | CURL* curl = curl_easy_init();
1626 | if(curl)
1627 | {
1628 | curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
1629 | curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
1630 |
1631 | // This will list the folders within the user's mailbox. If you want to
1632 | // list the folders within a specific folder, for example the inbox,
1633 | // then specify the folder as a path in the URL such as /INBOX
1634 | curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com");
1635 |
1636 | CURLcode res = curl_easy_perform(curl);
1637 | if(res != CURLE_OK) // Check for errors
1638 | {
1639 | fprintf(stderr, "curl_easy_perform() failed: %s\n",
1640 | curl_easy_strerror(res));
1641 | }
1642 |
1643 | curl_easy_cleanup(curl); // Always cleanup
1644 | }
1645 |
1646 | curl_global_cleanup();
1647 | return 0;
1648 | }
1649 |
1650 |
1651 | cURLpp
1652 |
1653 | Home:[http://www.curlpp.org/]
1654 |
1655 | 看名字就知道这是 cURL 的 C++ 封装。
1656 |
1657 | POCO::Net
1658 |
1659 | Docs:[http://pocoproject.org/docs/Poco.Net.html]
1660 |
1661 | POCO 前面已经介绍过。它提供了几种常见应用层协议(HTTP、SMTP、POP3、FTP、NTP ...)的封装类。
1662 |
1663 | === 8.3.2 HTTP ===
1664 |
1665 | (关于“HTTP 协议”,请参见另一个大类:“Web 相关”)
1666 |
1667 | === 8.3.3 DNS ===
1668 |
1669 | c-ares
1670 |
1671 | Home:[http://c-ares.haxx.se/]
1672 |
1673 | 这是一个 C 语言开发的 DNS 封装库,支持异步 DNS 请求,跨多种操作系统。
1674 |
1675 | 对比官网域名可知,它跟 cURL 是一家子。除了 cURL/libcurl 用到它,还有一些知名开源项目(比如:Wireshark、node.js ...)用到它。
1676 |
1677 | === 8.3.4 XMPP ===
1678 |
1679 | ([https://zh.wikipedia.org/wiki/XMPP XMPP] 的洋文全称是“Extensible Messaging and Presence Protocol”。这是一个标准化的 IM 交互协议)
1680 |
1681 | Swiften
1682 |
1683 | Home:[http://swift.im/swiften.html]
1684 |
1685 | 这是一个 C++ 语言开发的 XMPP 封装库。它同时也是 Swift 聊天客户端所用的后端。
1686 |
1687 | 它大量使用了 Boost 的子库(Signal、Bind、Optional、Smart Pointers ...)。
1688 |
1689 | QXmpp
1690 |
1691 | Home:[https://github.com/qxmpp-project/qxmpp]
1692 |
1693 | 这是一个 C++ 语言开发的 XMPP 封装库。从它的名称可以看出——依赖了 Qt 框架(需要 Qt 4.5 或更高版本)。
1694 |
1695 | == 8.4 自定义的应用层 ==
1696 |
1697 | Protocol Buffers
1698 |
1699 | Home:[https://developers.google.com/protocol-buffers/]
1700 |
1701 | Links:[https://en.wikipedia.org/wiki/Protocol_Buffers Wikipedia]
1702 |
1703 | 它是 Google 开发的一个跨语言的库,用于传输业务数据时的“编码/解码”。其优点是:跨多种语言、高性能、向前兼容、向后兼容。
1704 |
1705 | 具体的使用,可以参考俺前几年写过的一篇博文(在“[http://program-think.blogspot.com/2009/05/opensource-review-protocol-buffers.html 这里]”)。
1706 |
1707 | 作为 Protocol Buffers 的发明者,Google 默认实现了三种编程语言(C++、Java、Python)对它的支持。除了 Google 官方提供的这三种语言,它还支持很多其它的编程语言(由第三方提供)。
1708 |
1709 | Apache Thrift
1710 |
1711 | Home:[https://thrift.apache.org/]
1712 |
1713 | Links:[https://en.wikipedia.org/wiki/Apache_Thrift Wikipedia]
1714 |
1715 | 来自于 Apache 社区,提供了一种跨语言的通讯机制。
1716 |
1717 | 程序员通过 Thrift 的“接口定义语言”定义通讯协议格式,然后 Thrift 根据协议格式自动帮你生成服务端和客户端代码。
1718 |
1719 | (在这个方面,它有点类似于 Google 的 Protocol Buffers)
1720 |
1721 | == 8.5 网络库、框架、中间件 ==
1722 |
1723 | Boost.Asio
1724 |
1725 | Docs:[http://boost.org/libs/asio]
1726 |
1727 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了异步网络通讯和异步 I/O。
1728 |
1729 | 代码示例——TCP Server
1730 |
1731 | #include
1732 | #include
1733 | #include
1734 |
1735 | int main()
1736 | {
1737 | using boost::asio::ip::tcp;
1738 | try
1739 | {
1740 | boost::asio::io_service io_service;
1741 | tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));
1742 | while(true)
1743 | {
1744 | tcp::socket socket(io_service);
1745 | acceptor.accept(socket);
1746 |
1747 | std::string msg = "Hello, world";
1748 | boost::system::error_code ignored_err;
1749 | boost::asio::write(socket, boost::asio::buffer(msg), ignored_err);
1750 | }
1751 | }
1752 | catch(std::exception& err)
1753 | {
1754 | std::cerr << err.what() << std::endl;
1755 | }
1756 | return 0;
1757 | }
1758 |
1759 |
1760 | ACE
1761 |
1762 | Docs:[http://www.dre.vanderbilt.edu/Doxygen/Stable/libace-doc/annotated.html]
1763 |
1764 | ACE 前面已经介绍过。它提供了很多种用于网络通讯的设计模式。
1765 |
1766 | ZeroMQ(ØMQ)
1767 |
1768 | Home:[http://www.zeromq.org/]
1769 |
1770 | Links:[https://en.wikipedia.org/wiki/ZeroMQ Wikipedia] [https://zh.wikipedia.org/wiki/%C3%98MQ 维基百科]
1771 |
1772 | ZeroMQ 是一个轻量级、跨平台的开源库,提供了高性能、异步的消息队列。采用 C++ 开发,提供了多种语言的绑定。
1773 |
1774 | 与传统的消息中间件不同,使用 ZeroMQ 不需要额外的“消息代理(message broker)”。
1775 |
1776 | 俺曾经写过一篇博文推荐它(在“[http://program-think.blogspot.com/2011/08/opensource-review-zeromq.html 这里]”)。
1777 |
1778 | 代码示例——TCP Server
1779 |
1780 | #include
1781 |
1782 | int main()
1783 | {
1784 | zmq::context_t context(1);
1785 |
1786 | zmq::socket_t responder(context, ZMQ_REP);
1787 | responder.connect("tcp://localhost:5560");
1788 |
1789 | while(true)
1790 | {
1791 | // Wait for next request from client
1792 | std::string request = s_recv(responder);
1793 | std::cout << "Received request: " << request << std::endl;
1794 |
1795 | // Do some 'work'
1796 | sleep(1);
1797 |
1798 | // Send reply back to client
1799 | s_send(responder, "Hello, world");
1800 | }
1801 | }
1802 |
1803 |
1804 | nanomsg
1805 |
1806 | Home:[http://nanomsg.org/]
1807 |
1808 | 很类似 ZeroMQ 的库,比 ZMQ 更加轻量级。采用 C 开发,提供了多种语言的绑定。
1809 |
1810 | API 完全参照 BSD socket 的风格和语义。
1811 |
1812 | 代码示例——Request/Reply
1813 |
1814 | #include
1815 | #include
1816 | #include
1817 | #include
1818 | #include
1819 |
1820 | int reply(const char* url)
1821 | {
1822 | int sock = nn_socket(AF_SP, NN_PULL);
1823 | assert(sock >= 0);
1824 | assert(nn_bind(sock, url) >= 0);
1825 | while(1)
1826 | {
1827 | char* msg = NULL;
1828 | int bytes = nn_recv(sock, &msg, NN_MSG, 0);
1829 | assert(bytes >= 0);
1830 | printf("RECEIVED:\n%s\n", msg);
1831 | nn_freemsg(msg);
1832 | }
1833 | }
1834 |
1835 | int request(const char* url, const char* msg)
1836 | {
1837 | int sz_msg = strlen(msg) + 1; // '\0'
1838 | int sock = nn_socket(AF_SP, NN_PUSH);
1839 | assert(sock >= 0);
1840 | assert(nn_connect(sock, url) >= 0);
1841 | printf("SENDING:\n%s\n", msg);
1842 | int bytes = nn_send(sock, msg, sz_msg, 0);
1843 | assert(bytes == sz_msg);
1844 | return nn_shutdown(sock, 0);
1845 | }
1846 |
1847 |
1848 | ICE(Internet Communications Engine)
1849 |
1850 | Home:[https://zeroc.com/]
1851 |
1852 | Links:[https://en.wikipedia.org/wiki/Internet_Communications_Engine Wikipedia] [https://zh.wikipedia.org/wiki/ICE_(%E4%B8%AD%E9%97%B4%E4%BB%B6) 维基百科]
1853 |
1854 | 这是一个面向对象的通讯中间件,诞生于2002年。支持不同编程语言的通讯。
1855 |
1856 | 它的设计借鉴了 CORBA,好在没有 CORBA 那么复杂。
1857 |
1858 | libevent
1859 |
1860 | Home:[http://libevent.org/]
1861 |
1862 | Links:[https://en.wikipedia.org/wiki/Libevent Wikipedia] [https://zh.wikipedia.org/wiki/Libevent 维基百科]
1863 |
1864 | 它提供了异步事件处理机制。在网络开发中,可以用它替代传统的“event loop”,有助于简化代码。
1865 |
1866 | 它被一些知名的开源项目使用(比如:[https://zh.wikipedia.org/wiki/Tor Tor]、[https://zh.wikipedia.org/wiki/Memcached memcached])。
1867 |
1868 | 代码示例——HTTP Server(本示例基于 ANSI C)
1869 |
1870 | #include
1871 | #include
1872 | #include
1873 | #include
1874 | #include
1875 | #include
1876 |
1877 | void generic_request_handler(struct evhttp_request* req, void* arg)
1878 | {
1879 | struct evbuffer* return_buffer = evbuffer_new();
1880 |
1881 | evbuffer_add_printf(return_buffer, "Thanks for the request!");
1882 | evhttp_send_reply(req, HTTP_OK, "Client", return_buffer);
1883 | evbuffer_free(return_buffer);
1884 | }
1885 |
1886 | int main()
1887 | {
1888 | short http_port = 8080;
1889 | char* http_addr = "127.0.0.1";
1890 | struct evhttp* http_server = NULL;
1891 |
1892 | event_init();
1893 | http_server = evhttp_start(http_addr, http_port);
1894 | evhttp_set_gencb(http_server, generic_request_handler, NULL);
1895 |
1896 | fprintf(stderr, "Server started on port %d\n", http_port);
1897 | event_dispatch();
1898 |
1899 | return 0;
1900 | }
1901 |
1902 |
1903 | 代码示例——HTTP Server(本示例基于 C++ 11 标准)
1904 |
1905 | #include
1906 | #include
1907 | #include
1908 | #include
1909 |
1910 | int main()
1911 | {
1912 | if(!event_init())
1913 | {
1914 | std::cerr << "Failed to init libevent." << std::endl;
1915 | return -1;
1916 | }
1917 | char const SrvAddress[] = "127.0.0.1";
1918 | std::uint16_t SrvPort = 8080;
1919 | std::unique_ptr Server(evhttp_start(SrvAddress, SrvPort), &evhttp_free);
1920 | if(!Server)
1921 | {
1922 | std::cerr << "Failed to init http server." << std::endl;
1923 | return -1;
1924 | }
1925 |
1926 | void (*OnReq)(evhttp_request* req, void*) = [] (evhttp_request* req, void*)
1927 | {
1928 | auto* OutBuf = evhttp_request_get_output_buffer(req);
1929 | if(!OutBuf)
1930 | {
1931 | return;
1932 | }
1933 | evbuffer_add_printf(OutBuf, "Hello, World! ");
1934 | evhttp_send_reply(req, HTTP_OK, "", OutBuf);
1935 | };
1936 |
1937 | evhttp_set_gencb(Server.get(), OnReq, nullptr);
1938 | if(event_dispatch() == -1)
1939 | {
1940 | std::cerr << "Failed to run messahe loop." << std::endl;
1941 | return -1;
1942 | }
1943 | return 0;
1944 | }
1945 |
1946 |
1947 | libev
1948 |
1949 | Home:[http://libev.schmorp.de/]
1950 |
1951 | 看名称就能猜到它跟 libevent 很像。实际上,你可以把 libev 视为 libevent 的竞争性替代品。
1952 |
1953 | [http://www.gevent.org/ gevent] 官方博客的[http://blog.gevent.org/2011/04/28/libev-and-libevent/ 一篇文章]对比了这俩库的优缺点。
1954 |
1955 | libuv
1956 |
1957 | Home:[https://github.com/libuv/libuv]
1958 |
1959 | Links:[https://en.wikipedia.org/wiki/Libuv Wikipedia]
1960 |
1961 | 它提供了跨平台的异步 I/O 机制。主要是为了提供给 [https://en.wikipedia.org/wiki/Node.js Node.js] 使用。
1962 |
1963 | 除了支持网络通讯,还支持:线程池、Windows 命名管道、Unix domain sockets、文件系统事件通知 ......
1964 |
1965 | Dlib
1966 |
1967 | Docs:[http://dlib.net/network.html]
1968 |
1969 | Dlib 前面已经介绍过。它针对网络通讯,提供了比较高的抽象层。
1970 |
1971 | ----
1972 |
1973 | = 9 数据库 =
1974 |
1975 | == 9.1 开源数据库 ==
1976 |
1977 | MySQL
1978 |
1979 | Home:[https://www.mysql.com/]
1980 |
1981 | Links:[https://en.wikipedia.org/wiki/MySQL Wikipedia] [https://zh.wikipedia.org/wiki/MySQL 维基百科]
1982 |
1983 | 名气最大的开源数据库,诞生于1995年,采用 C 和 C++ 语言开发。如今隶属于 Oracle 公司。
1984 |
1985 | PostgreSQL
1986 |
1987 | Home:[http://postgresql.org/]
1988 |
1989 | Links:[https://en.wikipedia.org/wiki/PostgreSQL Wikipedia] [https://zh.wikipedia.org/wiki/PostgreSQL 维基百科]
1990 |
1991 | 名气仅次于 MySQL 的开源数据库,诞生于1996年。采用 C 语言开发。
1992 |
1993 | SQLite
1994 |
1995 | Home:[http://sqlite.org/]
1996 |
1997 | Links:[https://en.wikipedia.org/wiki/SQLite Wikipedia] [https://zh.wikipedia.org/wiki/SQLite 维基百科]
1998 |
1999 | 它是一个很优秀的嵌入式(进程内)数据库,非常轻量级,支持各种作系统平台。采用 C 语言开发。
2000 |
2001 | 俺前几年写过一篇博文推荐它(在“[http://program-think.blogspot.com/2009/04/how-to-use-sqlite.html 这里]”)。
2002 |
2003 | MongoDB
2004 |
2005 | Home:[https://www.mongodb.org/]
2006 |
2007 | Links:[https://en.wikipedia.org/wiki/MongoDB Wikipedia]
2008 |
2009 | 这是近几年兴起的 NoSQL 数据库的一员。它本身是基于 C++ 和 C 开发的。
2010 |
2011 | Redis
2012 |
2013 | Home:[http://redis.io/]
2014 |
2015 | Links:[https://zh.wikipedia.org/wiki/Redis 维基百科] [https://en.wikipedia.org/wiki/Redis Wikipedia]
2016 |
2017 | 诞生于2009年,是目前(2014~2015)最流行的键值存储数据库,基于 C 语言开发。
2018 |
2019 | 以性能高而著称,很多大型网站用到它(Twitter、GitHub、Flickr、Instagram、百度、新浪、腾讯、搜狐)
2020 |
2021 | Berkeley DB(BDB)
2022 |
2023 | Home:[http://www.oracle.com/us/products/database/berkeley-db/]
2024 |
2025 | Links:[https://en.wikipedia.org/wiki/Berkeley_DB Wikipedia] [https://zh.wikipedia.org/wiki/Berkeley_DB 维基百科]
2026 |
2027 | 诞生于1994年,是一个很老牌的嵌入式(进程内)数据库,提供“键值存储”的功能,基于 C 语言开发。
2028 |
2029 | 开发 BDB 的公司于2006年被 Oracle 收购。
2030 |
2031 | 很多开源项目用到它。甚至 MySQL 也包含了一个基于 BDB 的存储后端。
2032 |
2033 | LevelDB
2034 |
2035 | Home:[https://github.com/google/leveldb]
2036 |
2037 | Links:[https://en.wikipedia.org/wiki/LevelDB Wikipedia] [https://zh.wikipedia.org/wiki/LevelDB 维基百科]
2038 |
2039 | 它是 Google 基于 C++ 开发的 NoSQL 数据库,提供“键值存储”的功能。
2040 |
2041 | 号称速度很快,内置数据压缩(基于 [https://en.wikipedia.org/wiki/Snappy_(software) Snappy] 库)。
2042 |
2043 | 比特币项目用到它。Facebook 基于它开发出 RocksDB 数据库。
2044 |
2045 | Firebird
2046 |
2047 | Home:[http://www.firebirdsql.org/]
2048 |
2049 | Links:[https://en.wikipedia.org/wiki/Firebird_%28database_server%29 Wikipedia] [https://zh.wikipedia.org/wiki/Firebird_(%E6%95%B0%E6%8D%AE%E5%BA%93) 维基百科]
2050 |
2051 | 它是2000年的时候,从 [https://en.wikipedia.org/wiki/Borland Borland] 公司的 InterBase 数据库派生出来的。
2052 |
2053 | 基于 C++ 开发,支持多种操作系统平台。
2054 |
2055 | 关于它有个插曲:Firefox 浏览器曾经用过“Firebird”这个名称,因为跟 Firebird 数据库同名,后来才改用 Firefox 这个名称。
2056 |
2057 | ScyllaDB
2058 |
2059 | Home:[http://www.scylladb.com/]
2060 |
2061 | 这是2015年新兴的 NoSQL 数据库,相当于是用 C++ 重写了(Java 开发的)Cassandra。
2062 |
2063 | 号称性能提高10倍,并且延迟极低。
2064 |
2065 | == 9.2 数据库 API 的封装库 ==
2066 |
2067 | === 9.2.1 综合性的封装库 ===
2068 |
2069 | OTL
2070 |
2071 | Home:[http://otl.sourceforge.net/]
2072 |
2073 | Links:[https://en.wikipedia.org/wiki/Oracle_Template_Library Wikipedia]
2074 |
2075 | 原生支持的数据库:Oracle、SQL Server、DB2、Informix、TimesTen, MAX/DB;另支持 ODBC。
2076 |
2077 | 它的特色是:全部代码都在一个头文件中。
2078 |
2079 | 代码示例——操作 Oracle 数据库
2080 |
2081 | #include
2082 | #include
2083 |
2084 | #define OTL_ORA8 // Compile OTL 4.0/OCI8
2085 | #include // include the OTL 4.0 header file
2086 |
2087 | int main()
2088 | {
2089 | otl_connect::otl_initialize();
2090 | try
2091 | {
2092 | otl_connect db;
2093 | db.rlogon("scott/tiger"); // connect to Oracle
2094 | otl_cursor::direct_exec(
2095 | db,
2096 | "drop table test_tab",
2097 | otl_exception::disabled // disable OTL exceptions
2098 | );
2099 |
2100 | otl_cursor::direct_exec(
2101 | db,
2102 | "create table test_tab(f1 number, f2 varchar2(30))"
2103 | );
2104 | }
2105 | catch(otl_exception& err)
2106 | {
2107 | using namespace std;
2108 | // intercept OTL exceptions
2109 | cerr << err.msg << endl; // print error message
2110 | cerr << err.stm_text << endl; // print SQL that caused the error
2111 | cerr << err.var_info << endl; // print variable that caused the error
2112 | }
2113 |
2114 | db.logoff(); // disconnect from Oracle
2115 | return 0;
2116 | }
2117 |
2118 |
2119 | === 9.2.2 MySQL 封装库 ===
2120 |
2121 | MySQL Connector C++
2122 |
2123 | Home:[http://dev.mysql.com/doc/connector-cpp/en/]
2124 |
2125 | 这是 MySQL 官方提供的 C++ 封装。
2126 |
2127 | 代码示例——执行 SQL 语句
2128 |
2129 | sql::mysql::MySQL_Driver* driver = sql::mysql::MySQL_Driver::get_mysql_driver_instance();
2130 | sql::Connection* conn = driver->connect("tcp://127.0.0.1:3306", "user", "password");
2131 | sql::Statement* stmt = conn->createStatement();
2132 |
2133 | stmt->execute("USE EXAMPLE_DB");
2134 | stmt->execute("DROP TABLE IF EXISTS test");
2135 | stmt->execute("CREATE TABLE test(id INT, label CHAR(1))");
2136 | stmt->execute("INSERT INTO test(id, label) VALUES (1, 'a')");
2137 |
2138 | delete stmt;
2139 | stmt = NULL;
2140 | delete conn;
2141 | conn = NULL;
2142 |
2143 |
2144 | MySQL++
2145 |
2146 | Home:[http://www.tangentsoft.net/mysql%2B%2B/]
2147 |
2148 | 这是个老牌的库,诞生于1998年,提供了 MySQL API 的 C++ 封装。
2149 |
2150 | 代码示例——执行 SQL 语句
2151 |
2152 | #include
2153 | #include
2154 |
2155 | void query(db_name, server_name, user, password)
2156 | {
2157 | using namespace std;
2158 |
2159 | mysqlpp::Connection conn(false);
2160 | if(!conn.connect(db_name, server_name, user, password))
2161 | {
2162 | cerr << "DB connection failed: " << conn.error() << endl;
2163 | return;
2164 | }
2165 |
2166 | mysqlpp::Query query = conn.query("select item from table1");
2167 | mysqlpp::StoreQueryResult sqr = query.store()
2168 | if(!sqr)
2169 | {
2170 | cerr << "Failed to get item list: " << query.error() << endl;
2171 | return;
2172 | }
2173 |
2174 | mysqlpp::StoreQueryResult::const_iterator iter;
2175 | for(iter=sqr.begin(); iter!=sqr.end(); ++iter)
2176 | {
2177 | mysqlpp::Row row = *iter;
2178 | cout << '\t' << row[0] << endl;
2179 | }
2180 | }
2181 |
2182 |
2183 | POCO::Data::MySQL
2184 |
2185 | Docs:[http://pocoproject.org/docs/package-MySQL.MySQL.html]
2186 |
2187 | POCO 前面已经介绍过。它提供了 MySQL 的封装类
2188 |
2189 | === 9.2.3 PostgreSQL 封装库 ===
2190 |
2191 | libpq
2192 |
2193 | Home:[http://www.postgresql.org/docs/9.4/static/libpq.html]
2194 |
2195 | 这是由 PostgreSQL 官方提供的 C 封装类库。
2196 |
2197 | libpqxx
2198 |
2199 | Home:[http://pqxx.org/development/libpqxx/]
2200 |
2201 | 这是由 PostgreSQL 官方提供的 C++ 封装类库。
2202 |
2203 | 代码示例
2204 |
2205 | #include
2206 | #include
2207 |
2208 | void update(const std::string& name)
2209 | {
2210 | pqxx::connection conn("dbname=company user=accounting");
2211 | pqxx::work txn(conn);
2212 |
2213 | pqxx::result r = txn.exec("SELECT id FROM Employee WHERE name =" + name);
2214 | if(r.size() != 1)
2215 | {
2216 | std::cerr << "Expected 1 employee with name " << name << ", "
2217 | << "but found " << r.size() << std::endl;
2218 | return 1;
2219 | }
2220 |
2221 | int employee_id = r[0][0].as();
2222 | std::cout << "Updating employee #" << employee_id << std::endl;
2223 |
2224 | txn.exec(
2225 | "UPDATE EMPLOYEE SET salary = salary + 1 "
2226 | "WHERE id = " + txn.quote(employee_id)
2227 | );
2228 |
2229 | txn.commit();
2230 | }
2231 |
2232 |
2233 | === 9.2.4 Oracle 封装库 ===
2234 |
2235 | OCILIB
2236 |
2237 | Home:[http://vrogier.github.io/ocilib/]
2238 |
2239 | 这是一个跨平台的 C 开源库。如其名,它封装了 Oracle 官方的 OCI(Oracle Call Interface)。
2240 |
2241 | 它同时还提供了 C++ 的 API。
2242 |
2243 | 代码示例
2244 |
2245 | #include
2246 | using namespace ocilib;
2247 |
2248 | int main()
2249 | {
2250 | try
2251 | {
2252 | Environment::Initialize();
2253 | Connection conn("db", "user", "password");
2254 | Statement stmt(conn);
2255 | stmt.Execute("select intcol, strcol from table");
2256 |
2257 | Resultset rs = stmt.GetResultset();
2258 | while(rs.Next())
2259 | {
2260 | std::cout << rs.Get(1) << " - " << rs.Get(2) << std::endl;
2261 | }
2262 | }
2263 | catch(std::exception& err)
2264 | {
2265 | std::cout << err.what() << std::endl;
2266 | }
2267 |
2268 | Environment::Cleanup();
2269 | return 0;
2270 | }
2271 |
2272 |
2273 | === 9.2.5 DB2 封装库 ===
2274 |
2275 | === 9.2.6 SQLite 封装库 ===
2276 |
2277 | 官方的 C API
2278 |
2279 | Docs:[http://sqlite.org/c3ref/intro.html]
2280 |
2281 | SQLite 前面已经介绍过。由于 SQLite 本身就是用 C 语言开发的,因此它直接提供了基于 C 的 API 接口。
2282 |
2283 | 代码示例
2284 |
2285 | #include
2286 | #include
2287 |
2288 | static int callback(void* NotUsed, int argc, char** argv, char** azColName)
2289 | {
2290 | for(int i=0; i
2327 |
2328 | POCO::Data::SQLite
2329 |
2330 | Docs:[http://pocoproject.org/docs/package-SQLite.SQLite.html]
2331 |
2332 | POCO 前面已经介绍过。它提供了 sqlite 的封装类
2333 |
2334 | === 9.2.7 Redis 封装库 ===
2335 |
2336 | Hiredis
2337 |
2338 | Home:[https://github.com/redis/hiredis]
2339 |
2340 | 这是 Redis 官方提供的 C 客户端,很轻量级,支持“异步 API”。
2341 |
2342 | 代码示例——结合 libev 进行异步调用
2343 |
2344 | #include
2345 | #include
2346 | #include
2347 | #include
2348 |
2349 | #include
2350 | #include
2351 | #include
2352 |
2353 | void getCallback(redisAsyncContext* context, void* r, void* privdata)
2354 | {
2355 | redisReply* reply = r;
2356 | if(reply == NULL)
2357 | {
2358 | return;
2359 | }
2360 | printf("argv[%s]: %s\n", (char*)privdata, reply->str);
2361 | redisAsyncDisconnect(context); /* Disconnect after receiv reply */
2362 | }
2363 |
2364 | void connectCallback(const redisAsyncContext* context, int status)
2365 | {
2366 | if(status != REDIS_OK)
2367 | {
2368 | printf("Error: %s\n", context->errstr);
2369 | return;
2370 | }
2371 | printf("Connected...\n");
2372 | }
2373 |
2374 | void disconnectCallback(const redisAsyncContext* context, int status)
2375 | {
2376 | if(status != REDIS_OK)
2377 | {
2378 | printf("Error: %s\n", context->errstr);
2379 | return;
2380 | }
2381 | printf("Disconnected...\n");
2382 | }
2383 |
2384 | int main(int argc, char* argv[])
2385 | {
2386 | signal(SIGPIPE, SIG_IGN);
2387 |
2388 | redisAsyncContext* context = redisAsyncConnect("127.0.0.1", 6379);
2389 | if(context->err)
2390 | {
2391 | printf("Error: %s\n", context->errstr);
2392 | return 1; /* Let *context leak for now... */
2393 | }
2394 |
2395 | redisLibevAttach(EV_DEFAULT_ context);
2396 | redisAsyncSetConnectCallback(context, connectCallback);
2397 | redisAsyncSetDisconnectCallback(context, disconnectCallback);
2398 | redisAsyncCommand(context, NULL, NULL,
2399 | "SET key %b", argv[argc-1], strlen(argv[argc-1]));
2400 | redisAsyncCommand(context, getCallback, (char*)"end-1", "GET key");
2401 | ev_loop(EV_DEFAULT_ 0);
2402 | return 0;
2403 | }
2404 |
2405 |
2406 | === 9.2.8 MongoDB 封装库 ===
2407 |
2408 | 官方的 C API
2409 |
2410 | Docs:[https://api.mongodb.org/c/current/]
2411 |
2412 | MongoDB 前面已经介绍过。这是其官方提供的 API。
2413 |
2414 | 代码示例
2415 |
2416 | #include
2417 | #include
2418 | #include
2419 |
2420 | int main()
2421 | {
2422 | mongoc_init();
2423 |
2424 | mongoc_client_t* client = mongoc_client_new("mongodb://localhost:27017/");
2425 | mongoc_collection_t* collection = mongoc_client_get_collection(client, "test", "test");
2426 |
2427 | bson_t* doc = bson_new();
2428 |
2429 | bson_oid_t oid;
2430 | bson_oid_init(&oid, NULL);
2431 | BSON_APPEND_OID(doc, "_id", &oid);
2432 | BSON_APPEND_UTF8(doc, "hello", "world");
2433 |
2434 | bson_error_t error;
2435 | if(!mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error))
2436 | {
2437 | printf("%s\n", error.message);
2438 | }
2439 |
2440 | bson_destroy(doc);
2441 | mongoc_collection_destroy(collection);
2442 | mongoc_client_destroy(client);
2443 |
2444 | return 0;
2445 | }
2446 |
2447 |
2448 | POCO::MongoDB
2449 |
2450 | Docs:[http://pocoproject.org/docs/package-MongoDB.MongoDB.html]
2451 |
2452 | POCO 前面已经介绍过。它提供了 MongoDB 的封装类
2453 |
2454 | == 9.3 ODBC 相关 ==
2455 |
2456 | unixODBC
2457 |
2458 | Home:[http://www.unixodbc.org/]
2459 |
2460 | Links:[https://en.wikipedia.org/wiki/UnixODBC Wikipedia]
2461 |
2462 | 诞生于1999年,实现了全套的 ODBC 架构,包括:驱动管理器、相关的 GUI 界面和命令行界面。支持多种操作系统。
2463 |
2464 | Libodbc++
2465 |
2466 | Home:[http://libodbcxx.sourceforge.net/]
2467 |
2468 | 如其名,这是专门封装 ODBC 的 C++ 类库,支持多种操作系统。它提供的 API 类似于 JDBC 的 API
2469 |
2470 | POCO::Data::ODBC
2471 |
2472 | Docs:[http://pocoproject.org/docs/package-ODBC.ODBC.html]
2473 |
2474 | POCO 前面已经介绍过。它提供了操作 ODBC 的封装类。
2475 |
2476 | == 9.4 ORM(Object-Relational Mapping) ==
2477 |
2478 | ODB
2479 |
2480 | Home:[http://www.codesynthesis.com/products/odb]
2481 |
2482 | Links:[https://en.wikipedia.org/wiki/ODB_%28C%2B%2B%29 Wikipedia]
2483 |
2484 | 它的特色是:可以根据 C++ 类定义自动生成数据库的表结构。
2485 |
2486 | 为了获得高性能,它直接调用具体数据库的原生 API。支持的数据库包括:MySQL、PostgreSQL、Oracle、SQL Server、SQLite
2487 |
2488 | 代码示例——声明一个可持久化的类
2489 |
2490 | // 通过预处理语句“#pragma”来进行某些定制
2491 |
2492 | #pragma db object table("people")
2493 | class person
2494 | {
2495 | public:
2496 | // ......
2497 |
2498 | private:
2499 | friend class odb::access;
2500 | person();
2501 |
2502 | #pragma db id auto
2503 | unsigned long id_;
2504 |
2505 | string first_;
2506 | string last_;
2507 |
2508 | #pragma type("INT UNSIGNED")
2509 | unsigned short age_;
2510 | };
2511 |
2512 |
2513 | 代码示例——查询
2514 |
2515 | typedef odb::query query;
2516 | typedef odb::result result;
2517 |
2518 | transaction trans(db.begin());
2519 | result r(db.query(query::last == "Doe" && query::age < 30));
2520 |
2521 | for(result::iterator i(r.begin()); i!=r.end(); ++i)
2522 | {
2523 | cout << "Hello, " << i->first() << endl;
2524 | }
2525 |
2526 | trans.commit();
2527 |
2528 |
2529 | hiberlite
2530 |
2531 | Home:[https://github.com/paulftw/hiberlite]
2532 |
2533 | 专门提供给 Sqlite 的 ORM 封装库。基于 C++ 开发,其 API 采用类似 Boost.Serialization 的风格。
2534 |
2535 | ----
2536 |
2537 | = 10 Web =
2538 |
2539 | == 10.1 HTTP Server ==
2540 |
2541 | Apache HTTP Server
2542 |
2543 | Home:[https://httpd.apache.org/]
2544 |
2545 | Links:[https://en.wikipedia.org/wiki/Apache_HTTP_Server Wikipedia] [https://zh.wikipedia.org/wiki/Apache_HTTP_Server 维基百科]
2546 |
2547 | 大名鼎鼎的 Apache,诞生于1995年,采用 C 和 C++ 开发。长期作为 Web Server 市场份额的老大。
2548 |
2549 | Nginx
2550 |
2551 | Home:[http://nginx.org/]
2552 |
2553 | Links:[https://en.wikipedia.org/wiki/Nginx Wikipedia] [https://zh.wikipedia.org/wiki/Nginx 维基百科]
2554 |
2555 | Web Server 的后起之秀,诞生于2002年,采用 C 语言开发。其市场份额如今排名第二。
2556 |
2557 | POCO::Net
2558 |
2559 | Docs:[http://pocoproject.org/docs/package-Net.HTTPServer.html]
2560 |
2561 | POCO 前面已经介绍过。它提供了 HTTP Server 的封装类
2562 |
2563 | Dlib::server_http
2564 |
2565 | Docs:[http://dlib.net/network.html#server_http]
2566 |
2567 | Dlib 前面已经介绍过。它提供了一个简单的 HTTP Server 的类(server_http)。
2568 |
2569 | == 10.2 HTTP Client ==
2570 |
2571 | cURL & libcurl
2572 |
2573 | Docs:[http://curl.haxx.se/libcurl/c/]
2574 |
2575 | libcurl 前面已经介绍过。它提供了【完整的】HTTP 协议支持。另,HTTP 2.0 标准刚出来不久,它就已经支持了。
2576 |
2577 | 代码示例——HTTP POST
2578 |
2579 | #include
2580 | #include
2581 |
2582 | int main()
2583 | {
2584 | curl_global_init(CURL_GLOBAL_ALL);
2585 |
2586 | CURL* curl = curl_easy_init();
2587 | if(curl)
2588 | {
2589 | curl_easy_setopt(curl, CURLOPT_URL, "http://post.example.com/foo.cgi");
2590 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
2591 |
2592 | CURLcode res = curl_easy_perform(curl);
2593 | if(res != CURLE_OK) // Check for errors
2594 | {
2595 | fprintf(stderr, "curl_easy_perform() failed: %s\n",
2596 | curl_easy_strerror(res));
2597 | }
2598 | curl_easy_cleanup(curl); // always cleanup
2599 | }
2600 |
2601 | curl_global_cleanup();
2602 | return 0;
2603 | }
2604 |
2605 |
2606 | POCO::Net
2607 |
2608 | Docs:[http://pocoproject.org/docs/package-Net.HTTPClient.html]
2609 |
2610 | POCO 前面已经介绍过。它提供了 HTTP Client 的封装类。
2611 |
2612 | cpr
2613 |
2614 | Home:[https://github.com/whoshuu/cpr]
2615 |
2616 | 类似 Python 的 [http://docs.python-requests.org/ Requests 库],以【优雅的语法】实现 HTTP 请求。
2617 |
2618 | 代码示例——HTTP GET
2619 |
2620 | #include
2621 |
2622 | int main()
2623 | {
2624 | auto r = cpr::Get(cpr::Url{"https://api.github.com/repos/whoshuu/cpr/contributors"},
2625 | cpr::Authentication{"user", "pass"},
2626 | cpr::Parameters{{"anon", "true"}, {"key", "value"}});
2627 | r.status_code; // 200
2628 | r.header["content-type"]; // application/json; charset=utf-8
2629 | r.text; // JSON text string
2630 | return 0;
2631 | }
2632 |
2633 |
2634 | == 10.3 浏览器引擎 ==
2635 |
2636 | WebKit
2637 |
2638 | Home:[https://www.webkit.org/]
2639 |
2640 | Links:[https://en.wikipedia.org/wiki/WebKit Wikipedia] [https://zh.wikipedia.org/wiki/WebKit 维基百科]
2641 |
2642 | 它是很多浏览器使用的渲染引擎,基于 C++ 开发。
2643 |
2644 | Gecko
2645 |
2646 | Home:[https://developer.mozilla.org/]
2647 |
2648 | Links:[https://en.wikipedia.org/wiki/Gecko_(software) Wikipedia] [https://zh.wikipedia.org/wiki/Gecko 维基百科]
2649 |
2650 | 它是 Firefox 的渲染引擎,基于 C++ 开发,由 Mozilla 社区维护。
2651 |
2652 | == 10.4 浏览器整合 ==
2653 |
2654 | CEF(Chromium Embedded Framework)
2655 |
2656 | Home:[https://bitbucket.org/chromiumembedded/cef]
2657 |
2658 | Links:[https://en.wikipedia.org/wiki/Chromium_Embedded_Framework Wikipedia]
2659 |
2660 | 如其名,它提供了嵌入 Chrome 浏览器的框架。采用 C++ 开发。好几个商业公司(Google、Adobe、Facebook、Evernote...)的产品用到它。
2661 |
2662 | 以下是其它开源项目针对 CEF 的扩展,提供了其它编程语言的绑定。
2663 |
2664 | * dotNet - [https://github.com/chillitom/CefSharp]
2665 |
2666 | * dotNet (CEF1) - [https://bitbucket.org/fddima/cefglue]
2667 |
2668 | * dotNet/Mono (CEF3) - [https://bitbucket.org/xilium/xilium.cefglue]
2669 |
2670 | * dotNet (CEF3) - [https://bitbucket.org/chromiumfx/chromiumfx]
2671 |
2672 | * Java - [https://bitbucket.org/chromiumembedded/java-cef]
2673 |
2674 | * Go - [https://github.com/CzarekTomczak/cef2go]
2675 |
2676 | * Delphi (CEF3) - [https://github.com/hgourvest/dcef3]
2677 |
2678 | PhantomJS
2679 |
2680 | Home:[http://phantomjs.org/]
2681 |
2682 | Links:[https://en.wikipedia.org/wiki/PhantomJS Wikipedia]
2683 |
2684 | 2011年才诞生的。基于 C++ 开发,整合了 WebKit。
2685 |
2686 | 它本身没有提供 GUI 界面。但是提供了 JavaScript 的 API,让你可以操纵 WebKit 引擎。可以利用它进行 Web 界面的单元测试。
2687 |
2688 | == 10.5 (其它) ==
2689 |
2690 | WebSocket++
2691 |
2692 | Home:[http://www.zaphoyd.com/websocketpp/]
2693 |
2694 | 顾名思义,它提供了 [https://en.wikipedia.org/wiki/WebSocket WebSocket] 的 C++ 封装,基于 Boost Asio 构建。
2695 |
2696 | 支持多种操作系统平台,支持 TLS、proxy、IPv6。
2697 |
2698 | ----
2699 |
2700 | = 11 信息安全 =
2701 |
2702 | == 11.1 密码学 ==
2703 |
2704 | Crypto++
2705 |
2706 | Docs:[http://www.cryptopp.com/docs/ref/annotated.html]
2707 |
2708 | Crypto++ 前面已经介绍过。它提供了常见的对称加密算法(DES、AES、IDEA 等)、公钥加密算法(RSA、DSA 等)、散列算法(MD5、SHA1、RIPEMD 等)。
2709 |
2710 | 代码示例——计算 SHA256 散列值
2711 |
2712 | #include
2713 | using namespace CryptoPP;
2714 |
2715 | const byte* pbData = ...; // 要计算的数据的地址
2716 | unsigned int nDataLen = ...; // 字节数
2717 | byte abDigest[SHA256::DIGESTSIZE];
2718 | SHA256().CalculateDigest(abDigest, pbData, nDataLen);
2719 | // 注:abDigest 中通常会包含不可见字符,要输出为可见字符串需要做一下 Hex 编码
2720 |
2721 |
2722 | OpenSSL
2723 |
2724 | Home:[https://www.openssl.org/]
2725 |
2726 | Links:[https://en.wikipedia.org/wiki/OpenSSL Wikipedia] [https://zh.wikipedia.org/wiki/OpenSSL 维基百科]
2727 |
2728 | OpenSSL 基于 C 语言开发,在加密领域那可是大名鼎鼎。大部分常用的加密算法(对称、非对称)和散列算法,它都支持。
2729 |
2730 | 很多知名的软件(包括 Web Server)用到它,所以2014年的“[https://zh.wikipedia.org/wiki/%E5%BF%83%E8%84%8F%E5%87%BA%E8%A1%80%E6%BC%8F%E6%B4%9E 心脏滴血漏洞]”让好多网站中招。
2731 |
2732 | LibreSSL
2733 |
2734 | Home:[http://www.libressl.org/]
2735 |
2736 | Links:[https://en.wikipedia.org/wiki/LibreSSL Wikipedia] [https://zh.wikipedia.org/wiki/LibreSSL 维基百科]
2737 |
2738 | OpenSSL 爆出“心脏滴血漏洞”之后,OpenBSD 社区的程序员复制了 OpenSSL 版本 1.0.1g 的代码,然后另起炉灶。
2739 |
2740 | LibreSSL 的主要目标是“安全性”,其维护人员删除了原 OpenSSL 中大量过时的代码,替换了相关的内存管理函数(规避缓冲区溢出),增强了随机数生成算法....
2741 |
2742 | GnuTLS
2743 |
2744 | Home:[http://gnutls.org/]
2745 |
2746 | Links:[https://en.wikipedia.org/wiki/GnuTLS Wikipedia]
2747 |
2748 | 采用 C 语言开发,名气也挺大。如其名,主要提供 TLS/SSL 的相关功能。
2749 |
2750 | NaCl
2751 |
2752 | Home:[http://nacl.cr.yp.to/]
2753 |
2754 | Links:[https://en.wikipedia.org/wiki/NaCl_%28software%29 Wikipedia]
2755 |
2756 | 这个名称是“Networking and Cryptography library”的缩写。
2757 |
2758 | 它采用 C 语言开发,另有其它编程语言(Python、Ruby、PHP)的 API 绑定。
2759 |
2760 | 它的作者同时也是 [https://en.wikipedia.org/wiki/Qmail qmail] 和 [https://en.wikipedia.org/wiki/Curve25519 Curve25519] 的作者。
2761 |
2762 | libsodium
2763 |
2764 | Home:[https://github.com/jedisct1/libsodium]
2765 |
2766 | 它派生自 NaCl,提供了跟 NaCl 兼容的 API。支持的操作系统平台更多。
2767 |
2768 | shadowsocks 和 dnscrypt-proxy 用到它。
2769 |
2770 | Keyczar
2771 |
2772 | Home:[https://github.com/google/keyczar]
2773 |
2774 | 这是 Google 提供的加密库,同时提供 C++、Java、Python 三种语言的实现。
2775 |
2776 | 它提供了比较高层的 API, 使用者无需关心太多的细节。
2777 |
2778 | 代码示例——加密/解密文本
2779 |
2780 | #include
2781 | #include
2782 | #include
2783 | #include
2784 |
2785 | void test(const std::string& key_location)
2786 | {
2787 | keyczar::Keyczar* crypter = keyczar::Crypter::Read(key_location);
2788 | if(!crypter)
2789 | {
2790 | return;
2791 | }
2792 |
2793 | std::string plain = "Secret message";
2794 | std::cout << "Plain text: " << plain << std::endl;
2795 |
2796 | std::string cipher;
2797 | if(crypter->Encrypt(plain, &cipher))
2798 | {
2799 | std::cout << "Cipher text (Base64w): " << cipher << std::endl;
2800 | std::string decrypted;
2801 | if(crypter->Decrypt(cipher, &decrypted))
2802 | {
2803 | assert(plain == decrypted);
2804 | }
2805 | }
2806 | delete crypter;
2807 | }
2808 |
2809 |
2810 | POCO::Crypto
2811 |
2812 | Docs:[http://pocoproject.org/docs/Poco.Crypto.html]
2813 |
2814 | POCO 前面已经介绍过。它提供了常见的加密算法和哈希算法。
2815 |
2816 | ----
2817 |
2818 | = 12 处理文件格式 =
2819 |
2820 | == 12.1 结构化数据格式 ==
2821 |
2822 | === 12.1.1 CSV ===
2823 |
2824 | [https://en.wikipedia.org/wiki/Comma-separated_values CSV] 是一种历史悠久的结构化数据存储格式。其效果类似于一张数据库二维表。
2825 |
2826 | Boost.Tokenizer
2827 |
2828 | Docs:[http://boost.org/libs/tokenizer]
2829 |
2830 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,用来灵活地切割字符串。使用它,可以帮你提取 CSV 的行和列。
2831 |
2832 | === 12.1.2 JSON ===
2833 |
2834 | JSON 格式源自 JavaScript,如今在 Web 开发中广为应用。
2835 |
2836 | Boost.PropertyTree
2837 |
2838 | Docs:[http://boost.org/libs/property_tree]
2839 |
2840 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,封装了某种特殊的“树”结构(property_tree)。它支持对 JSON 的读写。
2841 |
2842 | 代码示例——读写 JSON 字符串
2843 |
2844 | #include
2845 | #include
2846 | #include
2847 |
2848 | using boost::property_tree::ptree;
2849 | using boost::property_tree::read_json;
2850 | using boost::property_tree::write_json;
2851 |
2852 | // Write json
2853 | ptree pt1;
2854 | pt1.put("foo", "bar");
2855 | std::ostringstream oss;
2856 | write_json(oss, pt1, false);
2857 | std::string json = oss.str(); // {"foo":"bar"}
2858 |
2859 | // Read json
2860 | std::istringstream iss(json);
2861 | ptree pt2;
2862 | read_json(iss, pt2);
2863 | std::string value = pt2.get("foo");
2864 |
2865 |
2866 | POCO::JSON
2867 |
2868 | Docs:[http://pocoproject.org/docs/package-JSON.JSON.html]
2869 |
2870 | POCO 前面已经介绍过。它提供了 JSON 的封装类
2871 |
2872 | rapidjson
2873 |
2874 | Home:[https://github.com/miloyip/rapidjson]
2875 |
2876 | 这是一个 C++ 的 JSON 库。提供了 SAX 和 DOM 风格的 API。
2877 |
2878 | (另,作者是香港同胞)
2879 |
2880 | jsoncpp
2881 |
2882 | Home:[https://github.com/open-source-parsers/jsoncpp]
2883 |
2884 | 如其名,这是个 C++ 的 JSON 封装库。
2885 |
2886 | === 12.1.3 YAML ===
2887 |
2888 | [https://en.wikipedia.org/wiki/YAML YAML] 是一种类似于 json 的结构化数据格式。它在确保可读性的基础上,提供了超越 json 的灵活性和扩展性。
2889 |
2890 | yaml-cpp
2891 |
2892 | Home:[https://github.com/jbeder/yaml-cpp]
2893 |
2894 | C++ 实现的 YAML 解析器。
2895 |
2896 | LibYAML
2897 |
2898 | Home:[http://pyyaml.org/wiki/LibYAML]
2899 |
2900 | C 语言实现的 YAML 解析器。
2901 |
2902 | == 12.2 压缩文件 & 打包文件 ==
2903 |
2904 | === 12.2.1 综合性的库 ===
2905 |
2906 | libarchive
2907 |
2908 | Home:[http://www.libarchive.org/]
2909 |
2910 | C 语言实现,支持的格式:
2911 |
2912 | 可读写的格式:zip、gzip、bzip2、xz、lzma、tar、ISO、cpio、ar、pax、mtree;
2913 |
2914 | 只读的格式:7z、rar、cab、rpm、lzh、lzop、raw、xar
2915 |
2916 | LZMA SDK
2917 |
2918 | Home:[http://www.7-zip.org/sdk.html]
2919 |
2920 | 这是由 7-zip 官方提供的。7-zip 就是用它进行压缩/解压缩。
2921 |
2922 | 支持的格式:7z、LZMA、LZMA2、XZ
2923 |
2924 | PhysicsFS
2925 |
2926 | Home:[http://icculus.org/physfs/]
2927 |
2928 | Links:[https://en.wikipedia.org/wiki/PhysicsFS Wikipedia]
2929 |
2930 | 针对不同的压缩/归档格式,提供了类似 VFS 的抽象封装层。主要用于游戏开发中。
2931 |
2932 | 支持的格式:zip、7z、GRP、PAK、HOG、MVL、WAD...
2933 |
2934 | zopfli
2935 |
2936 | Home:[https://github.com/google/zopfli]
2937 |
2938 | 这是由 Google 开发的 C 库,提供对 zip 和 gzip 格式的压缩(不提供解压)。
2939 |
2940 | 压缩的速度比较慢,但是可以得到更高的压缩率。
2941 |
2942 | === 12.2.2 zip ===
2943 |
2944 | [https://en.wikipedia.org/wiki/Zip_%28file_format%29 格式说明]
2945 |
2946 | libzip
2947 |
2948 | Home:[http://www.nih.at/libzip/]
2949 |
2950 | Links:[https://en.wikipedia.org/wiki/Libzip Wikipedia]
2951 |
2952 | 用 C 语言开发的库,基于 zlib 库。
2953 |
2954 | Poco::Zip
2955 |
2956 | Docs:[http://pocoproject.org/docs/Poco.Zip.html]
2957 |
2958 | POCO 前面已经介绍过。它提供了若干封装类,用于 zip 格式的压缩和解压。
2959 |
2960 | === 12.2.3 bzip2(bz2) ===
2961 |
2962 | [https://en.wikipedia.org/wiki/Bzip2 格式说明]
2963 |
2964 | libbzip2
2965 |
2966 | Home:[http://bzip.org/]
2967 |
2968 | 这是 bzip2 官方提供的库,C 语言实现。
2969 |
2970 | === 12.2.4 gzip(gz) ===
2971 |
2972 | zlib
2973 |
2974 | Home:[http://zlib.net/]
2975 |
2976 | Links:[https://en.wikipedia.org/wiki/Zlib Wikipedia] [https://zh.wikipedia.org/wiki/Zlib 维基百科]
2977 |
2978 | C 语言实现,诞生于1995年,被大量的开源项目使用(OpenSSL、OpenSSH、Apache、PostgreSQL、Git、libpng......)。
2979 |
2980 | === 12.2.5 tar ===
2981 |
2982 | libtar
2983 |
2984 | Home:[http://www.feep.net/libtar/]
2985 |
2986 | 基于 C 语言开发,可以对 tar 格式添加内容或读取内容。
2987 |
2988 | === 12.2.6 rar ===
2989 |
2990 | unrarlib
2991 |
2992 | Home:[http://www.unrarlib.org/]
2993 |
2994 | 该项目的开发已经停止。只支持对 RAR2 格式的解压缩。
2995 |
2996 | === 12.2.7 snappy ===
2997 |
2998 | snappy
2999 |
3000 | Home:[https://google.github.io/snappy/]
3001 |
3002 | 由 Google 开发的压缩格式,特点是非常快(不论是压缩还是解压);但是压缩率不如 gzip。
3003 |
3004 | 起先被用于 Google 内部的 BigTable,如今被用于多种 NoSQL 数据库(比如:Cassandra、Hadoop、LevelDB、MongoDB、RocksDB...)
3005 |
3006 | 支持多种语言的绑定(C#、Common Lisp、Erlang、Go、Haskell、Lua、Java、Node.js、Perl、PHP、Python、R、Ruby、Smalltalk)
3007 |
3008 | === 12.2.8 Brotli ===
3009 |
3010 | Brotli
3011 |
3012 | Home:[https://github.com/google/brotli]
3013 |
3014 | Links:[https://en.wikipedia.org/wiki/Brotli Wikipedia]
3015 |
3016 | 由 Google 开发的压缩格式,压缩率很高(据说高于 LZMA 和 bz2)。
3017 |
3018 | 该算法很新,是2015年9月才发布的。
3019 |
3020 | === 12.2.9 LZFSE ===
3021 |
3022 | LZFSE
3023 |
3024 | Home:[https://github.com/lzfse/lzfse]
3025 |
3026 | Links:[https://zh.wikipedia.org/wiki/LZFSE 维基百科]
3027 |
3028 | 由苹果开发的压缩格式。苹果称它的压缩率与“ZLib level 5”相似,但速度快2至3倍。
3029 |
3030 | 该算法是前不久(2016年7月)才开源出来的。
3031 |
3032 | == 12.3 标记语言 ==
3033 |
3034 | === 12.3.1 XML ===
3035 |
3036 | Expat
3037 |
3038 | Home:[http://www.libexpat.org/]
3039 |
3040 | Links:[https://en.wikipedia.org/wiki/Expat_(library) Wikipedia]
3041 |
3042 | 基于 C 语言实现,诞生于1998年。很多知名的开源项目(Apache Server、Firefox、Python、PHP、Perl)用到它。
3043 |
3044 | libxml2
3045 |
3046 | Home:[http://xmlsoft.org/]
3047 |
3048 | Links:[https://en.wikipedia.org/wiki/Libxml2 Wikipedia]
3049 |
3050 | 基于 C 语言实现,诞生于1999年。提供了多种语言(C++、Python、Ruby、Common Lisp、PHP、Perl)的 API 绑定。
3051 |
3052 | wxWidgets
3053 |
3054 | Docs:[http://docs.wxwidgets.org/trunk/group__group__class__xml.html]
3055 |
3056 | wxWidgets 前面已经介绍过。它提供了 XML 的封装类,其内部是基于 Expat 进行解析。
3057 |
3058 | POCO::XML
3059 |
3060 | Docs:[http://pocoproject.org/docs/package-XML.XML.html]
3061 |
3062 | POCO 前面已经介绍过。它提供了 XML 的封装类。
3063 |
3064 | libxml++
3065 |
3066 | Home:[http://libxmlplusplus.sourceforge.net/]
3067 |
3068 | 如其名,它是针对前面提到的 libxml2 的 C++ 封装。
3069 |
3070 | === 12.3.2 HTML ===
3071 |
3072 | htmlcxx
3073 |
3074 | Home:[http://htmlcxx.sourceforge.net/]
3075 |
3076 | 如其名,是基于 C++ 开发的。支持 HTML 和 CSS 的解析。
3077 |
3078 | == 12.4 PDF ==
3079 |
3080 | PoDoFo
3081 |
3082 | Home:[http://podofo.sourceforge.net/]
3083 |
3084 | 基于 C++ 开发的跨平台库,名称取自“Portable Document Format”每个单词的头两个字母 :)
3085 |
3086 | 它既支持 PDF 文件的生成,也支持 PDF 内容的提取。它同时还提供[http://podofo.sourceforge.net/tools.html 一堆命令行的小工具],用来操作 PDF 文件。
3087 |
3088 | Poppler
3089 |
3090 | Home:[https://poppler.freedesktop.org/]
3091 |
3092 | Links:[https://en.wikipedia.org/wiki/Poppler_%28software%29 Wikipedia]
3093 |
3094 | 派生自 Xpdf 3.0 的开源库,用于渲染 PDF 的内容。很多开源的 PDF 阅读软件用到它。
3095 |
3096 | 在开源界,它第一个【完整】实现了 ISO 32000-1(PDF 的 ISO 标准)。
3097 |
3098 | 它内置了若干命令行工具(poppler-utils),可以用来进行 PDF 的内容提取和格式转换。
3099 |
3100 | LibHaru
3101 |
3102 | Home:[http://libharu.org/]
3103 |
3104 | Links:[https://en.wikipedia.org/wiki/LibHaru Wikipedia]
3105 |
3106 | 它是基于 C 语言开发的跨平台库,可以用来生成 PDF 文件格式。
3107 |
3108 | 代码示例
3109 |
3110 | #include
3111 |
3112 | // 创建文档对象
3113 | HPDF_Doc doc = HPDF_New(error_handler, NULL);
3114 | if(!doc)
3115 | {
3116 | printf("ERROR: cannot create pdf object.\n");
3117 | return 1;
3118 | }
3119 |
3120 | // 设置文档属性
3121 | HPDF_SetCompressionMode(doc, HPDF_COMP_ALL);
3122 | HPDF_SetPageMode(doc, HPDF_PAGE_MODE_USE_OUTLINE);
3123 | HPDF_SetPassword(doc, "owner pwd", "user pwd");
3124 |
3125 | // 添加一页
3126 | HPDF_Page page_1 = HPDF_AddPage(doc);
3127 | // 设置页属性
3128 | HPDF_Page_SetSize(page_1, HPDF_PAGE_SIZE_B5, HPDF_PAGE_LANDSCAPE);
3129 |
3130 | // 保存到文件
3131 | HPDF_SaveToFile(doc, "test.pdf");
3132 |
3133 | // 结束
3134 | HPDF_Free(doc);
3135 |
3136 |
3137 | == 12.5 MS Office 文档 ==
3138 |
3139 | wvWare
3140 |
3141 | Home:[http://wvware.sourceforge.net/]
3142 |
3143 | 它能够读取 Word 文档的内容,支持的 Word 版本是(2000、97、95、6)。
3144 |
3145 | AbiWord 和 KWord 用到它。
3146 |
3147 | == 12.6 RTF ==
3148 |
3149 | LibRTF
3150 |
3151 | Home:[http://sourceforge.net/projects/librtf/]
3152 |
3153 | C 语言实现的库,可以解析 RTF 文件格式。
3154 |
3155 | == 12.7 CHM ==
3156 |
3157 | CHMLIB
3158 |
3159 | Home:[http://www.jedrea.com/chmlib/]
3160 |
3161 | 这是一个轻量级的库,基于 C 语言开发,可以用来提取 CHM 格式文件的内容。
3162 |
3163 | 它提供了多种编程语言(C++、Python、Perl、Common Lisp)的 API 绑定。
3164 |
3165 | libCHMxx
3166 |
3167 | Home:[http://www.mare.ee/indrek/libchmxx/]
3168 |
3169 | 它就是基于 CHMLIB 的 C++ 封装库。
3170 |
3171 | ----
3172 |
3173 | = 13 图像 =
3174 |
3175 | == 13.1 图像处理 ==
3176 |
3177 | ImageMagick
3178 |
3179 | Home:[http://imagemagick.org/]
3180 |
3181 | Links:[https://en.wikipedia.org/wiki/ImageMagick Wikipedia] [https://zh.wikipedia.org/wiki/ImageMagick 维基百科]
3182 |
3183 | ImageMagick 可说是最强大的开源图片处理工具集,采用 C 语言编写。诞生于1990年,其开发至今依然非常活跃。支持非常多的操作系统平台。
3184 |
3185 | 它提供许多编程语言的 API,对于 C++ 是 [http://www.imagemagick.org/Magick++/ Magick++],对于 C 是 [http://imagemagick.org/script/magick-wand.php MagickWand]
3186 |
3187 | Boost.GIL(Generic Image Library)
3188 |
3189 | Docs:[http://boost.org/libs/gil]
3190 |
3191 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,实现了图像处理功能。
3192 |
3193 | 代码示例——调整图像尺寸
3194 |
3195 | #include
3196 | #include
3197 | #include
3198 | #include
3199 | #include
3200 |
3201 | using namespace boost::gil;
3202 |
3203 | rgb8_image_t img;
3204 | jpeg_read_image("input.jpg", img);
3205 |
3206 | // Scale the image to 100x100 pixels using bilinear resampling
3207 | rgb8_image_t square(100, 100);
3208 | resize_view(const_view(img), view(square), bilinear_sampler());
3209 | jpeg_write_view("output.jpg", const_view(square));
3210 |
3211 |
3212 | Dlib
3213 |
3214 | Docs:[http://dlib.net/imaging.html]
3215 |
3216 | Dlib 前面已经介绍过。它提供了常见的图像处理功能(旋转、剪切、拉伸、过滤)。
3217 |
3218 | == 13.2 图像格式转换 ==
3219 |
3220 | ImageMagick
3221 |
3222 | ImageMagick 前面已经介绍过。它支持非常多的图片格式([http://imagemagick.org/script/formats.php 清单]),基本上你听说过的,它都支持。甚至包括 Postscript 和 PDF。
3223 |
3224 | 在支持的格式中,它可以实现其中几十种格式的相互转换。
3225 |
3226 | == 13.3 图像渲染 ==
3227 |
3228 | Cairo
3229 |
3230 | Home:[http://cairographics.org/]
3231 |
3232 | Links:[https://en.wikipedia.org/wiki/Cairo_%28graphics%29 Wikipedia] [https://zh.wikipedia.org/wiki/Cairo_(%E7%B9%AA%E5%9C%96) 维基百科]
3233 |
3234 | 它提供了矢量图像的渲染功能。支持多种后端输出(Win32 GDI、OpenGL、Xlib、XCB、PDF、PNG、SVG ......)。
3235 |
3236 | 基于 C 语言开发,提供多种语言绑定(C++、Java、C#、Python、Ruby、Perl、Scheme、Smalltalk)。
3237 |
3238 | cairomm
3239 |
3240 | Home:[http://cairographics.org/cairomm/]
3241 |
3242 | 这是针对 Cairo 的 C++ 封装库。
3243 |
3244 | Skia
3245 |
3246 | Home:[https://github.com/google/skia]
3247 |
3248 | Links:[https://en.wikipedia.org/wiki/Skia_Graphics_Engine Wikipedia] [https://zh.wikipedia.org/wiki/Skia_Graphics_Library 维基百科]
3249 |
3250 | 它是 Google 基于 C++ 开发的图像渲染库。支持多种后端输出(rasterization、OpenGL、PDF、SVG、SWF ......)。
3251 |
3252 | 原先由 Skia 公司开发,后来该公司被 Google 收购。被用于 Android、Chrome、Chrome OS、Firefox 等知名开源项目。
3253 |
3254 | PBRT(Physically Based Rendering Toolkit)
3255 |
3256 | Home:[http://pbrt.org/]
3257 |
3258 | 基于光线追踪的物理渲染系统,采用 C++ 开发。
3259 |
3260 | == 13.4 计算机视觉 ==
3261 |
3262 | OpenCV
3263 |
3264 | Home:[http://opencv.org/]
3265 |
3266 | Links:[https://en.wikipedia.org/wiki/OpenCV Wikipedia] [https://zh.wikipedia.org/wiki/OpenCV 维基百科]
3267 |
3268 | 它是一个跨平台的计算机视觉库,由 Intel 发起并参与开发。开发语言是 C 和 C++。
3269 |
3270 | 提供其它编程语言(Python、Java、MATLAB/OCTAVE ...)的 API 绑定。
3271 |
3272 | ----
3273 |
3274 | = 14 多媒体 =
3275 |
3276 | == 14.1 多媒体框架 ==
3277 |
3278 | FFmpeg
3279 |
3280 | Home:[http://ffmpeg.org/]
3281 |
3282 | Links:[https://en.wikipedia.org/wiki/FFmpeg Wikipedia] [https://zh.wikipedia.org/wiki/FFmpeg 维基百科]
3283 |
3284 | 名气非常大的开源多媒体框架,基于 C 和汇编开发,支持多种操作系统。
3285 |
3286 | 另外,该开源项目还提供了若干命令行工具,包含了一些辅助功能。
3287 |
3288 | * ffmpeg 格式转换工具
3289 |
3290 | * ffplay 简化版的播放器
3291 |
3292 | * ffserver 流媒体服务器
3293 |
3294 | * ffprobe 显示多媒体文件信息
3295 |
3296 | 几个知名的开源播放器(VLC、MPC-HC、xine)用到它,Google Chrome 也用到它。
3297 |
3298 | Libav
3299 |
3300 | Home:[http://libav.org/]
3301 |
3302 | Links:[https://en.wikipedia.org/wiki/Libav Wikipedia]
3303 |
3304 | 它是2011年从 FFmpeg 派生出来的。基于 C 语言开发,支持多种操作系统。
3305 |
3306 | == 14.2 视频库 ==
3307 |
3308 | libavcodec
3309 |
3310 | Home:[http://ffmpeg.org/]
3311 |
3312 | 它来自于 FFmpeg 社区,基于 C 语言实现,提供了多种视频格式和音频格式的编码/解码功能。
3313 |
3314 | 由于 Libav 从 FFmpeg 分裂出来,Libav 下也带有一个同名的库。
3315 |
3316 | == 14.3 音频库 ==
3317 |
3318 | PortMedia & PortAudio
3319 |
3320 | Home:[http://www.portaudio.com/]
3321 |
3322 | Links:[https://en.wikipedia.org/wiki/PortAudio Wikipedia]
3323 |
3324 | PortAudio 是 PortMedia 的组成部分,提供了音频的播放和录制功能。支持多种底层 API(ALSA、DirectSound、WASAPI、ASIO...)
3325 |
3326 | OpenAL
3327 |
3328 | Home:[http://www.openal.org/]
3329 |
3330 | Links:[https://en.wikipedia.org/wiki/OpenAL Wikipedia] [https://zh.wikipedia.org/wiki/OpenAL 维基百科]
3331 |
3332 | C 语言开发的 3D 音效库,跨平台。最初由 Loki Software 开发。Loki 倒闭以后,这个项目由开源社区继续维护。
3333 |
3334 | ----
3335 |
3336 | = 15 游戏 =
3337 |
3338 | == 15.1 综合性的游戏引擎 ==
3339 |
3340 | id Tech 系列
3341 |
3342 | Links:[https://en.wikipedia.org/wiki/Id_Tech Wikipedia]
3343 |
3344 | 这个系列来自于大名鼎鼎的 [https://en.wikipedia.org/wiki/Id_Software id Software 公司],由同样大名鼎鼎约翰·卡马克打造。
3345 |
3346 | 第一代诞生于1993年,是 DOS 时代的经典。
3347 |
3348 | 原先基于 C 和 汇编开发,从 id Tech 4 开始改用 C++ 开发。
3349 |
3350 | * id Tech 1——俗称:Doom 引擎
3351 |
3352 | * id Tech 2(Quake)——俗称:Quake 引擎
3353 |
3354 | * id Tech 2(Quake II)——俗称:Quake II 引擎
3355 |
3356 | * id Tech 3——俗称:Quake III 引擎
3357 |
3358 | * id Tech 4——俗称:Doom 3 引擎
3359 |
3360 | Crystal Space
3361 |
3362 | Home:[http://www.crystalspace3d.org/]
3363 |
3364 | Links:[https://en.wikipedia.org/wiki/Crystal_Space Wikipedia]
3365 |
3366 | 以 C++ 编写,功能包括:2D 和 3D 渲染、音效、AI... 它的物理引擎基于 ODE 和 Bullet
3367 |
3368 | Blender Game Engine
3369 |
3370 | Home:[http://www.blender.org/]
3371 |
3372 | Links:[https://en.wikipedia.org/wiki/Game_Blender Wikipedia] [https://zh.wikipedia.org/wiki/Game_Blender 维基百科]
3373 |
3374 | 它是 [https://en.wikipedia.org/wiki/Blender_%28software%29 Blender] 的组成部分,以 C++ 编写,使用 Python 脚本扩展。功能包括:3D 渲染、碰撞检测、角色编辑器、音效、网络通讯、AI、...
3375 |
3376 | Panda3D
3377 |
3378 | Home:[http://www.panda3d.org/]
3379 |
3380 | Links:[https://en.wikipedia.org/wiki/Panda3D Wikipedia]
3381 |
3382 | 以 C++ 编写,用 Python 脚本扩展。虽然它的名字有“3D”,但它不仅仅是 3D 引擎,还包括了其它功能(碰撞检测、音效、关卡编辑器...)。
3383 |
3384 | == 15.2 3D 渲染引擎 ==
3385 |
3386 | OGRE
3387 |
3388 | Home:[http://www.ogre3d.org/]
3389 |
3390 | Links:[https://en.wikipedia.org/wiki/OGRE Wikipedia] [https://zh.wikipedia.org/wiki/OGRE 维基百科]
3391 |
3392 | 著名的 3D 渲染引擎,C++ 开发,诞生于2005年。支持很多操作系统(包括两大手机操作系统)。很多商业游戏用到它。
3393 |
3394 | 支持其它编程语言(Python、Ruby、Perl)的 API 绑定。支持 JVM 和 dotNet 平台。
3395 |
3396 | Mesa 3D
3397 |
3398 | Home:[http://mesa3d.org/]
3399 |
3400 | Links:[https://en.wikipedia.org/wiki/Mesa_%28computer_graphics%29 Wikipedia] [https://zh.wikipedia.org/wiki/Mesa_3D 维基百科]
3401 |
3402 | 使用 C 语言开发,它是针对 OpenGL 规范的【纯软件】实现(大部分 OpenGL 的实现都用到了显卡硬件)。
3403 |
3404 | == 15.3 物理引擎 ==
3405 |
3406 | Bullet
3407 |
3408 | Home:[http://www.bulletphysics.org/]
3409 |
3410 | Links:[https://en.wikipedia.org/wiki/Bullet_%28software%29 Wikipedia] [https://zh.wikipedia.org/wiki/Bullet 维基百科]
3411 |
3412 | 采用 C 和 C++ 开发。电影《2012》用到它,游戏“侠盗猎车手”、“荒野大镖客”用到它。
3413 |
3414 | Box2D
3415 |
3416 | Home:[http://www.box2d.org/]
3417 |
3418 | Links:[https://en.wikipedia.org/wiki/Box2D Wikipedia] [https://zh.wikipedia.org/wiki/Box2D 维基百科]
3419 |
3420 | 基于 C++ 开发的2维物理引擎。“愤怒的小鸟”用到它。
3421 |
3422 | ODE(Open Dynamics Engine)
3423 |
3424 | Home:[http://www.ode.org/]
3425 |
3426 | Links:[https://en.wikipedia.org/wiki/Open_Dynamics_Engine Wikipedia] [https://zh.wikipedia.org/wiki/Open_Dynamics_Engine 维基百科]
3427 |
3428 | 诞生于2001年,采用 C 和 C++ 开发。
3429 |
3430 | Newton Game Dynamics
3431 |
3432 | Home:[http://www.newtondynamics.com/]
3433 |
3434 | Links:[https://en.wikipedia.org/wiki/Newton_Game_Dynamics Wikipedia]
3435 |
3436 | 基于 C++ 开发。
3437 |
3438 | ----
3439 |
3440 | = 16 数值运算 & 科学计算 =
3441 |
3442 | == 16.1 综合性的库 ==
3443 |
3444 | GSL(GNU Scientific Library)
3445 |
3446 | Home:[https://www.gnu.org/software/gsl/]
3447 |
3448 | Links:[https://en.wikipedia.org/wiki/GNU_Scientific_Library Wikipedia]
3449 |
3450 | 由 GNU 官方提供,包括:复数、多项式、矩阵、线性代数、特征向量、快速傅里叶变换、统计、模拟退火......
3451 |
3452 | 代码示例——贝塞尔函数
3453 |
3454 | #include
3455 | #include
3456 |
3457 | double x = 5.0;
3458 | double y = gsl_sf_bessel_J0(x);
3459 | printf("J0(%g) = %.18e\n", x, y);
3460 |
3461 |
3462 | == 16.2 有理数 ==
3463 |
3464 | Boost.Rational
3465 |
3466 | Docs:[http://boost.org/libs/rational]
3467 |
3468 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“有理数”的功能。
3469 |
3470 | == 16.3 高精度数值运算 ==
3471 |
3472 | GMP(GNU Multiple Precision)
3473 |
3474 | Home:[https://gmplib.org/]
3475 |
3476 | Links:[https://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library Wikipedia] [https://zh.wikipedia.org/wiki/GNU%E5%A4%9A%E9%87%8D%E7%B2%BE%E5%BA%A6%E8%BF%90%E7%AE%97%E5%BA%93 维基百科]
3477 |
3478 | 基于 C 语言的高精度数值运算库,诞生于1991年,非常老牌。
3479 |
3480 | 代码示例——大整数相乘
3481 |
3482 | #include
3483 | #include
3484 |
3485 | mpz_t x,y,result;
3486 |
3487 | mpz_init_set_str(x, "7612058254738945", 10);
3488 | mpz_init_set_str(y, "9263591128439081", 10);
3489 | mpz_init(result);
3490 |
3491 | mpz_mul(result, x, y);
3492 | gmp_printf("%Zd\n", result);
3493 |
3494 | /* free used memory */
3495 | mpz_clear(x);
3496 | mpz_clear(y);
3497 | mpz_clear(result);
3498 |
3499 |
3500 | Boost.Multiprecision
3501 |
3502 | Docs:[http://boost.org/libs/multiprecision]
3503 |
3504 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,实现了高精度数值运算。它还提供了针对 GMP 的数据类型的封装。
3505 |
3506 | == 16.4 矩阵 ==
3507 |
3508 | Boost.uBLAS.Matrix
3509 |
3510 | Docs:[http://boost.org/libs/numeric/ublas/doc/matrix.html]
3511 |
3512 | Boost 前面已经介绍过。这是 Boost 提供的矩阵模板类。
3513 |
3514 | 代码示例
3515 |
3516 | #include
3517 | #include
3518 |
3519 | using namespace boost::numeric::ublas;
3520 |
3521 | matrix m(3, 3);
3522 | for(unsigned i=0; i
3528 |
3529 | Dlib
3530 |
3531 | Docs:[http://dlib.net/linear_algebra.html#matrix]
3532 |
3533 | Dlib 前面已经介绍过。它提供了一个矩阵类。
3534 |
3535 | == 16.5 线性代数 ==
3536 |
3537 | Boost.uBLAS
3538 |
3539 | Docs:[http://boost.org/libs/numeric/ublas]
3540 |
3541 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,实现了 BLAS 的1、2、3级。
3542 |
3543 | 代码示例——计算矩阵与矢量的乘积
3544 |
3545 | #include
3546 | #include
3547 | #include
3548 | #include
3549 |
3550 | using namespace std;
3551 | using namespace boost::numeric::ublas;
3552 |
3553 | vector v(2);
3554 | v(0) = 1; v(1) = 2;
3555 |
3556 | matrix m(2,2);
3557 | m(0,0) = 0; m(0,1) = 1;
3558 | m(1,0) = 2; m(1,1) = 3;
3559 |
3560 | vector v2 = prod(m, v);
3561 | cout << v2 << endl;
3562 |
3563 |
3564 | Blitz++
3565 |
3566 | Home:[http://blitz.sourceforge.net/]
3567 |
3568 | Links:[https://en.wikipedia.org/wiki/Blitz%2B%2B Wikipedia]
3569 |
3570 | 它是基于 C++ 实现的。其特色是:采用“模板元编程”的技术进行编译时计算,从而优化了性能。
3571 |
3572 | Armadillo
3573 |
3574 | Home:[http://arma.sourceforge.net/]
3575 |
3576 | Links:[https://en.wikipedia.org/wiki/Armadillo_%28C%2B%2B_library%29 Wikipedia]
3577 |
3578 | 类似 Blitz++,Armadillo 也用了“模板元编程”的技术。
3579 |
3580 | 代码示例
3581 |
3582 | #include
3583 | #include
3584 |
3585 | using namespace std;
3586 | using namespace arma;
3587 |
3588 | vec v;
3589 | v << 2.0 << 5.0 << 2.0;
3590 |
3591 | // endr represents the end of a row in a matrix
3592 | mat m;
3593 | m << 1.0 << 2.0 << endr
3594 | << 2.0 << 3.0 << endr
3595 | << 1.0 << 3.0 << endr;
3596 |
3597 | cout << "Least squares solution:" << endl << solve(m,v) << endl;
3598 |
3599 |
3600 | Dlib
3601 |
3602 | Docs:[http://dlib.net/linear_algebra.html]
3603 |
3604 | Dlib 前面已经介绍过。它提供了线性代数相关的封装类。
3605 |
3606 | ----
3607 |
3608 | = 17 跨语言编程 =
3609 |
3610 | == 17.1 整合多种语言的库 ==
3611 |
3612 | SWIG
3613 |
3614 | Home:[http://swig.org/]
3615 |
3616 | Links:[https://en.wikipedia.org/wiki/SWIG Wikipedia]
3617 |
3618 | 这是一个很老牌的、有名气的工具,它可以把多种语言(Java、Python、C#、Ruby、PHP、Perl、Lua、Go ......)整合到 C/C++ 中。
3619 |
3620 | 整合之后,你的 C/C++ 程序就可以享受到其它这些语言的特性啦,非常爽!
3621 |
3622 | == 17.2 整合单一语言的库 ==
3623 |
3624 | === 17.2.1 整合 Python 语言 ===
3625 |
3626 | Boost.Python
3627 |
3628 | Docs:[http://boost.org/libs/python]
3629 |
3630 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,实现了 C++ 代码和 Python 代码的互操作。
3631 |
3632 | 代码示例——Hello world
3633 |
3634 | // 这是一个标准的 C 函数
3635 | const char* greet()
3636 | {
3637 | return "Hello, world";
3638 | }
3639 |
3640 | // 使用如下代码对上述函数进行包装
3641 | #include
3642 | BOOST_PYTHON_MODULE(hello_ext)
3643 | {
3644 | using namespace boost::python;
3645 | def("greet", greet);
3646 | }
3647 |
3648 | // 以下是调用该模块的 Python 代码
3649 | // import hello_ext
3650 | // print(hello_ext.greet())
3651 |
3652 |
3653 | Cython
3654 |
3655 | Home:[http://cython.org/]
3656 |
3657 | Links:[https://en.wikipedia.org/wiki/Cython Wikipedia]
3658 |
3659 | Cython 提供了一种机制(编译器)编译 Python 代码为【原生代码】。编译后的原生代码是个 Python 的 module(扩展名是 pyd 或 so),可以在常规的 Python 环境中用 import 语句加载。如此一来,既得到了类似 C/C++ 的高性能,又保留了 Python 语法的简介性。
3660 |
3661 | 另外,它也提供了把 C/C++ 代码编译为 Python 模块的机制。
3662 |
3663 | === 17.2.2 整合 JavaScript 语言 ===
3664 |
3665 | V8
3666 |
3667 | Home:[https://github.com/v8/v8]
3668 |
3669 | Links:[https://en.wikipedia.org/wiki/Chrome_V8 Wikipedia]
3670 |
3671 | 这就是大名鼎鼎的 V8 引擎,Google 公司开发,C++ 编写,被用于 Chrome 浏览器。
3672 |
3673 | 既然用于 Chrome 浏览器,显然【完整地】支持了 JS 语言的规范(ECMA-262)。
3674 |
3675 | 它既可以独立运行,也可以嵌入到 C++ 程序中。
3676 |
3677 | 代码示例——Hello world
3678 |
3679 | #include
3680 | #include
3681 | #include
3682 | #include
3683 | #include
3684 |
3685 | int main(int argc, char* argv[])
3686 | {
3687 | // Initialize V8.
3688 | v8::V8::InitializeICUDefaultLocation(argv[0]);
3689 | v8::V8::InitializeExternalStartupData(argv[0]);
3690 | std::unique_ptr platform = v8::platform::NewDefaultPlatform();
3691 | v8::V8::InitializePlatform(platform.get());
3692 | v8::V8::Initialize();
3693 |
3694 | // Create a new Isolate and make it the current one.
3695 | v8::Isolate::CreateParams create_params;
3696 | create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
3697 | v8::Isolate* isolate = v8::Isolate::New(create_params);
3698 |
3699 | {
3700 | v8::Isolate::Scope isolate_scope(isolate);
3701 | // Create a stack-allocated handle scope.
3702 | v8::HandleScope handle_scope(isolate);
3703 | // Create a new context.
3704 | v8::Local context = v8::Context::New(isolate);
3705 | // Enter the context for compiling and running the hello world script.
3706 | v8::Context::Scope context_scope(context);
3707 | // Create a string containing the JavaScript source code.
3708 | v8::Local source =
3709 | v8::String::NewFromUtf8(isolate, "'Hello World!'",
3710 | v8::NewStringType::kNormal).ToLocalChecked();
3711 | // Compile the source code.
3712 | v8::Local script = v8::Script::Compile(context, source).ToLocalChecked();
3713 | // Run the script to get the result.
3714 | v8::Local result = script->Run(context).ToLocalChecked();
3715 | // Convert the result to an UTF8 string and print it.
3716 | v8::String::Utf8Value utf8(isolate, result);
3717 | printf("%s\n", *utf8);
3718 | }
3719 |
3720 | // Dispose the isolate and tear down V8.
3721 | isolate->Dispose();
3722 | v8::V8::Dispose();
3723 | v8::V8::ShutdownPlatform();
3724 | delete create_params.array_buffer_allocator;
3725 | return 0;
3726 | }
3727 |
3728 |
3729 | nbind
3730 |
3731 | Home:[https://github.com/charto/nbind]
3732 |
3733 | 把 C++ 代码编译为 JS 的 package。编译方式支持“原生二进制”或“asm.js”。
3734 |
3735 | 编译需要依赖 Node.js,运行环境支持 Node.js 或浏览器。
3736 |
3737 | 代码示例——C++ 代码
3738 |
3739 | #include
3740 | #include
3741 |
3742 | struct Greeter
3743 | {
3744 | static void sayHello(std::string name)
3745 | {
3746 | std::cout << "Hello, " << name << "\n";
3747 | }
3748 | };
3749 |
3750 | // 建立绑定
3751 | #include
3752 |
3753 | NBIND_CLASS(Greeter)
3754 | {
3755 | method(sayHello);
3756 | }
3757 |
3758 |
3759 | 代码示例——node.js 环境调用代码
3760 |
3761 | var nbind = require("nbind");
3762 | var lib = nbind.init().lib;
3763 | lib.Greeter.sayHello("you");
3764 |
3765 |
3766 | 代码示例——浏览器环境调用代码
3767 |
3768 |
3769 |
3778 |
3779 |
3780 | ----
3781 |
3782 | = 18 (其它) =
3783 |
3784 | 一些不方便归类的,暂时放到这里。
3785 |
3786 | == 18.1 词法分析 & 语法分析 ==
3787 |
3788 | Boost.Spirit
3789 |
3790 | Docs:[http://boost.org/libs/spirit]
3791 |
3792 | Boost 前面已经介绍过。这是 Boost 的其中一个子库,提供了“基于 EBNF 的解析器框架”。
3793 |
3794 |
--------------------------------------------------------------------------------
/libs/python.wiki:
--------------------------------------------------------------------------------
1 | Python 开源库及示例代码
2 |
3 | = =
4 |
5 | = 说明 =
6 |
7 | 本页面汇总俺收集的各种 Python 代码库,不定期更新。
8 |
9 | 本页面列出的各种 Python 库/模块,如果注明了官网的网址,说明这个库是第三方的;否则就是 Python 语言内置的标准库。
10 |
11 | 如果你发现本页面的开源库有错漏之处,非常欢迎给俺提供反馈——有 GitHub 帐号的同学,可以[https://github.com/programthink/opensource/issues 给俺发 issue];没帐号的同学,可以去[https://program-think.blogspot.com/ 俺博客]留言。
12 |
13 | ----
14 |
15 | = 1 算法 =
16 |
17 | == 1.1 字符串 ==
18 |
19 | === 1.1.1 正则表达式 ===
20 |
21 | re
22 |
23 | 【标准库】
24 |
25 | 提供基于正则的匹配和替换。
26 |
27 | === 1.1.2 字符集 ===
28 |
29 | chardet
30 |
31 | Home:[https://github.com/erikrose/chardet]
32 |
33 | chardet 可以猜测任意一段文本的字符集编码。对于编码类型未知的文本,它会很有用。
34 |
35 | chardet 既可以作为模块来使用,也可以作为命令行工具来使用。
36 |
37 | 代码示例
38 |
39 | import chardet
40 | print(chardet.detect(bytes))
41 |
42 |
43 | === 1.1.3 (其它) ===
44 |
45 | StringIO & cStringIO
46 |
47 | 【标准库】
48 |
49 | 以读写文件的方式来操作字符串(有点类似于内存文件)。
50 |
51 | cStringIO 是 C 语言实现的,性能更高;而 StringIO 是 Python 实现的,提供 Unicode 兼容性。
52 |
53 | difflib
54 |
55 | 【标准库】
56 |
57 | 可以对两个字符串进行“按行”比较,其功能类似于命令行的 diff。
58 |
59 | 另外还支持“最佳匹配”功能——对给定的字符串 s 和字符串列表 l,在 l 里面找到最接近 s 的字符串。
60 |
61 | == 1.2 编码 & 解码 ==
62 |
63 | === 1.2.1 base64 ===
64 |
65 | [https://en.wikipedia.org/wiki/Base64 Base64] 是一组编码算法的总称。用于把二进制数据编码为文本。
66 |
67 | base64
68 |
69 | 【标准库】
70 |
71 | 提供 Base16、Base32、Base64 格式的编码和解码。
72 |
73 | === 1.2.2 UUencode ===
74 |
75 | [https://en.wikipedia.org/wiki/Uuencode UUencode] 出现于早期的 Unix 系统。用于把二进制编码为文本,以便通过邮件系统发送。
76 |
77 | uu
78 |
79 | 【标准库】
80 |
81 | 提供 UUencode 格式的编码和解码。
82 |
83 | === 1.2.3 BinHex ===
84 |
85 | [https://en.wikipedia.org/wiki/BinHex BinHex] 起先用于 Mac OS 系统,类似于 UUencode。
86 |
87 | binhex
88 |
89 | 【标准库】
90 |
91 | 提供 BinHex 格式的编码和解码。
92 |
93 | == 1.3 数学类 ==
94 |
95 | math
96 |
97 | 【标准库】
98 |
99 | 顾名思义,这个标准库封装了常用的数学函数(开方、指数、对数、三角函数......)。
100 |
101 | random
102 |
103 | 【标准库】
104 |
105 | 顾名思义,这个标准库是用来进行随机数生成滴。
106 |
107 | 代码示例——生成 0-100 的随机数
108 |
109 | import random
110 | random.seed()
111 | random.randint(0, 100)
112 |
113 |
114 | fractions
115 |
116 | 【标准库】
117 |
118 | 封装了跟有理数(分数)相关的运算
119 |
120 | == 1.4 容器 ==
121 |
122 | pygtrie
123 |
124 | Home:[https://github.com/google/pytrie]
125 |
126 | 这是 Google 实现的 [https://zh.wikipedia.org/wiki/Trie trie](前缀树/字典树)封装库。
127 |
128 | ----
129 |
130 | = 2 跨语言编程 =
131 |
132 | Python 可以很容易地跟其它编程语言整合。整合之后,就可以在 Python 代码中使用其它编程语言的函数、模块、库,非常爽!
133 | == 2.1 整合 C & C++ ==
134 |
135 | ctypes
136 |
137 | ctypes 在 Python 2.5 版本加入到标准库中。
138 |
139 | 通过它,你可以很方便地调用 C/C++ 动态库导出的函数,可以在 Python 中使用各种 C/C++ 的数据类型(包括“指针”和“引用”)。
140 |
141 | 代码示例——调用 Linux/Unix 系统的标准 C 函数,获取当前时间
142 |
143 | from ctypes import *
144 |
145 | libc = CDLL("libc.so.6")
146 | time = libc.time(None)
147 |
148 |
149 | 代码示例——调用 Windows 系统的 API,弹出消息提示框
150 |
151 | from ctypes import c_int, WINFUNCTYPE, windll
152 | from ctypes.wintypes import HWND, LPCSTR, UINT
153 |
154 | prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT)
155 | paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", None), (1, "flags", 0)
156 | MessageBox = prototype(("MessageBoxA", windll.user32), paramflags)
157 | MessageBox(text="Hello, world", flags=2)
158 |
159 |
160 | SWIG(Simplified Wrapper and Interface Generator)
161 |
162 | Home:[http://swig.org/]
163 |
164 | Links:[https://en.wikipedia.org/wiki/SWIG Wikipedia]
165 |
166 | 这是一个很老牌的、有名气的工具,它可以把多种语言(Java、Python、C#、Ruby、PHP、Perl、Lua、Go ...)整合到 C/C++ 中。
167 |
168 | Cython
169 |
170 | Home:[http://cython.org/]
171 |
172 | 这个工具可以让你用 Python 的语法写扩展模块的代码,然后它帮你把 Python 代码编译为本地动态库(机器码)。
173 |
174 | 用它编译出来的扩展模块,其性能跟 C/C++ 编写的扩展模块相当。
175 |
176 | == 2.2 整合 JVM 平台 ==
177 |
178 | Jython
179 |
180 | Home:[http://www.jython.org/]
181 |
182 | Links:[https://en.wikipedia.org/wiki/Jython Wikipedia] [https://zh.wikipedia.org/wiki/Jython 维基百科]
183 |
184 | 通过 Jython 可以让 Python 代码运行在 JVM 上,并且可以调用其它的 JVM 语言的代码(比如 Java、Scala)
185 |
186 | == 2.3 整合 dotNet 平台 ==
187 |
188 | IronPython
189 |
190 | Home:[http://ironpython.net/]
191 |
192 | Links:[https://en.wikipedia.org/wiki/IronPython Wikipedia] [https://zh.wikipedia.org/wiki/IronPython 维基百科]
193 |
194 | 通过 IronPython 可以让 Python 代码运行在 dotNET 平台上,并且可以调用其它的 dotNET 语言的代码(C#、F#、VB.Net ...)
195 |
196 | == 2.4 整合 Go ==
197 |
198 | gopy
199 |
200 | Home:[https://github.com/go-python/gopy]
201 |
202 | gopy 可以把 Go 源代码编译为 Python 的一个 module。
203 |
204 | 它提供了两种方式(命令行、Python 库)来实现:Go 源码编译为 Python 模块。
205 |
206 | == 2.5 整合 Objective-C ==
207 |
208 | PyObjC
209 |
210 | Home:[http://pyobjc.sourceforge.net/]
211 |
212 | 这是用 Python 封装 Mac OS X 上的 Objective-C 库。
213 |
214 | ----
215 |
216 | = 3 操作系统 =
217 |
218 | == 3.1 文件和目录操作 ==
219 |
220 | os
221 |
222 | 【标准库】
223 |
224 | 这是非常基本的标准库,提供了常见的操作系统相关功能,很多功能是针对文件系统。
225 |
226 | shutil
227 |
228 | 【标准库】
229 |
230 | 相对于 os 而言,shutil 提供了一些比较高级的文件和目录操作(目录递归复制、目录递归删除、目录压缩打包...)
231 |
232 | 代码示例——递归删除某个目录
233 |
234 | import shutil
235 | shutil.rmtree(xxxx)
236 |
237 |
238 | glob
239 |
240 | 【标准库】
241 |
242 | 用于查找文件,【支持通配符】(* 和 ?)
243 |
244 | 代码示例——获取当前目录所有 txt 文件
245 |
246 | import glob
247 | for file in glob.glob("./*.txt") :
248 | print(file)
249 |
250 |
251 | fnmatch
252 |
253 | 【标准库】
254 |
255 | 用于匹配文件名(支持通配符,类似上面的 glob)
256 |
257 | 代码示例——列出当前目录所有 txt 文件
258 |
259 | import os, fnmatch
260 |
261 | for file in os.listdir(".") :
262 | if fnmatch.fnmatch(file, "*.txt") :
263 | print(file)
264 |
265 |
266 | tempfile
267 |
268 | 【标准库】
269 |
270 | 使用它可以安全地生成临时文件或临时目录。
271 |
272 |
273 |
274 | == 3.2 线程 ==
275 |
276 | threading
277 |
278 | 【标准库】
279 |
280 | 提供了比较高层的线程封装 API。它本身包含了线程同步/互斥的机制。
281 |
282 | 代码示例——基于“函数”的线程
283 |
284 | import threading
285 | import time
286 |
287 | def my_thread() :
288 | print("Thread started!")
289 | time.sleep(3)
290 | print("Thread finished!")
291 |
292 | threading.Thread(target=my_thread).start()
293 |
294 |
295 | 代码示例——基于“类”的线程
296 |
297 | import threading
298 | import time
299 | from __future__ import print_function
300 |
301 | class MyThread(threading.Thread) :
302 | def run(self) :
303 | print("{} started!".format(self.getName()))
304 | time.sleep(3)
305 | print("{} finished!".format(self.getName()))
306 |
307 | if __name__ == "__main__" :
308 | for n in range(10) :
309 | mythread = MyThread(name = "Thread-{}".format(n + 1))
310 | mythread.start()
311 | time.sleep(1)
312 |
313 |
314 | == 3.3 进程 ==
315 |
316 | subprocess
317 |
318 | 【标准库】
319 |
320 | 用于进程管理,可以启动子进程,通过标准输入输出跟子进程交互。
321 |
322 | 代码示例——启动命令行进程,并获取该进程的标准输出
323 |
324 | import subprocess
325 | output = subprocess.check_output(["dir"]) # 获取当前目录的内容
326 | output = subprocess.check_output(["netstat", "-an"]) # 获取当前网络链接
327 |
328 |
329 | multiprocessing
330 |
331 | 【标准库】
332 |
333 | 它是 2.6 版本加入到标准库的,其 API 接口的风格类似于 threading 模块。
334 |
335 | 它本身包含了进程同步/互斥的机制。
336 |
337 | 代码示例——利用其 Lock 机制,确保多个子进程的标准输出不会混杂(每次只有一个进程调用 print)。
338 |
339 | from multiprocessing import Process, Lock
340 |
341 | def f(lock, n) :
342 | lock.acquire()
343 | print("hello world %d" % n)
344 | lock.release()
345 |
346 | if __name__ == "__main__" :
347 | lock = Lock()
348 | for num in range(10):
349 | Process(target=f, args=(lock, num)).start()
350 |
351 |
352 | sh
353 |
354 | Home:[https://github.com/amoffat/sh]
355 |
356 | 这个项目可以用来取代标准库中的 subprocess;同时兼容 Python2 和 Python3。
357 |
358 | 使用它可以写出比 subprocess 更简洁、更优雅的代码。
359 |
360 | 代码示例——获取命令输出
361 |
362 | from sh import ifconfig
363 | print(ifconfig("wlan0"))
364 |
365 |
366 | 代码示例——命令行参数
367 |
368 | from sh import curl
369 | # 传统风格
370 | curl("https://program-think.blogspot.com/", "-o", "test.html", "--silent")
371 | # 命名参数风格
372 | curl("https://program-think.blogspot.com/", o="test.html", silent=True)
373 |
374 |
375 | 代码示例——管道
376 |
377 | from sh import ls, wc
378 | print(wc(ls("/etc", "-1"), "-l"))
379 |
380 |
381 | == 3.4 本地进程间通信(IPC) ==
382 |
383 | mmap
384 |
385 | 【标准库】
386 |
387 | 提供了内存映射文件的支持。
388 |
389 | 代码示例——利用 mmap 在父子进程间交换数据
390 |
391 | import os
392 | import mmap
393 |
394 | map = mmap.mmap(-1, 13)
395 | map.write("Hello, world")
396 |
397 | pid = os.fork()
398 | if pid == 0 : # 子进程
399 | map.seek(0)
400 | print(map.readline())
401 | map.close()
402 |
403 |
404 | signal
405 |
406 | 【标准库】
407 |
408 | 用于进程信号处理的标准库(主要用于 Linux & UNIX 系统)。
409 |
410 | == 3.5 操作硬件 ==
411 |
412 | keyboard
413 |
414 | Home:[https://github.com/boppreh/keyboard]
415 |
416 | 顾名思义,这个库让你可以进行各种键盘相关的操作,包括:模拟按键、键盘钩子(hook),按键记录及重放。
417 |
418 | 支持复杂的组合键。纯 python 代码代码,同时支持 Windows 和 Linux。
419 |
420 | 代码示例
421 |
422 | import keyboard
423 |
424 | # 模拟按键。
425 | keyboard.press_and_release("shift+s, space")
426 |
427 | # 模拟按键,并执行相应代码。
428 | keyboard.add_hotkey("page up, page down", lambda: keyboard.write("xxxx"))
429 |
430 | # 等待特定按键,然后继续执行。
431 | keyboard.wait("esc")
432 |
433 | # 记录按键,直到用户按了 ESC;然后以3倍速重放刚才记录的按键。
434 | recorded = keyboard.record(until="esc")
435 | keyboard.play(recorded, speed_factor=3)
436 |
437 |
438 | == 3.6 获取系统信息 ==
439 |
440 | sys
441 |
442 | 【标准库】
443 |
444 | 这个模块可供访问由解释器使用或维护的变量和与解释器进行交互的函数。
445 |
446 | 代码示例
447 |
448 | sys.argv # 命令行参数 List,第一个元素是程序本身路径
449 | sys.exit(0) # 退出程序,正常退出时用 0 表示退出码
450 | sys.version # 获取 Python 解释程序的版本信息
451 |
452 |
453 | platform
454 |
455 | 【标准库】
456 |
457 | 这个模块提供了很多用于获取操作系统的信息的功能。
458 |
459 | 代码示例
460 |
461 | import platform
462 |
463 | platform.platform() # 获取操作系统名称及版本号,例如:"Windows-7-6.1.7601-SP1"
464 | platform.version() # 获取操作系统版本号,例如:"6.1.7601"
465 | platform.architecture() # 获取操作系统的架构,例如:("32bit", "WindowsPE")
466 |
467 |
468 | psutil
469 |
470 | Home:[https://github.com/giampaolo/psutil]
471 |
472 | psutil(Python system and process utilities)是一个跨平台的进程管理和系统工具库,可以处理”CPU、内存、磁盘、网络、用户“等信息。
473 |
474 | 主要用于系统资源的监控,分析,以及对进程进行一定的管理。
475 |
476 | 代码示例
477 |
478 | import psutil
479 |
480 | psutil.cpu_count() # 获取 CPU 数量
481 | psutil.cpu_freq() # 获取 CPU 频率
482 |
483 | psutil.virtual_memory() # 获取内存信息
484 | psutil.swap_memory() # 获取交换分区(换页文件)信息
485 |
486 | psutil.disk_partitions() # 获取分区信息
487 | psutil.disk_usage('/') # 获取某分区的使用情况
488 |
489 | psutil.users() # 获取用户信息
490 |
491 | p = psutil.Process(pid) # 根据给定的 pid 获得进程对象
492 | p.name() # 进程名
493 | p.exe() # 可执行程序的全路径
494 | p.cwd() # 进程的当前目录
495 | p.cmdline() # 启动进程的命令行参数
496 |
497 |
498 | == 3.7 Linux & Unix 系统相关 ==
499 |
500 | syslog
501 |
502 | 【标准库】
503 |
504 | 通过它可以很方便地跟 POSIX 的 syslog 服务进行交互。
505 |
506 | == 3.8 Windows 系统相关 ==
507 |
508 | PyWin32
509 |
510 | Home:[http://python.net/crew/mhammond/win32/]
511 |
512 | 这个第三方库封装了 Windows API 及 COM API。通过它可以方便地用 Python 进行 Windows 编程(调用 COM 组件、编写 Windows 服务、等)。
513 |
514 | == 3.9 程序打包 ==
515 |
516 | PyInstaller
517 |
518 | Home:[http://www.pyinstaller.org/]
519 |
520 | PyInstaller 可以把你的 Python 代码制作成独立运行的程序(不依赖 Python 环境就可以运行)。
521 |
522 | 该工具支持多种操作系统,包括:Windows、Linux、Mac OS X、Solaris、AIX、等。
523 |
524 | py2exe
525 |
526 | Home:[http://www.py2exe.org/]
527 |
528 | Links:[https://en.wikipedia.org/wiki/Py2exe Wikipedia]
529 |
530 | py2exe 的功能类似 PyInstaller,但只支持 Windows 平台。
531 |
532 | py2app
533 |
534 | Home:[https://bitbucket.org/ronaldoussoren/py2app]
535 |
536 | 它很类似于 [http://www.py2exe.org/ py2exe],差别在于 [http://www.py2exe.org/ py2exe] 支持 Windows 平台,而 [https://bitbucket.org/ronaldoussoren/py2app py2app] 支持 Mac OS X 平台。
537 |
538 | EasyInstall & Setuptools
539 |
540 | Home:[https://pypi.python.org/pypi/setuptools]
541 |
542 | 这套工具可以帮助你进行第三方库的管理(下载、编译、安装、升级、卸载)
543 |
544 | ----
545 |
546 | = 4 Web =
547 |
548 | == 4.1 HTTP Client ==
549 |
550 | httplib & httplib2 & http.request & urllib.parse
551 |
552 | 【标准库】
553 |
554 | 这几个库可以进行各种 HTTP 客户端请求(GET、POST、等)。
555 |
556 | Python2 的模块名是 httplib 和 httplib2;到 Python3,模块名改为 http.request 和 urllib.parse
557 |
558 | 代码示例——读取指定 URL 的网页内容
559 |
560 | import urllib
561 | handle = urllib.urlopen("http://www.google.com")
562 | page = handle.read()
563 | handle.close()
564 |
565 |
566 | Requests
567 |
568 | Home:[http://www.python-requests.org/]
569 |
570 | 这是一个用起来很优雅的库,如其名,封装了 HTTP 请求的功能。
571 |
572 | 代码示例
573 |
574 | >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
575 | >>> r.status_code
576 | 200
577 | >>> r.headers['content-type']
578 | 'application/json; charset=utf8'
579 | >>> r.encoding
580 | 'utf-8'
581 | >>> r.text
582 | u'{"type":"User"...'
583 | >>> r.json()
584 | {u'private_gists': 419, u'total_private_repos': 77, ...}
585 |
586 |
587 | == 4.2 HTTP Server ==
588 |
589 | SimpleHTTPServer & http.server
590 |
591 | 【标准库】
592 |
593 | 提供轻量级 HTTP Server 的标准库。
594 |
595 | Python2 的模块名叫 SimpleHTTPServer;到 Python3 模块名改为 http.server
596 |
597 | 代码示例——一个极简单的 HTTP 服务
598 |
599 | import SocketServer
600 | import SimpleHTTPServer
601 |
602 | PORT = 8080
603 | Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
604 | httpd = SocketServer.TCPServer(("", PORT), Handler)
605 | print("serving at port %d" % PORT)
606 | httpd.serve_forever()
607 |
608 |
609 | == 4.3 Web 开发框架 ==
610 |
611 | (Python 的 Web 框架数不胜数,俺只挑选几个代表性的)
612 | Django
613 |
614 | Home:[https://www.djangoproject.com/]
615 |
616 | Links:[https://en.wikipedia.org/wiki/Django_(web_framework) Wikipedia] [https://zh.wikipedia.org/wiki/Django 维基百科]
617 |
618 | 在 Python 社区,Django 是目前最有影响力的 Web 开发框架。该框架很重型,内置了 Web 服务端开发常用的组件(比如:ORM、用户管理)。
619 |
620 | Django 应用范围很广,比如 Google 的 Web 开发平台 GAE 就支持它。
621 |
622 | 而且它完全支持前面提到的 Jython 运行环境,可以运行在任何 J2EE 服务器上。
623 |
624 | TurboGears
625 |
626 | Home:[http://www.turbogears.org/]
627 |
628 | Links:[https://en.wikipedia.org/wiki/TurboGears Wikipedia] [https://zh.wikipedia.org/wiki/TurboGears 维基百科]
629 |
630 | 又一个重型的 Web 开发框架,名气仅次于 Django。
631 |
632 | 它跟 Django 一样,都是“Full-Stack Frameworks”。
633 |
634 | CherryPy
635 |
636 | Home:[http://www.cherrypy.org/]
637 |
638 | Links:[https://en.wikipedia.org/wiki/CherryPy Wikipedia]
639 |
640 | 轻量级的 Web 框架。某些 Web 框架(比如前面提到的 TurboGears)使用它作为底层。
641 |
642 | 代码示例——Hello world
643 |
644 | import cherrypy
645 |
646 | class HelloWorld(object) :
647 | def index(self) :
648 | return "Hello World!"
649 | index.exposed = True
650 |
651 | cherrypy.quickstart(HelloWorld())
652 |
653 |
654 | web.py
655 |
656 | Home:[http://webpy.org/]
657 |
658 | 与前两个(Django、TurboGears)不同,这是一个轻量级的框架。甚至被称为“It's the anti-framework framework.”
659 |
660 | 其作者是大名鼎鼎的黑客 [https://en.wikipedia.org/wiki/Aaron_Swartz Aaron Swartz]。(俺在[http://program-think.blogspot.nl/2013/01/weekly-share-37.html 某篇博文]中悼念过他)。
661 |
662 | 当年 Aaron Swartz 用 web.py 来搭建同样大名鼎鼎的网站 [https://en.wikipedia.org/wiki/Reddit reddit](该网站是 Web 2.0 的标杆)。
663 |
664 | 代码示例——Hello world
665 |
666 | import web
667 |
668 | urls = (
669 | "/", "index"
670 | )
671 |
672 | class index :
673 | def GET(self) :
674 | return "Hello, world!"
675 |
676 | if __name__ == "__main__" :
677 | app = web.application(urls, globals())
678 | app.run()
679 |
680 |
681 | Flask
682 |
683 | Home:[http://flask.pocoo.org/]
684 |
685 | Links:[https://zh.wikipedia.org/wiki/Flask 维基百科]
686 |
687 | 轻量级 Web 应用框架。基于 Werkzeug WSGI 工具箱和 Jinja2 模板引擎。
688 |
689 | 代码示例——Hello world
690 |
691 | from flask import Flask
692 | app = Flask(__name__)
693 |
694 | app.route("/")
695 | def hello_world() :
696 | return “Hello World!"
697 |
698 | if __name__ == "__main__" :
699 | app.run()
700 |
701 |
702 | Tornado
703 |
704 | Home:[http://www.tornadoweb.org/]
705 |
706 | Links:[https://zh.wikipedia.org/wiki/Tornado 维基百科]
707 |
708 | 同样也是轻量级的 Web 框架,类似 Web.py。提供异步非阻塞 IO 的处理方式使其拥有较为出色的抗负载能力。
709 |
710 | == 4.4 Web前端 & JS整合 ==
711 |
712 | Pyjamas & pyjs
713 |
714 | Home:[http://pyjs.org/]
715 |
716 | 这是从 GWT(Google Web Toolkit)移植的第三方库。提供了 Python 到 JS 的编译,AJAX 框架等功能。
717 |
718 | Pyjamas 甚至能用来开发桌面 GUI 应用。
719 |
720 | pyjaco
721 |
722 | Home:[https://github.com/chrivers/pyjaco]
723 |
724 | 这也是一个 Python 到 JavaScript 的编译工具。
725 |
726 | == 4.5 浏览器整合 ==
727 |
728 | webbrowser
729 |
730 | 【标准库】
731 |
732 | 操纵当前系统的默认浏览器,访问指定 URL 的页面。
733 |
734 | 代码示例——用默认浏览器打开 Google 主页
735 |
736 | import webbrowser
737 | webbrowser.open("http://www.google.com")
738 |
739 |
740 | pyv8
741 |
742 | Home:[https://pypi.python.org/pypi/PyV8]
743 |
744 | [https://developers.google.com/v8/ v8] 是 Google 开发的 JavaScript 解释引擎。这是对 v8 引擎的 Python 封装。
745 |
746 | 代码示例
747 |
748 | import PyV8
749 |
750 | ctxt1 = PyV8.JSContext()
751 | ctxt1.enter()
752 | ctxt1.eval("1+2") # 对 JS 表达式求值
753 |
754 | class Global(PyV8.JSClass) : # 定义一个兼容 JS 的类
755 | def hello(self) :
756 | print("Hello, world")
757 |
758 | ctxt2 = PyV8.JSContext(Global()) # 创建一个 JS 上下文,传入 Global 类的对象
759 | ctxt2.enter()
760 | ctxt2.eval("hello()") # 调用 hello() 函数
761 |
762 |
763 | PyWebKitGtk
764 |
765 | Home:[https://github.com/jmalonzo/pywebkitgtk]
766 |
767 | [http://webkitgtk.org/ WebKitGtk] 是一个基于 WebKit 的 Web 渲染引擎。
768 |
769 | PyWebKitGtk 则提供了对 WebKitGtk 的 Python 封装。
770 |
771 | == 4.6 WebSocket ==
772 |
773 | (关于 WebSocket 的介绍,可以参见维基百科的“[https://zh.wikipedia.org/wiki/WebSocket 这个链接]”)
774 | pywebsocket
775 |
776 | Home:[https://github.com/google/pywebsocket]
777 |
778 | 这是 Google 提供的 WebSocket【服务端】。
779 |
780 | 该项目包含一个可独立运行的 server 以及一个 Apache 扩展模块(mod_pywebsocket)。
781 |
782 | AutobahnPython
783 |
784 | Home:[https://github.com/crossbario/autobahn-python]
785 |
786 | 这是 [http://crossbar.io/autobahn Autobahn] 项目的子项目,同时提供了 WebSocket 的“服务端 & 客户端”。
787 |
788 | 它兼容 Python2 和 Python3,另外还兼容 PyPy 和 Jython。
789 |
790 | 网络方面,它可以跟“asyncio 标准库”以及“[https://en.wikipedia.org/wiki/Twisted_%28software%29 Twisted]”整合。
791 |
792 | 除了实现 WebSocket 协议,它还完整实现了 WAMP(Web Application Messaging Protocol)。
793 |
794 | 代码示例——Echo Server
795 |
796 | from autobahn.twisted.websocket import WebSocketServerProtocol
797 |
798 | class MyServerProtocol(WebSocketServerProtocol) :
799 | def onConnect(self, request) :
800 | print("Client connecting: {}".format(request.peer))
801 |
802 | def onOpen(self) :
803 | print("WebSocket connection open.")
804 |
805 | def onMessage(self, payload, isBinary) :
806 | if isBinary :
807 | print("Binary message received: {} bytes".format(len(payload)))
808 | else:
809 | print("Text message received: {}".format(payload.decode("utf8")))
810 | self.sendMessage(payload, isBinary)
811 |
812 | def onClose(self, wasClean, code, reason) :
813 | print("WebSocket connection closed: {}".format(reason))
814 |
815 |
816 | ws4py
817 |
818 | Home:[https://github.com/Lawouach/WebSocket-for-Python]
819 |
820 | 此项目同时提供了 WebSocket 的“服务端 & 客户端”;并同时兼容 Python2 和 Python3。
821 |
822 | 其【服务端】可以跟“CherryPy、gevent、wsgiref、asyncio”整合;其【客户端】可以跟“Tornado、gevent”整合。
823 |
824 | == 4.7 (其它) ==
825 |
826 | selenium
827 |
828 | Home:[http://www.seleniumhq.org/]
829 |
830 | selenium 是一个非常优秀的框架,用于爬虫和 Web 自动化测试。
831 |
832 | 代码示例——模拟登录
833 |
834 | from selenium import webdriver
835 |
836 | driver = webdriver.Chrome()
837 | driver.get("http://192.168.1.1")
838 | driver.find_element_by_xpath('//*[@id="lgPwd"]').send_keys("123456")
839 | driver.find_element_by_xpath('//*[@id="loginSub"]').click()
840 | driver.quit()
841 |
842 |
843 | scrapy
844 |
845 | Home:[https://scrapy.org/]
846 |
847 | Links:[https://en.wikipedia.org/wiki/Scrapy Wikipedia]
848 |
849 | Scrapy 是一个为了爬取网站数据,提取结构性数据而编写的应用框架。
850 |
851 | 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
852 |
853 | ----
854 |
855 | = 5 网络 =
856 |
857 | == 5.1 链路层 & 网络层 ==
858 |
859 | Scapy
860 |
861 | Home:[http://www.secdev.org/projects/scapy/]
862 |
863 | Links:[https://en.wikipedia.org/wiki/Scapy Wikipedia]
864 |
865 | 这是一个底层的网络库,可以在不同协议层次构造网络数据包(包括链路层、网络层、传输层),还支持 Sniffer 抓包。
866 |
867 | 搞网络安全的网友应该会喜欢这个库。
868 |
869 | 代码示例
870 |
871 | # 传统的 ping 扫描(网络层)
872 | ans,unans = sr(IP(dst="192.168.1.1-254")/ICMP())
873 |
874 | # 局域网内的 ARP 扫描(链路层)
875 | ans,unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"), timeout=2)
876 |
877 |
878 | == 5.2 传输层 ==
879 |
880 | socket
881 |
882 | Python 标准库很早就提供了对 socket 编程的支持。
883 |
884 | 这个标准库是对伯克利套接字进行简单的封装,其 API 基本上跟 BSD SOCKET 一一对应。
885 |
886 | asyncore
887 |
888 | 这个标准库提供了异步 SOCKET 的支持。
889 |
890 | asynchat
891 |
892 | 这个标准库基于上述的 asyncore,提供更高层的 API,简化异步通讯编程。
893 |
894 | == 5.3 标准的应用层 ==
895 |
896 | === 5.3.1 综合性的库 ===
897 |
898 | PycURL
899 |
900 | Home:[http://pycurl.sourceforge.net/]
901 |
902 | [https://en.wikipedia.org/wiki/Curl cURL] 是一个功能很强的网络库/网络工具,支持 N 多应用层协议。俺在前几年写过一篇博文推荐它(在“[https://program-think.blogspot.com/2009/03/opensource-review-curl-library.html 这里]”)。
903 |
904 | 看名称就能猜到——PycURL 是 cURL 的 Python 封装。
905 |
906 | 代码示例——发起 HTTP GET 请求
907 |
908 | import pycurl
909 | try :
910 | from io import BytesIO
911 | except ImportError :
912 | from StringIO import StringIO as BytesIO
913 |
914 | buffer = BytesIO()
915 | curl = pycurl.Curl()
916 | curl.setopt(curl.URL, "http://pycurl.sourceforge.net/")
917 | curl.setopt(curl.WRITEDATA, buffer)
918 | curl.perform()
919 | curl.close()
920 | body = buffer.getvalue()
921 |
922 |
923 | === 5.3.2 HTTP ===
924 |
925 | (关于“HTTP 协议”,请参见另一个大类:“Web”)
926 |
927 | === 5.3.3 文件传输 ===
928 |
929 | ftplib
930 |
931 | 【标准库】
932 |
933 | 封装 FTP(File Transfer Protocol)协议
934 |
935 | 代码示例——列出 FTP 服务器上某目录的内容
936 |
937 | from ftplib import FTP
938 |
939 | ftp = FTP("ftp.debian.org") # 连接服务器(如果不指定端口号,则用默认端口号 21)
940 | ftp.login() # 登录(如果不指定用户名和密码,则用匿名登录)
941 | ftp.cwd("debian") # 切换到 "debian" 目录
942 | ftp.retrlines("LIST") # 列出当前目录的内容
943 | ftp.quit()
944 |
945 |
946 | pysftp
947 |
948 | Home:[https://bitbucket.org/dundeemt/pysftp]
949 |
950 | 封装 [https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol SFTP] 协议,依赖于 ssh.py
951 |
952 | 代码示例——简单的上传/下载
953 |
954 | import pysftp
955 |
956 | with pysftp.Connection("hostxxx", username="userxxx", password="xxxxxx") as sftp :
957 | with sftp.cd("public") # 服务端当前目录切换到 public
958 | sftp.put("/my/local/filename") # 上传某个本地文件到服务端的 public 目录
959 | sftp.get_r("myfiles", "/local") # 递归复制某个服务端的目录到本地
960 |
961 |
962 | === 5.3.4 电子邮件 ===
963 |
964 | smtplib
965 |
966 | 【标准库】
967 |
968 | 封装 SMTP(Simple Mail Transfer Protocol)协议
969 |
970 | imaplib
971 |
972 | 【标准库】
973 |
974 | 封装 IMAP(Internet Message Access Protocol)协议
975 |
976 | poplib
977 |
978 | 【标准库】
979 |
980 | 封装 POP3(Post Office Protocol v3)协议
981 |
982 | yagmail
983 |
984 | Home:[https://github.com/kootenpv/yagmail]
985 |
986 | 一个非常简单易用的用来发送邮件的第三方库。
987 |
988 | 代码示例
989 |
990 | import yagmail
991 |
992 | yag = yagmail.SMTP("my_gmail_username", "my_gmail_password")
993 | contents = ["This is the body, and here is just text http://somedomain/image.png",
994 | "You can find an audio file attached.', '/local/path/song.mp3"]
995 | yag.send("to@someone.com", "subject", contents)
996 |
997 |
998 | === 5.3.5 即时通讯 ===
999 |
1000 | jabber.py
1001 |
1002 | Home:[http://jabberpy.sourceforge.net/]
1003 |
1004 | Jabber(又称 XMPP)是IM(即时通信)协议的标准。这是用 Python 封装的第三方库。
1005 |
1006 | irclib
1007 |
1008 | Home:[https://bitbucket.org/jaraco/irc]
1009 |
1010 | IRC 是 Internet Relay Chat 的缩写。这是用 Python 封装的第三方库。
1011 |
1012 | pyTelegramBotAPI
1013 |
1014 | Home:[https://github.com/eternnoir/pyTelegramBotAPI]
1015 |
1016 | 一个简单、易用的 [https://core.telegram.org/bots TelegramBot] 封装。
1017 |
1018 | Telethon
1019 |
1020 | Home:[https://github.com/LonamiWebs/Telethon]
1021 |
1022 | 纯 Python3 的 [https://telegram.org/ Telegram] 客户端封装。
1023 |
1024 | === 5.3.6 远程控制 ===
1025 |
1026 | telnetlib
1027 |
1028 | 【标准库】
1029 |
1030 | 封装 telnet 协议
1031 |
1032 | 代码示例——使用 telnet 登录到某个主机并执行简单命令
1033 |
1034 | import telnetlib
1035 | import getpass
1036 |
1037 | host = raw_input("Enter remote host: ")
1038 | user = raw_input("Enter your remote account: ")
1039 | password = getpass.getpass()
1040 |
1041 | tn = telnetlib.Telnet(host)
1042 |
1043 | tn.read_until("login: ")
1044 | tn.write(user + "\n")
1045 |
1046 | if password :
1047 | tn.read_until("Password: ")
1048 | tn.write(password + "\n")
1049 |
1050 | tn.write("ls\n")
1051 | tn.write("exit\n")
1052 |
1053 | print tn.read_all()
1054 |
1055 |
1056 | rdpy
1057 |
1058 | Home:[https://github.com/citronneur/rdpy]
1059 |
1060 | 纯 Python 实现的 RDP([https://en.wikipedia.org/wiki/Remote_Desktop_Protocol 微软远程桌面协议])和 VNC([https://en.wikipedia.org/wiki/Virtual_Network_Computing Virtual Network Computing])客户端,依赖于 Twisted 库
1061 |
1062 | paramiko
1063 |
1064 | Home:[http://www.paramiko.org/]
1065 |
1066 | paramiko 是用 python 语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。
1067 |
1068 | 除了 SSH 协议之外,paramiko 还支持SFTP。
1069 |
1070 | 代码示例
1071 |
1072 | import paramiko
1073 |
1074 | ssh = paramiko.SSHClient()
1075 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
1076 | ssh.connect("IP", port, "username", "password")
1077 |
1078 |
1079 | === 5.3.7 (其它) ===
1080 |
1081 | urlparse
1082 |
1083 | 【标准库】
1084 |
1085 | 用于解析 URL,提取各个部分的内容。从 Python 2.5 版本开始加入到标准库中,从 Python 2.7 开始支持包含 IPv6 的 URL
1086 |
1087 | == 5.4 自定义的应用层 ==
1088 |
1089 | Protocol Buffers
1090 |
1091 | Home:[https://developers.google.com/protocol-buffers/]
1092 |
1093 | Links:[https://en.wikipedia.org/wiki/Protocol_Buffers Wikipedia]
1094 |
1095 | 这是 Google 开发的一个跨语言的库,用于网络传输业务数据时的“编码/解码”。
1096 |
1097 | 其优点是:跨多种语言、高性能、向前兼容、向后兼容。俺前几年写过一篇博文推荐 protobuf(在“[https://program-think.blogspot.com/2009/05/opensource-review-protocol-buffers.html 这里]”)。
1098 |
1099 | 作为 Protocol Buffers 的发明者,Google 默认实现了三种编程语言(C++、Java、Python)对它的支持。
1100 |
1101 | Apache Thrift
1102 |
1103 | Home:[https://thrift.apache.org/]
1104 |
1105 | Links:[https://en.wikipedia.org/wiki/Apache_Thrift Wikipedia]
1106 |
1107 | 来自于 Apache 社区,提供了一种跨语言的通讯机制。
1108 |
1109 | 程序员通过 Thrift 的“接口定义语言”定义通讯协议格式,然后 Thrift 根据协议格式自动帮你生成服务端和客户端代码。
1110 |
1111 | (在这个方面,它有点类似于 Google 的 Protocol Buffers)
1112 |
1113 | == 5.5 网络库、框架、中间件 ==
1114 |
1115 | Twisted
1116 |
1117 | Home:[http://twistedmatrix.com/]
1118 |
1119 | Links:[https://en.wikipedia.org/wiki/Twisted_%28software%29 Wikipedia]
1120 |
1121 | 这是一个基于 Python 网络通讯开发框架,诞生于2002年,名气很大。
1122 |
1123 | 它的某些设计类似于 C++ 的 [https://en.wikipedia.org/wiki/Adaptive_Communication_Environment ACE] 框架。除了能用来进行传输层(TCP UDP)的开发,还提供了若干应用层协议(HTTP、XMPP、SSH、IRC ...)的支持。
1124 |
1125 | 代码示例——实现一个简单的 Echo 服务,监听在 12345 端口
1126 |
1127 | from twisted.internet import protocol, reactor
1128 |
1129 | class Echo(protocol.Protocol) :
1130 | def dataReceived(self, data) :
1131 | self.transport.write(data)
1132 |
1133 | class EchoFactory(protocol.Factory) :
1134 | def buildProtocol(self, addr) :
1135 | return Echo()
1136 |
1137 | reactor.listenTCP(12345, EchoFactory())
1138 | reactor.run()
1139 |
1140 |
1141 | gevent
1142 |
1143 | Home:[http://www.gevent.org/]
1144 |
1145 | 这是一个基于[https://zh.wikipedia.org/wiki/%E5%8D%8F%E7%A8%8B 协程]的网络库,原先其底层依赖于 libevent,后来改为 libev。
1146 |
1147 | 很多开源项目用到了 gevent,具体参见 [https://github.com/gevent/gevent/wiki/Projects gevent 官方的 wiki]。
1148 |
1149 | 代码示例——并发执行网络请求
1150 |
1151 | from gevent import socket
1152 | import gevent
1153 |
1154 | hosts = ["google.com", "github.com", "program-think.blogspot.com"]
1155 | jobs = [gevent.spawn(socket.gethostbyname, host) for host in hosts]
1156 | gevent.joinall(jobs, timeout=2)
1157 | print([job.value for job in jobs])
1158 |
1159 |
1160 | PyZMQ
1161 |
1162 | Home:[https://github.com/zeromq/pyzmq]
1163 |
1164 | 这是 ZMQ(ZeroMQ)的 Python 封装库。同时支持 Python2 和 Python3。
1165 |
1166 | PyZMQ 2.2 之后的版本同时支持 ZMQ 的 3.x 和 4.x 版本。
1167 |
1168 | nanomsg-python
1169 |
1170 | Home:[https://github.com/tonysimpson/nanomsg-python]
1171 |
1172 | 这是 nanomsg 的 Python 封装库。同时支持 Python2 和 Python3。
1173 |
1174 | 代码示例——Hello world
1175 |
1176 | from __future__ import print_function
1177 | from nanomsg import Socket, PAIR, PUB
1178 |
1179 | s1 = Socket(PAIR)
1180 | s2 = Socket(PAIR)
1181 | s1.bind("inproc://test")
1182 | s2.connect("inproc://test")
1183 | s1.send(b"hello world")
1184 | print(s2.recv())
1185 | s1.close()
1186 | s2.close()
1187 |
1188 |
1189 | == 5.6 云计算 ==
1190 |
1191 | Apache Libcloud
1192 |
1193 | Home:[https://libcloud.apache.org/]
1194 |
1195 | 如今云提供商越来越多。这个库提供了统一的 API 让你访问各大知名云提供商提供的各种服务。
1196 |
1197 | 代码示例——创建 DNS 记录
1198 |
1199 | from libcloud.dns.types import Provider, RecordType
1200 | from libcloud.dns.providers import get_driver
1201 |
1202 | cls = get_driver(Provider.ZERIGO)
1203 | driver = cls("email", "api key")
1204 |
1205 | zones = driver.list_zones()
1206 | zone = [zone for zone in zones if zone.domain == "mydomain.com"][0]
1207 |
1208 | record = zone.create_record(name="www", type=RecordType.A, data="127.0.0.1")
1209 | print(record)
1210 |
1211 |
1212 | ----
1213 |
1214 | = 6 数据库 =
1215 |
1216 | 为了便于数据库开发,Python 社区制定了数据库的 API 规范([https://www.python.org/dev/peps/pep-0249/ PEP 249])。
1217 |
1218 | 只要是涉及到数据库操作,标准库和大部分第三方库都会遵循该规范(请看如下几个模块的示例代码)。
1219 |
1220 | == 6.1 数据库中间件 ==
1221 |
1222 | === 6.1.1 ODBC ===
1223 |
1224 | pyODBC
1225 |
1226 | Home:[https://github.com/mkleehammer/pyodbc]
1227 |
1228 | pyODBC 封装了 ODBC API,通过它可以访问各种数据库(只要有 ODBC 驱动即可)。
1229 |
1230 | 代码示例——查询某个 ODBC 数据源的某个表
1231 |
1232 | import pyodbc
1233 |
1234 | conn = pyodbc.connect("DSN=xxx;PWD=password")
1235 | cursor = conn.cursor()
1236 | cursor.execute("SELECT field1 FROM table1")
1237 |
1238 | while True :
1239 | row = cursor.fetchone()
1240 | if not row :
1241 | break
1242 | print(row)
1243 |
1244 | cursor.close()
1245 | conn.close()
1246 |
1247 |
1248 | ceODBC
1249 |
1250 | Home:[http://ceodbc.sourceforge.net/]
1251 |
1252 | 又一个封装 ODBC API 的第三方库
1253 |
1254 | === 6.1.2 JDBC ===
1255 |
1256 | Jython
1257 |
1258 | Jython 前面已经介绍过。有了它,你可以基于 [https://en.wikipedia.org/wiki/Jdbc JDBC] 操作数据库。
1259 |
1260 | === 6.1.3 ADO & ADO.NET ===
1261 |
1262 | PyWin32
1263 |
1264 | PyWin32 前面已经介绍过。有了它,你可以基于 [https://en.wikipedia.org/wiki/ActiveX_Data_Objects ADO] 操作数据库。
1265 |
1266 | IronPython
1267 |
1268 | IronPython 前面已经介绍过。有了它,你可以基于 [https://en.wikipedia.org/wiki/ADO.NET ADO.NET] 操作数据库。
1269 |
1270 | == 6.2 特定数据库 ==
1271 |
1272 | === 6.2.1 MySQL ===
1273 |
1274 | MySQL for Python
1275 |
1276 | Home:[http://mysql-python.sourceforge.net/]
1277 |
1278 | 操作 MySQL 的第三方库。
1279 |
1280 | 代码示例——查询某个 MySQL 数据库的某个表
1281 |
1282 | import MySQLdb
1283 |
1284 | conn = MySQLdb.connect(db="test", passwd="password")
1285 | cursor = conn.cursor()
1286 | cursor.execute("SELECT field1 FROM table1")
1287 |
1288 | while True :
1289 | row = cursor.fetchone()
1290 | if not row :
1291 | break
1292 | print(row)
1293 |
1294 | cursor.close()
1295 | conn.close()
1296 |
1297 |
1298 | === 6.2.2 PostgreSQL ===
1299 |
1300 | psycopg
1301 |
1302 | Home:[http://initd.org/psycopg/]
1303 |
1304 | 操作 PostgreSQL 的第三方库。
1305 |
1306 | PyGreSQL
1307 |
1308 | Home:[http://www.pygresql.org/]
1309 |
1310 | 操作 PostgreSQL 的第三方库。
1311 |
1312 | === 6.2.3 Oracle ===
1313 |
1314 | cx_Oracle
1315 |
1316 | Home:[http://cx-oracle.sourceforge.net/]
1317 |
1318 | 操作 Oracle 的第三方库。
1319 |
1320 | === 6.2.4 MS SQL Server ===
1321 |
1322 | pymssql
1323 |
1324 | Home:[http://pymssql.org/]
1325 |
1326 | 操作微软 SQL Server 的第三方库。
1327 |
1328 | === 6.2.5 IBM DB2 ===
1329 |
1330 | ibm-db
1331 |
1332 | Home:[https://pypi.python.org/pypi/ibm_db]
1333 |
1334 | 操作 DB2 的第三方库。
1335 |
1336 | === 6.2.6 SQLite ===
1337 |
1338 | sqlite3
1339 |
1340 | 【标准库】
1341 |
1342 | sqlite3 从 Python 2.5 版本开始加入到标准库中。通过它,你可以很方便地操作 SQLite 数据库。
1343 |
1344 | [https://en.wikipedia.org/wiki/SQLite SQLite] 是一个很优秀的轻量级数据库,俺前几年写过一篇博文推荐它(在“[https://program-think.blogspot.com/2009/04/how-to-use-sqlite.html 这里]”)。
1345 |
1346 | 代码示例——创建一个内存数据库,建表并插入记录
1347 |
1348 | import sqlite3
1349 | conn = sqlite3.connect(":memory:") # ":memory:" 表示这是一个内存数据库
1350 | cursor = conn.cursor()
1351 | cursor.execute("CREATE TABLE person (name text, age int)")
1352 | cursor.execute("INSERT INTO stocks VALUES ('TOM',20)")
1353 | conn.commit()
1354 | conn.close()
1355 |
1356 |
1357 | === 6.2.7 MongoDB ===
1358 |
1359 | PyMongo
1360 |
1361 | Docs:[https://docs.mongodb.com/ecosystem/drivers/python/]
1362 |
1363 | 这是 MongoDB 官方提供的 Python 驱动。
1364 |
1365 | === 6.2.8 Apache HBase ===
1366 |
1367 | HappyBase
1368 |
1369 | Home:[https://github.com/wbolster/happybase]
1370 |
1371 | 操作 HBase 的 Python 库,基于 [https://en.wikipedia.org/wiki/Apache_Thrift Thrift] 连接到 HBase。
1372 |
1373 | 代码示例——简单的存取操作
1374 |
1375 | import happybase
1376 | connection = happybase.Connection("hostname")
1377 | table = connection.table("table-name")
1378 | table.put(b"row-key", {b"test1": b"data1", b"test2": b"data2"})
1379 | row = table.row(b"row-key")
1380 | print(row[b"test1"])
1381 |
1382 |
1383 | === 6.2.9 Redis ===
1384 |
1385 | redis-py
1386 |
1387 | Home:[https://github.com/andymccurdy/redis-py]
1388 |
1389 | 操作 Redis 的第三方 Python 客户端。
1390 |
1391 | 代码示例——简单的存取操作
1392 |
1393 | import redis
1394 | r = redis.StrictRedis(host="localhost", port=6379, db=0)
1395 | r.set("foo", "bar")
1396 | print(r.get("foo"))
1397 |
1398 |
1399 | === 6.2.10 LevelDB ===
1400 |
1401 | Plyvel
1402 |
1403 | Home:[https://github.com/wbolster/plyvel]
1404 |
1405 | 操作 LevelDB 的 Python 库,速度快,同时兼容 Python2 和 Python3。
1406 |
1407 | 代码示例——简单的存取操作
1408 |
1409 | import plyvel
1410 | db = plyvel.DB("/tmp/testdb/", create_if_missing=True)
1411 | db.put(b"key", b"value")
1412 | print(db.get(b"key"))
1413 | db.close()
1414 |
1415 |
1416 | === 6.2.11 Berkeley DB ===
1417 |
1418 | PyBSDDB
1419 |
1420 | Home:[http://www.jcea.es/programacion/pybsddb.htm]
1421 |
1422 | 操作 Berkeley DB 的第三方库。
1423 |
1424 | == 6.3 ORM(Object-Relational Mapping) ==
1425 |
1426 | SQLAlchemy
1427 |
1428 | Home:[http://www.sqlalchemy.org/]
1429 |
1430 | Links:[https://en.wikipedia.org/wiki/SQLAlchemy Wikipedia] [https://zh.wikipedia.org/wiki/SQLAlchemy 维基百科]
1431 |
1432 | SQLAlchemy 支持的数据库有:MySQL、PostgreSQL、Sqlite、Oracle、MS SQL Server、Firebird、Sybase SQL Server、Informix、等。
1433 |
1434 | 代码示例——通过对象的方式创建两张依赖关系的表
1435 |
1436 | from sqlalchemy import *
1437 | from sqlalchemy.ext.declarative import declarative_base
1438 | from sqlalchemy.orm import relation, sessionmaker
1439 |
1440 | Base = declarative_base()
1441 |
1442 | class Movie(Base) :
1443 | __tablename__ = "movies"
1444 |
1445 | id = Column(Integer, primary_key=True)
1446 | title = Column(String(255), nullable=False)
1447 | year = Column(Integer)
1448 | directed_by = Column(Integer, ForeignKey("directors.id"))
1449 | director = relation("Director", backref="movies", lazy=False)
1450 |
1451 | def __init__(self, title=None, year=None) :
1452 | self.title = title
1453 | self.year = year
1454 |
1455 | def __repr__(self) :
1456 | return "Movie(%r, %r, %r)" % (self.title, self.year, self.director)
1457 |
1458 | class Director(Base) :
1459 | __tablename__ = "directors"
1460 |
1461 | id = Column(Integer, primary_key=True)
1462 | name = Column(String(50), nullable=False, unique=True)
1463 |
1464 | def __init__(self, name=None) :
1465 | self.name = name
1466 |
1467 | def __repr__(self) :
1468 | return "Director(%r)" % (self.name)
1469 |
1470 | Base.metadata.create_all(create_engine("dbms://user:pwd@host/dbname"))
1471 |
1472 |
1473 | SQLObject
1474 |
1475 | Home:[http://sqlobject.org/]
1476 |
1477 | Links:[https://en.wikipedia.org/wiki/SQLObject Wikipedia]
1478 |
1479 | SQLObject 支持的数据库有:MySQL、PostgreSQL、Sqlite、MS SQL Server、Firebird、Sybase SQL Server、SAP DB、等。
1480 |
1481 | 代码示例——通过对象的方式创建表
1482 |
1483 | from sqlobject import *
1484 | sqlhub.processConnection = connectionForURI("sqlite:/:memory:")
1485 |
1486 | class Person(SQLObject) :
1487 | first_name = StringCol()
1488 | last_name = StringCol()
1489 |
1490 | Person.createTable()
1491 |
1492 |
1493 | Peewee
1494 |
1495 | Home:[http://www.peewee-orm.com/]
1496 |
1497 | 一个轻量级的 ORM,支持 SQLite、MySQL 和 PostgreSQL,通过插件机制支持更多数据库。
1498 |
1499 | 同时支持 Python2 和 Python3。
1500 |
1501 | 代码示例——通过对象的方式创建表
1502 |
1503 | from peewee import *
1504 |
1505 | db = SqliteDatabase("test.db")
1506 |
1507 | class Person(Model) :
1508 | name = CharField()
1509 | birthday = DateField()
1510 | is_relative = BooleanField()
1511 | class Meta :
1512 | database = db # This model uses the "test.db".
1513 |
1514 | class Pet(Model) :
1515 | owner = ForeignKeyField(Person, related_name="pets")
1516 | name = CharField()
1517 | animal_type = CharField()
1518 | class Meta :
1519 | database = db # This model uses the "test.db".
1520 |
1521 | db.connect()
1522 | db.create_tables([Person, Pet])
1523 |
1524 |
1525 | ----
1526 |
1527 | = 7 GUI =
1528 |
1529 | == 7.1 GUI 框架 ==
1530 |
1531 | === 7.1.1 基于 Tk ===
1532 |
1533 | [https://en.wikipedia.org/wiki/Tk_(framework) Tk] 是一个跨平台的界面组件库。
1534 |
1535 | Tkinter & tkinter
1536 |
1537 | 【标准库】
1538 |
1539 | 这是 Python 内置的标准库,封装了 Tcl/Tk 界面库。
1540 |
1541 | Python2 的模块名叫 Tkinter,到 Python3 模块名改为 tkinter
1542 |
1543 | 代码示例——用 Tkinter 写 Hello world
1544 |
1545 | from Tkinter import *
1546 |
1547 | if __name__ == "__main__" :
1548 | root = Tk()
1549 | label = Label(root, text="Hello, world")
1550 | label.pack()
1551 | root.mainloop()
1552 |
1553 |
1554 | === 7.1.2 基于 wxWidgets ===
1555 |
1556 | [https://en.wikipedia.org/wiki/WxWidgets wxWidgets] 是 C++ 开发的跨平台框架(不仅包括 GUI,还有其它功能)。
1557 | wxPython
1558 |
1559 | Home:[http://www.wxpython.org/]
1560 |
1561 | Links:[https://en.wikipedia.org/wiki/WxPython Wikipedia] [https://zh.wikipedia.org/wiki/WxPython 维基百科]
1562 |
1563 | 在所有的 wxWidgets 的 Python 封装库中,这个是名气最大的。
1564 |
1565 | [https://github.com/limodou/ulipad Ulipad](知名的国产的 Python IDE)就是基于 wxPython 开发的。
1566 |
1567 | 代码示例——用 wxPython 写 Hello world
1568 |
1569 | import wx
1570 |
1571 | class Frame(wx.Frame) :
1572 | pass
1573 |
1574 | class App(wx.App) :
1575 | def OnInit(self) :
1576 | self.frame = Frame(parent=None, title="Hello, world")
1577 | self.frame.Show()
1578 | self.SetTopWindow(self.frame)
1579 | return True
1580 |
1581 | if __name__ == "__main__" :
1582 | app = App()
1583 | app.MainLoop()
1584 |
1585 |
1586 | PythonCard
1587 |
1588 | Home:[http://pythoncard.sourceforge.net/]
1589 |
1590 | 又一个基于 wxWidgets 的 GUI 库。
1591 |
1592 | === 7.1.3 基于 GTK+ ===
1593 |
1594 | [https://en.wikipedia.org/wiki/GTK%2B GTK+] 全称是(GIMP Toolkit),由 C 开发的跨平台界面组件库。
1595 | PyGTK
1596 |
1597 | Home:[http://www.pygtk.org/]
1598 |
1599 | Links:[https://en.wikipedia.org/wiki/PyGTK Wikipedia]
1600 |
1601 | 它是 Python 对 GTK+2 的封装。
1602 |
1603 | 代码示例——用 PyGTK 写 Hello world
1604 |
1605 | import pygtk
1606 | pygtk.require("2.0")
1607 | import gtk
1608 |
1609 | class HelloWorld :
1610 | def __init__(self) :
1611 | self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
1612 | self.window.connect("delete_event", self.delete_event)
1613 | self.window.connect("destroy", self.destroy)
1614 | self.window.set_border_width(10)
1615 |
1616 | self.button = gtk.Button("Hello, world")
1617 | self.button.connect("clicked", self.hello, None)
1618 | self.button.connect_object("clicked", gtk.Widget.destroy, self.window)
1619 | self.window.add(self.button)
1620 |
1621 | self.button.show()
1622 | self.window.show()
1623 |
1624 | def main(self) :
1625 | gtk.main()
1626 |
1627 | def hello(self, widget, data=None) :
1628 | print("Hello, world")
1629 |
1630 | def delete_event(self, widget, event, data=None) :
1631 | print("delete event occurred")
1632 | return False
1633 |
1634 | def destroy(self, widget, data=None) :
1635 | gtk.main_quit()
1636 |
1637 | if __name__ == "__main__" :
1638 | hello = HelloWorld()
1639 | hello.main()
1640 |
1641 |
1642 | PyGObject(PyGI)
1643 |
1644 | Home:[https://live.gnome.org/PyGObject]
1645 |
1646 | 它是 Python 对 GTK+3 的封装。PyGTK 的官网也推荐它。
1647 |
1648 | 代码示例——用 PyGObject 写 Hello world
1649 |
1650 | from gi.repository import Gtk
1651 |
1652 | class MyWindow(Gtk.Window):
1653 | def __init__(self):
1654 | Gtk.Window.__init__(self, title="Hello World")
1655 |
1656 | self.button = Gtk.Button(label="Click Here")
1657 | self.button.connect("clicked", self.on_button_clicked)
1658 | self.add(self.button)
1659 |
1660 | def on_button_clicked(self, widget):
1661 | print("Hello, world!")
1662 |
1663 | win = MyWindow()
1664 | win.connect("delete-event", Gtk.main_quit)
1665 | win.show_all()
1666 | Gtk.main()
1667 |
1668 |
1669 | === 7.1.4 基于 Qt ===
1670 |
1671 | [https://en.wikipedia.org/wiki/Qt_(toolkit) Qt] 是 C++ 开发的跨平台框架(不仅包括 GUI,还有其它功能)。
1672 |
1673 | PyQt
1674 |
1675 | Home:[http://www.riverbankcomputing.com/software/pyqt/]
1676 |
1677 | Links:[https://en.wikipedia.org/wiki/PyQt Wikipedia] [https://zh.wikipedia.org/wiki/PyQt 维基百科]
1678 |
1679 | 这是 Python 对 Qt 的封装。
1680 |
1681 | 代码示例——用 pyQt 写 Hello world
1682 |
1683 | import sys
1684 | from PyQt4.QtGui import *
1685 |
1686 | if __name__ == "__main__" :
1687 | app = QApplication(sys.argv)
1688 | window = QWidget()
1689 |
1690 | window.resize(320, 240)
1691 | window.setWindowTitle("Hello, world")
1692 | window.show()
1693 | sys.exit(app.exec_())
1694 |
1695 |
1696 | PySide
1697 |
1698 | Home:[http://www.pyside.org/]
1699 |
1700 | 这也是 Python 对 Qt 的封装。
1701 |
1702 | === 7.1.5 基于 FLTK ===
1703 |
1704 | [https://en.wikipedia.org/wiki/FLTK FLTK] 全称是(Fast Light Tool Kit),由 C++ 开发的跨平台、轻量级界面组件库。
1705 | PyFLTK
1706 |
1707 | Home:[http://pyfltk.sourceforge.net/]
1708 |
1709 | 这是 Python 对 FLTK 的封装。
1710 |
1711 | === 7.1.6 基于 Windows 平台 ===
1712 |
1713 | PyWin32
1714 |
1715 | PyWin32 前面已经介绍过。它可以提供原生的 Windows GUI 界面。
1716 |
1717 | IronPython
1718 |
1719 | IronPython 前面已经介绍过。它可以提供 dotNET 的 GUI 界面。
1720 |
1721 | === 7.1.7 基于 JVM 平台 ===
1722 |
1723 | Jython
1724 |
1725 | Jython 前面已经介绍过。它可以提供基于 Java 的 [https://en.wikipedia.org/wiki/Swing_%28Java%29 Swing] 界面。
1726 |
1727 | === 7.1.8 (其它) ===
1728 |
1729 | EasyGUI
1730 |
1731 | Home:[http://easygui.sourceforge.net/]
1732 |
1733 | EasyGUI 这是一个很轻量级的库。跟其它 GUI 不同之处在于——它没有“事件驱动”。
1734 |
1735 | PyGUI
1736 |
1737 | Home:[http://www.cosc.canterbury.ac.nz/greg.ewing/python_gui/]
1738 |
1739 | PyGUI 是一个更高层的 GUI 库,底层分别封装了 [http://python.net/crew/mhammond/win32/ PyWin32](Windows 平台)、[http://www.pygtk.org/ PyGTK](Linux 平台)、[http://pyobjc.sourceforge.net/ PyObjC](Mac OS X 平台)。
1740 |
1741 | Kivy
1742 |
1743 | Home:[http://kivy.org/]
1744 |
1745 | 跨平台的多媒体框架和界面库,用来开发比较炫的界面。
1746 |
1747 | 除了支持桌面操作系统,还支持 Android / iOS,支持多点触摸。
1748 |
1749 | OcempGUI
1750 |
1751 | Home:[http://ocemp.sourceforge.net/gui.html]
1752 |
1753 | 基于 PyGame 的一个跨平台 GUI 库(PyGame 下面会提到)。
1754 |
1755 | == 7.2 图表 & 报表 ==
1756 |
1757 | matplotlib
1758 |
1759 | Home:[http://matplotlib.org/]
1760 |
1761 | Links:[https://en.wikipedia.org/wiki/Matplotlib Wikipedia]
1762 |
1763 | 这是一个有名的图形库,主要用来绘制数学相关的图形。
1764 |
1765 | 它跟后面提到的 [http://www.scipy.org/ SciPy] 整合可以起到类似 MATLAB 的效果。效果图在“[http://matplotlib.org/users/screenshots.html 这里]”。
1766 |
1767 | Gnuplot.py
1768 |
1769 | Home:[http://gnuplot-py.sourceforge.net/]
1770 |
1771 | 这是 Python 对 [http://www.gnuplot.info/ gnuplot] 的封装。gnuplot 的效果图在“[http://www.gnuplot.info/screenshots/index.html 这里]”。
1772 |
1773 | PyQtGraph
1774 |
1775 | Home:[http://www.pyqtgraph.org/]
1776 |
1777 | 这是一个纯 Python 的库,依赖于 PyQt4 / PySide。效果图在“[http://www.pyqtgraph.org/images/plotting_sm.png 这里]”。
1778 |
1779 | PyX
1780 |
1781 | Home:[http://pyx.sourceforge.net/]
1782 |
1783 | 这个库可以跟 TeX / LaTeX 无缝整合,支持导出为 PostScript / PDF 格式。适合用来制作报表。效果图在“[http://pyx.sourceforge.net/gallery/index.html 这里]”。
1784 |
1785 | Chaco
1786 |
1787 | Home:[http://code.enthought.com/chaco/]
1788 |
1789 | 这是一个商业公司维护的库,主要提供2维图表。效果图在“[http://docs.enthought.com/chaco/user_manual/annotated_examples.html 这里]”。
1790 |
1791 | Plotly
1792 |
1793 | Home:[https://plot.ly/]
1794 |
1795 | plotly 是现代平台的敏捷商业智能和数据科学库。
1796 |
1797 | 它作为一款开源的绘图库,可以应用于 Python、R、MATLAB、Excel、JavaScript、jupyter 等多种语言。
1798 |
1799 | ----
1800 |
1801 | = 8 信息安全 =
1802 |
1803 | == 8.1 密码学 ==
1804 |
1805 | hashlib
1806 |
1807 | 【标准库】
1808 |
1809 | 在 Python 2.5 版本加入到标准库中。通过它,你可以很方便地计算各种散列值。
1810 |
1811 | 它支持的哈希算法有:MD5 SHA1 SHA224 SHA256 SHA384 SHA512
1812 |
1813 | 关于散列算法,俺写过一篇扫盲(在“[https://program-think.blogspot.com/2013/02/file-integrity-check.html 这里]”)。
1814 |
1815 | 代码示例——计算字符串的 SHA1 散列值
1816 |
1817 | import hashlib
1818 | sha1 = hashlib.sha1("Hello, world").hexdigest()
1819 |
1820 |
1821 | PyCrypto
1822 |
1823 | Home:[http://www.dlitz.net/software/pycrypto/]
1824 |
1825 | 这个库包含了常见的对称加密算法(DES、AES、IDEA 等)、公钥加密算法(RSA、DSA 等)、散列算法(MD5、SHA1、RIPEMD 等)。
1826 |
1827 | pyOpenSSL
1828 |
1829 | Home:[http://pyopenssl.sourceforge.net/]
1830 |
1831 | [https://en.wikipedia.org/wiki/OpenSSL OpenSSL] 在加密领域可是大名鼎鼎。这个库使用 Python 对 OpenSSL 进行很薄的封装。
1832 |
1833 | Keyczar
1834 |
1835 | Home:[https://github.com/google/keyczar]
1836 |
1837 | 这是 Google 提供的加密库,同时提供 C++、Java、Python 三种语言的实现。
1838 |
1839 | 它提供了比较高层的 API, 使用者无需关心太多的细节。
1840 |
1841 | passlib
1842 |
1843 | Home:[https://bitbucket.org/ecollins/passlib/]
1844 |
1845 | passlib 是一个久经考验的非常成熟的跨平台的散列函数库,它所提供的功能包括随机盐密码的生成与验证,两步验证等。
1846 |
1847 | 代码示例——验证随机盐密码
1848 |
1849 | >>> # import the hash algorithm
1850 | >>> from passlib.hash import pbkdf2_sha256
1851 |
1852 | >>> # generate new salt, and hash a password
1853 | >>> hash = pbkdf2_sha256.hash("toomanysecrets")
1854 | >>> hash
1855 | '$pbkdf2-sha256$29000$N2YMIWQsBWBMae09x1jrPQ$1t8iyB2A.WF/Z5JZv.lfCIhXXN33N23OSgQYThBYRfk'
1856 |
1857 | >>> # verifying the password
1858 | >>> pbkdf2_sha256.verify("toomanysecrets", hash)
1859 | True
1860 | >>> pbkdf2_sha256.verify("joshua", hash)
1861 | False
1862 |
1863 |
1864 | == 8.2 访问控制 ==
1865 |
1866 | oauth2client
1867 |
1868 | Home:[https://github.com/google/oauth2client]
1869 |
1870 | 这是 Google 提供的 OAuth 客户端,支持 OAuth 2.0 规范。
1871 |
1872 | ----
1873 |
1874 | = 9 处理文件格式 =
1875 |
1876 | == 9.1 结构化数据格式 ==
1877 |
1878 | === 9.1.1 CSV ===
1879 |
1880 | [https://en.wikipedia.org/wiki/Comma-separated_values CSV] 是一种历史悠久的结构化数据存储格式。其效果类似于一张数据库二维表。
1881 | csv
1882 |
1883 | 【标准库】
1884 |
1885 | 提供 CSV 格式文件的读写,可以手动指定行列分隔符。
1886 |
1887 | === 9.1.2 JSON ===
1888 |
1889 | JSON 格式源自 JavaScript,如今在 Web 开发中广为应用。
1890 | json
1891 |
1892 | 【标准库】
1893 |
1894 | 提供 JSON 格式的编码和解码。
1895 |
1896 | 代码示例——编码/解码 JSON 字符串
1897 |
1898 | import json
1899 |
1900 | json.dumps(["foo", {"bar": ("baz", None, 1.0, 2)}])
1901 | # JSON 编码
1902 | # 得到如下【字符串】
1903 | # """["foo", {"bar": ["baz", null, 1.0, 2]}]"""
1904 |
1905 | json.loads("""["foo", {"bar":["baz", null, 1.0, 2]}]""")
1906 | # JSON 解码
1907 | # 得到如下【对象】
1908 | # [u"foo", {u"bar": [u"baz", None, 1.0, 2]}]
1909 |
1910 |
1911 | === 9.1.3 YAML ===
1912 |
1913 | [https://en.wikipedia.org/wiki/YAML YAML] 是一种类似于 json 的结构化数据格式。它在确保可读性的基础上,提供了超越 json 的灵活性和扩展性。
1914 | PyYAML
1915 |
1916 | Home:[http://pyyaml.org/]
1917 |
1918 | pyyaml 提供了 Python 对 YAML 的封装。
1919 |
1920 | == 9.2 压缩文件 & 打包文件 ==
1921 |
1922 | === 9.2.1 zip ===
1923 |
1924 | zipfile
1925 |
1926 | 【标准库】
1927 |
1928 | 提供对 zip 格式的读写。
1929 |
1930 | === 9.2.2 bzip2(bz2) ===
1931 |
1932 | bz2
1933 |
1934 | 【标准库】
1935 |
1936 | 提供对 bzip2 格式的读写。
1937 |
1938 | === 9.2.3 gzip(gz) ===
1939 |
1940 | gzip
1941 |
1942 | 【标准库】
1943 |
1944 | 提供对 gzip 格式的读写。
1945 |
1946 | zlib
1947 |
1948 | 【标准库】
1949 |
1950 | 提供对 zlib 格式的读写。
1951 |
1952 | === 9.2.4 tar ===
1953 |
1954 | tarfile
1955 |
1956 | 【标准库】
1957 |
1958 | 提供对 tar 格式的读写。
1959 |
1960 | === 9.2.5 7zip(7z) ===
1961 |
1962 | PyLZMA
1963 |
1964 | Home:[http://www.joachim-bauch.de/projects/pylzma/]
1965 |
1966 | 处理 7zip 格式的第三方库。
1967 |
1968 | === 9.2.6 rar ===
1969 |
1970 | rarfile
1971 |
1972 | Home:[http://rarfile.berlios.de/]
1973 |
1974 | 处理 rar 格式的第三方库。
1975 |
1976 | === 9.2.7 msi ===
1977 |
1978 | msilib
1979 |
1980 | 【标准库】
1981 |
1982 | 提供对 msi 格式的读写,从 Python 2.5 版本开始加入标准库。
1983 |
1984 | == 9.3 标记语言 ==
1985 |
1986 | === 9.3.1 XML ===
1987 |
1988 | xml.dom & xml.miniDom & xml.etree.ElementTree
1989 |
1990 | 【标准库】
1991 |
1992 | 用 DOM(Document Object Model)方式处理 XML 文件。
1993 |
1994 | xml.sax & xml.parsers.expat
1995 |
1996 | 【标准库】
1997 |
1998 | 用 SAX(Simple API for XML)方式处理 XML 文件。
1999 |
2000 | lxml
2001 |
2002 | Home:[http://lxml.de/]
2003 |
2004 | 著名的 C 语言库 libxml 和 libxslt 的 Python 封装。
2005 |
2006 | 功能很强,支持 XPath 1.0、XSLT 1.0、扩展 EXSLT、等。还可以用来解析 HTML 格式。
2007 |
2008 | === 9.3.2 HTML ===
2009 |
2010 | HTMLParser
2011 |
2012 | 【标准库】
2013 |
2014 | 以回调方式解析 HTML/XHTML 文件内容。
2015 |
2016 | beautifulsoup
2017 |
2018 | Home:[https://www.crummy.com/software/BeautifulSoup/]
2019 |
2020 | Links:[https://zh.wikipedia.org/zh-cn/Beautiful_Soup 维基百科]
2021 |
2022 | Beautiful Soup 可以从 HTML 或 XML 文件中提取数据。
2023 |
2024 | 它是写”爬虫“的利器,通常与 requests 或 selenium 配合。
2025 |
2026 | == 9.4 PDF ==
2027 |
2028 | pyfpdf
2029 |
2030 | Home:[https://github.com/reingart/pyfpdf]
2031 |
2032 | 这是 [http://www.fpdf.org/ FPDF] 的 Python 移植库,用来生成 PDF 文档。
2033 |
2034 | 支持的功能比较全(嵌入字体、嵌入图片),文档也比较详细。
2035 |
2036 | 代码示例——简单的 Hello World 示例
2037 |
2038 | from fpdf import FPDF
2039 |
2040 | pdf = FPDF()
2041 | pdf.add_page()
2042 | pdf.set_font("Arial", "B", 16)
2043 | pdf.cell(40, 10, "Hello, World")
2044 | pdf.output("test.pdf", "F")
2045 |
2046 |
2047 | 代码示例——支持写入 HTML 语法(目前支持几种常见的 HTML tag)
2048 |
2049 | from pyfpdf import FPDF, HTMLMixin
2050 |
2051 | class MyFPDF(FPDF, HTMLMixin) :
2052 | pass
2053 |
2054 | pdf = MyFPDF()
2055 | pdf.add_page()
2056 | pdf.write_html(html)
2057 | pdf.output("test.pdf", "F")
2058 |
2059 |
2060 | pyPdf & PyPDF2
2061 |
2062 | Home:[http://knowah.github.com/PyPDF2/]
2063 |
2064 | pyPdf 目前已经不继续升级维护了。PyPDF2 是从 pyPdf 派生出来的,并继续增加新功能。
2065 |
2066 | 它除了可以提取文件属性,还可以切分/合并文档,加密/解密文档。
2067 |
2068 | PDFMiner
2069 |
2070 | Home:[http://www.unixuser.org/~euske/python/pdfminer/]
2071 |
2072 | 它可以提取 PDF 文件属性以及每页的文本,支持把内容输出为 HTML 格式。
2073 |
2074 | == 9.5 MS Office 文档 ==
2075 |
2076 | === 9.5.1 Word(doc、docx) ===
2077 |
2078 | python-docx
2079 |
2080 | Home:[https://github.com/python-openxml/python-docx]
2081 |
2082 | 纯 python 实现的 docx 操作库,能够处理 docx 中的“文本、图片、样式”。
2083 |
2084 | 同时支持 Python2 和 Python3。
2085 |
2086 | PyWin32
2087 |
2088 | PyWin32 前面已经介绍过。它可以基于 [https://en.wikipedia.org/wiki/Component_Object_Model COM] 操作 Office 文档,包括 Word。
2089 |
2090 | (本地需要安装 Office)
2091 |
2092 | === 9.5.2 Excel(xls、xlsx) ===
2093 |
2094 | pyExcelerator
2095 |
2096 | Home:[http://sourceforge.net/projects/pyexcelerator/]
2097 |
2098 | 它可以支持 Office Excel(97/2000/XP/2003)以及 OpenOffice Calc 的文档。无需依赖外部软件。
2099 |
2100 | PyWin32
2101 |
2102 | PyWin32 前面已经介绍过。它可以基于 [https://en.wikipedia.org/wiki/Component_Object_Model COM] 操作 Office 文档,包括 Excel。
2103 |
2104 | (本地需要安装 Office)
2105 |
2106 | === 9.5.3 Power Point(ppt、pptx) ===
2107 |
2108 | python-pptx
2109 |
2110 | Home:[https://github.com/scanny/python-pptx]
2111 |
2112 | 它可以用来生成 pptx(Open XML PowerPoint)格式的文档。
2113 |
2114 | PyWin32
2115 |
2116 | PyWin32 前面已经介绍过。它可以基于 [https://en.wikipedia.org/wiki/Component_Object_Model COM] 操作 Office 文档,包括 Power Point。
2117 |
2118 | (本地需要安装 Office)
2119 |
2120 | == 9.6 RTF ==
2121 |
2122 | PyRTF
2123 |
2124 | Home:[http://pyrtf.sourceforge.net/]
2125 |
2126 | 它可以用来处理 RTF(富文本格式)文档。
2127 |
2128 | == 9.7 CHM ==
2129 |
2130 | PyCHM
2131 |
2132 | Home:[http://gnochm.sourceforge.net/pychm.html]
2133 |
2134 | 这是基于 [http://www.jedrea.com/chmlib/ chmlib] 的 Python 封装库。可以提取 CHM 文件的属性以及每个页面的内容。
2135 |
2136 | ----
2137 |
2138 | = 10 图像 =
2139 |
2140 | == 10.1 图像处理 ==
2141 |
2142 | Python Imaging Library(PIL)
2143 |
2144 | Home:[http://www.pythonware.com/products/pil/]
2145 |
2146 | Links:[https://en.wikipedia.org/wiki/Python_Imaging_Library Wikipedia]
2147 |
2148 | 这是一个很有名气的 Python 图像处理库,支持常见图像文件格式(BMP、JPG、GIF、PNG ...)。
2149 |
2150 | 它可以对图像进行各种常见的处理(旋转、缩放、剪切 ...)。
2151 |
2152 | 代码示例——为某个目录下所有 JPEG 创建缩略图
2153 |
2154 | import os, glob
2155 | from PIL import Image
2156 |
2157 | size = 128, 128
2158 | for file in glob.glob("*.jpg"):
2159 | name, ext = os.path.splitext(file)
2160 | img = Image.open(file)
2161 | img.thumbnail(size)
2162 | img.save(name+".thumbnail", "JPEG")
2163 |
2164 |
2165 | 代码示例——旋转某图片并显示
2166 |
2167 | from PIL import Image
2168 |
2169 | img = Image.open("xxx.jpg")
2170 | img = img.rotate(90)
2171 | img.show()
2172 |
2173 |
2174 | Wand
2175 |
2176 | Home:[http://docs.wand-py.org/]
2177 |
2178 | 它通过前面提到 ctypes 实现了对 [https://en.wikipedia.org/wiki/ImageMagick ImageMagick] 的封装(ImageMagick 是最强大的开源图片处理工具集)。
2179 |
2180 | 代码示例——旋转并缩放某图片
2181 |
2182 | from wand.image import Image
2183 | from wand.display import display
2184 |
2185 | with Image(filename="mona-lisa.png") as img :
2186 | print(img.size)
2187 | for r in 1, 2, 3 :
2188 | with img.clone() as new_img :
2189 | new_img.resize(int(new_img.width/2), int(new_img.height/2))
2190 | new_img.rotate(90 * r)
2191 | new_img.save(filename="mona-lisa-{0}.png".format(r))
2192 | display(new_img)
2193 |
2194 |
2195 | Pillow
2196 |
2197 | Home:[http://python-pillow.org/]
2198 |
2199 | 你可以把它视作“轻量级的 PIL”。
2200 |
2201 | 它的目标是比 PIL 更容易使用,并尽可能与 PIL 的 API 兼容。
2202 |
2203 | PyGraphviz
2204 |
2205 | Home:[https://github.com/pygraphviz/pygraphviz]
2206 |
2207 | [https://en.wikipedia.org/wiki/Graphviz Graphviz] 是一个功能很强大的关系图【自动】生成工具,具体介绍可以参见俺的博文(在“[https://program-think.blogspot.com/2016/02/opensource-review-graphviz.html 这里]”)
2208 |
2209 | 这个库如其名所示,提供了 Python 对 Graphviz 的封装(基于 SWIG)。
2210 |
2211 | Graphviz
2212 |
2213 | Home:[https://github.com/xflr6/graphviz]
2214 |
2215 | 这个库与上一个类似,也提供了 Graphviz 的 Python 的封装。
2216 |
2217 | 这两个库都在 GitHub 上。(可能是因为出现较晚)这个库的 Star 和 Fork 数都不如上一个,不过俺感觉文档比较全。
2218 |
2219 | 代码示例——创建一个 DOT 图并加入若干节点和连线
2220 |
2221 | from graphviz import Digraph
2222 |
2223 | dot = Digraph(comment='The Round Table')
2224 | # 添加节点
2225 | dot.node('A', 'King Arthur')
2226 | dot.node('B', 'Sir Bedevere the Wise')
2227 | dot.node('L', 'Sir Lancelot the Brave')
2228 | # 添加连线
2229 | dot.edges(['AB', 'AL'])
2230 | dot.edge('B', 'L', constraint='false')
2231 |
2232 |
2233 | == 10.2 图像格式转换 ==
2234 |
2235 | Python Imaging Library(PIL)
2236 |
2237 | PIL 前面已经介绍过。它支持常见图像文件格式(BMP、JPG、GIF、PNG ...)之间的相互转换。
2238 |
2239 | Wand
2240 |
2241 | Wand 前面已经介绍过。由于它是针对 [https://en.wikipedia.org/wiki/ImageMagick ImageMagick] 的封装。只要 ImageMagick 能转换的格式,它也可以转换。
2242 |
2243 | == 10.3 图像渲染 ==
2244 |
2245 | Pycairo
2246 |
2247 | Home:[http://cairographics.org/pycairo/]
2248 |
2249 | [https://en.wikipedia.org/wiki/Cairo_%28graphics%29 Cairo] 是一个图像渲染引擎,提供了矢量图像的渲染功能。支持多种后端输出(包括:Win32 GDI、OpenGL、Xlib、XCB、PDF、PNG、SVG......)。
2250 |
2251 | Pycairo 是 Cairo 官方提供 Python 封装。
2252 |
2253 | = 11 游戏 =
2254 |
2255 | == 11.1 综合性的游戏引擎 ==
2256 |
2257 | PyGame
2258 |
2259 | Home:[http://www.pygame.org/]
2260 |
2261 | Links:[https://en.wikipedia.org/wiki/Pygame Wikipedia] [https://zh.wikipedia.org/wiki/Pygame 维基百科]
2262 |
2263 | 这是名气很大的跨平台游戏引擎,构建于 [https://zh.wikipedia.org/wiki/SDL SDL](Simple DirectMedia Layer)之上。
2264 |
2265 | 它起先是用来替代终止开发的 pySDL,包含了图像和音频的库。
2266 |
2267 | Cocos2d
2268 |
2269 | Home:[http://cocos2d.org/]
2270 |
2271 | 它是一个开源的 2D 游戏框架,最初使用 Python 编写的。后来该框架已经被移植到了多种语言和平台上。
2272 |
2273 | 其功能包括了:GUI 组件、音效、物理引擎、脚本语言绑定、场景编辑器 ...
2274 |
2275 | 很多手机游戏是基于 Cocos2d 的衍生框架开发的。
2276 |
2277 | Blender Game Engine
2278 |
2279 | Home:[http://www.blender.org/]
2280 |
2281 | Links:[https://en.wikipedia.org/wiki/Game_Blender Wikipedia] [https://zh.wikipedia.org/wiki/Game_Blender 维基百科]
2282 |
2283 | 它是 [https://en.wikipedia.org/wiki/Blender_%28software%29 Blender] 的组成部分,虽然是以 C++ 编写,但内置了 Python 脚本的扩展。
2284 |
2285 | 其功能包括:3D 渲染、碰撞检测、角色编辑器、音效、网络通讯、AI ...
2286 |
2287 | == 11.2 3D 渲染引擎 ==
2288 |
2289 | PyOpenGL
2290 |
2291 | Home:[http://pyopengl.sourceforge.net/]
2292 |
2293 | 封装 [https://en.wikipedia.org/wiki/OpenGL OpenGL] 的 Python 库。
2294 |
2295 | Python-Ogre
2296 |
2297 | Home:[http://www.python-ogre.org/]
2298 |
2299 | 封装 [https://en.wikipedia.org/wiki/OGRE OGRE] 的 Python 库。
2300 |
2301 | ----
2302 |
2303 | = 12 数值计算 & 科学计算 =
2304 |
2305 | NumPy
2306 |
2307 | Home:[http://www.numpy.org/]
2308 |
2309 | Links:[https://en.wikipedia.org/wiki/NumPy Wikipedia] [https://zh.wikipedia.org/wiki/NumPy 维基百科]
2310 |
2311 | 它提供了功能强大、性能很高的数值数组,可以用来进行各种数值计算(包括矩阵运算)。
2312 |
2313 | 代码示例
2314 |
2315 | # 以下是传统 Python 写法,冗长且速度较慢
2316 | a = range(10000000)
2317 | b = range(10000000)
2318 | c = []
2319 | for i in range(len(a)) :
2320 | c.append(a[i] + b[i])
2321 |
2322 | # 以下是 NumPy 的写法,简洁且速度飞快
2323 | import numpy as np
2324 | a = np.arange(10000000)
2325 | b = np.arange(10000000)
2326 | c = a + b
2327 |
2328 |
2329 | SciPy
2330 |
2331 | Home:[http://www.scipy.org/]
2332 |
2333 | Links:[https://en.wikipedia.org/wiki/SciPy Wikipedia] [https://zh.wikipedia.org/wiki/SciPy 维基百科]
2334 |
2335 | 它依赖 NumPy 提供的多维数组。相比 NumPy,它提供了更高层的数学运算模块(统计、线性代数、积分、常微分方程求解、傅立叶变换、信号处理 ...)。
2336 |
2337 | 它被广泛用于科研和工程领域。
2338 |
2339 | SymPy
2340 |
2341 | Home:[http://sympy.org/]
2342 |
2343 | Links:[https://en.wikipedia.org/wiki/SymPy Wikipedia] [https://zh.wikipedia.org/wiki/SymPy 维基百科]
2344 |
2345 | 它是用来做符号计算的,其目标是成为一个全功能的“计算机代数系统”。
2346 |
2347 | 它支持的功能包括:符号计算、高精度计算、模式匹配、绘图、解方程、微积分、组合数学、离散数学、几何学、概率与统计 ......
2348 |
2349 | ----
2350 |
2351 | = 13 (其它) =
2352 |
2353 | 一些不方便归类的,暂时放到这里。
2354 |
2355 | PyPy
2356 |
2357 | Home:[http://www.pypy.org/]
2358 |
2359 | Links:[https://en.wikipedia.org/wiki/PyPy Wikipedia] [https://zh.wikipedia.org/wiki/PyPy 维基百科]
2360 |
2361 | 它是一个用 Python 写的 Python 解释器(有点绕口令)。
2362 |
2363 | PyPy 支持 JIT(Just-in-time compilation)和沙箱技术,可做到【比 CPython 更快的运行速度】。
2364 |
2365 |
--------------------------------------------------------------------------------