<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>软件设计</title><link>http://blog.vckbase.com/jzhang/category/953.html</link><description>面向对象软件设计，设计模式，软件框架设计和学习。</description><managingEditor>jzhang</managingEditor><dc:language>zh-CHS</dc:language><generator>.Text Version 0.958.2004.214</generator><item><dc:creator>jzhang</dc:creator><title>刨乐1.0发布</title><link>http://blog.vckbase.com/jzhang/archive/2007/07/02/27161.html</link><pubDate>Mon, 02 Jul 2007 01:10:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2007/07/02/27161.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/27161.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2007/07/02/27161.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/27161.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/27161.html</trackback:ping><description>刨乐是我过去半年开发的基于S60第二版的手机软件，用于在通话过程中播放背景音乐。&lt;BR&gt;支持mp3，支持自定义情景模式和热键，有S60第二版和第一版手机的朋友可以安装&lt;BR&gt;看看:)&lt;BR&gt;下载地址：&lt;BR&gt;&lt;BR&gt;&lt;A href="http://www.poporz.com/downloads/poporz.sis"&gt;http://www.poporz.com/downloads/poporz.sis&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;网站：&lt;BR&gt;&lt;A href="http://www.poporz.com"&gt;http://www.poporz.com&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;欢迎给我提意见，第一版还不完善，需要持续改进。&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/27161.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>AMR格式和在s60上的解码</title><link>http://blog.vckbase.com/jzhang/archive/2007/06/18/26949.html</link><pubDate>Mon, 18 Jun 2007 03:35:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2007/06/18/26949.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/26949.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2007/06/18/26949.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/26949.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/26949.html</trackback:ping><description>AMR 文件格式&lt;BR&gt;&lt;BR&gt;AMR 有8种采样率，分别是&lt;BR&gt;&lt;BR&gt;Mode 0 - AMR 4.75 - Encodes at 4.75kbit/s&lt;BR&gt;Mode 1 - AMR 5.15 - Encodes at 5.15kbit/s&lt;BR&gt;Mode 2 - AMR 5.9 - Encodes at 5.9kbit/s&lt;BR&gt;Mode 3 - AMR 6.7 - Encodes at 6.7kbit/s&lt;BR&gt;Mode 4 - AMR 7.4 - Encodes at 7.4kbit/s&lt;BR&gt;Mode 5 - AMR 7.95 - Encodes at 7.95kbit/s&lt;BR&gt;Mode 6 - AMR 10.2 - Encodes at 10.2kbit/s&lt;BR&gt;Mode 7 - AMR 12.2 - Encodes at 12.2kbit/s&lt;BR&gt;&lt;BR&gt;每种格式对应的帧的大小如下。&lt;BR&gt;CMR Mode Frame size (bytes)&lt;BR&gt;0 AMR 4.75 13&lt;BR&gt;1 AMR 5.15 14&lt;BR&gt;2 AMR 5.9 16&lt;BR&gt;3 AMR 6.7 18&lt;BR&gt;4 AMR 7.4 20&lt;BR&gt;5 AMR 7.95 21&lt;BR&gt;6 AMR 10.2 27&lt;BR&gt;7 AMR 12.2 32&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;三、文件格式&lt;BR&gt;Amr的文件格式极为简单，如图1所示：&lt;BR&gt;&lt;BR&gt;文件最开始时6个字节的header，&lt;BR&gt;[#!AMR\n] 括号间的部分&lt;BR&gt;(或者十六进制表示为 0x2321414d520a ).&lt;BR&gt;&lt;BR&gt;接下来就是连续的语音帧，&lt;BR&gt;&lt;BR&gt;+----------------------+&lt;BR&gt;| Header               |&lt;BR&gt;+----------------------+&lt;BR&gt;| Speech Frame 1       |&lt;BR&gt;+----------------------+&lt;BR&gt;: ...                  :&lt;BR&gt;+----------------------+&lt;BR&gt;| Speech Frame n       |&lt;BR&gt;+----------------------+&lt;BR&gt;&lt;BR&gt;每个帧包含一个帧头+语音数据，帧头是一个字节&lt;BR&gt;0 1 2 3 4 5 6 7&lt;BR&gt;+-+-+-+-+-+-+-+-+&lt;BR&gt;|P| FT   |Q|P|P|&lt;BR&gt;+-+-+-+-+-+-+-+-+&lt;BR&gt;&lt;BR&gt;P设置为0&lt;BR&gt;FT为编码模式，上面已经列举了可用的值。(0~7)&lt;BR&gt;&lt;BR&gt;Q为帧质量指示器，如果为0表明帧被损坏，接受者需要将RX_TYPE设置成SPEECH_BAD或者SID_BAD。&lt;BR&gt;&lt;BR&gt;具体在S60中可以如创建codec&lt;BR&gt;#define KAdvancedUidCodecAMRToPCM16 0x101FAF67&lt;BR&gt;iCodec = CMMFCodec::NewL( TUid::Uid( KAdvancedUidCodecAMRToPCM16 ) );&lt;BR&gt;KAdvancedUidCodecAMRToPCM16 是一个Nokia魔鬼数字.&lt;BR&gt;在跳过头6个字节后,再多读一个字节,获取其2,3,4,5bit.就可以知道实际的采样率和桢长度.&lt;BR&gt;然后就一个桢一个桢的读,调用&lt;BR&gt;iCodec的ProcessL方法转换为PCM16. 对了, PCM16每桢的长度为320&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/26949.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>S60开发的一些笔记</title><link>http://blog.vckbase.com/jzhang/archive/2007/06/11/26859.html</link><pubDate>Mon, 11 Jun 2007 09:19:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2007/06/11/26859.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/26859.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2007/06/11/26859.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/26859.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/26859.html</trackback:ping><description>1. 创建全屏幕程序，只要在创建View的时候传入ApplicationRect()而不是ClientRect()就可以了&lt;BR&gt;2. 发送短消息。第三版可以使用RSendAs,第二版就复杂了，需要用MTM的api.不过Nokia Forum有一个例子，&lt;BR&gt;    里面的ExampleEngine改造一下就可以拿来用了&lt;BR&gt;3. 获取来电号码，在第二版中，无法从RCall中获取到来电号码，只能通过读取日志来获取。 而读日志有一个&lt;BR&gt;    延迟，会比接收到Incoming call 的回调慢&lt;BR&gt;4. AMR有6个字节的头，每帧13个字节。PCM有44个字节的头，每帧320个字节。&lt;BR&gt;5. App程序可以不经过安装直接通过StartApp启动，但是不能使用StartDocument。启动后的程序可以用&lt;BR&gt;   TApaTask.Exists检测到，并且可以用SendMessage发送消息。&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/26859.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>S60开发，真是步步艰辛 - 请教一个问题</title><link>http://blog.vckbase.com/jzhang/archive/2007/05/21/26523.html</link><pubDate>Mon, 21 May 2007 09:31:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2007/05/21/26523.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/26523.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2007/05/21/26523.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/26523.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/26523.html</trackback:ping><description>几乎所有的问题都是问题，搞定一个问题又开始下一个问题。&lt;BR&gt;现在的问题是这样：&lt;BR&gt;程序不使用整个屏幕，只绘制一个小区域，其他部分原有的内容都要显示出来。&lt;BR&gt;这个我实现了，但是当这个程序在最上端的时候，所有的按键都被它接收了，&lt;BR&gt;但是我需要其他程序可以继续响应 进入和退出 两个按键。试验了各种办法，&lt;BR&gt;都不行。不知道谁有办法没？&lt;BR&gt;谢谢~&lt;BR&gt;&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/26523.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>S60编程学习资源</title><link>http://blog.vckbase.com/jzhang/archive/2007/02/12/24561.html</link><pubDate>Mon, 12 Feb 2007 03:37:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2007/02/12/24561.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/24561.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2007/02/12/24561.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/24561.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/24561.html</trackback:ping><description>断断续续折腾了一个月了，周末终于找到了点门道，实现了最重要的两个功能。感觉这一个月走了很多弯路，&lt;BR&gt;没有找到最合适入门的方法。所以写一下学习S60的一些资源，供有兴趣的人用。&lt;BR&gt;1. 找一本好书，千万不要一上来就看S60的SDK文档！！&lt;BR&gt;这个是血的教训，S60的SDK文档只能算一个API列表，9.0的好一些，7.2的真的是太差了。&lt;BR&gt;我看了3个礼拜的SDK，虽然学会了一些东西，但是却始终无法了解S60编程的全貌，一些&lt;BR&gt;极其重要的东西都没有学到。但是这个周末下载了一本书，豁然开朗。我下载的书的名字&lt;BR&gt;叫 &lt;STRONG&gt;Series 60应用程序开发（英文影印版）&lt;/STRONG&gt;，在netyi.net上有得下载。我本来想买这本书&lt;BR&gt;的，但是听说国内只有翻译版，而且质量极差。英文版的写的很不错，建议先读这本书，从&lt;BR&gt;最基本的概念，到一些非常重要的特性，都有介绍。&lt;BR&gt;2. 上开发论坛&lt;BR&gt;Nokia: &lt;A href="http://discussion.forum.nokia.com/forum/forumdisplay.php?f=6"&gt;http://discussion.forum.nokia.com/forum/forumdisplay.php?f=6&lt;/A&gt;&lt;BR&gt;这是官方论坛。&lt;BR&gt;&lt;BR&gt;NewLC: &lt;A href="http://forum.newlc.com/"&gt;http://forum.newlc.com/&lt;/A&gt;&lt;BR&gt;这个论坛不知道谁开的，上面有一些样例工程比较有价值。&lt;BR&gt;&lt;BR&gt;sf: &lt;A href="http://www.sf.org.cn/"&gt;http://www.sf.org.cn/&lt;/A&gt;&lt;BR&gt;困惑者推荐的论坛，中文的。&lt;BR&gt;&lt;BR&gt;两个论坛都很活跃，解答问题也比较及时。不过泡久了就会发现，有很多众所周知的bug一直没有办法&lt;BR&gt;解决，或者是只有使用S60的秘密api才能解决。而要使用秘密api，需要成为Nokia的开发伙伴。&lt;BR&gt;提问之前先Search一下，一般别人都问过了。&lt;BR&gt;&lt;BR&gt;3.SDK和Example&lt;BR&gt;SDK所携带的example还是比较有价值的。&lt;BR&gt;4. Google,Baidu&lt;BR&gt;搜索引擎提供的东西有限，毕竟做这个的人比较少。一些经验介绍的文章也不值得看，不如看那本书。&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/24561.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>在Linux上创建PHP4的C++扩展</title><link>http://blog.vckbase.com/jzhang/archive/2006/12/23/23633.html</link><pubDate>Sat, 23 Dec 2006 15:53:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2006/12/23/23633.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/23633.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2006/12/23/23633.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/23633.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/23633.html</trackback:ping><description>&lt;DIV class=article lang=en&gt;
&lt;DIV class=titlepage&gt;
&lt;DIV&gt;
&lt;DIV&gt;
&lt;H2 class=title&gt;&lt;A name=d0e1&gt;&lt;/A&gt;&amp;nbsp;&lt;/H2&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P class=toc&gt;&lt;SPAN class=section&gt;&lt;A href="PHPExt.html#d0e25"&gt;1. 必须的工具&lt;/A&gt;&lt;/SPAN&gt; &lt;/P&gt;
&lt;DIV class=toc&gt;
&lt;DL&gt;
&lt;DT&gt;&lt;SPAN class=section&gt;&lt;A href="PHPExt.html#d0e40"&gt;2. 主要步骤&lt;/A&gt;&lt;/SPAN&gt; 
&lt;DD&gt;
&lt;DL&gt;
&lt;DT&gt;&lt;SPAN class=section&gt;&lt;A href="PHPExt.html#d0e59"&gt;2.1. 创建&lt;/A&gt;&lt;/SPAN&gt; 
&lt;DT&gt;&lt;SPAN class=section&gt;&lt;A href="PHPExt.html#d0e149"&gt;2.2. 编译&lt;/A&gt;&lt;/SPAN&gt; 
&lt;DT&gt;&lt;SPAN class=section&gt;&lt;A href="PHPExt.html#d0e171"&gt;2.3. 调试&lt;/A&gt;&lt;/SPAN&gt;&lt;/DT&gt;&lt;/DL&gt;
&lt;DT&gt;&lt;SPAN class=section&gt;&lt;A href="PHPExt.html#d0e191"&gt;3. 总结&lt;/A&gt;&lt;/SPAN&gt;&lt;/DT&gt;&lt;/DL&gt;&lt;/DIV&gt;
&lt;DIV class=section lang=en&gt;
&lt;DIV class=titlepage&gt;
&lt;DIV&gt;
&lt;DIV&gt;
&lt;H2 class=title style="CLEAR: both"&gt;&lt;A name=d0e25&gt;&lt;/A&gt;1.&amp;nbsp;必须的工具&lt;/H2&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;如下工具是必须的：&lt;/P&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=1&gt;
&lt;LI&gt;
&lt;P&gt;gcc. 我使用的是3.4.3&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;autoconf. 我使用的是 2.13-5. 奇怪的是2.59是不能用的，如果你的系统里安装的是这个版本，要先卸载，然后安装2.13&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;PHP4的源代码。我使用的是PHP-4.4.4。在PHP的网站上可以下载到&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV class=section lang=en&gt;
&lt;DIV class=titlepage&gt;
&lt;DIV&gt;
&lt;DIV&gt;
&lt;H2 class=title style="CLEAR: both"&gt;&lt;A name=d0e40&gt;&lt;/A&gt;2.&amp;nbsp;主要步骤&lt;/H2&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;创建PHP的扩展很麻烦。熟悉其它脚本语言的人会觉得开发PHP的扩展真是罗嗦到了极点。不过给脚本写扩展的原理都是一样的：&lt;/P&gt;
&lt;P&gt;导出一个特定名字的函数，然后通过这个函数返回关于这个扩展的全部信息，其中重要的有：&lt;/P&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=1&gt;
&lt;LI&gt;
&lt;P&gt;名字，描述，版本信息&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;模块所提供的功能，这个一般都是一个函数名和函数指针成对的数组&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;通过一些函数实现脚本和扩展之间的数据交换.这方面各个语言都不相同,TCL是直接传递字符串,Python提供了PyArg_ParseTuple,Py_BuildValue等函数,Lua则通过一个堆栈来交换数据.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;
&lt;P&gt;PHP提供了一系列的工具和宏来封装这个过程，可惜的是在我看来这反而让它更加复杂。&lt;/P&gt;
&lt;DIV class=section lang=en&gt;
&lt;DIV class=titlepage&gt;
&lt;DIV&gt;
&lt;DIV&gt;
&lt;H3 class=title&gt;&lt;A name=d0e59&gt;&lt;/A&gt;2.1.&amp;nbsp;创建&lt;/H3&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=1&gt;
&lt;LI&gt;
&lt;P&gt;将PHP-4 的源代码解压缩。下文将这个目录称为PHPSRC.&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;进入PHPSRC/ext目录，执行./ext_skel 扩展名。假设我们的扩展名字叫testext,那就是输入./ext_skel testext. 这个程序将会为你在ext目录下创建如下内容：&lt;/P&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=a&gt;
&lt;LI&gt;
&lt;P&gt;testext目录&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;在testext目录下又包括：&lt;/P&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=i&gt;
&lt;LI&gt;
&lt;P&gt;testext.c - 这是扩展模块的源文件&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;php_testext.h - 头文件&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;config.m4 - 用于autoconf的配置文件，autoconf会通过这个文件的内容决定应该如何编译链接这个模块。&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;testext.php - 自动产生的测试脚本&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;tests 目录 - 忽略&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;P&gt;然后我们必须简单的理解一下config.m4这个文件。&lt;/P&gt;
&lt;P&gt;m4 is a macro processor, in the sense that it copies its input to the output, expanding macros as it goes. Macros are either builtin or user-defined, and can take any number of arguments. Besides just doing macro expansion, m4 has builtin functions for including named files, running shell commands, doing integer arithmetic, manipulating text in various ways, performing recursion, etc.... m4 can be used either as a front-end to a compiler, or as a macro processor in its own right. &lt;/P&gt;
&lt;P&gt;The m4 macro processor is widely available on all UNIXes, and has been standardized by POSIX. Usually, only a small percentage of users are aware of its existence. However, those who find it often become committed users. The popularity of GNU Autoconf, which requires GNU m4 for generating configure scripts, is an incentive for many to install it, while these people will not themselves program in m4. GNU m4 is mostly compatible with the System V, Release 3 version, except for some minor differences. See Compatibility, for more details. &lt;/P&gt;
&lt;P&gt;Some people find m4 to be fairly addictive. They first use m4 for simple problems, then take bigger and bigger challenges, learning how to write complex sets of m4 macros along the way. Once really addicted, users pursue writing of sophisticated m4 applications even to solve simple problems, devoting more time debugging their m4 scripts than doing real work. Beware that m4 may be dangerous for the health of compulsive programmers. &lt;/P&gt;
&lt;P&gt;以上内容来自&lt;A href="http://www.gnu.org/" target=_top&gt;http://www.gnu.org&lt;/A&gt;,所以我就不多说了. 总之PHP使用了这种技术来帮助我们构建扩展.&lt;/P&gt;
&lt;P&gt;只记录一下对我们有用的东西: &lt;/P&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=a&gt;
&lt;LI&gt;
&lt;P&gt;dnl是注释.好怪&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;PHP_ARG_WITH或者PHP_ARG_ENABLE指定了PHP模块的工作方式,任选一种,我选择的是WITH&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;PHP_REQUIRE_CXX()用于指定这个扩展用到了C++&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;PHP_SUBST(SYSFILE_SHARED_LIBADD)用于说明这个扩展编译成动态链接库的形式&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;PHP_ADD_LIBRARY(stdc++,"",SYSFILE_SHARED_LIBADD)用于将标准C++库链接进入扩展&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;PHP_NEW_EXTENSION用于指定有哪些源文件应该被编译,文件和文件之间用空格隔开. &lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;
&lt;P&gt;ext_skel默认生成的模块框架是针对C的,我们要使用C++,那以上的3,5两个宏就是必须的.另外还要把testext.c改名成testext.cpp,所以PHP_NEW_EXTENSION原本包括的testext.c也要修改.&lt;/P&gt;
&lt;P&gt;在使用C++之后要注意一个小问题,那就是php_testext.h这个文件可能被PHP的其他部分所引用到,而引用者很可能是一个.c文件,所以不能在php_testext.h里包含任何C++所独有的东西.比如标准模版库,类,或者bool类型等等.&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;默认生成的testext.c(现在改名为testext.cpp)了,已经包含了一个测试性质的导出函数,通过那个例子就可以大概明白怎么添加自己的函数了. zend_function_entry是导出函数列表, zend_module_entry描述了模块的信息. 不过因为是C++了,还是有几点要修改的: &lt;/P&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=a&gt;
&lt;LI&gt;
&lt;P&gt;#include "php.h" #include "php_ini.h" #include "ext/standard/info.h"&lt;/P&gt;
&lt;P&gt;要用extern "C" 修饰.&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;ZEND_GET_MODULE也要用extern "C"修饰&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;zend_module_entry就是用于描述模块信息的类型,其实就是一个结构,其中第二项不知道是什么含意.在Windows上,这好像是一个描述信息,可以是一个长长的字符串,但是在Linux上似乎只能是跟模块名相同.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;P&gt;之后的工作就是写自己的代码了.根据设计,提供对外的接口函数,然后写C/C++代码来实现.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV class=section lang=en&gt;
&lt;DIV class=titlepage&gt;
&lt;DIV&gt;
&lt;DIV&gt;
&lt;H3 class=title&gt;&lt;A name=d0e149&gt;&lt;/A&gt;2.2.&amp;nbsp;编译&lt;/H3&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=1&gt;
&lt;LI&gt;
&lt;P&gt;代码写好以后,到PHPSRC目录,运行./buildconf --force,除非m4文件有错或者autoconf安装有问题,否则这个步骤不会有什么错误,时间也不长. 通过删除configure文件,可以强迫buildconf重新生成一遍.&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;运行./configure --disable-all --with-testext=shared&lt;/P&gt;
&lt;P&gt;--disable-all是为了减少配置和下一步编译的时间,因为我们只需要自己的模块&lt;/P&gt;
&lt;P&gt;--with-testext=shared指明了讲这个模块编译成动态链接库,而不是集成到PHP内部&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;运行make&lt;/P&gt;
&lt;P&gt;这个过程时间比较长,如果你的代码有问题,就会出现编译或者链接错误,根据提示自己修改就是了. 如果没什么问题,就会在PHPSRC/modules下面生成扩展文件testext.so,同时也会生成PHPSRC/sapi/cli/php. 可以运行./sapi/cli/app ext/testext/testext.php来测试模块是否正常. 不过这之前要先把testext.so复制到某个特定的目录下,这个目录不同的系统不一样,你可以根据运行/sapi/cli/app ext/testext/testext.php得到的错误信息来知道这个目录.&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;如果测试没有问题,就可以安装到正式的PHP里去了,通过修改php.ini文件然后重起Apache就可以.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV class=section lang=en&gt;
&lt;DIV class=titlepage&gt;
&lt;DIV&gt;
&lt;DIV&gt;
&lt;H3 class=title&gt;&lt;A name=d0e171&gt;&lt;/A&gt;2.3.&amp;nbsp;调试&lt;/H3&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;用gdb可以调试PHP的扩展.首先要写一个php脚本用来测试你想测试的功能, 把它放到PHPSRC目录下,比如叫test.php. 然后按如下步骤进行:&lt;/P&gt;
&lt;DIV class=orderedlist&gt;
&lt;OL type=1&gt;
&lt;LI&gt;
&lt;P&gt;gdb&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;file ./sapi/cli/php&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;用b命令下断点.因为是C++程序,所以扩展的导出函数名并不是我们输入的名字,可以用nm命令查看扩展的所有导出函数,找到编译器最终分配的名字.这个名字是肯定包含了你原本输入的名字的,所以很好找.&lt;/P&gt;
&lt;P&gt;gdb会提示说这个符号在当前程序(php)里找不到,问你要不要在以后的shared library里找,回答Yes&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;run test.php,之后就会停在断点上了. 用n,s,display之类的命令调试的.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV class=section lang=en&gt;
&lt;DIV class=titlepage&gt;
&lt;DIV&gt;
&lt;DIV&gt;
&lt;H2 class=title style="CLEAR: both"&gt;&lt;A name=d0e191&gt;&lt;/A&gt;3.&amp;nbsp;总结&lt;/H2&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;P&gt;一句话,PHP的模块扩展比谁都麻烦,规则太多.其实我希望它提供一个文档,提供我在第二节开头描述的那些信息就够了. 不过也许是我学艺不精吧,对本来挺正常的事深恶痛绝,:)&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/23633.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>笔记: WinCE缺少的重要特性</title><link>http://blog.vckbase.com/jzhang/archive/2006/11/28/23268.html</link><pubDate>Tue, 28 Nov 2006 07:11:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2006/11/28/23268.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/23268.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2006/11/28/23268.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/23268.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/23268.html</trackback:ping><description>越做发现的越多:&lt;BR&gt;1. 不支持管道。可以通过流接口驱动来模拟，但是使用很麻烦。这种方法最经典的用例是wince的telnet服务&lt;BR&gt;2. 不支持环境变量。一般情况下不算太严重的问题，但是CGI是一定要使用环境变量来传递数据的。没找到&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 解决办法。&lt;BR&gt;3. 不支持&amp;#8220;当前目录&amp;#8221;。这个问题更加严重，类似fopen(&amp;#8221;data.txt&amp;#8221;,&amp;#8221;r&amp;#8221;)的代码会失败，除非data.txt位于&lt;BR&gt;/windows目录或者根目录。有很多C代码都是依赖当前目录而工作的。没有想到很好的解决办法，一种可能&lt;BR&gt;是提供一个静态库，需要使用&amp;#8220;当前目录&amp;#8221;的程序链接这个库，同时把fopen等操作都用宏定义的方式指向&lt;BR&gt;自己定义的包装函数。&lt;BR&gt;不知道winCE6.0能不能解决这些问题。&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/23268.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>shttpd和Lua组合-提供嵌入式web服务</title><link>http://blog.vckbase.com/jzhang/archive/2006/11/11/23070.html</link><pubDate>Sat, 11 Nov 2006 03:24:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2006/11/11/23070.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/23070.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2006/11/11/23070.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/23070.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/23070.html</trackback:ping><description>&lt;html&gt;
&lt;header&gt;
&lt;title&gt;shttpd和Lua的组合-提供嵌入式web服务&lt;/title&gt;
&lt;/header&gt;
&lt;body&gt;
&lt;center&gt;&lt;h3&gt;shttpd和Lua的组合-提供嵌入式web服务&lt;/h3&gt;&lt;/center&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;简单介绍：&lt;/b&gt;&lt;br&gt;
  &amp;nbsp;&amp;nbsp;lua是一个小巧的脚本语言，专用于嵌入和扩展。它和C/C++代码有着良好
