﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><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>C++博客-qiezi的学习园地-随笔分类-自家破烂</title><link>http://www.cppblog.com/cpunion/category/48.html</link><description>AS/C/C++/D/Java/JS/Python/Ruby</description><language>zh-cn</language><lastBuildDate>Mon, 26 May 2008 15:24:30 GMT</lastBuildDate><pubDate>Mon, 26 May 2008 15:24:30 GMT</pubDate><ttl>60</ttl><item><title>搬家</title><link>http://www.cppblog.com/cpunion/archive/2006/10/09/13499.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 09 Oct 2006 14:33:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/10/09/13499.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/13499.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/10/09/13499.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/13499.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/13499.html</trackback:ping><description><![CDATA[因兴趣转移，最近比较迷ruby和d，为了不再影响这里的c++氛围，搬到http://qiezi.javaeye.com。<img src ="http://www.cppblog.com/cpunion/aggbug/13499.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-10-09 22:33 <a href="http://www.cppblog.com/cpunion/archive/2006/10/09/13499.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>段落文本渲染引擎</title><link>http://www.cppblog.com/cpunion/archive/2006/10/09/13484.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 09 Oct 2006 03:44:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/10/09/13484.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/13484.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/10/09/13484.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/13484.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/13484.html</trackback:ping><description><![CDATA[最近在一个项目中要渲染段落文本，找了很多文字渲染库，发现都不能满足我的要求，所以只能自己做。字体渲染还是找freetype完成吧，虽然小字号效果不好，不过可以生成大图再缩小来解决掉，自己写一个字体渲染引擎也是不可望也不可及的事。<br /><br />有了freetype实现底层字体渲染，我只需要处理一些布局方法即可，其中要实现的有以下几点：<br /><br />1、英、中字体<br />很多中文字体中的英文字体都比较难看，所以在X的字体配置中设置了一个字体顺序。我也可以学学，传递一个字体列表，拿到一个字符时，按顺序从字体列表中查询，查询不到时就查下一个字体，这样就可以实现英、中使用不同字体了。<br /><br />2、分行<br />段落分行要考虑到中、英文不同的分割方式，还有标点符号，某引起标点符号不能在行尾（比如“&lt;等），某些标点不能在行首（比如”&gt;），某些标点不能分割（比如破折号），所以实际上要有一个分割算法，把段落分成一个个的标记，汉字直接分割，英文按空格分割，不能在行首的标点就分到前面单词里，不能在行尾的就分在后面的单词里。<br /><br />3、对齐<br />对齐方式有左、中、右、两端(Full Justification)这几种方式，目前大部分开源渲染库都不支持两端对齐，这也是我要自己实现的主要原因。左、中、右只要计算出一行的所有字符宽度，再计算出左边距即可。两端对齐则需要计算每个单词的间距。<br /><br />4、段首缩进<br />
原来设想在分段后直接加上全角空格，不想这个空格在转成UNICODE编码时，它的编码是\u0000，不能获取到全角空格的宽度。于是把它设成字体高度，看了一下效果还好。<br /><img src ="http://www.cppblog.com/cpunion/aggbug/13484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-10-09 11:44 <a href="http://www.cppblog.com/cpunion/archive/2006/10/09/13484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[private] 文字绘图库资料收集</title><link>http://www.cppblog.com/cpunion/archive/2006/09/28/13124.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Thu, 28 Sep 2006 12:03:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/09/28/13124.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/13124.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/09/28/13124.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/13124.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/13124.html</trackback:ping><description><![CDATA[主要收集可以绘制文字的绘图库。<br /><br />一、imagemagick:<br />http://www.cit.gu.edu.au/~anthony/graphics/imagick6/<br />可以绘制文字，不过中文好像不能自动断行。<br /><br />二、vips<br />http://vips.sourceforge.net<br />使用pango绘制文字，中文可以断行，缺少2端对齐功能。自己修改代码增加了调整行距功能，做成ruby扩展库，amd64上使用失败，原因待查。<br /><br />三、freetype<br />http://vips.sourceforge.net<br />不依赖其它图形/窗口库，其它不熟悉，待查。<br /><br />四、Graphite<br />跨平台的字体渲染库。待查。<br /><br /><br />搜寻已有数月，目前看到的几个库都不太理想，mac osx上可能比较专业，不过集成较困难。<br /><br />苹果网站上的比较完整的字体绘制和布局方面的资料：<br />http://developer.apple.com/documentation/Carbon/Conceptual/ATSUI_Concepts/index.html<br />其中布局方面的专业知识：<br />http://developer.apple.com/documentation/Carbon/Conceptual/ATSUI_Concepts/atsui_chap3/chapter_3_section_3.html#//apple_ref/doc/uid/TP30000029-TPXREF157<br /><br /><br />其它资料：<br /><ul><li><a href="http://anonymouse.org/cgi-bin/anon-www.cgi/http://en.wikipedia.org/wiki/Uniscribe" title="Uniscribe">Uniscribe</a> (Windows multilingual text rendering engine)</li><li><a href="http://anonymouse.org/cgi-bin/anon-www.cgi/http://en.wikipedia.org/wiki/WorldScript" title="WorldScript">WorldScript</a> (Old Macintosh multilingual text rendering engine)</li><li><a href="http://anonymouse.org/cgi-bin/anon-www.cgi/http://en.wikipedia.org/wiki/Apple_Type_Services_for_Unicode_Imaging" title="Apple Type Services for Unicode Imaging">Apple Type Services for Unicode Imaging</a> (New Macintosh multilingual text rendering engine)</li></ul><br /><img src ="http://www.cppblog.com/cpunion/aggbug/13124.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-09-28 20:03 <a href="http://www.cppblog.com/cpunion/archive/2006/09/28/13124.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 实现一个auto_redirect_to</title><link>http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Fri, 19 May 2006 18:33:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7434.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7434.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7434.html</trackback:ping><description><![CDATA[最近在使用RoR做项目，体会到了快速开发的乐趣，也遇到了一些困难，其中一个就是redirect_to。<br /><br />我遇到的一个问题是，当使用Ajax更新页面局部内容时，session内容已经过期，这时需要整个页面跳转到登录页面。<br /><br />直接调用redirect_to会使局部内容显示成登录页面，它是在HTTP头里写入重定向参数来实现的。在我这里的特殊情况下，正确的做法是让它执行一个包含在&lt;script&gt;标记中的脚本，在脚本中更改窗口location值来跳转。<br /><br />不过RoR中使用Ajax时，会根据:update参数来决定是使用Updater还是Request。如果使用Updater方式，则应返回一段纯脚本；如果是Request方式，应返回一段包括在&lt;script&gt;标记中的脚本；如果是普通方式，就应该使用原有的redirect_to函数了。因为服务端无法区分使用的是哪种方式来请求，所以简单的做法是每个请求都附加一个参数用来区分，不加参数则是普通请求方式。<br /><br />为了达到这个目的，我修改了prototype_helper中的remote_function函数。这个函数根据传递进来的参数来决定使用Request或是Updater，我就在这里下手：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">      def remote_function(options)<br />        javascript_options </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> options_for_ajax(options)<br /><br />        update </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">''</span><span style="color: rgb(0, 0, 0);"><br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:update] and options[:update].is_a</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);">Hash<br />          update  </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> []<br />          update </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">success:'#{options[:update][:success]}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:update][:success]<br />          update </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">failure:'#{options[:update][:failure]}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:update][:failure]<br />          update  </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> update.join(</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">}</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />        elsif options[:update]<br />          update </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">'#{options[:update]}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />        end<br /><br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> update.empty</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> <br />          </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">new Ajax.Request(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> :<br />          </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">new Ajax.Updater(#{update}, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />    <br />        url_options </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> options[:url]<br /><font color="#ff0000"><b>        ajax_options </b></font></span><font color="#ff0000"><b><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> options[:update] </span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> {:ajax </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">} : {:ajax </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">request</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">}<br />        url_options </span><span style="color: rgb(0, 0, 0);">=</span></b></font><span style="color: rgb(0, 0, 0);"><font color="#ff0000"><b> url_options.merge(ajax_options)</b></font><br />        url_options </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> url_options.merge(:escape </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> url_options.is_a</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> Hash<br />        function </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">'#{url_for(url_options)}'</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />        function </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, #{javascript_options})</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br /><br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{options[:before]}; #{function}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:before]<br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{function}; #{options[:after]}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:after]<br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">if (#{options[:condition]}) { #{function}; }</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:condition]<br />        function </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> options[:confirm]<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> function<br />      end</span></div><br />有红色的2行是我添加的，由于这个编辑器的原因，没有显示成整行红色。这2行的作用是判断是否有:update参数，用它来决定是添加ajax=update还是ajax=request。<br /><br />现在可以实现一个简单的auto_redirect_to了：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">  def auto_redirect_to(method, url)<br />    </span><span style="color: rgb(0, 0, 255);">case</span><span style="color: rgb(0, 0, 0);"> method<br />    when </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">request</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />      request_redirect_to(url)<br />    when </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">update</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />      update_redirect_to(url)<br />    </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />      redirect_to(url)<br />    end<br />  end<br />  <br />  def request_redirect_to(url)<br />    render :update </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">page</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />      page.redirect_to(url)<br />    end<br />  end<br />  <br />  def update_redirect_to(url)<br />    render :inline </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;-</span><span style="color: rgb(0, 0, 0);">EOS<br />      </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">script language</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">javascript</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />      </span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"><br />        render :update </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">page</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />          page.redirect_to(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{url_for(url)}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />        end<br />      </span><span style="color: rgb(0, 0, 0);">%&gt;</span><span style="color: rgb(0, 0, 0);"><br />      </span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">script</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />    EOS<br />  end</span></div><br />使用helper方式使它能够被include到ApplicationController中就行了。<br /><br />为了不和参数绑得太死，这里把method作为参数由调用者传入。<br /><br />使用方法，以Login Engine为例，它在access_denied中处理跳转。在ApplicationController中重写这个函数：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">    def access_denied<br />      auto_redirect_to(</span><span style="color: rgb(0, 0, 255);">params</span><span style="color: rgb(0, 0, 0);">[:ajax], :controller </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">/user</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, :action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">login</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />      </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);"><br />    end  </span></div><br />现在可以测试了。请求可以是普通的（超链接），Updater方式（请求到一个DIV里），Request方式，现在都能够跳转到正确页面。<br /><br />ajax参数通过hack库代码来实现，对于使用者来说基本上是透明的。<br /><img src ="http://www.cppblog.com/cpunion/aggbug/7434.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-20 02:33 <a href="http://www.cppblog.com/cpunion/archive/2006/05/20/7434.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 在RoR中调用.Net webservice</title><link>http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sun, 14 May 2006 12:08:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7138.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7138.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7138.html</trackback:ping><description><![CDATA[首先写一个简单的webservice：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System;<br /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.Web;<br /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.Web.Services;<br /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.Web.Services.Protocols;<br /><br />[WebService(Namespace </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://tempuri.org/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br />[WebServiceBinding(ConformsTo </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> WsiProfiles.BasicProfile1_1)]<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Service : System.Web.Services.WebService<br />{<br />    [WebMethod]<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000"> HelloWorld(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000"> name) {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> name;<br />    }<br />    <br />}</span></div><br />在RoR项目里，添加app/apis/test_api.rb：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> TestApi </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionWebService::API::Base<br />  api_method :HelloWorld, :expects </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> [{:name </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> :string}], :returns </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> [:string]<br />end<br /></span></div><br />这是RoR里面通用的webservice元信息描述。<br /><br />添加app/controllers/test_controller.rb:<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> TestController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  web_client_api :test, :soap, </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">http://localhost/test/Service.asmx</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">, <br />                 :namespace </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">http://tempuri.org/</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">,<br />                 :soap_action_base </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">http://tempuri.org</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">,<br />                 :driver_options</span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000">{:default_encodingstyle </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> SOAP::EncodingStyle::ASPDotNetHandler::Namespace }<br /><br />  </span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000"> hello<br />    render_text test.HelloWorld(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">Li Jie</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">)<br />  end<br />end</span></div><br />:soap_action_base选项是一个修补，不加这个选项会产生SOAPAction头错误。<br /><br />运行服务器，在浏览器中访问/test/hello，发现名字为空。经过长时间调试，发现.Net在解析SOAP消息体时，不能处理这种命名空间：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">n1:HelloWorld </span><span style="COLOR: #ff0000">xmlns:n1</span><span style="COLOR: #0000ff">="http://tempuri.org/"</span><span style="COLOR: #ff0000"><br />        soap:encodingStyle</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/soap/encoding/"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br />      </span><span style="COLOR: #0000ff">&lt;name</span><span style="COLOR: #800000"> </span><span style="COLOR: #ff0000">xsi:type</span><span style="COLOR: #0000ff">="xsd:string"</span><span style="COLOR: #0000ff">&gt;Li Jie</span><span style="COLOR: #0000ff">&lt;/name</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br />    </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">n1:HelloWorld</span><span style="COLOR: #0000ff">&gt;</span></div><br />把n1去掉就行了。不过这部分实现在rubylib/soap/rpc/proxy.rb里面，实在不方便修改。为了让这个测试通过，暂时做了点小修改：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000"> route(req_header, req_body, reqopt, resopt)<br />    req_env </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ::SOAP::SOAPEnvelope.new(req_header, req_body)<br />    unless reqopt[:envelopenamespace].nil?<br />      set_envelopenamespace(req_env, reqopt[:envelopenamespace])<br />    end<br />    reqopt[:external_content] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> nil<br />    conn_data </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> marshal(req_env, reqopt)<br />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ext </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> reqopt[:external_content]<br />      mime </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> MIMEMessage.new<br />      ext.each do </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">k, v</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />          mime.add_attachment(v.data)<br />      end<br />      mime.add_part(conn_data.send_string </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">\r\n</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">)<br />      mime.close<br />      conn_data.send_string </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> mime.content_str<br />      conn_data.send_contenttype </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> mime.headers[</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">content-type</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">].str<br />    end<br /><br /><strong>    conn_data.send_string.gsub!(</strong></span><strong><span style="COLOR: #000000">/</span><span style="COLOR: #000000">:n1</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">''</span></strong><strong><span style="COLOR: #000000">)<br />    conn_data.send_string.gsub!(</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">n1:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">''</span></strong><span style="COLOR: #000000"><strong>)</strong><br /><br />    conn_data </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> @streamhandler.send(@endpoint_url, conn_data,<br />      reqopt[:soapaction])<br />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> conn_data.receive_string.empty?<br />      </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> nil<br />    end<br />    unmarshal(conn_data, resopt)<br />  end</span></div><br />加粗的2行是我添加的代码，勉强可以让它工作，不过显然不是正确的方法。<br /><br />不知道是不是.Net库里面的BUG。<img src ="http://www.cppblog.com/cpunion/aggbug/7138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-14 20:08 <a href="http://www.cppblog.com/cpunion/archive/2006/05/14/7138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 脚本模拟RJS刷新页面</title><link>http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sat, 13 May 2006 15:49:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7087.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7087.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7087.html</trackback:ping><description><![CDATA[使用脚本来模拟RJS语法及功能。<br /><br />演示页面直接在浏览器中观看。<br /><br /><a href="/Files/cpunion/script_action_demo.zip">演示下载</a><img src ="http://www.cppblog.com/cpunion/aggbug/7087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-13 23:49 <a href="http://www.cppblog.com/cpunion/archive/2006/05/13/7087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 用javascript脚本模拟一个action</title><link>http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Fri, 12 May 2006 15:41:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/7046.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/7046.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/7046.html</trackback:ping><description><![CDATA[rails 1.1以上版本提供了强大优雅的RJS，可能执行一个请求多个更新。<br /><br />有些时候我们并不需要请求服务器，只想在浏览器上执行某些脚本更新，但又想使用RJS。所以为RoR增加了这项功能。<br /><br />使用方法：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">script language</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">javascript</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> <br />render :update do </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">page</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />  page.define_action </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">test_action</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> do<br />    page.call_script </span><span style="COLOR: #000000">&lt;&lt;-</span><span style="COLOR: #000000">EOS<br />      alert(params.comment.title);<br />      alert(params.comment.body);<br />    EOS<br />    page.replace_html </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">errors</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">ERROR</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"><br />  end<br /><br />  page.define_action </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">link_action</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> do<br />    page.replace_html </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">errors</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">, </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">ERROR</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"><br />  end<br />end<br /></span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><br /></span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">div id</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">errors</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">&gt;&lt;/</span><span style="COLOR: #000000">div</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> form_local_tag :html </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> {:action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">test_action</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">} </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br />  </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input name</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">comment[title]</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">/&gt;&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />  </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input name</span><span style="COLOR: #000000">=</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">comment[body]</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">/&gt;&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />  </span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> submit_tag </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">Create</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> end_form_tag </span><span style="COLOR: #000000">%&gt;</span><span style="COLOR: #000000"><br /><br /></span><span style="COLOR: #000000">&lt;%=</span><span style="COLOR: #000000"> link_to_local </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">Test</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">, :action </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">link_action()</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">%&gt;</span></div><br />上面演示了form_local_tag和link_to_local的使用，打开这个页面以后，可以关掉服务器测试，会发现它不请求服务器也能执行相应脚本。<br /><br />define_action定义一个脚本函数，call_script用来实现javascript和RJS代码的混合。当使用form_local_tag时，action方法的参数已经被处理过，所以可以直接在action中使用params.comment.title。<br /><br />当然现在还不完善，比如还只能使用转换完的页面模板，一些动态页面将看不出效果。要做到这点，需要用javascript实现一整套的ActionView辅助方法。<br /><br />下面提供一个针对rails 1.1.2的一个补丁文件：<br /><br /><a href="/Files/cpunion/script_action.zip">补丁文件下载</a><img src ="http://www.cppblog.com/cpunion/aggbug/7046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-12 23:41 <a href="http://www.cppblog.com/cpunion/archive/2006/05/12/7046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[RoR] 简单的角色权限检查插件</title><link>http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 08 May 2006 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/6790.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/6790.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/6790.html</trackback:ping><description><![CDATA[代码比较简单：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">module ActionController </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br />  class CheckGroupError </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionControllerError </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    attr_reader </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">group_name<br />    def initialize(group_name)<br />      </span><span style="COLOR: #800080">@group_name</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> group_name<br />    end<br />  end<br />  <br />  class CheckRoleError </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionControllerError </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    attr_reader </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">role_name<br />    def initialize(role_name)<br />      </span><span style="COLOR: #800080">@role_name</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> role_name<br />    end<br />  end<br />  <br />  class Base </span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">:nodoc:</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    def roles<br />      []<br />    end<br />    <br />    def groups<br />      []<br />    end<br />    <br />    def check_roles(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">role_args)<br />      role_args</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">each</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">role</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />        check_role(role)<br />      end<br />    end<br />    <br />    def check_groups(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">group_args)<br />      group_args</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">each</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">group</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"><br />        check_group(group)<br />      end<br />    end<br />    <br />    def check_group(group)<br />      raise CheckGroupError</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">new(group</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s) </span><span style="COLOR: #0000ff">unless</span><span style="COLOR: #000000"> groups()</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">include</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">(group</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s)<br />    end<br />    <br />    def check_role(role)<br />      raise CheckRoleError</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">new(role</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s)   </span><span style="COLOR: #0000ff">unless</span><span style="COLOR: #000000"> roles()</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">include</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">(role</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">to_s)      <br />    end<br />  end<br />  <br />end</span></div><br />只需要在ApplicationController中实现roles和groups这2个方法，对数据库模式没有任何限制，只要能保证这2个方法能够得到当前用户的角色和组即可。<br /><br />有4个check方法可用，可任意使用一个或多个。<br /><br />简单模拟测试一下：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">class ApplicationController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ActionController</span><span style="COLOR: #000000">::</span><span style="COLOR: #000000">Base<br />  def roles<br />    </span><span style="COLOR: #800080">%w</span><span style="COLOR: #000000">(add show)<br />  end<br /><br />  def groups<br />    </span><span style="COLOR: #800080">%w</span><span style="COLOR: #000000">(users)<br />  end<br />end</span></div><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">class TestController </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ApplicationController<br />  def test1<br />    check_role </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">add<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br /><br />  def test2<br />    check_role </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">add<br />    check_group </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">users<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br /><br />  def test3<br />    check_groups </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">admin</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">users<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br /><br />  def test4<br />    check_roles </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">add</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">remove<br />    render_text </span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="FONT-WEIGHT: bold; COLOR: #000000">OK</span><span style="FONT-WEIGHT: bold; COLOR: #000000">"</span><span style="COLOR: #000000"><br />  end<br />end</span></div><br />其中，test1、test2都会成功，而test3和test4则会失败显示异常，只需要处理rescue_action把它修改为自己的显示页面即可。<img src ="http://www.cppblog.com/cpunion/aggbug/6790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2006-05-08 21:30 <a href="http://www.cppblog.com/cpunion/archive/2006/05/08/6790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C＋＋实现简单的类型库</title><link>http://www.cppblog.com/cpunion/archive/2005/09/26/435.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Mon, 26 Sep 2005 09:31:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/26/435.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/435.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/26/435.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/435.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/435.html</trackback:ping><description><![CDATA[很久以前看到有人问“如何在C＋＋中实现动态加载类”时，简单地做了一个。<BR><BR>不过当时没有去考虑动态加载DLL的情况。<BR><BR>今天在<A href="mailto:cpp@codingnow.com">cpp@codingnow.com</A>中也有人问到这个问题，就把它给做完了。<BR><BR>当然只是简单地做到了“从全局类型库中，根据类名创建实例，支持动态DLL加载”，说得更明白点：<BR><BR>在应用程序App1中，向全局类型库中注册一个类型"Test"，在另一个隐式链接的DLL中（即App1一启动就加载的DLL），向全局类型库中注册另外几个类型。这时可以在App1中通过类型的名字生成实例。<BR><BR>在另一个显式加载的DLL中（即调用LoadLibrary加载），向全局类型库中注册其它几个类型。这时通过LoadLibrary加载这个DLL，就可以生成这几个类型的实例了。<BR><BR>这地方不能上传文件，就把代码贴一点吧：<BR><BR>typelib.h文件：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">#ifndef&nbsp;__TYPE_LIB_H__<BR></SPAN><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000">&nbsp;__TYPE_LIB_H__</SPAN><SPAN style="COLOR: #000000"><BR><BR>typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">CREATE_FUNC)();<BR>typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">RELEASE_FUNC)(</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">);<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;regtype&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;name,&nbsp;CREATE_FUNC&nbsp;cfunc,&nbsp;RELEASE_FUNC&nbsp;rfunc);<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;createObject&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;name);<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;releaseObject&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;name,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;p);<BR><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;ITestInterface<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">~</SPAN><SPAN style="COLOR: #000000">ITestInterface&nbsp;()&nbsp;{}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;print&nbsp;()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;create&nbsp;()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;T;<BR>}<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;release&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;p)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;(T</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)p;<BR>}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">#endif</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;__TYPE_LIB_H__</SPAN></DIV><BR>typelib.cpp文件：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">#include&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">typelib.h</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000"><BR><BR>#include&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>#include&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">map</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">using</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">namespace</SPAN><SPAN style="COLOR: #000000">&nbsp;std;<BR><BR></SPAN><SPAN style="COLOR: #0000ff">namespace</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeRegistry<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;map&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;pair</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">CREATE_FUNC,&nbsp;RELEASE_FUNC</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;types_info;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;regType&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">&nbsp;name)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;types_info.insert&nbsp;(make_pair(name,&nbsp;make_pair(create</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;release</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)));<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;regtype&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;name,&nbsp;CREATE_FUNC&nbsp;cfunc,&nbsp;RELEASE_FUNC&nbsp;rfunc)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;TypeRegistry::types_info.insert&nbsp;(make_pair(name,&nbsp;make_pair(cfunc,&nbsp;rfunc)));<BR>}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;createObject&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;name)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;map&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;pair</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">CREATE_FUNC,&nbsp;RELEASE_FUNC</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::const_iterator&nbsp;iter;<BR>&nbsp;&nbsp;&nbsp;&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeRegistry::types_info.find&nbsp;(name);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(iter&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeRegistry::types_info.end&nbsp;())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">iter</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">second.first)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;NULL;<BR>}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;releaseObject&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;name,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;p)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;map&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;pair</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">CREATE_FUNC,&nbsp;RELEASE_FUNC</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::const_iterator&nbsp;iter;<BR>&nbsp;&nbsp;&nbsp;&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeRegistry::types_info.find&nbsp;(name);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(iter&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeRegistry::types_info.end&nbsp;())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">iter</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">second.second)(p);<BR>}</SPAN></DIV><BR>把它编译成静态lib或DLL，就可以使用了。<BR><BR>在那2个为我们提供类型的DLL中，DllMain函数中加入下面的代码：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;FirstTest和SecondTest是2个类名</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">regtype(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">FirstTest</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;create</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">FirstTest</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;release</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">FirstTest</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">);<BR>regtype(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">FirstTest</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;create</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">SecondTest</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;release</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">SecondTest</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">);</SPAN></DIV><BR>就可以向全局类型库中注册类型。注意在类型库中是没有保存类信息的，所以最好是使用单根类库来做。<BR><BR>下面是一点测试代码：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;程序启动时注册类型。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;实际上启动时就加载了另一个动态链接库，那里面有3个类型，所以现在有4个类型</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regtype&nbsp;(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">MyTest</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;create</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">MyTest</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;release</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">MyTest</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">while</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;class_name;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cin&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;class_name;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(class_name&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">q</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">break</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;当输入load时，把另一个动态链接库加载进来，那个链接库中有2个类型，现在共有6个类型可用。</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(class_name&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">load</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LoadLibrary(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">typelibdll_test.dll</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">continue</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ITestInterface</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;test&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(ITestInterface</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)createObject&nbsp;(class_name.c_str());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">test)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">This&nbsp;type&nbsp;not&nbsp;found</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">continue</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">print&nbsp;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;releaseObject&nbsp;(class_name.c_str(),&nbsp;test);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}<BR></SPAN></DIV><BR>还有一个没考虑的地方，就是没有给它加锁，因为有可能在一个线程中加载一个DLL。<BR><BR>不过我还有些怀疑这东西是否真的有用？<img src ="http://www.cppblog.com/cpunion/aggbug/435.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-26 17:31 <a href="http://www.cppblog.com/cpunion/archive/2005/09/26/435.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（二）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/20/349.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Tue, 20 Sep 2005 14:34:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/20/349.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/349.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/20/349.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/349.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/349.html</trackback:ping><description><![CDATA[<P>说明：<BR>要看懂后面那部分代码，即使用Typelist的部分，最好预先看过《C＋＋设计新思维》，英文版名为《Modern C++ Design》。<BR>If模板类在写完后想起来好像在哪见过，早晨去公司查阅了一下，在《产生式编程——方法、工具与应用》一书中有讲，英文名为《Generative Programming -- Methods, Tools, and Applications》基本和本篇中一个样。<BR><BR><BR>前2篇乱七八糟地讲了一些，有一个遗留问题，函数原型的推导。<BR><BR>简要描述如下：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;method;<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;同步调用</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;str&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hello</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">;<BR>method&nbsp;(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;str,&nbsp;value</SPAN><SPAN style="COLOR: #000000">);<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;异步调用1</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">method.async_call&nbsp;(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hello</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;异步调用2</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;test_func&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">);<BR>method.async_call&nbsp;(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hello</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;test_func);</SPAN></DIV>
<P><BR>要产生这3种函数形式。参数类型如何转换，是以后的话题，本篇主要解决异步调用的函数原形推导问题。本篇也不讨论Method的模板参数（即那个函数类型）返回类型不为void的情况。<BR><BR>第一种形式，同步调用，比较好处理，参数个数和模板参数的数量相同。<BR><BR>后2种形式，如何让编译器根据in/out来推导出函数原型？<BR><BR>我们需要编译器做这样的处理，async_call的参数类型中，in类型的参数将保留，out类型的参数不需要，inout类型也需要保留。<BR><BR>要用到的Loki头文件：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">#include&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">static_check.h</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>#include&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Typelist.h</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR><BR></SPAN><SPAN style="COLOR: #0000ff">using</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">namespace</SPAN><SPAN style="COLOR: #000000">&nbsp;Loki;<BR></SPAN><SPAN style="COLOR: #0000ff">using</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">namespace</SPAN><SPAN style="COLOR: #000000">&nbsp;Loki::TL;</SPAN></DIV>
<P><BR>首先看看in/inout/out的声明。为了简化，这里去掉了跟类型推导无关的部分。</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;NullType&nbsp;();<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;inout<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>};<BR></SPAN></DIV><BR>下面Method模板类的声明，使用偏特化来产生代码。为了简化，我只取函数参数个数为4个参数的版本，比照着上面的代码来解释，只解释method.async_call (3, 'a', "hello", test_func);这个版本，因为另一个比它简单。<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Method<BR>{<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Ret,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Ret(A,B,C,D)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR>{<BR>};</SPAN></DIV>
<P><BR>根据上面Method的定义，Method &lt; void(in<INT>, in<CHAR>, inout<STRING>, out<SHORT>) &gt; ，async_call函数的类型将是：<SPAN style="COLOR: #000000"></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;FUNC_TYPE&nbsp;func);</SPAN></DIV></SPAN><BR>实际上FUNC_TYPE应该能够接受更广泛的类型，比如void(int, char, char*, short)，这可以在内部做一些转换，不过本篇的重点不在这里，所以只讲上面的那种形式。<BR><BR>直接在Method类中实现有些麻烦，所以我把这个函数放在一个基类中实现，只要编译器能帮我们推导出下面这种形式就行了：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Ret,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Ret(A,B,C,D)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;B,&nbsp;C&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>};</SPAN></DIV>
<P><BR>注意，这里是以Method &lt; void(in<INT>, in<CHAR>, inout<STRING>, out<SHORT>) &gt;这种形式来讲的，才会有上面那种继承关系。而实际上，由于in/out在参数中的位置、数量都是未知的，要到定义时才能确定，所以使用模板来推导。（入正题了）</P>
<P>也就是说，只要我们能使用静态推导方式，获得A,B,C,D这四个参数中所有的in类型，把它交给Base作为模板参数就成了。</P>
<P>这里需要一个辅助的模板类，用来在编译时帮助推导：<BR><BR></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;Loki::CompileTimeError&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;Not_Supported_Type;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">};<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">};<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">};<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">};<BR>};</SPAN></DIV></SPAN><BR>通过另一个模板类InList来帮我们产生所有的in类型，它的结果是一个Typelist。为了方便以后使用，我把out类型产生器也做了一个OutList。<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;CONDITION,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_IF,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_ELSE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;If<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_IF&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_IF,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_ELSE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;_IF,&nbsp;_ELSE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_ELSE&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;E&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;F&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;G&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;H&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType<BR></SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InList<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isin,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Typelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;typename&nbsp;InList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;InList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G,H</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isin,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&gt;</SPAN><SPAN style="COLOR: #000000">::Result<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;E&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;F&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;G&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;H&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType<BR></SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;OutList<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isout,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Typelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;typename&nbsp;OutList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;OutList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G,H</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;OutList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};</SPAN></DIV><BR>它的原理是，根据If模板类来判断一个类型是不是in类型，是的话就把它加入到Typelist中，不是就排除它。<BR><BR>InList <IN<INT>, in<CHAR>, inout<STRING>, out<SHORT>::Result是一个Typelist <IN<INT>, Typelist<IN<CHAR>, Typelist<INOUT<STRING>, NullType&gt; &gt; &gt;类型，说简单点，它和MakeTypelist &lt; in<INT>, in<CHAR>, inout<STIRNG> &gt;::Result是等价的。<BR><BR>现在Base模板类将接受一个模板参数，它是一个Typelist类型，这个不详细讲了，把它的定义写出来：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;T_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Length&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::value&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;Loki::CompileTimeError&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;Only_Use_Partial_Specialisation_Version;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;FUNC_TYPE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v3,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v3)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};</SPAN></DIV><BR>这部分有点多，其实还是比较清晰的。注意这个Base的版本已经不是上面所讲的那个了。<BR><BR>函数原形推导问题就讲完了。上面的代码不一定还能编译，昨天是能编译的，被我修改了一些，为了解释，又改成昨天那样子。<img src ="http://www.cppblog.com/cpunion/aggbug/349.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-20 22:34 <a href="http://www.cppblog.com/cpunion/archive/2005/09/20/349.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正式建立asgard项目 (因ancients已经被人使用了）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/20/327.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Tue, 20 Sep 2005 02:30:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/20/327.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/327.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/20/327.html#Feedback</comments><slash:comments>16</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/327.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/327.html</trackback:ping><description><![CDATA[“为C++实现一个IDL”这个主题，我已经考虑得差不多了，最后几个问题也解决了，打算建立一个项目来实现它。<BR><BR>项目命名为ancients，字面意思是“远古的，旧的”，实际上这个主题也算是旧的了。原本打算命名为C++ Remoting，不过想了一下，还是换个名字，免得让人一看就想拿去跟java, c#的remoting比较。<BR><BR>取这个名字主要是因为喜欢看《星际之门》剧集，里面最喜欢的一个种族就是ancients。<BR><BR>asgard是另一个种族，在ancients这个名字被人占用了的情况下，只好选它了。它的字面意思是“仙宫”，也是不错的名字，呵呵。asgard这个种族的科技非常发达，有先进的亚空间旅行技术，先进的光传送技术，身体也比较符合一些报道中外星人的样子。<BR><BR>暂时还没找到合适的空间来放这个项目，就以压缩包的形式在这个blog上做吧。<BR><BR>打算先实现动态部分，我给它命名为reflection，模仿java的，当然也不会做它那么完整。这部分必须先做，这样方便用来测试静态结构。<BR><BR>然后是静态结构部分，前面已经写了2篇乱七八糟的描述，剩余问题（函数原形推导问题）基本已经解决了。<BR><BR>整个框架在Service以下都是环境无关的，这里的环境指的是协议、通讯等环境。也就是说，定义一个Service，并不在一开始就指定它所使用的通讯协议。定义完成以后，把它指定给一个协议，就可以实现协议绑定，甚至在运行时刻动态切换到另一个协议。当然这可能是不合理的，不过我认为如果支持这种做法，本身就是灵活性的一种体现。<BR><BR><BR><BR>前面还有些地方，和实际情况有些差别的，需要补充完善。简要描述如下：<BR><BR>使用宏来定义Service，前面只定义了方法的原型、名称、服务端绑定的函数，其实还差一个重要的东西，就是参数的名字。<BR>如果使用自己的协议，或者是顺序存储的协议，比如BENCODE，来作为远程调用协议，那么参数的名字是不重要的，只要按顺序把参数序列化、反序列化就可以了。<BR>但在使用SOAP作为远程调用协议时，就得考虑为参数加上名字了，SOAP是从XML元素中，按参数名称来提取参数值的，虽然我们可以为参数生成一个名字，但这个名字不能描述参数所表达的意思。<BR>所以需要考虑为参数取上名字。<BR><BR>暂时就补充这一点，其它方面有等进一步研究。<img src ="http://www.cppblog.com/cpunion/aggbug/327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-20 10:30 <a href="http://www.cppblog.com/cpunion/archive/2005/09/20/327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（一）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/17/284.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sat, 17 Sep 2005 11:40:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/17/284.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/284.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/17/284.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/284.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/284.html</trackback:ping><description><![CDATA[<P>前面简单写了点静态结构，这一次将主要关注动态模型以及调用方式。</P>
<P>这个系列的名字叫“为C++实现一个IDL”，实际上应该叫“为C++实现一个Remoting”可能更好一些，说是IDL，主要是想通过宏，使用简单的类型定义达到自动生成调用代码的目的。</P>
<P><STRONG>一、首先来看看调用习惯。</STRONG></P>
<P>从调用习惯入手，主要是因为看到目前有很多库/工具包在调用上都有很多不便之处。假如能在一开始就从这点出发，就能把调用接口设计得更好一些。</P>
<P>先来看看服务端如何开放一个服务。</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 发布为SOAP服务，先生成一个服务容器。<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 服务将发布在localhost的7911上，localhost用来绑定loopback网卡。</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR><BR>    TestService test_service; <BR>    soap_service.addService  (“test_service”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test_service);<BR><BR>    TestService service1;<BR>    soap_service.addService (“HelloService”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">service1);<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">{<BR>        soap_service.run ();<BR>    } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SocketException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>    {<BR>    } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SignalException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>    {<BR>    }<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><BR>我希望就是这么简单，客户端调用有多种方式：<BR>1、 使用服务的IDL定义，直接调用：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">{<BR>        TestService test_service (“test_service”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">soap_service);<BR>        test_service.method1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">);<BR>    } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SocketException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>    {<BR>    }<BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><BR>这种方式比较简单，调用时会检查是否已经连接，然后发送调用请求，并处理调用结果。</P>
<P>2、 服务验证方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR>    TestService test_service;<BR>    soap_service.getService (“test_service”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test_service);<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (test_service)<BR>    {<BR>        </SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">{<BR>            test_service.method1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">);<BR>        } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SocketException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>        {<BR>        }<BR>    }<BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><BR>3、 服务发现方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR>    vector </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> services_name </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> soap_service.getServiceNames ();<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> <IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">    IService</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> test_service </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> soap_service.getService (“test_service”);<BR>    </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (test_service)<BR>    {<BR>        vector </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> methods </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getMethodNames ();<BR>        IMethod</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> method </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getMethod (“method1”);<BR>        vector </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Type</SPAN><SPAN style="COLOR: #000000">*></SPAN><SPAN style="COLOR: #000000"> types </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getParameterType s()<BR>        method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">addArg (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">);<BR>        method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">addArg (</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> <IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">        method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">invoke ();<BR>        </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> <IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">    }<BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><STRONG><BR>二、基本需求。<BR><BR></STRONG>简单分析一下，上面一共涉及了哪些类型？<BR>IProxy:<BR>这是所有Proxy类的基类(和接口)，它可以容纳多个服务对象，提供服务绑定、服务查询、服务发现、服务验证。<BR>IService:<BR>所有Service类的基类，可以容纳多个方法(Method)，提供方法查询、服务验证。<BR>IMethod:<BR>所有Method模板类的基类，容纳多个参数，包括返回值，可通过查询参数类型获得方法的类型定义。<BR>IParameter:<BR>所有参数的基类，包含一个参数类型描述和一个参数值。<BR>IType:<BR>所有类型的基类，预定义了一些基本类型，可自定义类型。</P>
<P>看起来挺多的，其实很难接触到这些，只需要使用宏来定义一个服务，就可以通过模板的类型推导，自动生成这些复杂的定义。</P><STRONG>三、调用过程。<BR><BR></STRONG>以下只简单分析一下同步调用，异步调用将是以后的扩充话题。<BR>根据第二节的3种不同调用过程，简要描述如下： 
<OL>
<LI>直接调用。<BR><BR>
<UL>
<LI>生成SOAPProxy，让它连接到远程主机。<BR>
<LI>生成一个TestService对象，设置远程主机上的服务名称，并指定使用SOAPProxy，也即使用SOAP协议。<BR>
<LI>调用TestService::method1方法。根据method1的定义，把服务名称、方法名称、各个in参数等打包成一个“集合”，交给SOAPProxy处理。<BR>
<LI>SOAPProxy把这个“集合”转换成SOAP消息，发送到远程主机，阻塞线程。<BR>
<LI>远程主机上的SOAPProxy对象收到数据，进行解析。当解析出一个服务调用时，把它交给TestService服务处理。<BR>
<LI>TestService解析出一个方法调用，把它交给Method处理。<BR>
<LI>Method解析出各个参数，验证参数类型、完整性等，并执行调用或返回错误。<BR>
<LI>Method调用的返回信息(包括调用结果、返回值、out参数等)被打包成一个“集合”，交给TestService处理。<BR>
<LI>TestService处理后，交给SOAPProxy。<BR>
<LI>SOAPProxy把结果打包成SOAP消息，发回调用端。<BR>
<LI>调用端解析SOAP消息，把OUT参数值赋给调用者提供的对象，调用完成。 </LI></UL>
<P> </P>
<LI>服务验证方式。<BR>
<UL>
<LI>生成SOAPProxy，让它连接到远程主机。<BR>
<LI>生成TestService对象，调用SOAPProxy的getService验证版本。<BR>
<LI>SOAPProxy把TestService对象的信息(名称、成员及基类型等)发送到远程主机，阻塞。<BR>
<LI>远程主机解析收到的信息，查找服务名，并比较查找到的服务类型与解析得到的类型。<BR>
<LI>比较结果发回给调用端。<BR>
<LI>调用端接着采用直接调用的方式，调用远程服务。</LI></UL><BR>这种方式看起来多了一些操作，不过验证的好处是能够减少调用时的异常。 
<P></P>
<LI>服务发现方式。<BR>
<UL>
<LI>生成SOAPProxy，让它连接到远程主机。<BR>
<LI>查询远程开放的服务名称。(可省略)<BR>
<LI>查找特定服务，得到服务描述信息。<BR>
<LI>查找服务中的方法，得到方法描述信息。<BR>
<LI>压入各个参数，并执行调用。<BR>
<LI>调用前先判断参数是否与描述一致，然后调用SOAPProxy生成SOAP消息，发送到远程主机，阻塞。<BR>
<LI>远程主机解析出调用。。。后面过程与第1种方式相同，远程主机并不知道客户端使用的是哪种方式来调用。远程主机处理结束，将返回SOAP消息给调用端。<BR>
<LI>调用端解析出调用结果，并把各个OUT参数的值赋给method对象。</LI></UL><BR>使用这种方式，调用端不需要服务的类型定义。 
<P></P></LI></OL>
<P><STRONG>四、异步调用/异步分派(AMI/AMD)。<BR></STRONG><BR>同步调用时，调用端线程需要等待调用结果，服务端线程也要等待调用结束返回，才处理下一个调用。<BR>为了在服务调用期间让线程能做更多的事：<BR>调用端把调用交给线程池完成，并在调用完成后采用某种机制通知线程处理结果，或者直接由线程池中的调用线程调用结果处理函数。这种方式称为AMI(异步方法调用)。<BR>服务端主线程则把接收到的消息解析后，放入处理队列，由线程池去处理调用过程。当调用完成后，结果放入结果队列，由主线程处理成消息，发送回调用端。这种方式称为AMD(异步方法分派)。<BR>调用端和服务端依旧是使用通讯协议来沟通，双方都不知道对方是否采用了异步方式。</P>
<P>AMI和AMD对于静态定义的服务是有影响的，比如下面一个服务：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService<BR>{<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> method1;<BR>}</SPAN></DIV>
<P><BR>在同步调用时，它的调用方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">TestService test_service;<BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> a;<BR>service.method1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, a); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 或者 service.method1 (3, &a)，打算兼容这2种方式。</SPAN></DIV>
<P><BR>异步调用时，调用方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> method1_result (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">);<BR>TestService test_service;<BR>test_service.method1.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, method1_result); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 调用完成后，让调用线程去调用method1_result通知调用结果。<BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 或者像下面</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">IMethod</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> result </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service.method1.async_call (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #0000ff">while</SPAN><SPAN style="COLOR: #000000"> (</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">result</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">done())  </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 还有很多好办法，这里只是为了简单。</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">{<BR>    sleep (</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">);<BR>}<BR>cout </SPAN><SPAN style="COLOR: #000000"><<</SPAN><SPAN style="COLOR: #000000"> result</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getArg(</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">toInt(); <BR></SPAN></DIV>
<P><BR>正如上面演示的一样，异步调用的结果有2种方式去处理。<BR>一是由线程池调用完以后，接着调用一个函数以通知结果。它不需要轮询，不过涉及到了线程问题，增加了一些复杂性。<BR>另一种方式调用结束后，原调用线程在某个适当的“时机”去查询调用结果。这个时机可以是定时查询，也可以是被线程消息通知而去处理。</P>
<P><STRONG>五、其它。<BR></STRONG><BR>这一篇加上前一篇，应该是提到了全部的要点。<BR>目前剩下的唯一一个难点，可能是在处理异步调用时，Method的定义。<BR>正如上面演示的，一个方法在同步调用和异步调用时，就有3种调用方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">service.method1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, a);<BR>test_service.method1.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, method1_result);<BR>IMethod</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> result </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service.method1.async_call (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">);</SPAN></DIV>
<P><BR>特别地，它如何根据in和个数和out的个数，产生那2个参数个数匹配的异步调用函数？<BR>再来回顾一下method1的定义：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> method1;</SPAN></DIV>
<P><BR>显然有一定的复杂性，不过我认为还是可以处理掉的。拿3个参数的偏特化版本来说明：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Ret, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> A, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> B, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> C</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Ret</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">(A,B,C)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> MethodBase </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Ret</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">,A,B,C</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR>{<BR>};<BR><BR>template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Ret</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> A</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> B</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> C</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> D</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, IN_COUNT</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">InCount</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000"> A,B,C,D</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">::value </SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> MethodBase<BR>{<BR>};<BR><BR></SPAN></DIV>
<P><BR>通过对MethodBase类的IN＿COUNT参数定义偏特化，即可定义出这些不同的版本。<BR><BR>当然仅仅是知道了IN参数的个数，还没有提取出IN参数的类型，所以还不能生成函数的原型，或许需要把typelist加进来了（loki中的那个）。<BR><BR><BR><BR>这是后面要考虑的内容，今天先想到这。</P><img src ="http://www.cppblog.com/cpunion/aggbug/284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-17 19:40 <a href="http://www.cppblog.com/cpunion/archive/2005/09/17/284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（零）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/15/272.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Wed, 14 Sep 2005 17:27:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/15/272.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/272.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/15/272.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/272.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/272.html</trackback:ping><description><![CDATA[<P>一、问题。<BR><BR>这段时间考虑实现一个纯C＋＋的分布式服务包装库，简要描述如下：</P>
<P>有如下类和函数：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> Test<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">out</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>};<BR><BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">inout</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);</SPAN></DIV></DIV>
<P><BR>想把它们作为服务发布出去，以SOAP或其它方式。发布为一个TestService，并让它携带多一些信息:</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>};</SPAN></DIV></DIV>
<P><BR>C＋＋有许多工具、库来做到这点，但是，都需要生成一堆代码，很是不爽。<BR><BR>其它语言，比如python, java, c#等，都可以通过自省机制，抛开IDL在语言内实现。<BR><BR>C＋＋并非不能做这个，它只是缺少足够的类型信息。比如上面的例子，如果要发布为服务，那么至少应该把它的参数、返回值搞得明确些，否则要么会造成不必要的参数传递，要么会产生错误（把OUT参数取值可不是安全的）。<BR><BR>比如上面出现的int, int&, int*，在作为in参数时，我们是想传递它的值，类型为int。而int*和string*作为out参数时，我们想让它传递指针或引用，当调用返回时，我们给它赋值。<BR><BR>C＋＋语言的类型极为丰富，却没有描述一个参数到底是in还是out。java也没有，但它可以正常序列化一个null值，在C＋＋中，这可能存在一些麻烦。<BR><BR>再考虑一下char*类型，假如它是in参数，那么它是要传递一个字符还是一个字符串？C＋＋语言没有对它进行描述。<BR><BR>所以要实现一个分布式服务包装（或代理）库，必须让发布者提供这些信息。<BR><BR>我们知道，要查询一个远程服务，必须查询相应主机端口，获取服务信息。最简单的服务信息包括：服务列表，每个服务中的方法列表，方法的类型（包括参数和返回值类型，in/out信息等）。<BR><BR>实际上，我们是要为C＋＋增加一些简单的自省能力。上面那个服务发布接口，实际上离这个要求还有很远，再来看一下：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>};</SPAN></DIV></DIV>
<P><BR>可以想见，它是没有一点自省能力的，我们如何向它查询，它的名字？它的方法列表？方法的类型？它如何与Test类的成员函数以及test_func函数关联？</P>
<P>二、方向。<BR><BR>要让上面那个服务具有自省能力，要做的扩充其实并不多。考虑下面的代码：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> Service<BR>{<BR>    TestService ();<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func;<BR>};</SPAN></DIV></DIV>
<P><BR>这几个Method可以用自己写的委托类来做。<BR><BR>1、假如我们在TestService的构造函数里给它分配一个“TestService”名字，并且Service类实现了查询名字的接口，那么它就知道它自己的名字了。<BR><BR>2、假如在TestService的构造函数里为各个Method分配名字，并且注册到TestService，那么它就能够查询方法列表。<BR><BR>3、方法的类型？通过模板方式，把各个参数类型收集起来，给个字符串名称就可以了。<BR><BR>使用宏来实现，大概可以写成这样：<BR><BR></P>
<P></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE (TestService)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func, test_func)<BR>END_SERVICE ()</SPAN></DIV></DIV>
<P><BR>通过上面这几个宏，我们能够生成TestService声明。<BR><BR>不过，有几个问题，罗列如下，并一一解决它：<BR><BR>1、如何把函数指针传给它？如何把方法名称传给它？<BR>这个只是C＋＋语言为我们增加了一些麻烦，我们无法在定义成员的地方调用它的构造函数，不过这并不会造成多大障碍。<BR>上面的METHOD宏如果只是生成类的声明，那么函数指针可以省略。我把它加上的原因是，它可以被我用Ctrl+C, Ctrl+V这种世界上最先进的技术原样拷贝下来，并且通过简单修改的方法实现这种世界上最先进的重用。<BR><BR>上面的代码经过修改，结果就成这样：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE (TestService)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func, test_func)<BR><BR>    BEGIN_DEFINE (TestService)<BR>        METHOD_DEFINE (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>        METHOD_DEFINE(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>        METHOD_DEFINE(</SPAN><SPAN style="COLOR: #0000ff">int(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func, test_func)<BR>    END_DEFINE ()<BR><BR>END_SERVICE ()</SPAN></DIV></DIV>
<P><BR>看上去对应得非常整齐，修改起来也比较简单。上面那部分被扩充为如下代码：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> Service<BR>{<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func;<BR>    TestService ()<BR>    : Service (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TestService</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR>    {<BR>        test1.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test1</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        test1.setMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test1);<BR>        test2.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test2</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        test2.setMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test2);<BR>        test_func.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test_func</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        test_func.setMethod (test_func);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test3);<BR>    }<BR>};</SPAN></DIV></DIV>
<P><BR>基本上需要的东西都在这里了。<BR><BR>2、客户端的问题。<BR></P>
<P>上面这种映射，直接拿到客户端会有问题，Test类和test_func函数我们并不打算交给客户端，所以使用函数指针会出现链接错误。<BR><BR>实际上客户端不需要这个，我们想办法把它拿掉就行了。客户端实际需要生成的代码如下：<BR><BR></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> Service<BR>{<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func;<BR>    TestService ()<BR>    : Service (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TestService</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR>    {<BR>        test1.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test1</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test1);<BR>        test2.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test2</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test2);<BR>        test_func.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test_func</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test3);<BR>    }<BR>};</SPAN></DIV></DIV>
<P><BR>还是上面提到的，C++给我们带来的麻烦。这次需要另一组宏来完成它：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE_D (TestService)<BR>    METHOD_D (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1)<BR>    METHOD_D (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2)<BR>    METHOD_D (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func)<BR><BR>    BEGIN_DEFINE_D (TestService)<BR>        METHOD_DEFINE_D (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1)<BR>        METHOD_DEFINE_D(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2)<BR>        METHOD_DEFINE_D(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func)<BR>    END_DEFINE_D ()<BR><BR>END_SERVICE_D ()</SPAN></DIV></DIV>
<P><BR>METHOD*和METHOD_DEFINE*宏的参数都有一些多余的信息，没有去掉是因为放在一起容易看到写错的地方。（这个技巧来源于前几天看的一篇BLOG，很报歉没有记下地址）<BR><BR>3、使用的问题。<BR><BR>如何才能比较方便地使用？我考虑了下面这种方式：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> T</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> IProxy;<BR><BR>template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> T</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> SOAPProxy;<BR><BR>SOAPProxy </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">TestService</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> service;<BR>service.connect (</SPAN><SPAN style="COLOR: #000000">5000</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">localhost</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> a</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">n </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">a;<BR>service.test1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, n);<BR>service.test1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">n);<BR>service.test2 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, n);<BR>service.test2 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">n);<BR>service.test2 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, NONE);<BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN></DIV></DIV>
<P><BR>Method::operator ()的各个参数都将可以接受相容的类型，像上面一样，因为在TestService中我们已经定义了它要传输的值的类型。<BR><BR>a.NONE是什么？其实是为异步调用考虑的。假如指定某个OUT参数为NONE，则这个参数的值并不真正的OUT，而是保存在Method中。实际上Method中保存每个参数的值。<BR><BR>b.Method与Service如何发生关系？<BR>从TestService的定义中我们知道，Method向Service注册自己以实现自省，但它同时也会保存Service的指向。<BR>我们的Proxy实际上是一个继承模板，上面并没有把它指出来。它的定义是：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> T</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> XProxy : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> T<XPROXY><BR>{<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">};</SPAN></DIV></DIV>
<P><BR>所以我们的TestService其实也是模板类，它将使用XProxy中定义的序列化类。XProxy将实现Service基类中序列化虚函数以及调用虚函数。<BR><BR>当一个Method调用时，它会调用Service的序列化，由于被重写了，所以调用的是XProxy中的序列化方法。这个方法会把这个Method的各in/inout参数序列化，然后执行远程调用，再把调用结果反序列化给inout/out参数。<BR><BR>4、其它想法。<BR><BR>在考虑上面的定义方式时，我也考虑了其它方式，主要是返回值处理的方法，简述如下。<BR><BR>前面我们假设了一段将被开放为远程服务的代码：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> Test<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">out</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>};<BR><BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">inout</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);</SPAN></DIV></DIV>
<P><BR>在前面的做法中，我们的服务描述是放在那一组宏里面，好处是不用改这段代码，坏处就是代码定义的地方和描述不在一起，协调可能会有一些不便。<BR><BR>我也考虑了另一种做法：<BR><BR></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> Test<BR>{<BR>    idl </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>    idl </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>};<BR><BR>idl </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);</SPAN></DIV></DIV>
<P><BR>对于实现代码，只需要修改返回值为void的函数，把return;修改为return VOID;，并且为没有写此语句的分支加上此句。<BR><BR>VOID是一个特殊类型的静态变量，专为void返回值的函数设定。<BR><BR>这种做法修改了原有的代码，不过在定义服务时可以节省一些工作：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE (TestService)<BR>    METHOD (test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>    METHOD (test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>    METHOD (test_func, test_func)<BR><BR>    BEGIN_DEFINE (TestService)<BR>        METHOD_DEFINE (test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>        METHOD_DEFINE (test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>        METHOD_DEFINE (test_func, test_func)<BR>    END_DEFINE ()<BR><BR>END_SERVICE ()</SPAN></DIV></DIV>
<P><BR>它所需要的函数类型，将由函数指针推导。<BR><BR>在G＋＋编译器下，可以使用typeof来获得函数指针的类型而不需要真得获得函数指针值，不过目前仅仅在G＋＋下可用。（顺便说一下，typeof已经列入c++0x）<BR><BR>最终我放弃了这个想法，毕竟它要修改现有的代码，某些情况下这是不可能的，而且typeof目前也不能跨编译器。<BR><BR>三、实现。<BR><BR>老实说我现在还没有一份完整的或半完整的实现，大部分想法还在头脑中，测试代码倒是写了不少，主要是用来测试上述想法能否实现，我想大部分情况都已经测试了，只需要有时间来把它实现出来。<BR><BR>这是我近期要做的事之一，争取月内把它做完罢。</P><img src ="http://www.cppblog.com/cpunion/aggbug/272.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-15 01:27 <a href="http://www.cppblog.com/cpunion/archive/2005/09/15/272.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>