<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Vimer的程序世界 &#187; 操作系统</title>
	<atom:link href="http://www.vimer.cn/category/os/feed" rel="self" type="application/rss+xml" />
	<link>http://www.vimer.cn</link>
	<description></description>
	<lastBuildDate>Thu, 17 May 2012 11:40:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>最近的一些技术整理（20120405）</title>
		<link>http://www.vimer.cn/2012/04/%e6%9c%80%e8%bf%91%e7%9a%84%e4%b8%80%e4%ba%9b%e6%8a%80%e6%9c%af%e6%95%b4%e7%90%86%ef%bc%8820120405%ef%bc%89.html</link>
		<comments>http://www.vimer.cn/2012/04/%e6%9c%80%e8%bf%91%e7%9a%84%e4%b8%80%e4%ba%9b%e6%8a%80%e6%9c%af%e6%95%b4%e7%90%86%ef%bc%8820120405%ef%bc%89.html#comments</comments>
		<pubDate>Thu, 05 Apr 2012 12:24:27 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[uwsgi]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=2525</guid>
		<description><![CDATA[还是和往常一样，没啥主题，就是记录下这段时间遇到的技术问题，分享一下。 1. 在javascript中实现简单的模板替换 最近搞了一下js，最不习惯的就是字符串生成都要用字符串拼装或者join的方... ]]></description>
			<content:encoded><![CDATA[<p>还是和往常一样，没啥主题，就是记录下这段时间遇到的技术问题，分享一下。</p>
<p><strong>1. 在javascript中实现简单的模板替换</strong></p>
<p>最近搞了一下js，最不习惯的就是字符串生成都要用字符串拼装或者join的方式，所以尝试一下看能否实现简单的模板替换，效果还不错。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> str_format<span style="color: #009900;">&#40;</span>str<span style="color: #339933;">,</span> obj<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> str.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/\{\s*(\w+)\s*\}/g</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>_i<span style="color: #339933;">,</span> _1<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> obj<span style="color: #009900;">&#91;</span>_1<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> <span style="color: #003366; font-weight: bold;">null</span> <span style="color: #339933;">?</span> obj<span style="color: #009900;">&#91;</span>_1<span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>很多朋友会说性能差一些，可能确实如此，不过对我来说，相比编写的舒适来说，这点性能差别实在无足轻重了。</p>
<p><strong>2. uwsgi报readv() faild</strong></p>
<p>用uwsgi+nginx搭建的server，发现当用post请求时，会返回数据超时。查了一下uwsgi的error.log:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">9825#0: *745262 readv() failed (104: Connection reset by peer) while reading upstream, client: 121.14.96.125</pre></td></tr></table></div>

<p>后来在网上搜了一下文档：<br />
<a href="http://comments.gmane.org/gmane.comp.python.wsgi.uwsgi.general/1021" target="_blank" >http://comments.gmane.org/gmane.comp.python.wsgi.uwsgi.general/1021</a></p>
<p>其解释说解决方案有两种：<br />
在uwsgi执行参数上增加：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #660033;">--pep333-input</span>
<span style="color: #660033;">--post-buffering</span> <span style="color: #000000;">4096</span></pre></td></tr></table></div>

<p>试了一下，只有第二种有效，所以由于google了一下命令的具体含义：</p>
<p>
post-buffering<br />
打开http body缓冲, 如果HTTP body的大小超过指定的限制,那么就保存到磁盘上.
</p>
<p>参考链接：<br />
<a href="http://simple-is-better.com/news/301" target="_blank" >http://simple-is-better.com/news/301</a></p>
<p>OK，就是这样~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2012/04/%e6%9c%80%e8%bf%91%e7%9a%84%e4%b8%80%e4%ba%9b%e6%8a%80%e6%9c%af%e6%95%b4%e7%90%86%ef%bc%8820120405%ef%bc%89.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>通过引用计数解决野指针的问题(C&amp;C++)</title>
		<link>http://www.vimer.cn/2011/06/%e9%80%9a%e8%bf%87%e5%bc%95%e7%94%a8%e8%ae%a1%e6%95%b0%e8%a7%a3%e5%86%b3%e9%87%8e%e6%8c%87%e9%92%88%e7%9a%84%e9%97%ae%e9%a2%98cc.html</link>
		<comments>http://www.vimer.cn/2011/06/%e9%80%9a%e8%bf%87%e5%bc%95%e7%94%a8%e8%ae%a1%e6%95%b0%e8%a7%a3%e5%86%b3%e9%87%8e%e6%8c%87%e9%92%88%e7%9a%84%e9%97%ae%e9%a2%98cc.html#comments</comments>
		<pubDate>Mon, 13 Jun 2011 11:44:43 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[delete]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[pty_proxy]]></category>
		<category><![CDATA[互指指针]]></category>
		<category><![CDATA[引用]]></category>
		<category><![CDATA[引用计数]]></category>
		<category><![CDATA[指针释放]]></category>
		<category><![CDATA[析构]]></category>
		<category><![CDATA[野指针]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=2207</guid>
		<description><![CDATA[C/C++代码中，野指针问题历来已久，当然，大家都知道new/delete要成对出现: 1 2 3 A *p = new A&#40;&#41;; delete p; p = NULL; 然而现实中却并不是总是如此简单，考虑如下例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16... ]]></description>
			<content:encoded><![CDATA[<p>C/C++代码中，野指针问题历来已久，当然，大家都知道new/delete要成对出现:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">A <span style="color: #000040;">*</span>p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000dd;">delete</span> p<span style="color: #008080;">;</span>
p <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>然而现实中却并不是总是如此简单，考虑如下例子:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> A
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    C<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~C<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> B
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        m_pA <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> SetA<span style="color: #008000;">&#40;</span>A<span style="color: #000040;">*</span> p<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        m_pA <span style="color: #000080;">=</span> p<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    A<span style="color: #000040;">*</span> m_pA<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
A<span style="color: #000040;">*</span> pA <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
B<span style="color: #000040;">*</span> pB <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
pB<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>SetA<span style="color: #008000;">&#40;</span>pA<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000dd;">delete</span> pA<span style="color: #008080;">;</span>
pA <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
<span style="color: #666666;">//此时B中的m_pA已经无效，但是m_pA仍然不等于NULL，所以用 != NULL来判断不会有任何作用</span></pre></td></tr></table></div>

<p>简单来说，即pA被赋值为NULL，对B中的m_pA没有产生影响，那么怎么才能产生影响呢？<br />
我们有两个做法：<br />
第一种，在A的析构函数里面去B.SetA(NULL)，但是这个相当于A去操作了B的数据，这是不合理的。而且当外面的指针非常多的时候，也根本不可能实现。<br />
第二种方法呢？是的，我们可以用二级指针。<br />
考虑如下代码:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> A
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    C<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~C<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> B
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        m_ppA <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> SetA<span style="color: #008000;">&#40;</span>A<span style="color: #000040;">**</span> pp<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        m_ppA <span style="color: #000080;">=</span> pp<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    A<span style="color: #000040;">**</span> m_ppA<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
A<span style="color: #000040;">**</span> ppA <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #008000;">&#40;</span>A<span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>ppA<span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
B<span style="color: #000040;">*</span> pB <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
pB<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>SetA<span style="color: #008000;">&#40;</span>ppA<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000dd;">delete</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>ppA<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>ppA<span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #666666;">//这个时候，B中的m_ppA也会收到影响，即*m_ppA == NULL</span></pre></td></tr></table></div>

<p>这样确实可以解决野指针的问题，但是同时也引入了另一个问题，那就是ppA本身该什么时候释放呢？答案是：当最后一个引用ppA的类释放掉的时候。<br />
最后一个，对，我们可以使用引用计数！<br />
OK，正式放出我们的代码，其中使用了引用计数来确定当最后一个类释放掉的时候，ppA指针的内存被析构:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #ff0000; font-style: italic;">/*=============================================================================
#
#     FileName: ptr_proxy.h
#         Desc: 这个类的作用，就是为了解决互指指针，不知道对方已经析构的问题
#
#       Author: dantezhu
#        Email: zny2008@gmail.com
#     HomePage: http://www.vimer.cn
#
#      Created: 2011-06-13 15:24:12
#      Version: 0.0.1
#      History:
#               0.0.1 | dantezhu | 2011-06-13 15:24:12 | initialization
#
=============================================================================*/</span>
&nbsp;
<span style="color: #339900;">#ifndef __PTR_PROXY_H__</span>
<span style="color: #339900;">#define __PTR_PROXY_H__</span>
<span style="color: #339900;">#include &lt;stdio.h&gt;</span>
<span style="color: #339900;">#include &lt;string.h&gt;</span>
<span style="color: #339900;">#include &lt;stdint.h&gt;</span>
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;memory&gt;</span>
<span style="color: #339900;">#include &lt;sstream&gt;</span>
<span style="color: #339900;">#include &lt;algorithm&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #339900;">#include &lt;map&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> ptr_proxy
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    ptr_proxy<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">*</span> pobj<span style="color: #000080;">=</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> m_ppobj<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>, m_pcount<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pobj <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        init<span style="color: #008000;">&#40;</span>pobj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    ptr_proxy<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> ptr_proxy<span style="color: #000040;">&amp;</span> rhs<span style="color: #008000;">&#41;</span> <span style="color: #666666;">// 拷贝构造函数</span>
    <span style="color: #008000;">&#123;</span>
        m_ppobj <span style="color: #000080;">=</span> rhs.<span style="color: #007788;">m_ppobj</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 指向同一块内存</span>
        m_pcount <span style="color: #000080;">=</span> rhs.<span style="color: #007788;">m_pcount</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 使用同一个计数值</span>
        add_count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">virtual</span> ~ptr_proxy<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        dec_count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   如果指向的对象被释放了，一定要调用这个函数让他知道
     */</span>
    <span style="color: #0000ff;">void</span> set2null<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_ppobj<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>m_ppobj<span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   copy构造函数
     *
     * @param   rhs         被拷贝对象
     *
     * @return  自己的引用
     */</span>
    ptr_proxy<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> ptr_proxy<span style="color: #000040;">&amp;</span> rhs<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span> m_ppobj <span style="color: #000080;">==</span> rhs.<span style="color: #007788;">m_ppobj</span> <span style="color: #008000;">&#41;</span> <span style="color: #666666;">// 首先判断是否本来就指向同一内存块</span>
            <span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 是则直接返回</span>
&nbsp;
        dec_count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        m_ppobj <span style="color: #000080;">=</span> rhs.<span style="color: #007788;">m_ppobj</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 指向同一块内存</span>
        m_pcount <span style="color: #000080;">=</span> rhs.<span style="color: #007788;">m_pcount</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 使用同一个计数值</span>
        add_count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 是则直接返回</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    ptr_proxy<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">*</span> pobj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>m_ppobj <span style="color: #000040;">&amp;&amp;</span> <span style="color: #000040;">*</span>m_ppobj <span style="color: #000080;">==</span> pobj<span style="color: #008000;">&#41;</span> <span style="color: #666666;">// 首先判断是否本来就指向同一内存块</span>
            <span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 是则直接返回</span>
        dec_count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        init<span style="color: #008000;">&#40;</span>pobj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   获取内部关联的obj的指针
     *
     * @return
     */</span>
    T<span style="color: #000040;">*</span> true_ptr<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_ppobj<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span>m_ppobj<span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">else</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   获取内部关联的obj的指针
     *
     * @return
     */</span>
    T<span style="color: #000040;">*</span> operator<span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> true_ptr<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   获取内部关联的obj的个数
     *
     * @return  个数
     */</span>
    <span style="color: #0000ff;">int</span> count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_pcount <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span>m_pcount<span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   判断智能指针是否为空
     *
     * @return
     */</span>
    <span style="color: #0000ff;">bool</span> is_null<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_ppobj <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span> <span style="color: #000040;">||</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>m_ppobj<span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span> init<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">*</span> pobj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        m_ppobj <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #008000;">&#40;</span>T<span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #000040;">*</span>m_ppobj <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>T<span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span>pobj<span style="color: #008080;">;</span>
        m_pcount <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 初始化计数值为 1</span>
        <span style="color: #000040;">*</span>m_pcount <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> add_count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_pcount <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>m_pcount<span style="color: #008000;">&#41;</span> <span style="color: #000040;">++</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   计数减1
     */</span>
    <span style="color: #0000ff;">void</span> dec_count<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_pcount <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span> <span style="color: #000040;">||</span> m_ppobj <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>m_pcount<span style="color: #008000;">&#41;</span><span style="color: #000040;">--</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 计数值减 1 ，因为该指针不再指向原来内存块了</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span> <span style="color: #000040;">*</span>m_pcount <span style="color: #000080;">&lt;=</span> <span style="color: #0000dd;">0</span> <span style="color: #008000;">&#41;</span> <span style="color: #666666;">// 已经没有别的指针指向原来内存块了</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #666666;">//我们不去主动析构对象</span>
            <span style="color: #666666;">//free_sptr(*m_ppobj);//把对象析构</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_ppobj <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #0000dd;">delete</span> m_ppobj<span style="color: #008080;">;</span>
                m_ppobj <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
&nbsp;
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_pcount <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #0000dd;">delete</span> m_pcount<span style="color: #008080;">;</span>
                m_pcount <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
    T<span style="color: #000040;">**</span> m_ppobj<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> m_pcount<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> IPtrProxy
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    IPtrProxy<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        m_ptr_proxy <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>T<span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~IPtrProxy<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        m_ptr_proxy.<span style="color: #007788;">set2null</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    ptr_proxy<span style="color: #000080;">&lt;</span>T<span style="color: #000080;">&gt;</span><span style="color: #000040;">&amp;</span> get_ptr_proxy<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> m_ptr_proxy<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
    ptr_proxy<span style="color: #000080;">&lt;</span>T<span style="color: #000080;">&gt;</span> m_ptr_proxy<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>我们来写段测试代码测试一下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
<span style="color: #339900;">#include &lt;string.h&gt;</span>
<span style="color: #339900;">#include &lt;stdint.h&gt;</span>
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;memory&gt;</span>
<span style="color: #339900;">#include &lt;sstream&gt;</span>
<span style="color: #339900;">#include &lt;algorithm&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #339900;">#include &lt;map&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;ptr_proxy.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> A <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IPtrProxy<span style="color: #000080;">&lt;</span>A<span style="color: #000080;">&gt;</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> B <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IPtrProxy<span style="color: #000080;">&lt;</span>B<span style="color: #000080;">&gt;</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> print<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;this is print<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> SetAPtr<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> ptr_proxy<span style="color: #000080;">&lt;</span>A<span style="color: #000080;">&gt;</span><span style="color: #000040;">&amp;</span> pptr<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        m_ptr_a <span style="color: #000080;">=</span> pptr<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> check<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_ptr_a.<span style="color: #007788;">is_null</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;is null<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">else</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;is not null<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    ptr_proxy<span style="color: #000080;">&lt;</span>A<span style="color: #000080;">&gt;</span> m_ptr_a<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    A<span style="color: #000040;">*</span> a <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    B<span style="color: #000040;">*</span> b <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    b<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>SetAPtr<span style="color: #008000;">&#40;</span>a<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>get_ptr_proxy<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">delete</span> a<span style="color: #008080;">;</span>
    b<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>check<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    b<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>get_ptr_proxy<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">true_ptr</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>print<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">delete</span> b<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>输出为:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">is null
this is print</pre></div></div>

<p>这个类最有效的使用场景是当出现大量互指指针时，那么指向对象的指针有效性判断就尤其重要，而这个类可以完美解决这个问题。</p>
<p>可能想的比较深的朋友会问，既然引用计数都已经用上了，那么为什么不直接通过引用计数来析构呢？<br />
其实这几天我也在尝试，C++是否能引入完美的引用计数进行对象管理，而最终卡在一个地方，即：</p>
<p>如果，在类的构造函数里面，需要将引用计数对象构造出来，那么引用计数就会出现问题，如:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> A
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        Count t<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
Count c <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>这个时候就会出现问题，除非把Count构造的计数对象放到一个对象池中管理，但是又会增加对象查找的成本，所以最终放弃了这个想法。<br />
另外一点就是，C/C++的指针在很多情况下是最方便的，过度的封装很可能会弄巧成拙，所以适度就好。</p>
<p>OK，惯例代码还是放到googlecode上：<br />
<a href="http://code.google.com/p/vimercode/source/browse/#svn%2Ftrunk%2Fptr_proxy" target="_blank" >http://code.google.com/p/vimercode/source/browse/#svn%2Ftrunk%2Fptr_proxy</a></p>
<p>目前代码使用中没有发现明显问题，欢迎大家交流~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2011/06/%e9%80%9a%e8%bf%87%e5%bc%95%e7%94%a8%e8%ae%a1%e6%95%b0%e8%a7%a3%e5%86%b3%e9%87%8e%e6%8c%87%e9%92%88%e7%9a%84%e9%97%ae%e9%a2%98cc.html/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>最近遇到的问题整理(linux下创建线程内存泄漏,php的json_encode等)</title>
		<link>http://www.vimer.cn/2011/04/%e6%9c%80%e8%bf%91%e9%81%87%e5%88%b0%e7%9a%84%e9%97%ae%e9%a2%98%e6%95%b4%e7%90%86linux%e4%b8%8b%e5%88%9b%e5%bb%ba%e7%ba%bf%e7%a8%8b%e5%86%85%e5%ad%98%e6%b3%84%e6%bc%8fphp%e7%9a%84json_encode.html</link>
		<comments>http://www.vimer.cn/2011/04/%e6%9c%80%e8%bf%91%e9%81%87%e5%88%b0%e7%9a%84%e9%97%ae%e9%a2%98%e6%95%b4%e7%90%86linux%e4%b8%8b%e5%88%9b%e5%bb%ba%e7%ba%bf%e7%a8%8b%e5%86%85%e5%ad%98%e6%b3%84%e6%bc%8fphp%e7%9a%84json_encode.html#comments</comments>
		<pubDate>Fri, 15 Apr 2011 12:30:37 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[pthread_create]]></category>
		<category><![CDATA[pthread_detach]]></category>
		<category><![CDATA[thread]]></category>
		<category><![CDATA[内存泄漏]]></category>
		<category><![CDATA[线程]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=2170</guid>
		<description><![CDATA[这次还是把遇到的几个问题整理一下，希望再遇到的同学能轻松解决。另外最近博客的feeds延迟更新的原因也会一起说明一下。 1.linux下创建线程导致内存泄漏 今天在外网发布了一个server之后，... ]]></description>
			<content:encoded><![CDATA[<p>这次还是把遇到的几个问题整理一下，希望再遇到的同学能轻松解决。另外最近博客的feeds延迟更新的原因也会一起说明一下。</p>
<p><b>1.linux下创建线程导致内存泄漏</b><br />
今天在外网发布了一个server之后，用top发现virt的使用量一直在涨，而且一次涨8m。于是可以断定有内存泄漏了，经过排查，最终确定原因出在多线程的问题上:<br />
代码如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">pthread_t thread_id<span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> ret<span style="color: #000080;">=</span>pthread_create<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>thread_id, <span style="color: #0000ff;">NULL</span>, flush_thread_work, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">&amp;</span>m_sql_client<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
    APPSCORE_ERROR<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Thread creation failed:%d&quot;</span>,ret<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> ret<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>在flush_thread_work函数内部:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> flush_thread_work<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> args<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">//....do something</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>代码中启动了一个线程之后，主进程就继续执行，任由新线程自生自灭了（没有调用thread_join），而主进程每隔一段时间就会拉起这样一个线程来做一些数据落地的事情。</p>
<p>这样的写法实际上是会造成内存泄漏的.<br />
Linux man page 里有已经说明了这个问题：</p>
<blockquote><p>
When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called  once  for each joinable thread created to avoid memory leaks.
</p></blockquote>
<p>也就说线程执行完后如果不join的话，线程的资源会一直得不到释放而导致内存泄漏！</p>
<p>解决方法有两种:<br />
a.在线程执行的函数内手工释放</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> flush_thread_work<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> args<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">//....do something</span>
    pthread_detach<span style="color: #008000;">&#40;</span>pthread_self<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>b.在线程启动时，设置线程的PTHREAD_CREATE_DETACHED属性</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">pthread_attr_t attr<span style="color: #008080;">;</span>
pthread_attr_init <span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>attr<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
pthread_attr_setdetachstate <span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>attr, PTHREAD_CREATE_DETACHED<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> ret<span style="color: #000080;">=</span>pthread_create<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>thread_id, <span style="color: #000040;">&amp;</span>attr, flush_thread_work, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">&amp;</span>m_sql_client<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">//记住attr也要析构，否则又是一个内存泄漏</span>
    pthread_attr_destroy <span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>attr<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    APPSCORE_ERROR<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Thread creation failed:%d&quot;</span>,ret<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> ret<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span> 
&nbsp;
<span style="color: #666666;">//记住attr也要析构，否则又是一个内存泄漏</span>
pthread_attr_destroy <span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>attr<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>这样问题就可以解决了。<br />
参考资料:<br />
<a href="http://www.cnblogs.com/bits/archive/2009/12/04/no_join_or_detach_memory_leak.html" target="_blank" >解决了一个隐蔽的内存泄漏——pthread_create后没有detach导致内存持续增长 </a></p>
<p><b>2.php的json_encode函数问题</b><br />
在公司做了一个应用，是php与c++进行网络交互，所以选择了json这种比较通用的序列化格式，然而却遇到了比较奇怪的问题。<br />
先来看如下代码(php):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$objs</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'a'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'b'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'d'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$objs</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>输出的结果如下：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">{&quot;0&quot;:&quot;a&quot;,&quot;1&quot;:&quot;b&quot;,&quot;3&quot;:&quot;d&quot;}</pre></div></div>

<p>这样是正常的，用jsoncpp也可以正确的解析出来，php自动将$objs当作一个关联数组来生成json数据了。<br />
然而当把代码换成如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$objs</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'a'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'b'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'c'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'d'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$objs</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>则输出结果如下:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">[&quot;a&quot;,&quot;b&quot;,&quot;c&quot;,&quot;d&quot;]</pre></div></div>

<p>jsoncpp按照之前的解析方法是解析不出来的~<br />
其实对php来说，这也是合理的，问题在于在php里面普通数组和关联数组都是array，而对c++来说，却存在vector和map之分，所以如果还是想要json_encode生成关联数组的格式，那么需要这样写:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$objs</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'a'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'b'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'c'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$objs</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'d'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>object<span style="color: #009900;">&#41;</span><span style="color: #000088;">$objs</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>结果如下:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">{&quot;0&quot;:&quot;a&quot;,&quot;1&quot;:&quot;b&quot;,&quot;2&quot;:&quot;c&quot;,&quot;3&quot;:&quot;d&quot;}</pre></div></div>

<p><b>3.本博feed延迟不更新的原因</b><br />
之前由于对feedsky的feed更新十分不满，所以参考网上的做法，建立了一个feed.vimer.cn，而本博所在的域名空间会自动根据域名创建一个子目录 - feed，修改这个目录下的.htaccess文件如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;</span>IfModule mod_rewrite.c<span style="color: #000000; font-weight: bold;">&gt;</span>
RewriteEngine On
RewriteBase <span style="color: #000000; font-weight: bold;">/</span>
RewriteRule . http:<span style="color: #000000; font-weight: bold;">//</span>feed.feedsky.com<span style="color: #000000; font-weight: bold;">/</span>vimer <span style="color: #7a0874; font-weight: bold;">&#91;</span>L<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">&lt;/</span>IfModule<span style="color: #000000; font-weight: bold;">&gt;</span></pre></td></tr></table></div>

<p>那么当访问 feed.vimer.cn 时，会自动跳转到 <a href="http://feed.feedsky.com/vimer" target="_blank" >http://feed.feedsky.com/vimer</a>。<br />
然而我忽略了一个问题，那就是wordpress默认的feed链接是 <a href="http://vimer.cn/feed/rss2" target="_blank" >http://vimer.cn/feed/rss2</a>，而/feed/rss2会被解析成子目录，从而自动跳转到 <a href="http://feed.feedsky.com/vimer" target="_blank" >http://feed.feedsky.com/vimer</a> ，所以feedsky就会不停的读 <a href="http://feed.feedsky.com/vimer" target="_blank" >http://feed.feedsky.com/vimer</a> 这个链接的feed，当然不会有任何新数据。。</p>
<p>所以最后还是把这种方式废弃掉了，看来真是冤枉了feedsky呀~~~</p>
<p>OK，最近的总结就这么多~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2011/04/%e6%9c%80%e8%bf%91%e9%81%87%e5%88%b0%e7%9a%84%e9%97%ae%e9%a2%98%e6%95%b4%e7%90%86linux%e4%b8%8b%e5%88%9b%e5%bb%ba%e7%ba%bf%e7%a8%8b%e5%86%85%e5%ad%98%e6%b3%84%e6%bc%8fphp%e7%9a%84json_encode.html/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>有限状态机的C++实现(2)-bayonet开源网络服务器框架</title>
		<link>http://www.vimer.cn/2011/02/%e6%9c%89%e9%99%90%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84%e5%ae%9e%e7%8e%b02-bayonet%e5%bc%80%e6%ba%90%e7%bd%91%e7%bb%9c%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%a1%86%e6%9e%b6.html</link>
		<comments>http://www.vimer.cn/2011/02/%e6%9c%89%e9%99%90%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84%e5%ae%9e%e7%8e%b02-bayonet%e5%bc%80%e6%ba%90%e7%bd%91%e7%bb%9c%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%a1%86%e6%9e%b6.html#comments</comments>
		<pubDate>Fri, 18 Feb 2011 08:35:39 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[开源项目]]></category>
		<category><![CDATA[bayonet]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[epoll]]></category>
		<category><![CDATA[fuload]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[开源]]></category>
		<category><![CDATA[异步]]></category>
		<category><![CDATA[网络服务器]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=1983</guid>
		<description><![CDATA[接着上一篇文章: 有限状态机的C++实现(1)-epoll状态机，我们今天来介绍更复杂和深入的部分。 为什么会在标题中提到bayonet这个开源项目呢？笔者本人一直想要写一套架构优美、功能完善的异步s... ]]></description>
			<content:encoded><![CDATA[<p>接着上一篇文章: <a href="http://www.vimer.cn/2011/01/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84c%E5%AE%9E%E7%8E%B01-epoll%E7%8A%B6%E6%80%81%E6%9C%BA.html" target="_blank" >有限状态机的C++实现(1)-epoll状态机</a>，我们今天来介绍更复杂和深入的部分。</p>
<p>为什么会在标题中提到<a href="http://code.google.com/p/bayonet/" target="_blank" >bayonet</a>这个开源项目呢？笔者本人一直想要写一套架构优美、功能完善的异步server框架，也看过很多朋友、同事实现的版本，虽然功能上基本能满足需求，但是架构上我却始终觉得是有瑕疵的，直到后来和同事讨论，发现可以让一个客户端请求的到来作为一个session，而之后的每一次与其他server的交互都可以看作是一次状态转化，才感觉架构比较合理了。</p>
<p>简单来说即，一个session从开始到介绍会经历两种状态机的变化：</p>
<ul>
<li>1.业务逻辑层面的状态变化，例如先验证登录态，再验证权限，再获取用户资料</li>
<li>2.每一个与其他server交互的socket自身的状态变化，如recv、send、等，而socket的状态变化会触发逻辑层的状态变化。</li>
</ul>
<p>按照这种思路，目前的代码开发已经完成了70%，即可以正常的进行一个session的开始和结束，主要还缺一些细节的代码，比如超时的检测及超时之后的处理，健全的统计之类。好了，我们来用vs看一下代码的整体类图（图压缩比较严重，请单击后查看）：</p>
<p><a href="http://www.vimer.cn/wp-content/uploads/2011/02/bayonet_code.png" target="_blank" ><img title="http://www.vimer.cn/wp-content/uploads/2011/02/bayonet_code.png" src="http://www.vimer.cn/wp-content/uploads/2011/02/bayonet_code.png" width="570" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" alt="1" border="0" /></a></p>
<p>每个类的用处已经在途中简单说明了，这里就不再赘述，我们重点来看一下用这个框架来实现一个逻辑server时需要做哪些事情。<br />
<a href="http://code.google.com/p/bayonet/source/browse/#svn%2Ftrunk%2Fsrc%2Fsvr2" target="_blank" >svr2</a>目录下的main.cpp即实现了一个最简单的server，我们按部分来看其实现:<br />
<b>1.逻辑层状态的定义</b></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CAppFsmLogic1 <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> CAppFsmBase
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">virtual</span> ~CAppFsmLogic1 <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> HandleEntry<span style="color: #008000;">&#40;</span>CActionInfoSet <span style="color: #000040;">*</span>pActionInfoSet, CAppActorBase<span style="color: #000040;">*</span> pAppActor<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">static</span> CActionFirst actionFirst<span style="color: #008080;">;</span>
        StActionInfoParam param<span style="color: #008080;">;</span>
        param.<span style="color: #007788;">id</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
        param.<span style="color: #007788;">ip</span> <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;127.0.0.1&quot;</span><span style="color: #008080;">;</span>
        param.<span style="color: #007788;">port</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">100</span><span style="color: #008080;">;</span>
        param.<span style="color: #007788;">protoType</span> <span style="color: #000080;">=</span> PROTO_TYPE_UDP<span style="color: #008080;">;</span>
        param.<span style="color: #007788;">pAction</span> <span style="color: #000080;">=</span> <span style="color: #000040;">&amp;</span>actionFirst<span style="color: #008080;">;</span>
        param.<span style="color: #007788;">actionType</span> <span style="color: #000080;">=</span> ACTIONTYPE_SENDONLY<span style="color: #008080;">;</span>
        param.<span style="color: #007788;">timeout_ms</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">1000</span><span style="color: #008080;">;</span>
&nbsp;
        CActionInfo <span style="color: #000040;">*</span> pActionInfo <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> CActionInfo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        pActionInfo<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Init<span style="color: #008000;">&#40;</span>param<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        pActionInfo<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>SetAppActor<span style="color: #008000;">&#40;</span>pAppActor<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        pActionInfoSet<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Add<span style="color: #008000;">&#40;</span>pActionInfo<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> HandleProcess<span style="color: #008000;">&#40;</span>CActionInfoSet <span style="color: #000040;">*</span>pActionInfoSet, CAppActorBase<span style="color: #000040;">*</span> pAppActor<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        trace_log<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;HandleProcess&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        set<span style="color: #000080;">&lt;</span>CActionInfo<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">&amp;</span>setAction <span style="color: #000080;">=</span> pActionInfoSet<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetActionSet<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>set<span style="color: #000080;">&lt;</span>CActionInfo<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it <span style="color: #000080;">=</span> setAction.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> setAction.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            trace_log<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;error no:%d&quot;</span>,<span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetErrno<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> APP_FSM_RSP<span style="color: #008080;">;</span><span style="color: #666666;">//代表要回复客户端啦</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> HandleExit<span style="color: #008000;">&#40;</span>CActionInfoSet <span style="color: #000040;">*</span>pActionInfoSet, CAppActorBase<span style="color: #000040;">*</span> pAppActor<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>CAppFsmLogic1是一个逻辑层的状态:</p>
<ul>
<li>1.HandleEntry代表当这个状态第一次进入的时候要做的事情，其函数中创建了一个向其他server发包的action(CActionFirst的定义我们在后面介绍)。</li>
<li>2.HandleProcess代表当这个状态的所有action都完成时需要做的事情，return APP_FSM_RSP;代表向客户端回包</li>
</ul>
<p>看到这里大家应该很奇怪，对于每一个socket，判断收包长度以及受到包之后的解包在哪里完成呢？所以我们还需要定义action:<br />
<b>2.action的定义</b></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define APP_FSM_LOGIC1 2000</span>
&nbsp;
<span style="color: #0000ff;">class</span> CAppFsmLogic1<span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> CActionFirst <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IAction
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #666666;">// 为发送打包</span>
    <span style="color: #0000ff;">int</span> HandleEncodeSendBuf<span style="color: #008000;">&#40;</span>
            IActor<span style="color: #000040;">*</span> pSocketActor,
            IActor<span style="color: #000040;">*</span> pAppActor,
            string <span style="color: #000040;">&amp;</span> strSendBuf,
            <span style="color: #0000ff;">int</span> <span style="color: #000040;">&amp;</span>len<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        trace_log<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;send&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        strSendBuf<span style="color: #000080;">=</span><span style="color: #FF0000;">&quot;woainizhende111111&quot;</span><span style="color: #008080;">;</span>
        len <span style="color: #000080;">=</span> strSendBuf.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #666666;">// 回应包完整性检查</span>
    <span style="color: #0000ff;">int</span> HandleInput<span style="color: #008000;">&#40;</span>
            IActor<span style="color: #000040;">*</span> pSocketActor,
            IActor<span style="color: #000040;">*</span> pAppActor,
            <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>buf,
            <span style="color: #0000ff;">int</span> len<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> len<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #666666;">// 回应包解析</span>
    <span style="color: #0000ff;">int</span> HandleDecodeRecvBuf<span style="color: #008000;">&#40;</span>
            IActor<span style="color: #000040;">*</span> pSocketActor,
            IActor<span style="color: #000040;">*</span> pAppActor,
            <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>buf, 
            <span style="color: #0000ff;">int</span> len<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        CAppActorBase <span style="color: #000040;">*</span> app_actor <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> CAppActorBase<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        app_actor<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>AttachFrame<span style="color: #008000;">&#40;</span>pSocketActor<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetFrame<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        app_actor<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>AttachCommu<span style="color: #008000;">&#40;</span>pSocketActor<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        app_actor<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>ChangeState<span style="color: #008000;">&#40;</span>APP_FSM_LOGIC1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        trace_log<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;listen tcp HandleDecodeRecvBuf&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>每个函数的意义已经在代码中说明了，可以看出在HandleDecodeRecvBuf中创建逻辑层的actor: app_actor，并ChangeState为APP_FSM_LOGIC1。<br />
最后就是main函数的实现了:<br />
<b>3.main函数实现</b></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    CBayonetFrame srv<span style="color: #008080;">;</span>
    StFrameParam param<span style="color: #008080;">;</span>
    param.<span style="color: #007788;">ip</span><span style="color: #000080;">=</span><span style="color: #FF0000;">&quot;0.0.0.0&quot;</span><span style="color: #008080;">;</span>
    param.<span style="color: #007788;">port</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">10001</span><span style="color: #008080;">;</span>
    param.<span style="color: #007788;">bKeepcnt</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
    <span style="color: #666666;">//param.protoType = PROTO_TYPE_UDP;</span>
    param.<span style="color: #007788;">protoType</span> <span style="color: #000080;">=</span> PROTO_TYPE_TCP<span style="color: #008080;">;</span>
    param.<span style="color: #007788;">pAction</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> CActionFirst<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    srv.<span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span>param<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    srv.<span style="color: #007788;">RegFsm</span><span style="color: #008000;">&#40;</span>APP_FSM_LOGIC1,<span style="color: #0000dd;">new</span> CAppFsmLogic1<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    srv.<span style="color: #007788;">Process</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>注释的部分是可以随时切换TCP还是UDP的。<br />
当然作为一个server来说，这里还是太过简单了，比如信号的处理等都没有加上，但是笔者认为那是业务代码需要做的逻辑，所以并没有放到框架中。</p>
<p>OK，整个项目的结构就是这个样子了。<br />
但是也不得不说点扫兴的话，由于笔者最近有另外一个项目需要投入大量的精力，所以该项目的更新可能会被延缓，这是我所不愿意看到的，所以很希望有志同道合的朋友能够加入到这个项目的开发中来，一起把这个事情做出来。</p>
<p>按照我当初的想法，压力测试框架<a href="http://code.google.com/p/fuload/" target="_blank" >fuload</a>已经就绪了，等到bayonet完成，我们就用fuload来测试一下bayonet的性能究竟如何。</p>
<p>最后，附上bayonet的项目地址:<br />
<a href="http://code.google.com/p/bayonet/" target="_blank" >http://code.google.com/p/bayonet/</a><br />
十分欢迎大家感兴趣的朋友与我联系。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2011/02/%e6%9c%89%e9%99%90%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84%e5%ae%9e%e7%8e%b02-bayonet%e5%bc%80%e6%ba%90%e7%bd%91%e7%bb%9c%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%a1%86%e6%9e%b6.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>有限状态机的C++实现(1)-epoll状态机</title>
		<link>http://www.vimer.cn/2011/01/%e6%9c%89%e9%99%90%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84c%e5%ae%9e%e7%8e%b01-epoll%e7%8a%b6%e6%80%81%e6%9c%ba.html</link>
		<comments>http://www.vimer.cn/2011/01/%e6%9c%89%e9%99%90%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84c%e5%ae%9e%e7%8e%b01-epoll%e7%8a%b6%e6%80%81%e6%9c%ba.html#comments</comments>
		<pubDate>Thu, 20 Jan 2011 03:55:03 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[epoll]]></category>
		<category><![CDATA[Finite-state machine]]></category>
		<category><![CDATA[fsm]]></category>
		<category><![CDATA[有限状态机]]></category>
		<category><![CDATA[状态机]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=1965</guid>
		<description><![CDATA[之前公司的同事写了一个基于epoll的网络服务器，其中涉及到socket状态的转化(如等待接收，接收中，接收完成等)，以及socket之间的转化（如验证完ip权限之后，验证完登录态），可见是一个多... ]]></description>
			<content:encoded><![CDATA[<p>之前公司的同事写了一个基于epoll的网络服务器，其中涉及到socket状态的转化(如等待接收，接收中，接收完成等)，以及socket之间的转化（如验证完ip权限之后，验证完登录态），可见是一个多层次的状态机。<br />
但是在原来的实现中却并没有使用状态模式，导致整个逻辑非常复杂，状态之间的跳转也很难把握。本系列的文章将会通过状态模式来重构整套代码。</p>
<p>状态机模式本身这里就不做详细介绍了，读者可以google一下，笔者在仔细对比过《设计模式之禅》，《研磨设计模式》以及游戏中NPC状态机的实现之后，抽象了如下的一套接口.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #ff0000; font-style: italic;">/*=============================================================================
#  Author:          dantezhu - http://www.vimer.cn
#  Email:           zny2008@gmail.com
#  FileName:        interfaces.h
#  Description:     公共接口
#  Version:         1.0
#  LastChange:      2011-01-19 23:24:33
#  History:         
=============================================================================*/</span>
<span style="color: #339900;">#ifndef _INTERFACES_H_</span>
<span style="color: #339900;">#define _INTERFACES_H_</span>
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;map&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> IFsm<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> IActor
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">virtual</span> ~IActor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> AttachFsmMgr<span style="color: #008000;">&#40;</span>map<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span>, IFsm<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">*</span>mapFsmMgr<span style="color: #008000;">&#41;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> ChangeState<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> destState<span style="color: #008000;">&#41;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
&nbsp;
<span style="color: #0000ff;">class</span> IFsm
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">virtual</span> ~IFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   在进入这个状态的时候，obj需要做的事情
     *
     * @param   obj
     *
     * @return  0           succ
     *          else        fail
     */</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Init<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   执行这个状态该做的事情
     *
     * @param   obj
     *
     * @return  应该进入的另一个状态
     *          0           结束本次Process执行，不进入其他状态
     *          &lt;0          结束整个请求（obj需要被后续删除）
     *          else        其他状态（可以返回自己，但是会造成循环，有点危险）
     *          
     */</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Process<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #ff0000; font-style: italic;">/**
     * @brief   退出这个状态时需要做的事情
     *
     * @param   obj
     *
     * @return  0           succ
     *          else        fail
     */</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Fini<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>IActor是整个状态转化所依附的实体，比如socket可以是recv状态，也可是send状态，那么socket就是一个IActor；而IFsm是状态类的抽象，其中的Init，Process，Fini几个函数都只有一个参数即IActor* obj，IFsm的具体实现类会根据情况来调用obj不同的函数（action）。<br />
所以这里有两个问题:</p>
<ul>
<li>1.代码中可以看出IFsm是无状态的，即IFsm本身不会存储obj的任何数据，那么为什么不把IFsm的几个函数都定义成static类型呢？这里笔者思索了很久，最终的结论是由于语言的问题，如果是在python中，那么是可以直接传递类名来作为参数的，而在C++中，只能传递一个类的实例在作为参数，这就是原因。</li>
<li>2.既然Process注释中说明返回的是下一个状态，那为什么不直接返回一个IFsm指针，而是返回数字呢，这里会在下面的代码中回答</li>
</ul>
<p>定义了状态之后，我们还缺少一个状态管理器：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">map<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span>, IFsm<span style="color: #000040;">*</span> <span style="color: #000080;">&gt;</span> m_mapFsmMgr<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>这个是定义在后面会介绍的world里的，之所以有这个管理器</p>
<ul>
<li>1.是因为C++不同于python，可以直接传递类名</li>
<li>2.通过int来做映射能够更好的实现配置化</li>
</ul>
<p>所以在状态机启动之前，一般需要有如下代码:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">m_mapFsmMgr<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">new</span> CWaitSendFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
m_mapFsmMgr<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">new</span> CSendingFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
m_mapFsmMgr<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">new</span> CSendOverFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>那这里还有一个异议，即有的书上推荐将状态指针定义成CFsmMgr的static变量，当进行状态转化的时候，直接用这个指针即可。但是因为配置化以及底层逻辑与应用逻辑分离的原因，这里个人不建议用如下方式:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CFsmMgr
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    CFsmMgr <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~CFsmMgr <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> IFsm<span style="color: #000040;">*</span> WaitSendFsmObj<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">static</span> IFsm<span style="color: #000040;">*</span> SendingFsmObj<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">static</span> IFsm<span style="color: #000040;">*</span> SendOverFsmObj<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
IFsm<span style="color: #000040;">*</span> CFsmMgr<span style="color: #008080;">::</span><span style="color: #007788;">WaitSendFsmObj</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> CWaitSendFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
IFsm<span style="color: #000040;">*</span> CFsmMgr<span style="color: #008080;">::</span><span style="color: #007788;">SendingFsmObj</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> CSendingFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
IFsm<span style="color: #000040;">*</span> CFsmMgr<span style="color: #008080;">::</span><span style="color: #007788;">SendOverFsmObj</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> CSendOverFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>接下来是Actor的基类实现:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CBaseActor <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IActor
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    CBaseActor <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        m_Fsm <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
        m_mapFsmMgr <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~CBaseActor <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">int</span> AttachFsmMgr<span style="color: #008000;">&#40;</span>map<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span>, IFsm<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">*</span> mapFsmMgr<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        m_mapFsmMgr <span style="color: #000080;">=</span> mapFsmMgr<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">int</span> ChangeState<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> destState<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_mapFsmMgr <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span> <span style="color: #000080;">==</span> destState<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #666666;">//此次处理结束</span>
            <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>destState <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #666666;">//需要关闭整个请求</span>
            <span style="color: #0000ff;">return</span> destState<span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        IFsm <span style="color: #000040;">*</span> destFsm <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
        destFsm <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>m_mapFsmMgr<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#91;</span>destState<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> state <span style="color: #000080;">=</span> doChangeFsm<span style="color: #008000;">&#40;</span>destFsm<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> ChangeState<span style="color: #008000;">&#40;</span>state<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">int</span> doChangeFsm<span style="color: #008000;">&#40;</span>IFsm<span style="color: #000040;">*</span> destFsm<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>destFsm <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_Fsm <span style="color: #000040;">!</span><span style="color: #000080;">=</span> destFsm<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_Fsm <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                m_Fsm<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Fini<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            m_Fsm <span style="color: #000080;">=</span> destFsm<span style="color: #008080;">;</span>
            m_Fsm<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Init<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> m_Fsm<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Process<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
    IFsm<span style="color: #000040;">*</span> m_Fsm<span style="color: #008080;">;</span>
    map<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span>, IFsm<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">*</span>m_mapFsmMgr<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>这个代码也是实现了Actor进行状态转化时的一些逻辑，对于状态转化的触发一般会有两种方式:</p>
<ul>
<li>1.外界调用ChangeState，即由外界触发-如epoll出发的recv事件导致socket的状态转化成recving</li>
<li>2.状态在执行Process之后自行转化为其他状态-如recving状态在recv结束之后自动转化为recvover状态</li>
</ul>
<p>所以基于第二点的原因，上面的代码中实现了递归调用的逻辑（这里在状态机的设计中需要注意环的出现）。<br />
下面是一个继承自Actor基类的socketActor，实现如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CSocketActor <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> CBaseActor
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    CSocketActor <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~CSocketActor <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">int</span> HandleSend<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;sending&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">rand</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">%</span> <span style="color: #0000dd;">5</span> <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #666666;">//代表发送完了</span>
            <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> HandleRecv<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;recving&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> HandleError<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;error&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> HandleTimeout<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;timeout&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>再来看一下状态类的具体实现:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">//waitsend sending sendover waitrecv recving recvover waitclose closing closeover error timeout</span>
&nbsp;
<span style="color: #0000ff;">class</span> CWaitSendFsm <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IFsm
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    CWaitSendFsm <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~CWaitSendFsm <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Init<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Init WaitSend&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Process<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Process WaitSend&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Fini<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Fini WaitSend&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> CSendingFsm <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IFsm
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    CSendingFsm <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~CSendingFsm <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Init<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Init Sending&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Process<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Process Sending&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        CSocketActor <span style="color: #000040;">*</span> chirdObj <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>CSocketActor<span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span> obj<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> chirdObj<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>HandleSend<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ret <span style="color: #000080;">==</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">3</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Fini<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Fini Sending&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> CSendOverFsm <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IFsm
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    CSendOverFsm <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~CSendOverFsm <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Init<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Init SendOver&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Process<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Process SendOver&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">int</span> Fini<span style="color: #008000;">&#40;</span>IActor<span style="color: #000040;">*</span> obj<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Fini SendOver&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>OK，这样一切准备工作就完成，暂时先不把真正的epoll引入进来，我们来模拟一个epoll环境（比较假，没有考虑状态的顺序，大家能明白就行）：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CWorld
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    CWorld <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">srand</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">time</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> ~CWorld <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">int</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">int</span> count <span style="color: #000080;">=</span> <span style="color: #0000dd;">10</span><span style="color: #008080;">;</span>
&nbsp;
        m_mapFsmMgr<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">new</span> CWaitSendFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        m_mapFsmMgr<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">new</span> CSendingFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        m_mapFsmMgr<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #0000dd;">new</span> CSendOverFsm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> count<span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            IActor <span style="color: #000040;">*</span> actor <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> CSocketActor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            m_vecActors.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>actor<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
            actor<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>AttachFsmMgr<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>m_mapFsmMgr<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            actor<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>ChangeState<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> Run<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">int</span> state <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">int</span> val <span style="color: #000080;">=</span> <span style="color: #0000dd;">rand</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">%</span> <span style="color: #0000dd;">5</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>val<span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">:</span>
                <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">:</span>
                    state <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">2</span><span style="color: #008080;">:</span>
                    state <span style="color: #000080;">=</span> <span style="color: #0000dd;">2</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #0000ff;">default</span><span style="color: #008080;">:</span>
                    state <span style="color: #000080;">=</span> <span style="color: #0000dd;">3</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            foreach <span style="color: #008000;">&#40;</span>m_vecActors, it<span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>ChangeState<span style="color: #008000;">&#40;</span>state<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>   
            <span style="color: #008000;">&#125;</span>
            sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    vector<span style="color: #000080;">&lt;</span>IActor<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span> m_vecActors<span style="color: #008080;">;</span>
    map<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span>, IFsm<span style="color: #000040;">*</span> <span style="color: #000080;">&gt;</span> m_mapFsmMgr<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>main函数如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;fsm_achieve.h&quot;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    CWorld world<span style="color: #008080;">;</span>
    world.<span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    world.<span style="color: #007788;">Run</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>执行结果如下（部分）:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Init WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend
Process WaitSend</pre></div></div>

<p>这样，一个一层的状态机就实现出来了~后面的文章，我们会面向应用来讨论两层状态机的实现。<br />
附:<br />
<a href="http://code.google.com/p/vimercode/source/browse/#svn%2Ftrunk%2Ffsm%2Fepoll_fsm" target="_blank" >代码下载</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2011/01/%e6%9c%89%e9%99%90%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84c%e5%ae%9e%e7%8e%b01-epoll%e7%8a%b6%e6%80%81%e6%9c%ba.html/feed</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>最近遇到的几个C++问题(隐式转化，字节对齐)</title>
		<link>http://www.vimer.cn/2011/01/%e6%9c%80%e8%bf%91%e9%81%87%e5%88%b0%e7%9a%84%e5%87%a0%e4%b8%aac%e9%97%ae%e9%a2%98%e9%9a%90%e5%bc%8f%e8%bd%ac%e5%8c%96%ef%bc%8c%e5%ad%97%e8%8a%82%e5%af%b9%e9%bd%90.html</link>
		<comments>http://www.vimer.cn/2011/01/%e6%9c%80%e8%bf%91%e9%81%87%e5%88%b0%e7%9a%84%e5%87%a0%e4%b8%aac%e9%97%ae%e9%a2%98%e9%9a%90%e5%bc%8f%e8%bd%ac%e5%8c%96%ef%bc%8c%e5%ad%97%e8%8a%82%e5%af%b9%e9%bd%90.html#comments</comments>
		<pubDate>Thu, 13 Jan 2011 10:28:30 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[字节对齐]]></category>
		<category><![CDATA[隐式转换]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=1947</guid>
		<description><![CDATA[最近遇到了几个C++问题，在这里总结一下，希望可以避免其他朋友犯同样的错误。 一.隐式转换引发的血案 我们直接来看一段代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include &#60;i... ]]></description>
			<content:encoded><![CDATA[<p>最近遇到了几个C++问题，在这里总结一下，希望可以避免其他朋友犯同样的错误。<br />
<b>一.隐式转换引发的血案</b><br />
我们直接来看一段代码:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #339900;">#include &lt;map&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> a<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">bool</span> input<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;I amd first&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>input<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> a<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> string <span style="color: #000040;">&amp;</span>input<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;I amd second&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>input<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc,<span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    a<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;str&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>  <span style="color: #666666;">// 是调用第二个a函数吗?</span>
    a<span style="color: #008000;">&#40;</span>string<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;str&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>运行结果会是啥呢？好吧，可能让你失望了，结果如下:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">I amd first
1
I amd second
str</pre></div></div>

<p>char*类型的"str"居然被隐式转化成了bool类型，我简单做了一下测试:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #339900;">#include &lt;map&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> a <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span> b <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;wo&quot;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">float</span> c <span style="color: #000080;">=</span> <span style="color:#800080;">1.1</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">bool</span> x<span style="color: #008080;">;</span>
    x <span style="color: #000080;">=</span> a<span style="color: #008080;">;</span>
    x <span style="color: #000080;">=</span> b<span style="color: #008080;">;</span>
    x <span style="color: #000080;">=</span> c<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>int,char*,float确实都可以隐式转化成bool而不会有任何警告，导致出现问题很不容易发现，这里在重载函数的时候确实需要万分注意。</p>
<p><b>二.字节对齐引发的惨案</b><br />
先来介绍一下背景，我这里有个server，会在运行时调用一个so，正常情况下都一切正常，但是在引用了一个第三方给的头文件之后，在调用so的一个函数的时候就会core掉。<br />
百思不得其解之下，去看了一下那个第三方头文件的定义:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef HEADER_OPENAPILOG_PROTOCOL</span>
<span style="color: #339900;">#define HEADER_OPENAPILOG_PROTOCOL</span>
<span style="color: #339900;">#pragma pack(1)</span>
&nbsp;
<span style="color: #666666;">//一些结构体定义</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>只调用了#pragma pack(1)却没有在文件结束时调用#pragma pack()！而我的主调server虽然重新编译了，但是so却没有重新编译，导致其共用的结构体一个做了字节对齐，一个没有做。<br />
修改成如下即正常:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef HEADER_OPENAPILOG_PROTOCOL</span>
<span style="color: #339900;">#define HEADER_OPENAPILOG_PROTOCOL</span>
<span style="color: #339900;">#pragma pack(1)</span>
&nbsp;
<span style="color: #666666;">//一些结构体定义</span>
&nbsp;
<span style="color: #339900;">#pragma pack()</span>
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>每个复杂的问题背后都有一个简单的原因，OK，就这样。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2011/01/%e6%9c%80%e8%bf%91%e9%81%87%e5%88%b0%e7%9a%84%e5%87%a0%e4%b8%aac%e9%97%ae%e9%a2%98%e9%9a%90%e5%bc%8f%e8%bd%ac%e5%8c%96%ef%bc%8c%e5%ad%97%e8%8a%82%e5%af%b9%e9%bd%90.html/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>关于柔性服务的一些实践和思考</title>
		<link>http://www.vimer.cn/2011/01/%e5%85%b3%e4%ba%8e%e6%9f%94%e6%80%a7%e6%9c%8d%e5%8a%a1%e7%9a%84%e4%b8%80%e4%ba%9b%e5%ae%9e%e8%b7%b5%e5%92%8c%e6%80%9d%e8%80%83.html</link>
		<comments>http://www.vimer.cn/2011/01/%e5%85%b3%e4%ba%8e%e6%9f%94%e6%80%a7%e6%9c%8d%e5%8a%a1%e7%9a%84%e4%b8%80%e4%ba%9b%e5%ae%9e%e8%b7%b5%e5%92%8c%e6%80%9d%e8%80%83.html#comments</comments>
		<pubDate>Wed, 12 Jan 2011 12:39:06 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[算法]]></category>
		<category><![CDATA[ema]]></category>
		<category><![CDATA[柔性可用]]></category>
		<category><![CDATA[柔性服务]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=1938</guid>
		<description><![CDATA[最近花了大力气在做openapi的优化，使其尽量柔性可用，借此也有些想法想和大家分享一下。 柔性服务，google一下，在网上并没有这样一个标准的概念，所以应该是公司自己取的一个名字。但是... ]]></description>
			<content:encoded><![CDATA[<p>最近花了大力气在做openapi的优化，使其尽量柔性可用，借此也有些想法想和大家分享一下。<br />
柔性服务，google一下，在网上并没有这样一个标准的概念，所以应该是公司自己取的一个名字。但是这种概念，相信大家都应该很容易能明白，即:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">最大程度的保证关键服务的可用性</pre></div></div>

<p>通俗点来说，一个人不能走路了，他起码可以说话，不能说话了，起码可以点头，头都不能点了，起码得能活着，即心脏还在跳动。这就是柔性。<br />
对应互联网服务来说就是要实现两点:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">1.要尽可能成功返回关键数据
2.要尽可能正常接收请求，不能堵死</pre></div></div>

<p>笔者总结了一下，只要CGI满足其中一个或几个特点，就可以考虑使用柔性服务:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">1.在整个CGI的执行过程中，存在关键路径和非关键路径
2.CGI中存在循环调用接口，导致执行时间不确定</pre></div></div>

<p>我们分上面两种特点来看:<br />
对于第一种，我们举一个简单的例子，比如有一个CGI，做了两件事情分别是:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">1.验证登录态
2.获取用户信息</pre></div></div>

<p>很明显可以看出，验证登录态这个接口是关键路径，而获取用户信息这个接口是非关键的。所以按照柔性服务的定义，当获取用户信息接口失败时，起码还应该返回登录成功。<br />
但是这个时候毕竟还是要区分出完全成功和部分成功的，所以我们可以定义返回码如下(目前腾讯社区开放平台的openapi就是如下定义):</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">ret==0:完全成功
0&lt;ret&lt;1000:部分成功
ret&gt;=1000:完全失败</pre></div></div>

<p>这样就很明白了，我们在调用获取个人信息接口失败是，返回ret=1即可。</p>
<p>但是这样是否足够了呢？<br />
考虑一下，如果获取个人信息接口此时是超时，那么会导致整个CGI的返回变慢，从而导致接收进程挂死。此时虽然我们做了所谓的柔性服务，但是仍然是无法正常提供服务的。</p>
<p>怎么解决呢？我们需要一个能够动态调整超时时间的算法，当接口的响应时间远大于平常的平均值时，分配给接口的超时时间也要响应的调小。<br />
伪编码如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">EMA g_CGITimeoutMng<span style="color: #008080;">;</span><span style="color: #666666;">//超时时间管理</span>
&nbsp;
<span style="color: #0000ff;">class</span> CCGI 
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        CCGI <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            m_TrueRet<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
            g_CGITimeoutMng.<span style="color: #007788;">start</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">virtual</span> ~CCGI <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            g_CGITimeoutMng.<span style="color: #007788;">stop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">int</span> HandleInput<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> check_login<span style="color: #008000;">&#40;</span>g_CGITimeoutMng.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">1000</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            ret <span style="color: #000080;">=</span> get_profile<span style="color: #008000;">&#40;</span>g_CGITimeoutMng.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                m_TrueRet<span style="color: #000040;">++</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            <span style="color: #0000ff;">return</span> m_TrueRet<span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">int</span> m_TrueRet<span style="color: #008080;">;</span><span style="color: #666666;">//容错返回码</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>那这里的动态调整算法使用什么呢？目前使用的是EMA来估算出下一时间点应当分配的超时时间，EMA一开始是用于股票的，后来公司的某大牛将其引入进来动态计算超时时间，大家可以google一下EMA的定义。</p>
<p>现在看来问题是解决了，但是这里会有一个比较大的限制，即:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">关键路径和非关键路径要有明确的分割，即不可以颠倒顺序，或者互相穿插</pre></div></div>

<p>但是万一就是有出现不符合这种限制的情况，该怎么办呢？其实也是有解决方法的，之前我们是只定义了一个g_CGITimeoutMng，他负责分配CGI的总处理时间，但是我们还可以再定义一个g_InterfaceTimeoutMng1，来动态调整某个接口的超时时间。<br />
一般情况下我们仅需要对非关键接口加上这种单独的调整，并且取g_CGITimeoutMng.remainTime()和g_InterfaceTimeoutMng1.remainTime()中的较小值。<br />
示例代码如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">EMA g_CGITimeoutMng<span style="color: #008080;">;</span><span style="color: #666666;">//超时时间管理</span>
EMA g_InterfaceTimeoutMng1<span style="color: #008080;">;</span><span style="color: #666666;">//超时时间管理</span>
<span style="color: #0000ff;">class</span> CCGI 
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        CCGI <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            m_TrueRet<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
            g_CGITimeoutMng.<span style="color: #007788;">start</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">virtual</span> ~CCGI <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            g_CGITimeoutMng.<span style="color: #007788;">stop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">int</span> HandleInput<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> check_login<span style="color: #008000;">&#40;</span>g_CGITimeoutMng.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">1000</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            g_InterfaceTimeoutMng1.<span style="color: #007788;">start</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
            timeout <span style="color: #000080;">=</span> g_CGITimeoutMng.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;</span>g_InterfaceTimeoutMng1.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">?</span>g_CGITimeoutMng.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span>g_InterfaceTimeoutMng1.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
            ret <span style="color: #000080;">=</span> get_profile<span style="color: #008000;">&#40;</span>timeout<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            g_InterfaceTimeoutMng1.<span style="color: #007788;">stop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                m_TrueRet<span style="color: #000040;">++</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            ret <span style="color: #000080;">=</span> check_right<span style="color: #008000;">&#40;</span>g_CGITimeoutMng.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">1001</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            <span style="color: #0000ff;">return</span> m_TrueRet<span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">int</span> m_TrueRet<span style="color: #008080;">;</span><span style="color: #666666;">//容错返回码</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>这样的话，基本就可以完美解决了。</p>
<p>再回来说一下第二种，即有循环调用的问题，其实要做柔性的主要原因也是因为如果不计算使用的时间而直接容错的话，会导致时间很长。<br />
示例代码如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">EMA g_CGITimeoutMng<span style="color: #008080;">;</span><span style="color: #666666;">//超时时间管理</span>
&nbsp;
<span style="color: #0000ff;">class</span> CCGI 
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        CCGI <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            m_TrueRet<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
            g_CGITimeoutMng.<span style="color: #007788;">start</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">virtual</span> ~CCGI <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            g_CGITimeoutMng.<span style="color: #007788;">stop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">int</span> HandleInput<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">int</span> ret<span style="color: #008080;">;</span>
            <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span>i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> count<span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                ret <span style="color: #000080;">=</span> get_somedata<span style="color: #008000;">&#40;</span>g_CGITimeoutMng.<span style="color: #007788;">remainTime</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ret<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
                <span style="color: #008000;">&#123;</span>
                    m_TrueRet<span style="color: #000040;">++</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #666666;">//做取到数据之后该做的事情</span>
            <span style="color: #008000;">&#125;</span>
            <span style="color: #0000ff;">return</span> m_TrueRet<span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">int</span> m_TrueRet<span style="color: #008080;">;</span><span style="color: #666666;">//容错返回码</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>PS:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">上面的代码在调用接口接口之前并没有判断g_CGITimeoutMng.remainTime()&lt;=0，这是因为我们假定接口内部对timeout&lt;=0都是直接返回错误的。如果不是这样的话，需要在调用接口前进行判断。</pre></div></div>

<p>这样，服务才能做到真正的柔性可用。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2011/01/%e5%85%b3%e4%ba%8e%e6%9f%94%e6%80%a7%e6%9c%8d%e5%8a%a1%e7%9a%84%e4%b8%80%e4%ba%9b%e5%ae%9e%e8%b7%b5%e5%92%8c%e6%80%9d%e8%80%83.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>C,C++中调用python脚本(2)-高级应用</title>
		<link>http://www.vimer.cn/2010/12/cc%e4%b8%ad%e8%b0%83%e7%94%a8python%e8%84%9a%e6%9c%ac2-%e9%ab%98%e7%ba%a7%e5%ba%94%e7%94%a8.html</link>
		<comments>http://www.vimer.cn/2010/12/cc%e4%b8%ad%e8%b0%83%e7%94%a8python%e8%84%9a%e6%9c%ac2-%e9%ab%98%e7%ba%a7%e5%ba%94%e7%94%a8.html#comments</comments>
		<pubDate>Tue, 14 Dec 2010 15:17:40 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[cpp调用python]]></category>
		<category><![CDATA[c调用python]]></category>
		<category><![CDATA[PyObject]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=1874</guid>
		<description><![CDATA[还是先说一下背景吧，之前有写过C,C++代码中调用python脚本，但也仅是停留在浅尝辄止的地步，这次由于在fuload中要实现调用python的脚本，所以继续深入了解了一下。 提前打好招呼，这篇文章... ]]></description>
			<content:encoded><![CDATA[<p>还是先说一下背景吧，之前有写过<a href="http://www.vimer.cn/2010/11/cc%E4%BB%A3%E7%A0%81%E4%B8%AD%E8%B0%83%E7%94%A8python%E8%84%9A%E6%9C%AC.html" target="_blank" >C,C++代码中调用python脚本</a>，但也仅是停留在浅尝辄止的地步，这次由于在<a href="http://code.google.com/p/fuload/" target="_blank" >fuload</a>中要实现调用python的脚本，所以继续深入了解了一下。<br />
提前打好招呼，这篇文章有点长，但是信息量也比较大，如果感兴趣希望能耐心读下去。<br />
另外，文章中的代码都可以直接到<a href="http://code.google.com/p/fuload/" target="_blank" >fuload</a>项目下看到:<br />
<a href="http://code.google.com/p/fuload/source/browse/#svn/trunk/src/slave/py_module" target="_blank" >http://code.google.com/p/fuload/source/browse/#svn/trunk/src/slave/py_module</a><br />
先来看一下so的cpp文件：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #339900;">#include &lt;map&gt;</span>
<span style="color: #339900;">#include &lt;python2.7/Python.h&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#define PYMODULE_NAME   &quot;fl_module&quot;</span>
<span style="color: #339900;">#define PYFUNC_INIT     &quot;fuload_handle_init&quot;</span>
<span style="color: #339900;">#define PYFUNC_PROCESS  &quot;fuload_handle_process&quot;</span>
<span style="color: #339900;">#define PYFUNC_FINI     &quot;fuload_handle_fini&quot;</span>
&nbsp;
<span style="color: #339900;">#define PYMODULE_PATH   &quot;../py_module/&quot;</span>
&nbsp;
PyObject <span style="color: #000040;">*</span> g_pModule <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
PyObject <span style="color: #000040;">*</span> g_pInitFunc <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
PyObject <span style="color: #000040;">*</span> g_pProcessFunc <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
PyObject <span style="color: #000040;">*</span> g_pFiniFunc <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
string log_python_exception<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> strErrorMsg<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>Py_IsInitialized<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        strErrorMsg <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Python 运行环境没有初始化！&quot;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> strErrorMsg<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>PyErr_Occurred<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        PyObject <span style="color: #000040;">*</span>type_obj, <span style="color: #000040;">*</span>value_obj, <span style="color: #000040;">*</span>traceback_obj<span style="color: #008080;">;</span>
        PyErr_Fetch<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>type_obj, <span style="color: #000040;">&amp;</span>value_obj, <span style="color: #000040;">&amp;</span>traceback_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>value_obj <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
            <span style="color: #0000ff;">return</span> strErrorMsg<span style="color: #008080;">;</span>
&nbsp;
        PyErr_NormalizeException<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>type_obj, <span style="color: #000040;">&amp;</span>value_obj, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>PyString_Check<span style="color: #008000;">&#40;</span>PyObject_Str<span style="color: #008000;">&#40;</span>value_obj<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            strErrorMsg <span style="color: #000080;">=</span> PyString_AsString<span style="color: #008000;">&#40;</span>PyObject_Str<span style="color: #008000;">&#40;</span>value_obj<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>traceback_obj <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            strErrorMsg <span style="color: #000040;">+</span><span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Traceback:&quot;</span><span style="color: #008080;">;</span>
&nbsp;
            PyObject <span style="color: #000040;">*</span> pModuleName <span style="color: #000080;">=</span> PyString_FromString<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;traceback&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            PyObject <span style="color: #000040;">*</span> pTraceModule <span style="color: #000080;">=</span> PyImport_Import<span style="color: #008000;">&#40;</span>pModuleName<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            Py_XDECREF<span style="color: #008000;">&#40;</span>pModuleName<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pTraceModule <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                PyObject <span style="color: #000040;">*</span> pModuleDict <span style="color: #000080;">=</span> PyModule_GetDict<span style="color: #008000;">&#40;</span>pTraceModule<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pModuleDict <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
                <span style="color: #008000;">&#123;</span>
                    PyObject <span style="color: #000040;">*</span> pFunc <span style="color: #000080;">=</span> PyDict_GetItemString<span style="color: #008000;">&#40;</span>pModuleDict,<span style="color: #FF0000;">&quot;format_exception&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pFunc <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
                    <span style="color: #008000;">&#123;</span>
                        PyObject <span style="color: #000040;">*</span> errList <span style="color: #000080;">=</span> PyObject_CallFunctionObjArgs<span style="color: #008000;">&#40;</span>pFunc,type_obj,value_obj, traceback_obj,<span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>errList <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
                        <span style="color: #008000;">&#123;</span>
                            <span style="color: #0000ff;">int</span> listSize <span style="color: #000080;">=</span> PyList_Size<span style="color: #008000;">&#40;</span>errList<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                            <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>i <span style="color: #000080;">&lt;</span> listSize<span style="color: #008080;">;</span><span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
                            <span style="color: #008000;">&#123;</span>
                                strErrorMsg <span style="color: #000040;">+</span><span style="color: #000080;">=</span> PyString_AsString<span style="color: #008000;">&#40;</span>PyList_GetItem<span style="color: #008000;">&#40;</span>errList,i<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                            <span style="color: #008000;">&#125;</span>
                        <span style="color: #008000;">&#125;</span>
                    <span style="color: #008000;">&#125;</span>
                <span style="color: #008000;">&#125;</span>
                Py_XDECREF<span style="color: #008000;">&#40;</span>pTraceModule<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
        Py_XDECREF<span style="color: #008000;">&#40;</span>type_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        Py_XDECREF<span style="color: #008000;">&#40;</span>value_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        Py_XDECREF<span style="color: #008000;">&#40;</span>traceback_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> strErrorMsg<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/**
 * @brief   清理python环境
 */</span>
<span style="color: #0000ff;">void</span> clear_pyenv<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Py_CLEAR<span style="color: #008000;">&#40;</span>g_pModule<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Py_CLEAR<span style="color: #008000;">&#40;</span>g_pInitFunc<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Py_CLEAR<span style="color: #008000;">&#40;</span>g_pProcessFunc<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Py_CLEAR<span style="color: #008000;">&#40;</span>g_pFiniFunc<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Py_Finalize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//调用Py_Finalize，这个跟Py_Initialize相对应的。</span>
&nbsp;
    g_pModule <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    g_pInitFunc <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    g_pProcessFunc <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    g_pFiniFunc <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #ff0000; font-style: italic;">/**
 * @brief   第一次进入so时，需要做的初始化工作，只会执行一次。
 *
 * @return  0               succ
 *          else            fail
 */</span>
<span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">&quot;C&quot;</span> <span style="color: #0000ff;">int</span> fuload_handle_init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Py_Initialize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//使用python之前，要调用Py_Initialize();这个函数进行初始化</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>Py_IsInitialized<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;init error<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1001</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    PyRun_SimpleString<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;import sys&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    PyRun_SimpleString<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;sys.path.append('./')&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    PyRun_SimpleString<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;sys.path.append('&quot;</span>PYMODULE_PATH<span style="color: #FF0000;">&quot;')&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    g_pModule <span style="color: #000080;">=</span>PyImport_ImportModule<span style="color: #008000;">&#40;</span>PYMODULE_NAME<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//这里是要调用的文件名</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>g_pModule<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Cant open python file!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>,log_python_exception<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        clear_pyenv<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1002</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    g_pInitFunc <span style="color: #000080;">=</span> PyObject_GetAttrString<span style="color: #008000;">&#40;</span>g_pModule, PYFUNC_INIT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//这里是要调用的函数名</span>
    g_pProcessFunc <span style="color: #000080;">=</span> PyObject_GetAttrString<span style="color: #008000;">&#40;</span>g_pModule, PYFUNC_PROCESS<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//这里是要调用的函数名</span>
    g_pFiniFunc <span style="color: #000080;">=</span> PyObject_GetAttrString<span style="color: #008000;">&#40;</span>g_pModule, PYFUNC_FINI<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//这里是要调用的函数名</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>g_pInitFunc <span style="color: #000040;">||</span> <span style="color: #000040;">!</span>g_pProcessFunc <span style="color: #000040;">||</span> <span style="color: #000040;">!</span>g_pFiniFunc<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;func name not find<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        clear_pyenv<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1003</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    PyObject <span style="color: #000040;">*</span>objResult <span style="color: #000080;">=</span>  PyObject_CallFunction<span style="color: #008000;">&#40;</span>g_pInitFunc, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//调用函数</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>objResult<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        clear_pyenv<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1004</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> PyInt_AsLong<span style="color: #008000;">&#40;</span>objResult<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> ret<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/**
 * @brief   业务逻辑，每次进入
 *
 * @param   mapParams       将输入数据按照url方式解析之后的key-value结构
 *
 * @return  0               succ
 *          else            返回值,会用来做统计
 */</span>
<span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">&quot;C&quot;</span> <span style="color: #0000ff;">int</span> fuload_handle_process<span style="color: #008000;">&#40;</span>map<span style="color: #000080;">&lt;</span>string,string<span style="color: #000080;">&gt;</span><span style="color: #000040;">&amp;</span> mapParams<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>g_pProcessFunc<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1001</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    PyObject <span style="color: #000040;">*</span> t_dict <span style="color: #000080;">=</span> PyDict_New<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>map<span style="color: #000080;">&lt;</span>string, string<span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it <span style="color: #000080;">=</span> mapParams.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> mapParams.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        PyDict_SetItemString<span style="color: #008000;">&#40;</span>t_dict,it<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>first.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>,Py_BuildValue<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;s&quot;</span>, it<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>second.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    PyObject <span style="color: #000040;">*</span>objResult <span style="color: #000080;">=</span> PyObject_CallFunctionObjArgs<span style="color: #008000;">&#40;</span>g_pProcessFunc,t_dict,<span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>objResult<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>,log_python_exception<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1002</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> PyInt_AsLong<span style="color: #008000;">&#40;</span>objResult<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> ret<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/**
 * @brief   so结束时的收尾工作，只会调用一次。一般不用编写
 *
 * @return  0               succ
 *          else            fail
 */</span>
<span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">&quot;C&quot;</span> <span style="color: #0000ff;">int</span> fuload_handle_fini<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    PyObject <span style="color: #000040;">*</span>objResult <span style="color: #000080;">=</span>  PyObject_CallFunction<span style="color: #008000;">&#40;</span>g_pFiniFunc, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">//调用函数</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>objResult<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        clear_pyenv<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1004</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> PyInt_AsLong<span style="color: #008000;">&#40;</span>objResult<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    clear_pyenv<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> ret<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #339900;">#ifdef FL_MODULE_MAIN</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    map<span style="color: #000080;">&lt;</span>string,string<span style="color: #000080;">&gt;</span> mapParams<span style="color: #008080;">;</span>
    mapParams<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;first&quot;</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #FF0000;">&quot;1&quot;</span><span style="color: #008080;">;</span>
    mapParams<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;second&quot;</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #FF0000;">&quot;2&quot;</span><span style="color: #008080;">;</span>
    fuload_handle_init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    fuload_handle_process<span style="color: #008000;">&#40;</span>mapParams<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    fuload_handle_fini<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>然后看一下其调用的fl_module.py:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
#=============================================================================
#  Author:          dantezhu - http://www.vimer.cn
#  Email:           zny2008@gmail.com
#  FileName:        fl_module.py
#  Description:     给python用的module主文件
#  Version:         1.0
#  LastChange:      2010-12-13 18:45:10
#  History:         
#=============================================================================
'</span><span style="color: #483d8b;">''</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> fuload_handle_init<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'init'</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> fuload_handle_process<span style="color: black;">&#40;</span>mapParams<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">urllib</span>.<span style="color: black;">urlopen</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;http://www.vimer.cn&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> fuload_handle_fini<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'fini'</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    fuload_handle_process<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>代码逻辑都是比较简单的，就不详细解释了，只列出几个链接，大家有兴趣可以看一下：<br />
<a href="http://docs.python.org/c-api/object.html" target="_blank" >PyObject的常用函数</a><br />
<a href="http://docs.python.org/c-api/concrete.html" target="_blank" >将python类型转换成C类型</a><br />
<a href="http://docs.python.org/release/1.5.2p1/api/node24.html" target="_blank" >通过C类型生成python类型</a><br />
<a href="http://docs.python.org/release/1.5.2p2/ext/buildValue.html" target="_blank" >Py_BuildValue的说明</a></p>
<p>OK，其实最郁闷的并不是在代码的编写上，而是在makefile的编写上。<br />
由于一开始想先通过编译成可执行程序来测试，所以makefile如下:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="make" style="font-family:monospace;">CXX <span style="color: #004400;">=</span> g<span style="color: #004400;">++</span> 
&nbsp;
TARGET <span style="color: #004400;">=</span> main
&nbsp;
C_FLAGS <span style="color: #004400;">+=</span> <span style="color: #004400;">-</span>g <span style="color: #004400;">-</span>Wall <span style="color: #004400;">-</span>pthread
LIB     <span style="color: #004400;">=</span> <span style="color: #004400;">-</span>L<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>local<span style="color: #004400;">/</span>lib<span style="color: #004400;">/</span> <span style="color: #004400;">-</span>lpython2<span style="color: #004400;">.</span>7 <span style="color: #004400;">-</span>ldl <span style="color: #004400;">-</span>lutil
INC     <span style="color: #004400;">=</span> <span style="color: #004400;">-</span>I<span style="color: #004400;">.</span> <span style="color: #004400;">-</span>I<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>local<span style="color: #004400;">/</span><span style="color: #666622; font-weight: bold;">include</span><span style="color: #004400;">/</span>python2<span style="color: #004400;">.</span>7<span style="color: #004400;">/</span>
&nbsp;
all<span style="color: #004400;">:</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TARGET</span><span style="color: #004400;">&#41;</span>
&nbsp;
main<span style="color: #004400;">:</span>  main<span style="color: #004400;">.</span>o
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$@</span> <span style="color: #000088; font-weight: bold;">$^</span>  <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">LIB</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">C_FLAGS</span><span style="color: #004400;">&#41;</span>
&nbsp;
<span style="color: #004400;">.</span>cpp<span style="color: #004400;">.</span>o<span style="color: #004400;">:</span>
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>c <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>o <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">INC</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">C_FLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>cpp
<span style="color: #004400;">.</span>cc<span style="color: #004400;">.</span>o<span style="color: #004400;">:</span>
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>c <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>o <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">INC</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">C_FLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>cc
&nbsp;
&nbsp;
clean<span style="color: #004400;">:</span>
    <span style="color: #004400;">-</span>rm <span style="color: #004400;">-</span>f <span style="color: #004400;">*.</span>o <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TARGET</span><span style="color: #004400;">&#41;</span></pre></td></tr></table></div>

<p>但是编译出来的程序在执行的时候会报如下错误:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">ImportError: /usr/local/lib/python2.7/lib-dynload/_socket.so: undefined symbol: PyExc_ValueError</pre></div></div>

<p>后来发现这个问题是有两种解决方案：<br />
1.如果python在编译安装的时候，没有使用:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #660033;">--enable-shared</span></pre></td></tr></table></div>

<p>那么就会造成在/usr/local/lib/目录下只有libpython2.7.a而没有libpython2.7.so，这个时候需要给makefile加一个参数:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="make" style="font-family:monospace;"><span style="color: #004400;">-</span>export<span style="color: #004400;">-</span>dynamic</pre></td></tr></table></div>

<p>即makefile变成:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="make" style="font-family:monospace;">CXX <span style="color: #004400;">=</span> g<span style="color: #004400;">++</span> 
&nbsp;
TARGET <span style="color: #004400;">=</span> main
&nbsp;
C_FLAGS <span style="color: #004400;">+=</span> <span style="color: #004400;">-</span>g <span style="color: #004400;">-</span>Wall <span style="color: #004400;">-</span>pthread <span style="color: #004400;">-</span>export<span style="color: #004400;">-</span>dynamic
LIB     <span style="color: #004400;">=</span> <span style="color: #004400;">-</span>L<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>local<span style="color: #004400;">/</span>lib<span style="color: #004400;">/</span> <span style="color: #004400;">-</span>lpython2<span style="color: #004400;">.</span>7 <span style="color: #004400;">-</span>ldl <span style="color: #004400;">-</span>lutil
INC     <span style="color: #004400;">=</span> <span style="color: #004400;">-</span>I<span style="color: #004400;">.</span> <span style="color: #004400;">-</span>I<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>local<span style="color: #004400;">/</span><span style="color: #666622; font-weight: bold;">include</span><span style="color: #004400;">/</span>python2<span style="color: #004400;">.</span>7<span style="color: #004400;">/</span>
&nbsp;
all<span style="color: #004400;">:</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TARGET</span><span style="color: #004400;">&#41;</span>
&nbsp;
main<span style="color: #004400;">:</span>  main<span style="color: #004400;">.</span>o
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$@</span> <span style="color: #000088; font-weight: bold;">$^</span>  <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">LIB</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">C_FLAGS</span><span style="color: #004400;">&#41;</span>
&nbsp;
<span style="color: #004400;">.</span>cpp<span style="color: #004400;">.</span>o<span style="color: #004400;">:</span>
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>c <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>o <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">INC</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">C_FLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>cpp
<span style="color: #004400;">.</span>cc<span style="color: #004400;">.</span>o<span style="color: #004400;">:</span>
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>c <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>o <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">INC</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">C_FLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #000088; font-weight: bold;">$*</span><span style="color: #004400;">.</span>cc
&nbsp;
&nbsp;
clean<span style="color: #004400;">:</span>
    <span style="color: #004400;">-</span>rm <span style="color: #004400;">-</span>f <span style="color: #004400;">*.</span>o <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TARGET</span><span style="color: #004400;">&#41;</span></pre></td></tr></table></div>

<p>成功~<br />
2.我们也可以在python编译安装的时候就加上</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #660033;">--enable-shared</span></pre></td></tr></table></div>

<p>这样原来的makefile不用做任何更改也是可以用的。<br />
用man看了一下:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">-E
--export-dynamic
--no-export-dynamic
   When creating a dynamically linked executable, using the -E option or the
   --export-dynamic option causes the linker to add all symbols to the dynamic symbol
   table.  The dynamic symbol table is the set of symbols which are visible from dynamic
   objects at run time.
&nbsp;
   If you do not use either of these options (or use the --no-export-dynamic option to
   restore the default behavior), the dynamic symbol table will normally contain only
   those symbols which are referenced by some dynamic object mentioned in the link.
&nbsp;
   If you use &quot;dlopen&quot; to load a dynamic object which needs to refer back to the symbols
   defined by the program, rather than some other dynamic object, then you will probably
   need to use this option when linking the program itself.
&nbsp;
   You can also use the dynamic list to control what symbols should be added to the
   dynamic symbol table if the output format supports it.  See the description of
   --dynamic-list.
&nbsp;
   Note that this option is specific to ELF targeted ports.  PE targets support a similar
   function to export all symbols from a DLL or EXE; see the description of
   --export-all-symbols below.</pre></div></div>

<p>OK，这样可执行程序就没有问题了，但是关键我们要实现的是编译一个so。<br />
-------------------------------------我是分割线-----------------------------------<br />
无论我们是否已经用</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #660033;">--enable-shared</span></pre></td></tr></table></div>

<p>编译了python，为保险起见，都用如下makefile编译so：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
</pre></td><td class="code"><pre class="make" style="font-family:monospace;">CC <span style="color: #004400;">=</span> gcc 
CXX <span style="color: #004400;">=</span> g<span style="color: #004400;">++</span> 
CFLAGS  <span style="color: #004400;">=</span> <span style="color: #004400;">-</span>Wall <span style="color: #004400;">-</span>pipe <span style="color: #004400;">-</span>DDEBUG <span style="color: #004400;">-</span>D_NEW_LIC <span style="color: #004400;">-</span>g <span style="color: #004400;">-</span>D_GNU_SOURCE \
          <span style="color: #004400;">-</span>shared <span style="color: #004400;">-</span>D_REENTRANT <span style="color: #004400;">-</span>fPIC <span style="color: #004400;">-</span>pthread
&nbsp;
LIB     <span style="color: #004400;">=</span> <span style="color: #004400;">-</span>L<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>local<span style="color: #004400;">/</span>lib<span style="color: #004400;">/</span> <span style="color: #004400;">-</span>lpython2<span style="color: #004400;">.</span>7 <span style="color: #004400;">-</span>ldl <span style="color: #004400;">-</span>lutil <span style="color: #004400;">-</span>Xlinker <span style="color: #004400;">-</span>export<span style="color: #004400;">-</span>dynamic
INC     <span style="color: #004400;">=</span> <span style="color: #004400;">-</span>I<span style="color: #004400;">.</span> <span style="color: #004400;">-</span>I<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>local<span style="color: #004400;">/</span><span style="color: #666622; font-weight: bold;">include</span><span style="color: #004400;">/</span>python2<span style="color: #004400;">.</span>7<span style="color: #004400;">/</span>
&nbsp;
OO  <span style="color: #004400;">=</span> main<span style="color: #004400;">.</span>o
&nbsp;
TARGETS <span style="color: #004400;">=</span> libmodule<span style="color: #004400;">.</span>so
&nbsp;
all<span style="color: #004400;">:</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TARGETS</span><span style="color: #004400;">&#41;</span>
&nbsp;
<span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TARGETS</span><span style="color: #004400;">&#41;</span><span style="color: #004400;">:</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">OO</span><span style="color: #004400;">&#41;</span>
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CFLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">INC</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">OO</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$@</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">LIB</span><span style="color: #004400;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #004400;">.</span>c<span style="color: #004400;">.</span>o<span style="color: #004400;">:</span>
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CC</span><span style="color: #004400;">&#41;</span>  <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CFLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>c <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">INC</span><span style="color: #004400;">&#41;</span> <span style="color: #000088; font-weight: bold;">$&lt;</span>
    echo <span style="color: #000088; font-weight: bold;">$@</span>
&nbsp;
<span style="color: #004400;">.</span>cpp<span style="color: #004400;">.</span>o<span style="color: #004400;">:</span>
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CXX</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CFLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>c <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">INC</span><span style="color: #004400;">&#41;</span> <span style="color: #000088; font-weight: bold;">$&lt;</span>
    echo <span style="color: #000088; font-weight: bold;">$@</span>
&nbsp;
<span style="color: #004400;">%:%.</span>c
    <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CC</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CFLAGS</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>o <span style="color: #000088; font-weight: bold;">$@</span> <span style="color: #000088; font-weight: bold;">$&lt;</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">OO</span><span style="color: #004400;">&#41;</span>
    echo <span style="color: #000088; font-weight: bold;">$@</span>
&nbsp;
clean<span style="color: #004400;">:</span>
    rm <span style="color: #004400;">-</span>f <span style="color: #004400;">*.</span>o
    rm <span style="color: #004400;">-</span>f <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TARGETS</span><span style="color: #004400;">&#41;</span></pre></td></tr></table></div>

<p>用如下代码加载so:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">SoObj<span style="color: #000080;">=</span>dlopen<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span>moduleFile.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>,RTLD_LAZY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SoObj<span style="color: #000080;">==</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>   
    <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> 
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>会发现报如下错误:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">/usr/local/lib/python2.7/lib-dynload/_socket.so: undefined symbol: forkptyTraceback:Traceback (most recent call last):
File &quot;../py_module/fl_module.py&quot;, line 16, in &lt;module&gt;
import urllib
File &quot;/usr/local/lib/python2.7/urllib.py&quot;, line 26, in &lt;module&gt;
import socket
File &quot;/usr/local/lib/python2.7/socket.py&quot;, line 47, in &lt;module&gt;
import _socket
ImportError: /usr/local/lib/python2.7/lib-dynload/_socket.so: undefined symbol: forkpty</pre></div></div>

<p>这里可真是苦了我了，在网上遍寻原因未果，后来终于突发奇想，原来是加载so的调用有问题，改成如下方式后正常:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">SoObj<span style="color: #000080;">=</span>dlopen<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span>moduleFile.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>,RTLD_LAZY<span style="color: #000040;">|</span>RTLD_GLOBAL<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SoObj<span style="color: #000080;">==</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>   
    <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> 
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>搜到的解释如下:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">RTLD_LAZY:在dlopen返回前，对于动态库中存在的未定义的变量(如外部变量extern，也可以是函数)不执行解析，就是不解析这个变量的地址。
&nbsp;
RTLD_NOW：与上面不同，他需要在dlopen返回前，解析出每个未定义变量的地址，如果解析不出来，在dlopen会返回NULL，错误为：
: undefined symbol: xxxx.......
&nbsp;
RTLD_GLOBAL:它的含义是使得库中的解析的定义变量在随后的随后其它的链接库中变得可以使用。</pre></div></div>

<p>OK，到此为止，我们的程序总算是调通了，文章很长，但是相信也是值得的.<br />
这里再附赠一个函数，当调用python脚本失败，打印异常信息(参考自:<a href="http://www.cppblog.com/why/archive/2010/11/08/132999.html" target="_blank" >http://www.cppblog.com/why/archive/2010/11/08/132999.html</a>):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">string log_python_exception<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> strErrorMsg<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>Py_IsInitialized<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        strErrorMsg <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Python 运行环境没有初始化！&quot;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> strErrorMsg<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>PyErr_Occurred<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        PyObject <span style="color: #000040;">*</span>type_obj, <span style="color: #000040;">*</span>value_obj, <span style="color: #000040;">*</span>traceback_obj<span style="color: #008080;">;</span>
        PyErr_Fetch<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>type_obj, <span style="color: #000040;">&amp;</span>value_obj, <span style="color: #000040;">&amp;</span>traceback_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>value_obj <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
            <span style="color: #0000ff;">return</span> strErrorMsg<span style="color: #008080;">;</span>
&nbsp;
        PyErr_NormalizeException<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>type_obj, <span style="color: #000040;">&amp;</span>value_obj, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>PyString_Check<span style="color: #008000;">&#40;</span>PyObject_Str<span style="color: #008000;">&#40;</span>value_obj<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            strErrorMsg <span style="color: #000080;">=</span> PyString_AsString<span style="color: #008000;">&#40;</span>PyObject_Str<span style="color: #008000;">&#40;</span>value_obj<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>traceback_obj <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            strErrorMsg <span style="color: #000040;">+</span><span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Traceback:&quot;</span><span style="color: #008080;">;</span>
&nbsp;
            PyObject <span style="color: #000040;">*</span> pModuleName <span style="color: #000080;">=</span> PyString_FromString<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;traceback&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            PyObject <span style="color: #000040;">*</span> pTraceModule <span style="color: #000080;">=</span> PyImport_Import<span style="color: #008000;">&#40;</span>pModuleName<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            Py_XDECREF<span style="color: #008000;">&#40;</span>pModuleName<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pTraceModule <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                PyObject <span style="color: #000040;">*</span> pModuleDict <span style="color: #000080;">=</span> PyModule_GetDict<span style="color: #008000;">&#40;</span>pTraceModule<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pModuleDict <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
                <span style="color: #008000;">&#123;</span>
                    PyObject <span style="color: #000040;">*</span> pFunc <span style="color: #000080;">=</span> PyDict_GetItemString<span style="color: #008000;">&#40;</span>pModuleDict,<span style="color: #FF0000;">&quot;format_exception&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pFunc <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
                    <span style="color: #008000;">&#123;</span>
                        PyObject <span style="color: #000040;">*</span> errList <span style="color: #000080;">=</span> PyObject_CallFunctionObjArgs<span style="color: #008000;">&#40;</span>pFunc,type_obj,value_obj, traceback_obj,<span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>errList <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
                        <span style="color: #008000;">&#123;</span>
                            <span style="color: #0000ff;">int</span> listSize <span style="color: #000080;">=</span> PyList_Size<span style="color: #008000;">&#40;</span>errList<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                            <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>i <span style="color: #000080;">&lt;</span> listSize<span style="color: #008080;">;</span><span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
                            <span style="color: #008000;">&#123;</span>
                                strErrorMsg <span style="color: #000040;">+</span><span style="color: #000080;">=</span> PyString_AsString<span style="color: #008000;">&#40;</span>PyList_GetItem<span style="color: #008000;">&#40;</span>errList,i<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                            <span style="color: #008000;">&#125;</span>
                        <span style="color: #008000;">&#125;</span>
                    <span style="color: #008000;">&#125;</span>
                <span style="color: #008000;">&#125;</span>
                Py_XDECREF<span style="color: #008000;">&#40;</span>pTraceModule<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
        Py_XDECREF<span style="color: #008000;">&#40;</span>type_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        Py_XDECREF<span style="color: #008000;">&#40;</span>value_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        Py_XDECREF<span style="color: #008000;">&#40;</span>traceback_obj<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> strErrorMsg<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2010/12/cc%e4%b8%ad%e8%b0%83%e7%94%a8python%e8%84%9a%e6%9c%ac2-%e9%ab%98%e7%ba%a7%e5%ba%94%e7%94%a8.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>时间相关的一些前后台知识</title>
		<link>http://www.vimer.cn/2010/12/%e6%97%b6%e9%97%b4%e7%9b%b8%e5%85%b3%e7%9a%84%e4%b8%80%e4%ba%9b%e5%89%8d%e5%90%8e%e5%8f%b0%e7%9f%a5%e8%af%86.html</link>
		<comments>http://www.vimer.cn/2010/12/%e6%97%b6%e9%97%b4%e7%9b%b8%e5%85%b3%e7%9a%84%e4%b8%80%e4%ba%9b%e5%89%8d%e5%90%8e%e5%8f%b0%e7%9f%a5%e8%af%86.html#comments</comments>
		<pubDate>Sun, 12 Dec 2010 12:58:40 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[mktime]]></category>
		<category><![CDATA[strftime]]></category>
		<category><![CDATA[strptime]]></category>
		<category><![CDATA[time]]></category>
		<category><![CDATA[time_t]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=1869</guid>
		<description><![CDATA[最近有很多时间相关的一些技术积累，主要分为三块， 1.gettimeofday时间差不准的bug 2.时间的字符串形式和时间戳形式的转化（C语言） 3.提供时间日期选择的控件 一.gettimeofday时间不准的bug 先从... ]]></description>
			<content:encoded><![CDATA[<p>最近有很多时间相关的一些技术积累，主要分为三块，</p>
<ul>
<li>1.gettimeofday时间差不准的bug</li>
<li>2.时间的字符串形式和时间戳形式的转化（C语言）</li>
<li>3.提供时间日期选择的控件</li>
</ul>
<p>一.gettimeofday时间不准的bug<br />
先从第一个说起吧，前几天在<a href="http://code.google.com/p/fuload/" target="_blank" >fuload</a>项目通过如下代码统计调用消耗的时间：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">struct</span> timeval stBegin<span style="color: #008080;">;</span>
<span style="color: #0000ff;">struct</span> timeval stEnd<span style="color: #008080;">;</span>
gettimeofday<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>stBegin, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
ret <span style="color: #000080;">=</span> process<span style="color: #008000;">&#40;</span>swi<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
gettimeofday<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>stEnd, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
time_ms <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>stEnd.<span style="color: #007788;">tv_sec</span><span style="color: #000040;">-</span>stBegin.<span style="color: #007788;">tv_sec</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">*</span><span style="color: #0000dd;">1000000</span><span style="color: #000040;">+</span><span style="color: #008000;">&#40;</span>stEnd.<span style="color: #007788;">tv_usec</span><span style="color: #000040;">-</span>stBegin.<span style="color: #007788;">tv_usec</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">/</span><span style="color: #0000dd;">1000</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>按理说是很平常的写法，但是在实际的曲线图中，却发现每隔20分钟就会出现一个很大的波动，在网上苦询答案未果，最后突然想起来，既然是规律性的出现问题，是不是crontab中有每隔20分钟的调用导致的问题呢？最终在crontab中发现了这个：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">*/</span><span style="color: #000000;">20</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span>ntpdate 172.23.32.142 172.24.18.141 172.18.70.180</pre></td></tr></table></div>

<p>原来每隔20分钟就会对时一次，难怪出现问题，果断注释后，恢复正常。</p>
<p>二.时间的字符串形式和时间戳形式的转化（C语言）<br />
之前在博客里是有谢过C语言中，时间戳和字符串的转化函数的(<a href="http://www.vimer.cn/2009/10/%E6%97%B6%E9%97%B4time_t%E5%92%8Cstring%E6%A0%BC%E5%BC%8F%E4%BA%92%E8%BD%AC.html" target="_blank" >时间time_t和string(char*)格式互转</a>)，不过可定制话太低了，恰好之前在内部论坛看到同事分享的另一种做法，所以拿出来和大家分享一下。<br />
linux下默认提供了两个时间转化的函数（python中的time模块下也有相同名称的定义）：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">//时间转字符串</span>
<span style="color: #0000ff;">size_t</span> <span style="color: #0000dd;">strftime</span><span style="color: #008000;">&#40;</span>
<span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>strDest, 
<span style="color: #0000ff;">size_t</span> maxsize, 
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>format, 
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">struct</span> <span style="color: #0000ff;">tm</span> <span style="color: #000040;">*</span>timeptr <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #666666;">//字符串转时间</span>
<span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>strptime<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>s,
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>format,
<span style="color: #0000ff;">struct</span> <span style="color: #0000ff;">tm</span> <span style="color: #000040;">*</span><span style="color: #0000ff;">tm</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>我在这里简单写了一个测试程序:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
<span style="color: #339900;">#include &lt;time.h&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">struct</span> <span style="color: #0000ff;">tm</span> <span style="color: #000040;">*</span>ptr<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">time_t</span> lt<span style="color: #008080;">;</span> 
    <span style="color: #0000ff;">char</span> szData<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">128</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
    lt<span style="color: #000080;">=</span><span style="color: #0000dd;">time</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    ptr<span style="color: #000080;">=</span><span style="color: #0000dd;">localtime</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">strftime</span><span style="color: #008000;">&#40;</span>szData,<span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>szData<span style="color: #008000;">&#41;</span><span style="color: #000040;">-</span><span style="color: #0000dd;">1</span>,<span style="color: #FF0000;">&quot;%Y-%m-%d %H:%M:%S&quot;</span>,ptr<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>,szData<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">struct</span> <span style="color: #0000ff;">tm</span> t_tm<span style="color: #008080;">;</span>
    strptime<span style="color: #008000;">&#40;</span>szData,<span style="color: #FF0000;">&quot;%Y-%m-%d %H:%M:%S&quot;</span>,<span style="color: #000040;">&amp;</span>t_tm<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%u<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>,<span style="color: #0000dd;">mktime</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>t_tm<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>输出结果如下:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">2010-12-12 20:42:21
1292157741</pre></div></div>

<p>特别需要注意的第一点是：strftime的第二个参数如果小于实际要存放的长度的话，这个函数是不会自动在最后一个字符补上\0的。<br />
参考:<a href="http://baike.baidu.com/view/1284677.htm" target="_blank" >http://baike.baidu.com/view/1284677.htm</a></p>
<p>三.提供时间日期选择的控件<br />
也是<a href="http://code.google.com/p/fuload/" target="_blank" >fuload</a>项目中使用的一个控件，之前本来是直接使用了django后台的日期选择控件，后来发现精度要求达到分钟，所以不得不去寻找一款能同时选择日期和时间的控件，好在后来还是被我找到啦，截图如下:</p>
<p><a href="http://www.vimer.cn/wp-content/uploads/2010/12/time1.png" target="_blank" ><img title="http://www.vimer.cn/wp-content/uploads/2010/12/time1.png" src="http://www.vimer.cn/wp-content/uploads/2010/12/time1.png" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" alt="1" border="0" /></a></p>
<p>插件名为:<a href="http://trentrichardson.com/examples/timepicker/" target="_blank" >Timepicker Addon for jQuery UI Datepicker</a>，是在jquery的datepicker基础上修改的，插件主页：<a href="http://trentrichardson.com/examples/timepicker/" target="_blank" >http://trentrichardson.com/examples/timepicker/</a><br />
使用时需要下载安装jQuery UI，这里简单列出一下用法：<br />
在head中加入:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;style type=&quot;text/css&quot;&gt;
    /* css for timepicker */
    .ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; }
    .ui-timepicker-div dl{ text-align: left; }
    .ui-timepicker-div dl dt{ height: 25px; }
    .ui-timepicker-div dl dd{ margin: -25px 0 10px 65px; }
    .ui-timepicker-div td { font-size: 90%; }
&lt;/style&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/site_media/js/jquery-1.4.3.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/site_media/js/jquery-ui-1.8.6.custom.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/site_media/js/jquery-ui-timepicker-addon.js&quot;&gt;&lt;/script&gt;</pre></td></tr></table></div>

<p>并对你需要弹出选择框的元素进行绑定:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_begintime'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">datetimepicker</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_begintime'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">datetimepicker</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;option&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;dateFormat&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;yy-mm-dd&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>但是需要注意一点的是，如果有多个元素需要绑定选择框是不能用如下方法的：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">//错误写法！</span>
$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_begintime'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">datetimepicker</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_begintime'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">datetimepicker</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;option&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;dateFormat&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;yy-mm-dd&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_endtime'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">datetimepicker</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_endtime'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">datetimepicker</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;option&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;dateFormat&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;yy-mm-dd&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>而必须使用:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_begintime,#id_endtime'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">datetimepicker</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
            dateFormat<span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;yy-mm-dd&quot;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>OK，就这样~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2010/12/%e6%97%b6%e9%97%b4%e7%9b%b8%e5%85%b3%e7%9a%84%e4%b8%80%e4%ba%9b%e5%89%8d%e5%90%8e%e5%8f%b0%e7%9f%a5%e8%af%86.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>参考python来简写C代码</title>
		<link>http://www.vimer.cn/2010/12/%e5%8f%82%e8%80%83python%e6%9d%a5%e7%ae%80%e5%86%99c%e4%bb%a3%e7%a0%81.html</link>
		<comments>http://www.vimer.cn/2010/12/%e5%8f%82%e8%80%83python%e6%9d%a5%e7%ae%80%e5%86%99c%e4%bb%a3%e7%a0%81.html#comments</comments>
		<pubDate>Wed, 08 Dec 2010 06:48:27 +0000</pubDate>
		<dc:creator>Dante</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[cpp]]></category>

		<guid isPermaLink="false">http://www.vimer.cn/?p=1865</guid>
		<description><![CDATA[由于python语法的简洁，所以在写c代码的时候，有时候也会想能不能把C代码写的更简练一点，这几天遇到一个，给大家分享一下。 比如我们要用C写一个判断语句，然后根据不同的值返回不同的... ]]></description>
			<content:encoded><![CDATA[<p>由于python语法的简洁，所以在写c代码的时候，有时候也会想能不能把C代码写的更简练一点，这几天遇到一个，给大家分享一下。<br />
比如我们要用C写一个判断语句，然后根据不同的值返回不同的内容。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #000080;">==</span> val<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">&quot;this is one&quot;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span> <span style="color: #000080;">==</span> val<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">&quot;this is two&quot;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span> <span style="color: #000080;">==</span> val<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">&quot;this is three&quot;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>如果判断的逻辑很多，代码就会显得很臃肿（文中的例子用switch也可以，但是也还是很难看），如果用python，就会这样写（为了和C类比，这里没有用字典）:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">datas = <span style="color: black;">&#91;</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #483d8b;">&quot;this is one&quot;</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>,<span style="color: #483d8b;">&quot;this is two&quot;</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #483d8b;">&quot;this is three&quot;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> v <span style="color: #ff7700;font-weight:bold;">in</span> datas:
    <span style="color: #ff7700;font-weight:bold;">if</span> v<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == val:
        <span style="color: #ff7700;font-weight:bold;">return</span> v<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>那在c里面是否能同样的方法实现呢，是可以的:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">struct</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> key<span style="color: #008080;">;</span>
    string strdata<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>arr_datas<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #000080;">=</span><span style="color: #008000;">&#123;</span>
    <span style="color: #008000;">&#123;</span><span style="color: #0000dd;">1</span>,<span style="color: #FF0000;">&quot;this is one&quot;</span><span style="color: #008000;">&#125;</span>,
    <span style="color: #008000;">&#123;</span><span style="color: #0000dd;">2</span>,<span style="color: #FF0000;">&quot;this is two&quot;</span><span style="color: #008000;">&#125;</span>,
    <span style="color: #008000;">&#123;</span><span style="color: #0000dd;">3</span>,<span style="color: #FF0000;">&quot;this is three&quot;</span><span style="color: #008000;">&#125;</span>,
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span>i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">3</span><span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>arr_datas<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">key</span> <span style="color: #000080;">==</span> val<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> arr_datas<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">strdata</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>附:<br />
有人可能想到用stl的map，查找速度会快一些，不过想到定义一个map，然后调用一堆insert其实也挺麻烦的，而且例子中用的是int，但是并不是所有的类型都是可hash的，所以有些情况下map并不能胜任。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vimer.cn/2010/12/%e5%8f%82%e8%80%83python%e6%9d%a5%e7%ae%80%e5%86%99c%e4%bb%a3%e7%a0%81.html/feed</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
	</channel>
</rss>