的交互能力。由于体积小，很适合嵌入到其他程序中为程序提供脚本功能。
lua在大多数平台上都可以顺利编译、运行。网址 &lt;image src="http://jason.rocklv.net/techdoc/logo.gif"&gt;&lt;/image&gt;&lt;a href="http://www.lua.org" target="blank"&gt;http://www.lua.org&lt;/a&gt;&lt;p&gt;
  &amp;nbsp;&amp;nbsp;shttpd是一个小巧的web服务器，小巧到只有一个.c文件，4000余行代码。
虽然体积很小，却具备了最基本的功能，比如CGI。它既可以独立运行，
也可以嵌入到其他的应用程序当中。shttpd在大多数平台上都可以顺利
编译、运行。网址 &lt;a href="http://shttpd.sourceforge.net" target="blank"&gt;http://shttpd.sourceforge.net&lt;/a&gt;&lt;p&gt;
&lt;td&gt;
&lt;/tr&gt;  
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;应用方式：&lt;/b&gt;&lt;br&gt;
  &amp;nbsp;&amp;nbsp;很多设备都提供Web服务用于配置，比如路由器，ADSL猫等等。这种设备所
提供的web服务的典型用例是用户填写一些参数，提交给Web服务器，Web服务器
将这些参数写入硬件，并将操作结果或者其他信息生成页面返回给浏览器。
如果使用Apache,PHP,MySQL这种组合，一方面资源未必能承受，另一方面这些
硬&amp;nbsp;&amp;nbsp;件所使用的操作系统也未必能支持这些软件(如pSOS,VxWorks,WinCE)。&lt;p&gt;
  &amp;nbsp;&amp;nbsp;如果shttpd和lua结合起来，一个用来提供基本的web服务，另一个用来编写
CGI脚本，应该是一个很不错的选择。他们都具备体积小，占用资源少的特点，
又都宣称源码级可移植。如果有更高的需要，也可以把sqlite加入，提供数据
库服务(sqlite是一个嵌入式的数据库，同样体积小巧，并且可以在很多平台
上工作)。不带sqlite，体积仅仅300k，加上sqlite大约500k，对于嵌入式应
用非常合适。&lt;p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;向WinCE移植：&lt;/b&gt;&lt;br&gt;
  &amp;nbsp;&amp;nbsp;虽然lua使用的是比ANSI还要小的clean C，并且号称在所有平台上不用修改
任何东西就可以直接make成功，但是WinCE却是一个例外。事实上，对大多数
源码级可移植的C/C++程序，WinCE都是一个例外：因为它对标准C库的支持是
不完整的。&lt;p&gt;
  &amp;nbsp;&amp;nbsp;Lua 5.0版本的时候，有人提供了一个for WinCE的移植，工作的很好。基于
这个移植，我把Lua 5.1也移植了过去。因为Lua使用的是clean C，所以需要
做的改动不算很多，具体参看代码中的lua.c,lua.h,error.h和luacerun.c就
明白了。&lt;p&gt;
  &amp;nbsp;&amp;nbsp;shttpd就麻烦得多了，一方面它使用的是ANSI C，需要自己实现的函数更多，
比如文件读写，线程操作等。这些部分虽然麻烦，但是我还是一个个的把这些
缺失的函数自己实现了。更严重的是，WinCE 缺失了两个必不可少的特性：
管道和环境变量。&lt;p&gt;
  &amp;nbsp;&amp;nbsp;传统的CGI执行原理是web server通过管道将CGI程序的标准输入输出重定向，
从而向CGI程序发送数据并接收其输出的结果，同时通过设置CGI进程的环境变量，
将HTTP请求的各种信息传递给CGI程序，其中包括GET命令的查询串。这两个功能
WinCE都没有。 重定向的问题，可以通过编写特殊的WinCE驱动模拟解决，但是
也很受限制，使用不便；环境变量的问题则一点办法也没有了。&lt;p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;解决方案：&lt;/b&gt;&lt;br&gt;
  &amp;nbsp;&amp;nbsp;不过Lua为我们提供了可能的解决方案: 将Lua引擎直接嵌入shttpd。&lt;p&gt;
  &amp;nbsp;&amp;nbsp;如果将Lua直接嵌入shttpd,那在处理CGI请求的时候，我们不再需要创建新的
进程，而只需要创建一个新的Lua解释器，并交给一个线程去执行就可以了，这样
不仅在效率上有了提高，也可以适应某些古老的不支持多进程的操作系统了（在
这样的系统上，需要把shttpd也嵌入到主程序当中去）。为了传递原来用环境变
量方式传递的数据，我们在执行脚本之前，在新创建的Lua的解释器里创建一个叫
REQUEST的mapping类型的变量，将所有的数据设置在这个变量中。这样在脚本中
就可以直接使用这个变量了。&lt;p&gt;
  &amp;nbsp;&amp;nbsp;CGI程序还必须能够从标准输入接收POST请求，以及从标准输出发送HTML页面。
这一点可以通过修改shttpd,为Lua引擎扩展两个函数来实现，分别是HTTPRead和
HTTPWrite。在脚本中调用这两个函数来实现输入和输出。为了使用方便和习惯，
再把标准的print和io.read函数指向HTTPWrite和HTTPRead(函数在Lua中是第一
类型)。&lt;p&gt;
  &amp;nbsp;&amp;nbsp;这两个问题解决之后，剩下的就是用Lua脚本写一个简单的CGI开发框架了，
LuaCGI就是一个很好的框架，只需要把它所使用的SAPI替换成shttpd提供的
接口就可以了。&lt;p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;总结：&lt;/b&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;用shttp+lua的组合，可以在各种不同的平台，尤其是嵌入式平台上提供web服务
，满足在资源有限的环境中工作的需要。由于Lua是直接嵌入到shttpd中的，它
有着比一般的CGI更高的效率。&lt;p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;table&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/23070.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>WinCE下的输入输出重定向</title><link>http://blog.vckbase.com/jzhang/archive/2006/09/05/22252.html</link><pubDate>Tue, 05 Sep 2006 10:10:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2006/09/05/22252.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/22252.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2006/09/05/22252.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/22252.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/22252.html</trackback:ping><description>WinCE不支持管道，所以在Windows/Linux平台利用管道进行重定向的办法无效。&lt;BR&gt;通过阅读WinCE telnetd的代码发现，在WinCE下进行重定向用的是流接口驱动的&lt;BR&gt;办法。&lt;BR&gt;简单的说，就是写一个设备驱动，host程序打开它，然后把slave程序的stdin/out设置&lt;BR&gt;到这个设备上(SetStdioPathW)。因为WinCE的设备驱动其实是一个运行在用户模式&lt;BR&gt;下的Dll,而且在内存中永远只有一份。所以可以通过这个Dll来实现 Host和Slave&lt;BR&gt;程序之间的交互。&lt;BR&gt;比较复杂的情况是多进程/线程的问题，因为不同的进程可以同时使用这个驱动。&lt;BR&gt;&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/22252.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>jzhang</dc:creator><title>奇怪的MVC模式 - 谢谢FastZhao</title><link>http://blog.vckbase.com/jzhang/archive/2006/08/10/21810.html</link><pubDate>Thu, 10 Aug 2006 09:54:00 GMT</pubDate><guid>http://blog.vckbase.com/jzhang/archive/2006/08/10/21810.html</guid><wfw:comment>http://blog.vckbase.com/jzhang/comments/21810.html</wfw:comment><comments>http://blog.vckbase.com/jzhang/archive/2006/08/10/21810.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://blog.vckbase.com/jzhang/comments/commentRss/21810.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/jzhang/services/trackbacks/21810.html</trackback:ping><description>在GoF的Design Patterns一书的1.2节，作者简单的描述了SmallTalk 中的 MVC 模式，但是奇怪的是，&lt;BR&gt;在书的正文部分的23种模式中却没有MVC的位置。原文对MVC简要解释如下：&lt;BR&gt;1. MVC consists of three kinds of objects. The Model is the application object, the View is its screen presentations, &lt;BR&gt;and the Controller defines the way the user inteface reacts to&amp;nbsp;user input . &lt;BR&gt;2. MVC decouples views and modules by establishing a subscribe/notify protocol between them. &lt;BR&gt;&lt;BR&gt;在绝大多数桌面应用程序中，MVC中的V和C都合并了。这是因为M需要多个V是常见的，但是同一个&lt;BR&gt;View需要不同的Controller却很少见。书上举的例子就是可以实现ReadOnly的View,通过配置一个什么也不&lt;BR&gt;能干的Controller来实现。&lt;BR&gt;&lt;BR&gt;本来MVC就这么多内容了，但是我却被迷惑了很长的时间：&lt;BR&gt;1. MFC 里的 Document/View 结构是不是MVC模式？&amp;nbsp;&lt;BR&gt;2. Web应用中的MVC和SmallTalk定义的MVC是不是一回事？ &lt;BR&gt;&lt;BR&gt;to be completed&lt;BR&gt;欢迎大家在回复你帮我解答这两个问题。回家吃饭先~&lt;BR&gt;&lt;BR&gt;继续，谢谢 &lt;A id=Comments1_CommentList__ctl0_NameLink target=_blank&gt;fastzhao&lt;/A&gt;的回复：&lt;BR&gt;1. MFC的Document/View 结构并没有实现观察者模式。他不过是简单的划分了谁负责&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 保存数据，谁负责绘制以及相应操作。所以我们常常可以看到一些应用程序把所有的&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 数据处理的逻辑集中在了View里。View和View之间也是直接操纵。究其原因，主要 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 是因为抽象出这个Model其实很不容易，所以常常把它当作一个大仓库和save/open的&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 工具了事。真正的Model应该把对数据的读写都封装起来，并且实现观察者模式。&lt;BR&gt;2. 在Web应用中，同样也没有MV之间的观察者模式。不过MVC都是完整的。一般Model&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;代表了数据库，controller接受HTTP请求(GET,POST)，调用Model处理，然后调用View来Render.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;所以，GoF里描述的MVC，实际上用的并不广泛。虽然它复合了多种模式，是一个理想的例子，&lt;BR&gt;但是在实际应用中，并不是按照理论上的描述来实现的。&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;img src ="http://blog.vckbase.com/jzhang/aggbug/21810.html" width = "1" height = "1" /&gt;</description></item></channel></rss>