﻿<?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++博客-twzheng's cppblog-文章分类-vc++.net</title><link>http://www.cppblog.com/twzheng/category/3938.html</link><description>『站在风口浪尖紧握住鼠标旋转！』  人在台北心在汉</description><language>zh-cn</language><lastBuildDate>Mon, 15 Mar 2010 04:03:27 GMT</lastBuildDate><pubDate>Mon, 15 Mar 2010 04:03:27 GMT</pubDate><ttl>60</ttl><item><title>求windows xp 繁体版</title><link>http://www.cppblog.com/twzheng/articles/109710.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Sun, 14 Mar 2010 16:05:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/109710.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/109710.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/109710.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/109710.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/109710.html</trackback:ping><description><![CDATA[求windows xp 繁体版，最好是台湾版的，要能一步步的手动安装(想装双系统)<br><br>找了好几天了，很多资源都下不动<br><br>今天好不容易下了一个，但是香港版的，且安装到选择盘符时，键盘所有键都不能使用，所以还是无法安装<br><br>谢谢各位大哥大姐帮帮忙，小弟感激不尽！<img src ="http://www.cppblog.com/twzheng/aggbug/109710.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2010-03-15 00:05 <a href="http://www.cppblog.com/twzheng/articles/109710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>完成端口中的单句柄数据结构与单IO数据结构的理解与设计</title><link>http://www.cppblog.com/twzheng/articles/25359.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Sat, 02 Jun 2007 15:19:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/25359.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/25359.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/25359.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/25359.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/25359.html</trackback:ping><description><![CDATA[<span id=ArticleTitle1_ArticleTitle1_lblTitle><strong>完成端口中的单句柄数据结构与单IO数据结构的理解与设计</strong></span><br><br>本文作者：sodme<br>本文出处：<font style="COLOR: #000000" color=#0000ff>http://blog.csdn.net/sodme</font><br>声明：本文可以不经作者同意任意转载、复制、传播，但任何对本文的引用均须保留本文的作者、出处及本行声明信息！谢谢！<br><br>　　完成端口模型，针对于WIN平台的其它异步网络模型而言，最大的好处，除了性能方面的卓越外，还在于完成端口在传递网络事件的通知时，可以一并传递与此事件相关的应用层数据。这个应用层数据，体现在两个方面：一是单句柄数据，二是单IO数据。<br><br>　　GetQueuedCompletionStatus函数的原型如下：<br>　　WINBASEAPI<br>　　BOOL<br>　　WINAPI<br>　　GetQueuedCompletionStatus(<br>&nbsp;&nbsp;&nbsp; 　　IN&nbsp; HANDLE CompletionPort,<br>&nbsp;&nbsp;&nbsp;　　 OUT LPDWORD lpNumberOfBytesTransferred,<br>&nbsp;&nbsp;&nbsp; 　　OUT PULONG_PTR lpCompletionKey,<br>&nbsp;&nbsp;&nbsp; 　　OUT LPOVERLAPPED *lpOverlapped,<br>&nbsp;&nbsp;&nbsp; 　　IN&nbsp; DWORD dwMilliseconds<br>&nbsp;&nbsp;&nbsp; 　);<br>　　其中，我们把第三个参数lpCompletionKey称为完成键，由它传递的数据称为单句柄数据。我们把第四个参数lpOverlapped称为重叠结构体，由它传递的数据称为单IO数据。<br><br>　　以字面的意思来理解，lpCompletionKey内包容的东西应该是与各个socket一一对应的，而lpOverlapped是与每一次的wsarecv或wsasend操作一一对应的。<br><br>　　在网络模型的常见设计中，当一个客户端连接到服务器后，服务器会通过accept或AcceptEx创建一个socket，而应用层为了保存与此socket相关的其它信息（比如：该socket所对应的sockaddr_in结构体数据，该结构体内含客户端IP等信息，以及为便于客户端的逻辑包整理而准备的数据整理缓冲区等），往往需要创建一个与该socket一一对应的客户端底层通信对象，这个对象可以负责保存仅在网络层需要处理的数据成员和方法，然后我们需要将此客户端底层通信对象放入一个类似于list或map的容器中，待到需要使用的时候，使用容器的查找算法根据socket值找到它所对应的对象然后进行我们所需要的操作。<br><br>　　让人非常高兴的是，完成端口&#8220;体贴入微&#8221;，它已经帮我们在每次的完成事件通知时，稍带着把该socket所对应的底层通信对象的指针送给了我们，这个指针就是lpCompletionKey。也就是说，当我们从GetQueuedCompletionStatus函数取得一个数据接收完成的通知，需要将此次收到的数据放到该socket所对应的通信对象整理缓冲区内对数据进行整理时，我们已经不需要去执行list或map等的查找算法，而是可以直接定位这个对象了，当客户端连接量很大时，频繁查表还是很影响效率的。哇哦，太帅了，不是吗？呵呵。<br><br>　　基于以上的认识，我们的lpCompletionKey对象可以设计如下：<br>　　typedef struct PER_HANDLE_DATA<br>　　{<br>　　　　SOCKET socket;　　　　　　　　　　&nbsp;&nbsp; //本结构体对应的socket值<br>　　　　sockaddr_in addr;　　　　　　　　　　//用于存放客户端IP等信息<br>　　　　char DataBuf[ 2*MAX_BUFFER_SIZE ];　　//整理缓冲区,用于存放每次整理时的数据<br>　　}<br><br>　　PER_HANDLE_DATA与socket的绑定，通过CreateIOCompletionPort完成，将该结构体地址作为该函数的第三个参数传入即可。而PER_HANDLE_DATA结构体中addr成员，是在accept执行成功后进行赋值的。DataBuf则可以在每次WSARecv操作完成，需要整理缓冲区数据时使用。<br><br>　　下面我们再来看看完成端口的收、发操作中所使用到的重叠结构体OVERLAPPED。<br><br>　　关于重叠IO的知识，请自行GOOGLE相关资料。简单地说，OVERLAPPED是应用层与核心层交互共享的数据单元，如果要执行一个重叠IO操作，必须带有OVERLAPPED结构。在完成端口中，它允许应用层对OVERLAPPED结构进行扩展和自定义，允许应用层根据自己的需要在OVERLAPPED的基础上形成新的扩展OVERLAPPED结构。一般地，扩展的OVERLAPPED结构中，要求放在第一个的数据成员是原OVERLAPPED结构。我们可以形如以下方式定义自己的扩展OVERLAPPED结构：<br>　　typedef struct PER_IO_DATA<br>　　{<br>　　　　OVERLAPPED ovl;<br>　　　　WSABUF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf;<br>　　　　char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RecvDataBuf[&nbsp;MAX_BUFFER_SIZE ];&nbsp;&nbsp; //接收缓冲区<br>　　　　char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SendDataBuf[ MAX_BUFFER_SIZE&nbsp;];&nbsp;&nbsp; //发送缓冲区<br>　　　　OpType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; opType;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //操作类型：发送、接收或关闭等<br>　　}<br>　　<br>　　在执行WSASend和WSARecv操作时，应用层会将扩展OVERLAPPED结构的地址传给核心，核心完成相应的操作后，仍然通过原有的这个结构传递操作结果，比如&#8220;接收&#8221;操作完成后，RecvDataBuf里存放便是此次接收下来的数据。<br><br>　　根据各自应用的不同，不同的完成端口设计者可能会设计出不同的PER_HANDLE_DATA<br>和PER_IO_DATA，我这里给出的设计也只是针对自己的应用场合的，不一定就适合你。但我想，最主要的还是要搞明白PER_HANDLE_DATA和PER_IO_DATA两种结构体的含义、用途，以及调用流程。<br>
<img src ="http://www.cppblog.com/twzheng/aggbug/25359.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-06-02 23:19 <a href="http://www.cppblog.com/twzheng/articles/25359.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows Sockets 2.0:使用完成端口高性能，可扩展性Winsock服务程序</title><link>http://www.cppblog.com/twzheng/articles/25140.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Wed, 30 May 2007 09:24:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/25140.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/25140.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/25140.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/25140.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/25140.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Windows Sockets 2.0:使用完成端口高性能，可扩展性Winsock服务程序[摘自]http://blog.csdn.net/vcbear/翻译说明： 完成端口基本上公认为一种在windows服务平台上比较成熟和高效的IO方法，理解和编写程序都不是很困难。目前我正在进行这方面的实践，代码还没有完全调试和评价，只有这一篇拙劣的学习翻译文摘，见笑见笑。翻译这个文章，是因为我近期在...&nbsp;&nbsp;<a href='http://www.cppblog.com/twzheng/articles/25140.html'>阅读全文</a><img src ="http://www.cppblog.com/twzheng/aggbug/25140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-05-30 17:24 <a href="http://www.cppblog.com/twzheng/articles/25140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类似于QQ游戏百万人同时在线的服务器架构实现 </title><link>http://www.cppblog.com/twzheng/articles/24801.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Thu, 24 May 2007 18:58:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/24801.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/24801.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/24801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/24801.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/24801.html</trackback:ping><description><![CDATA[<span style="FONT-SIZE: 18pt">类似于QQ游戏百万人同时在线的服务器架构实现</span><br><br>本文作者：sodme　本文出处：http://blog.csdn.net/sodme<br>版权声明：本文可以不经作者同意任意转载，但转载时烦请保留文章开始前两行的版权、作者及出处信息。<br><br>　　QQ游戏于前几日终于突破了百万人同时在线的关口，向着更为远大的目标迈进，这让其它众多传统的棋牌休闲游戏平台黯然失色，相比之下，联众似乎已经根本不是QQ的对手，因为QQ除了这100万的游戏在线人数外，它还拥有3亿多的注册量（当然很多是重复注册的）以及QQ聊天软件900万的同时在线率，我们已经可以预见未来由QQ构建起来的强大棋牌休闲游戏帝国。<br>　　那么，在技术上，QQ游戏到底是如何实现百万人同时在线并保持游戏高效率的呢？<br>　　事实上，针对于任何单一的网络服务器程序，其可承受的同时连接数目是有理论峰值的，通过C＋＋中对TSocket的定义类型：word，我们可以判定这个连接理论峰值是65535，也就是说，你的单个服务器程序，最多可以承受6万多的用户同时连接。但是，在实际应用中，能达到一万人的同时连接并能保证正常的数据交换已经是很不容易了，通常这个值都在2000到5000之间，据说QQ的单台服务器同时连接数目也就是在这个值这间。<br>　　如果要实现2000到5000用户的单服务器同时在线，是不难的。在windows下，比较成熟的技术是采用IOCP－－完成端口。与完成端口相关的资料在网上和CSDN论坛里有很多，感兴趣的朋友可以自己搜索一下。只要运用得当，一个完成端口服务器是完全可以达到2K到5K的同时在线量的。但，5K这样的数值离百万这样的数值实在相差太大了，所以，百万人的同时在线是单台服务器肯定无法实现的。<br>　　要实现百万人同时在线，首先要实现一个比较完善的完成端口服务器模型，这个模型要求至少可以承载2K到5K的同时在线率（当然，如果你MONEY多，你也可以只开发出最多允许100人在线的服务器）。在构建好了基本的完成端口服务器之后，就是有关服务器组的架构设计了。之所以说这是一个服务器组，是因为它绝不仅仅只是一台服务器，也绝不仅仅是只有一种类型的服务器。<br>　　简单地说，实现百万人同时在线的服务器模型应该是：登陆服务器＋大厅服务器＋房间服务器。当然，也可以是其它的模型，但其基本的思想是一样的。下面，我将逐一介绍这三类服务器的各自作用。<br>　　登陆服务器：一般情况下，我们会向玩家开放若干个公开的登陆服务器，就如QQ登陆时让你选择的从哪个QQ游戏服务器登陆一样，QQ登陆时让玩家选择的六个服务器入口实际上就是登陆服务器。登陆服务器主要完成负载平衡的作用。详细点说就是，在登陆服务器的背后，有N个大厅服务器，登陆服务器只是用于为当前的客户端连接选择其下一步应该连接到哪个大厅服务器，当登陆服务器为当前的客户端连接选择了一个合适的大厅服务器后，客户端开始根据登陆服务器提供的信息连接到相应的大厅上去，同时客户端断开与登陆服务器的连接，为其他玩家客户端连接登陆服务器腾出套接字资源。在设计登陆服务器时，至少应该有以下功能：N个大厅服务器的每一个大厅服务器都要与所有的登陆服务器保持连接，并实时地把本大厅服务器当前的同时在线人数通知给各个登陆服务器，这其中包括：用户进入时的同时在线人数增加信息以及用户退出时的同时在线人数减少信息。这里的各个大厅服务器同时在线人数信息就是登陆服务器为客户端选择某个大厅让其登陆的依据。举例来说，玩家A通过登陆服务器1连接到登陆服务器，登陆服务器开始为当前玩家在众多的大厅服务器中根据哪一个大厅服务器人数比较少来选择一个大厅，同时把这个大厅的连接IP和端口发给客户端，客户端收到这个IP和端口信息后，根据这个信息连接到此大厅，同时，客户端断开与登陆服务器之间的连接，这便是用户登陆过程中，在登陆服务器这一块的处理流程。<br>　　大厅服务器：大厅服务器，是普通玩家看不到的服务器，它的连接IP和端口信息是登陆服务器通知给客户端的。也就是说，在QQ游戏的本地文件中，具体的大厅服务器连接IP和端口信息是没有保存的。大厅服务器的主要作用是向玩家发送游戏房间列表信息，这些信息包括：每个游戏房间的类型，名称，在线人数，连接地址以及其它如游戏帮助文件URL的信息。从界面上看的话，大厅服务器就是我们输入用户名和密码并校验通过后进入的游戏房间列表界面。大厅服务器，主要有以下功能：一是向当前玩家广播各个游戏房间在线人数信息；二是提供游戏的版本以及下载地址信息；三是提供各个游戏房间服务器的连接IP和端口信息；四是提供游戏帮助的URL信息；五是提供其它游戏辅助功能。但在这众多的功能中，有一点是最为核心的，即：为玩家提供进入具体的游戏房间的通道，让玩家顺利进入其欲进入的游戏房间。玩家根据各个游戏房间在线人数，判定自己进入哪一个房间，然后双击服务器列表中的某个游戏房间后玩家开始进入游戏房间服务器。<br>　　游戏房间服务器：游戏房间服务器，具体地说就是如&#8220;斗地主1&#8221;，&#8220;斗地主2&#8221;这样的游戏房间。游戏房间服务器才是具体的负责执行游戏相关逻辑的服务器。这样的游戏逻辑分为两大类：一类是通用的游戏房间逻辑，如：进入房间，离开房间，进入桌子，离开桌子以及在房间内说话等；第二类是游戏桌子逻辑，这个就是各种不同类型游戏的主要区别之处了，比如斗地主中的叫地主或不叫地主的逻辑等，当然，游戏桌子逻辑里也包括有通用的各个游戏里都存在的游戏逻辑，比如在桌子内说话等。总之，游戏房间服务器才是真正负责执行游戏具体逻辑的服务器。<br>　　这里提到的三类服务器，我均采用的是完成端口模型，每个服务器最多连接数目是5000人，但是，我在游戏房间服务器上作了逻辑层的限定，最多只允许300人同时在线。其他两个服务器仍然允许最多5000人的同时在线。如果按照这样的结构来设计，那么要实现百万人的同时在线就应该是这样：首先是大厅，1000000/5000＝200。也就是说，至少要200台大厅服务器，但通常情况下，考虑到实际使用时服务器的处理能力和负载情况，应该至少准备250台左右的大厅服务器程序。另外，具体的各种类型的游戏房间服务器需要多少，就要根据当前玩各种类型游戏的玩家数目分别计算了，比如斗地主最多是十万人同时在线，每台服务器最多允许300人同时在线，那么需要的斗地主服务器数目就应该不少于：100000/300=333，准备得充分一点，就要准备350台斗地主服务器。<br>　　除正常的玩家连接外，还要考虑到：<br>　　对于登陆服务器，会有250台大厅服务器连接到每个登陆服务器上，这是始终都要保持的连接；<br>　　而对于大厅服务器而言，如果仅仅有斗地主这一类的服务器，就要有350多个连接与各个大厅服务器始终保持着。所以从这一点看，我的结构在某些方面还存在着需要改进的地方，但核心思想是：尽快地提供用户登陆的速度，尽可能方便地让玩家进入游戏中。
<img src ="http://www.cppblog.com/twzheng/aggbug/24801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-05-25 02:58 <a href="http://www.cppblog.com/twzheng/articles/24801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A Reusable Windows Socket Server Class With C++</title><link>http://www.cppblog.com/twzheng/articles/SSC.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Tue, 22 May 2007 16:12:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/SSC.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/24653.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/SSC.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/24653.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/24653.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: A Reusable Windows Socket Server Class With C++ Contributed by Len Holgate 摘自：http://www.devarticles.com&nbsp;Ever thought of writing your own Windows socket server class? In this article Len sh...&nbsp;&nbsp;<a href='http://www.cppblog.com/twzheng/articles/SSC.html'>阅读全文</a><img src ="http://www.cppblog.com/twzheng/aggbug/24653.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-05-23 00:12 <a href="http://www.cppblog.com/twzheng/articles/SSC.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>您也使用托管C++吗？</title><link>http://www.cppblog.com/twzheng/articles/24396.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Sat, 19 May 2007 09:36:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/24396.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/24396.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/24396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/24396.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/24396.html</trackback:ping><description><![CDATA[<a class=singleposttitle id=viewpost1_TitleUrl href="http://www.cnblogs.com/ly4cn/archive/2006/03/31/363738.html"><font color=#223355>您也使用托管C++吗？</font></a><br>摘自：<a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/ly4cn/"><font face="Trebuchet MS">沐枫小筑</font></a>&nbsp;（博客园博客）<br><br>转向.NET后，手头上往往仍有旧的模块要重用。也许这些模块是Delphi写的，也许是C/C++写的，或者是其它编程语言&#8230;&#8230;为了能把它们移植到.NET下，或者是在.NET中调用，To be or not to be, that is a question。<br>　　在这里，我笔记了几个在工作中遇到的几个场景。不过，这里不包括完全使用C#来重写原来用C++编写的程序这种变态的需求。当你被要求做这种事的时候，请三思而后行&#8230;&#8230;这简直是种非人的折磨。<br><br><a class=singleposttitle id=viewpost1_TitleUrl href="http://www.cnblogs.com/archive/2006/03/31/363738.html"><font color=#223355>您也使用托管C++吗？</font></a> 　<a id=BlogTitleLink href="http://www.cnblogs.com/" href_cetemp="/"><font color=#6b86b3>如沐枫林</font></a><br><br>　　<strong>场景一</strong>：在.NET中调用WindowsAPI或DLL。<br><br>　　这是比较普遍的需求。一般来说，简单的函数调用，大可直接用C#/VB.NET，经过DllImport属性包装出函数来调用。如：
<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">[DllImport(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">KERNEL32.DLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;EntryPoint</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">MoveFileW</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;&nbsp;SetLastError</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>CharSet</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CharSet.Unicode,&nbsp;ExactSpelling</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>CallingConvention</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CallingConvention.StdCall)]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;MoveFile(String&nbsp;src,&nbsp;String&nbsp;dst);<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>　　由于WindowsAPI用到的人实在是多，因此有一个专门的wiki站点，收集这方面的资料：<a href="http://www.pinvoke.net/"><font color=#1d58d1>http://www.pinvoke.net/</font></a>，对于常用的函数甚至有完整的应用例子和帮助。当然，如果你有相应的资料和例子，你也可以贡献你的力量，给其它人帮助。<br><br>&nbsp;　　<strong>场景二</strong>：用托管C++包装现有的DLL，供C#调用<br><br>　　当函数的参数或返回值比较复杂，或函数比较多的时候，这种方法对与人来说，实在是一个折磨。常常这些接口和定义就要用掉几千行的代码，而且还不能保证是正确的。这些错误往往在运行时才能显现出来，甚至有些错误会引起内存泄漏，或其它更为隐蔽的错误。<br>　　在这种情况下，使用C++/Managed代码来包装，就成了最合理的选择。因为托管C++代码可以直接引用原有的头文件，直接调用非托管函数，而不需要声明。这样，既减少了工作量，又避免引入错误。缺点是，这种方法会增加一个DLL。<span style="COLOR: #ff0000">要注意的是托管字符串和非托管字符串是有区别的，并需要转换（特别要注意的Unicode字符串和多字节字符串的转换）。<br></span><br>　　仍以MoveFile为例吧，这样比较简单：<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">vcclr.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;System;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;wrapper<br><img id=Codehighlighter1_84_382_Open_Image onclick="this.style.display='none'; Codehighlighter1_84_382_Open_Text.style.display='none'; Codehighlighter1_84_382_Closed_Image.style.display='inline'; Codehighlighter1_84_382_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_84_382_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_84_382_Closed_Text.style.display='none'; Codehighlighter1_84_382_Open_Image.style.display='inline'; Codehighlighter1_84_382_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_84_382_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_84_382_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_115_379_Open_Image onclick="this.style.display='none'; Codehighlighter1_115_379_Open_Text.style.display='none'; Codehighlighter1_115_379_Closed_Image.style.display='inline'; Codehighlighter1_115_379_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_115_379_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_115_379_Closed_Text.style.display='none'; Codehighlighter1_115_379_Open_Image.style.display='inline'; Codehighlighter1_115_379_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">ref</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ApiWrapper&nbsp;</span><span id=Codehighlighter1_115_379_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_115_379_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;MoveFile(String&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;lpExistingFileName,&nbsp;String&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;lpNewFileName&nbsp;)<br><img id=Codehighlighter1_205_376_Open_Image onclick="this.style.display='none'; Codehighlighter1_205_376_Open_Text.style.display='none'; Codehighlighter1_205_376_Closed_Image.style.display='inline'; Codehighlighter1_205_376_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_205_376_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_205_376_Closed_Text.style.display='none'; Codehighlighter1_205_376_Open_Image.style.display='inline'; Codehighlighter1_205_376_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_205_376_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_205_376_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pin_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;wchar_t</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;src&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;PtrToStringChars(lpExistingFileName);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pin_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;wchar_t</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;dst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;PtrToStringChars(lpNewFileName);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;::MoveFile(src,&nbsp;dst);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>　　然后在C#中，引用上面代码生成的DLL文件，就可以直接调用了：<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">wrapper.ApiWrapper.MoveFile(</span><span style="COLOR: #000000">@"</span><span style="COLOR: #000000">c:\debug.log</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">@"</span><span style="COLOR: #000000">c:\debug.txt</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span></div>
<br>　　假如原有的代码是基于COM的，那么太好了，VisualStudio等IDE会自动生成一个用于包装的dll，供你调用。当然因特殊需要而手工编码的是另一回事。<br><br>　　<strong>场景三</strong>：现有C++原代码，包装后供C#调用。<br><br>　　C++的原代码，实际上可以直接编译成托管代码。MFC也好ATL也好&#8230;&#8230;这样看起来在.NET中最强大的编程语言就是C++了：它不仅可以编写托管程序，甚至可以将标准C++的代码也编译成托管程序！其实VC++最强大的地方不止如此，它还在于能够编写混合了托管和非托管的代码的程序！！！这样最大的好处不仅可以将关键代码直接编译成非托管的代码，还可以避免被反编译。<br>　　<br>　　假设现有C++代码如下：<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"><img id=Codehighlighter1_21_97_Open_Image onclick="this.style.display='none'; Codehighlighter1_21_97_Open_Text.style.display='none'; Codehighlighter1_21_97_Closed_Image.style.display='inline'; Codehighlighter1_21_97_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_21_97_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_21_97_Closed_Text.style.display='none'; Codehighlighter1_21_97_Open_Image.style.display='inline'; Codehighlighter1_21_97_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;UnmanagedClass&nbsp;</span><span id=Codehighlighter1_21_97_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_21_97_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_55_67_Open_Image onclick="this.style.display='none'; Codehighlighter1_55_67_Open_Text.style.display='none'; Codehighlighter1_55_67_Closed_Image.style.display='inline'; Codehighlighter1_55_67_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_55_67_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_55_67_Closed_Text.style.display='none'; Codehighlighter1_55_67_Open_Image.style.display='inline'; Codehighlighter1_55_67_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;LPCWSTR&nbsp;GetPropertyA()&nbsp;</span><span id=Codehighlighter1_55_67_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_55_67_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;L"Hello!"</span><span style="COLOR: #000000">;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_94_95_Open_Image onclick="this.style.display='none'; Codehighlighter1_94_95_Open_Text.style.display='none'; Codehighlighter1_94_95_Closed_Image.style.display='inline'; Codehighlighter1_94_95_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_94_95_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_94_95_Closed_Text.style.display='none'; Codehighlighter1_94_95_Open_Image.style.display='inline'; Codehighlighter1_94_95_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;MethodB(&nbsp;LPCWSTR&nbsp;)&nbsp;</span><span id=Codehighlighter1_94_95_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_94_95_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;</span></div>
　　我们只要再增加一个包装类到工程文件中：
<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;wrapper<br><img id=Codehighlighter1_18_711_Open_Image onclick="this.style.display='none'; Codehighlighter1_18_711_Open_Text.style.display='none'; Codehighlighter1_18_711_Closed_Image.style.display='inline'; Codehighlighter1_18_711_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_18_711_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_18_711_Closed_Text.style.display='none'; Codehighlighter1_18_711_Open_Image.style.display='inline'; Codehighlighter1_18_711_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_18_711_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_18_711_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_51_708_Open_Image onclick="this.style.display='none'; Codehighlighter1_51_708_Open_Text.style.display='none'; Codehighlighter1_51_708_Closed_Image.style.display='inline'; Codehighlighter1_51_708_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_51_708_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_51_708_Closed_Text.style.display='none'; Codehighlighter1_51_708_Open_Image.style.display='inline'; Codehighlighter1_51_708_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">ref</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ManagedClass&nbsp;</span><span id=Codehighlighter1_51_708_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_51_708_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Allocate&nbsp;the&nbsp;native&nbsp;object&nbsp;on&nbsp;the&nbsp;C++&nbsp;Heap&nbsp;via&nbsp;a&nbsp;constructor</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_176_177_Open_Image onclick="this.style.display='none'; Codehighlighter1_176_177_Open_Text.style.display='none'; Codehighlighter1_176_177_Closed_Image.style.display='inline'; Codehighlighter1_176_177_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_176_177_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_176_177_Closed_Text.style.display='none'; Codehighlighter1_176_177_Open_Image.style.display='inline'; Codehighlighter1_176_177_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ManagedClass()&nbsp;:&nbsp;m_Impl(&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;UnmanagedClass&nbsp;)&nbsp;</span><span id=Codehighlighter1_176_177_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_176_177_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Deallocate&nbsp;the&nbsp;native&nbsp;object&nbsp;on&nbsp;a&nbsp;destructor</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_248_270_Open_Image onclick="this.style.display='none'; Codehighlighter1_248_270_Open_Text.style.display='none'; Codehighlighter1_248_270_Closed_Image.style.display='inline'; Codehighlighter1_248_270_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_248_270_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_248_270_Closed_Text.style.display='none'; Codehighlighter1_248_270_Open_Image.style.display='inline'; Codehighlighter1_248_270_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">ManagedClass()&nbsp;</span><span id=Codehighlighter1_248_270_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_248_270_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;m_Impl;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Deallocate&nbsp;the&nbsp;native&nbsp;object&nbsp;on&nbsp;the&nbsp;finalizer&nbsp;just&nbsp;in&nbsp;case&nbsp;no&nbsp;destructor&nbsp;is&nbsp;called</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_391_413_Open_Image onclick="this.style.display='none'; Codehighlighter1_391_413_Open_Text.style.display='none'; Codehighlighter1_391_413_Closed_Image.style.display='inline'; Codehighlighter1_391_413_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_391_413_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_391_413_Closed_Text.style.display='none'; Codehighlighter1_391_413_Open_Image.style.display='inline'; Codehighlighter1_391_413_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">ManagedClass()&nbsp;</span><span id=Codehighlighter1_391_413_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_391_413_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;m_Impl;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_460_539_Open_Image onclick="this.style.display='none'; Codehighlighter1_460_539_Open_Text.style.display='none'; Codehighlighter1_460_539_Closed_Image.style.display='inline'; Codehighlighter1_460_539_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_460_539_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_460_539_Closed_Text.style.display='none'; Codehighlighter1_460_539_Open_Image.style.display='inline'; Codehighlighter1_460_539_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;property&nbsp;String&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;&nbsp;get_PropertyA&nbsp;</span><span id=Codehighlighter1_460_539_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_460_539_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_480_535_Open_Image onclick="this.style.display='none'; Codehighlighter1_480_535_Open_Text.style.display='none'; Codehighlighter1_480_535_Closed_Image.style.display='inline'; Codehighlighter1_480_535_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_480_535_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_480_535_Closed_Text.style.display='none'; Codehighlighter1_480_535_Open_Image.style.display='inline'; Codehighlighter1_480_535_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">()&nbsp;</span><span id=Codehighlighter1_480_535_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_480_535_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;gcnew&nbsp;String(&nbsp;m_Impl</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">GetPropertyA());<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_579_667_Open_Image onclick="this.style.display='none'; Codehighlighter1_579_667_Open_Text.style.display='none'; Codehighlighter1_579_667_Closed_Image.style.display='inline'; Codehighlighter1_579_667_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_579_667_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_579_667_Closed_Text.style.display='none'; Codehighlighter1_579_667_Open_Image.style.display='inline'; Codehighlighter1_579_667_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;MethodB(&nbsp;String&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;theString&nbsp;)&nbsp;</span><span id=Codehighlighter1_579_667_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_579_667_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pin_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;WCHAR</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;PtrToStringChars(theString);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_Impl</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">MethodB(str);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnmanagedClass&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;m_Impl;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>　　然后，改变编译选项为&#8220;使用公共语言扩展 /clr&#8221;就可以了。这样，我们把代码编译成DLL文件就可以供.NET其它语言调用了。<br>　　最后，C#中可以象如下的代码一样调用C++类了：
<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">ManagedClass&nbsp;mc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ManagedClass();<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>mc.MethoB(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;s&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;mc.get_PropertyA;</span></div>
<br>　　<strong>场景四</strong>：如何在托管C++代码中混合托管和非托管代码<br><br>　　很简单，只要从#pragma unmanaged编译指示开始的程序，一率编译成非托管代码；要想恢复成托管代码，只要使用#pragma managed就可以了。如：<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#pragma&nbsp;unmanaged<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></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><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_93_115_Open_Image onclick="this.style.display='none'; Codehighlighter1_93_115_Open_Text.style.display='none'; Codehighlighter1_93_115_Closed_Image.style.display='inline'; Codehighlighter1_93_115_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_93_115_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_93_115_Closed_Text.style.display='none'; Codehighlighter1_93_115_Open_Image.style.display='inline'; Codehighlighter1_93_115_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f(T&nbsp;t)</span><span id=Codehighlighter1_93_115_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_93_115_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;t&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>#pragma&nbsp;managed<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;System;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_178_204_Open_Image onclick="this.style.display='none'; Codehighlighter1_178_204_Open_Text.style.display='none'; Codehighlighter1_178_204_Closed_Image.style.display='inline'; Codehighlighter1_178_204_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_178_204_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_178_204_Closed_Text.style.display='none'; Codehighlighter1_178_204_Open_Image.style.display='inline'; Codehighlighter1_178_204_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;m(String&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;s)</span><span id=Codehighlighter1_178_204_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_178_204_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Console::WriteLine(s);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_218_246_Open_Image onclick="this.style.display='none'; Codehighlighter1_218_246_Open_Text.style.display='none'; Codehighlighter1_218_246_Closed_Image.style.display='inline'; Codehighlighter1_218_246_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_218_246_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_218_246_Closed_Text.style.display='none'; Codehighlighter1_218_246_Open_Image.style.display='inline'; Codehighlighter1_218_246_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()</span><span id=Codehighlighter1_218_246_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_218_246_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;f(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;m(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">World</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
　　<br>　　生成exe文件后，用反编译程序查看 f 函数：
<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">[PreserveSig,&nbsp;MethodImpl(MethodImplOptions.Unmanaged,&nbsp;MethodCodeType</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">MethodCodeType.Native),&nbsp;SuppressUnmanagedCodeSecurity]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">unsafe</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;modopt(CallConvCdecl)&nbsp;f</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">sbyte</span><span style="COLOR: #000000">&nbsp;modopt(IsSignUnspecifiedByte)&nbsp;modopt(IsConst)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">);</span></div>
　　<br>　　看不到源码，而方法属性标记为Unmanaged。<br>　　如果没有加上#pragma unmanaged，反编译得到的 f 函数为：
<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">internal</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">unsafe</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;modopt(CallConvCdecl)&nbsp;f</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">sbyte</span><span style="COLOR: #000000">&nbsp;modopt(IsSignUnspecifiedByte)&nbsp;modopt(IsConst)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;t)<br><img id=Codehighlighter1_122_595_Open_Image onclick="this.style.display='none'; Codehighlighter1_122_595_Open_Text.style.display='none'; Codehighlighter1_122_595_Closed_Image.style.display='inline'; Codehighlighter1_122_595_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_122_595_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_122_595_Closed_Text.style.display='none'; Codehighlighter1_122_595_Open_Image.style.display='inline'; Codehighlighter1_122_595_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_122_595_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_122_595_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std.basic_ostream</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">,std::char_traits</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">(std.</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">&lt;&lt;&lt;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;std::char_traits</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">((basic_ostream</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">,std::char_traits</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&gt;*</span><span style="COLOR: #000000">&nbsp;modopt(IsImplicitlyDereferenced)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">__imp_std.cout),&nbsp;t),&nbsp;(basic_ostream</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">,std::char_traits</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&gt;*</span><span style="COLOR: #000000">&nbsp;modopt(IsImplicitlyDereferenced)&nbsp;modopt(CallConvCdecl)&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(basic_ostream</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">,std::char_traits</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&gt;*</span><span style="COLOR: #000000">&nbsp;modopt(IsImplicitlyDereferenced)))&nbsp;__unep@</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">endl@std@@$$FYAAAV</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">$basic_ostream@DU</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">$char_traits@D@std@@@</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">@AAV21@@Z);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>　　其中的函数内容一目了然。如果你的函数没有调用operator等不好理解的类库，那么反编译出来的代码简直和源码没差别。&nbsp;<br><br>　　<strong>开心一刻</strong>：我只会C++不懂.NET不懂C#，怎么编写.NET程序？<br><br>　　很简单，你照样用你的C++写你的程序，然后测试没有错误后，将编译选项改为/clr，好了，Rebuild，你的程序现在是.NET了。<br><br>　　<strong style="COLOR: #ff0000">恶搞</strong>：&#8220;我想问一下，在能将现有的C＋＋代码直接进行封装，被C＃进行调用，而不是去调用DLL，也就是不生成DLL，就在C＃下能直接调用VC的工程源文件不？&#8221;<br><br>　　我想，提问的人是不是指，现有c++源码，但不想费劲去转换成C#源码，但又想能与C#一起编译。<br>　　于是我就给了一个极其变态的方法，不过，个人是不建议使用这种变态的方法啊。方法如下：<br>　　１　先将C++源码，改用CLR编译选项，编译成.NET的Assembly（DLL文件）。 <br>　　２　然后用reflector等反编译软件，反编译成C#代码，并导出（reflector有专门的导出插件）。 <br>　　３　将导出的C#代码，添加上新写的C#代码一起编译。 <br>　　<br>　　这种方法生成的代码很是恐怖，强烈建议不要把C++源码就这么丢了，否则后果自负。<br><br>　　<strong>场景五</strong>：不想要DLL，能不能直接把C++源代码与C#源代码一起编译成一个单独的Assembly呢？
<p _fckxhtmljob="1">　　当然是可以的。具体参见：<font color=#1d58d1 _fckxhtmljob="1"><a id=_3d6e54bc9a32_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl00_TitleUrl href="http://www.cnblogs.com/archive/2006/04/12/373494.html">让C++代码与C#代码一起生成一个单一的Assembly</a></font><br><br>-------<br>部份例子来自MSDN. </p>
<img src ="http://www.cppblog.com/twzheng/aggbug/24396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-05-19 17:36 <a href="http://www.cppblog.com/twzheng/articles/24396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Control.KeyPress 事件</title><link>http://www.cppblog.com/twzheng/articles/24252.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Wed, 16 May 2007 16:02:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/24252.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/24252.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/24252.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/24252.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/24252.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: .NET&nbsp;Framework&nbsp;类库            &nbsp;            Control.KeyPress 事件在控件有焦点的情况下按下键时发生。[Visual&nbsp;Basic]Public&nbsp;Event&nbsp;KeyPress&nbsp;As&nbsp;KeyPressEventHa...&nbsp;&nbsp;<a href='http://www.cppblog.com/twzheng/articles/24252.html'>阅读全文</a><img src ="http://www.cppblog.com/twzheng/aggbug/24252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-05-17 00:02 <a href="http://www.cppblog.com/twzheng/articles/24252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET Remoting</title><link>http://www.cppblog.com/twzheng/articles/24074.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Sun, 13 May 2007 16:30:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/24074.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/24074.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/24074.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/24074.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/24074.html</trackback:ping><description><![CDATA[<strong><font face=Arial size=4>.NET Remoting<br></font></strong>By <a href="http://www.developer.com/feedback.php/http://www.developer.com/net/cplus/article.php/1479761"><u><font color=#0000ff>Mark Strawmyer</font></u></a>&nbsp;<br><br>[源] <a href="http://www.developer.com/net/cplus/article.php/10919_1479761_1">http://www.developer.com/net/cplus/article.php/10919_1479761_1</a><br><br>
<p>The last two Nuts and Bolts articles focused on database related topics. This month we'll change gears and focus on something different. The focus of this month's article will be .NET remoting. We'll discuss what is .NET Remoting, how it compares to DCOM and Web services, and go through an example. </p>
<h3>What is .NET Remoting? </h3>
<p>.NET Remoting is an enabler for application communication. It is a generic system for different applications to use to communicate with one another. .NET objects are exposed to remote processes, thus allowing interprocess communication. The applications can be located on the same computer, different computers on the same network, or even computers across separate networks.</p>
<h3>.NET Remoting versus Distributed COM</h3>
<p>In the past interprocess communication between applications was handled through Distributed COM, or DCOM. DCOM works well and the performance is adequate when applications exist on computers of similar type on the same network. However, DCOM has its drawbacks in the Internet connected world. DCOM relies on a proprietary binary protocol that not all object models support, which hinders interoperability across platforms. In addition, have you tried to get DCOM to work through a firewall? DCOM wants to communicate over a range of ports that are typically blocked by firewalls. There are a ways to get it to work, but they either decrease the effectiveness of the firewall (why bother to even have the firewall if you open up a ton of ports on it), or require you to get a firewall that allows support for binary traffic over port 80.</p>
<p>.NET Remoting eliminates the difficulties of DCOM by supporting different transport protocol formats and communication protocols. This allows .NET Remoting to be adaptable to the network environment in which it is being used. </p>
<h3>.NET Remoting versus Web Services</h3>
<p>Unless you have been living in a cave, or are way behind in your reading, you have probably read something about Web services. When you read the description of .NET Remoting it may remind you a lot of what you're read about Web services. That is because Web services fall under the umbrella of .NET Remoting, but have a simplified programming model and are intended for a wide target audience. </p>
<p>Web services involve allowing applications to exchange messages in a way that is platform, object model, and programming language independent. Web services are stateless and know nothing about the client that is making the request. The clients communicate by transferring messages back and forth in a specific format known as the Simple Object Access Protocol, or SOAP. (Want to get some funny looks in the hallway? Stand around in the hallway near the marketing department with your colleagues and discuss the benefits of using SOAP). </p>
<p>The following list outlines some of the major differences between .NET Remoting and Web services that will help you to decide when to use one or the other: </p>
<ul>
    <li>ASP.NET based Web services can only be accessed over HTTP. .NET Remoting can be used across any protocol.<br>
    <li>Web services work in a stateless environment where each request results in a new object created to service the request. .NET Remoting supports state management options and can correlate multiple calls from the same client and support callbacks.<br>
    <li>Web services serialize objects through XML contained in the SOAP messages and can thus only handle items that can be fully expressed in XML. .NET Remoting relies on the existence of the common language runtime assemblies that contain information about data types. This limits the information that must be passed about an object and allows objects to be passed by value or by reference.<br>
    <li>Web services support interoperability across platforms and are good for heterogeneous environments. .NET Remoting requires the clients be built using .NET, or another framework that supports .NET Remoting, which means a homogeneous environment. </li>
</ul>
<h3>Channels</h3>
<p>Remote objects are accessed through Channels. Channels physically transport the messages to and from remote objects. There are two existing channels TcpChannel and HttpChannel. Their names give away the protocols that they use. In addition, the TcpChannel or HttpChannel can be extended, or a new channel created if you determine the existing channels do not meet your needs. </p>
<h3>Create a Remotable Object</h3>
<p>&#160;</p>
<p>A remotable object is nothing more than an object that inherits from MarshalByRefObject. The following sample demonstrates a simple class to expose the omnipresent hello world. This object exposes a single method HelloWorld that will return a string. The only values that can be returned from methods are the classes in the .NET Framework that are serializable such as string and DataSet. In addition, if you need to return a user-defined object then the object needs to be marked as serializable. </p>
<p>&#160;</p>
<p>Create a new C# class library project. Add a class called SampleObject and put in the following code. Add a reference to System.Runtime.Remoting in the project, otherwise the TcpChannel will not be found. Compile the class to make sure you have everything correct. </p>
<pre>using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CodeGuru.Remoting
{<span class=codeComment>
/// &lt;remarks&gt;
/// Sample object to demonstrate the use of .NET Remoting.
/// &lt;/remarks&gt;</span>
public class SampleObject : MarshalByRefObject
{
<span class=codeComment>/// &lt;summary&gt;
/// Constructor
/// &lt;/summary&gt; </span>
public SampleObject()
{
}
<span class=codeComment>
/// &lt;summary&gt;
/// Return a hello message
/// &lt;/summary&gt;
/// &lt;returns&gt;Hello world message&lt;/returns&gt;</span>
public string HelloWorld()
{
return "Hello World!";
}
}
}
</pre>
<h3>Create a Server To Expose the Remotable Object</h3>
<p>We need to create a server object that will act as a listener to accept remote object requests. For this example we will use the TCP/IP channel. We first create an instance of the channel and then register it for use by clients at a specific port. The service can be registered as WellKnownObjectMode.SingleCall, which results in a new instance of the object for each client, or as WellKnownObjectMode.Singleton, which results in one instance of the object used for all clients. </p>
<p>It is not necessary to create the server listener if you are planning to use IIS. For obvious reasons, IIS only supports the use of the HttpChannel. Create a virtual directory for your application and then put code to register your service in the Application_Start event. </p>
<p>For our example, we'll go ahead and create a server listener in case you don't have IIS. Since the service needs to be bound to an available port, for our example I chose 8080, which is a port that I know to be unused on my computer. You may need to choose a different port depending upon what ports you have available. To see a list of the used ports on your computer open a command prompt and issue the command "netstat --a". It may produce a long listing so make sure the command prompt buffer sizes are set to allow scrolling. Compile the class to make sure you have everything correct. </p>
<p>Create a new C# console application project. Add a class called SampleServer and paste in the following code. Add a reference to System.Runtime.Remoting in the project, otherwise the TcpChannel will not be found. In addition, add a reference to the project containing the SampleObject, otherwise the code will not compile because it won't know how to find a reference to SampleObject. </p>
<pre>using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CodeGuru.Remoting
{
<span class=codeComment>/// &lt;remarks&gt;
/// Sample server to demonstrate the use of .NET Remoting.
/// &lt;/remarks&gt;</span>
public class SampleServer
{
public static int Main(string [] args)
{
<span class=codeComment>// Create an instance of a channel</span>
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);
<span class=codeComment>// Register as an available service with the name HelloWorld</span>
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(SampleObject),
"HelloWorld",
WellKnownObjectMode.SingleCall );
System.Console.WriteLine("Press the enter key to exit...");
System.Console.ReadLine();
return 0;
}
}
}
<h3>Create a Client To Use the Remotable Object</h3>
<p>Now that we have our remotable object and a server object to listen for requests, let's create a client to use it. Our client will be very simple. It will connect to the server, create an instance of the object using the server, and then execute the HelloWorld method. </p>
<p>Create a new C# console application project. Add a class called SampleClient and paste in the following code. Add a reference to System.Runtime.Remoting in the project, otherwise the TcpChannel will not be found. In addition, add a reference to the project containing the SampleObject, otherwise the code will not compile because it won't know how to find a reference to SampleObject. Compile the class to make sure you have everything correct. </p>
<pre>using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CodeGuru.Remoting
{
<span class=codeComment>/// &lt;remarks&gt;
/// Sample client to demonstrate the use of .NET Remoting.
/// &lt;/remarks&gt;</span>
public class SampleClient
{
public static int Main(string [] args)
{
<span class=codeComment>// Create a channel for communicating w/ the remote object
// Notice no port is specified on the client</span>
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
<span class=codeComment>// Create an instance of the remote object</span>
SampleObject obj = (SampleObject) Activator.GetObject(
typeof(CodeGuru.Remoting.SampleObject),
"tcp://localhost:8080/HelloWorld" );
<span class=codeComment>// Use the object</span>
if( obj.Equals(null) )
{
System.Console.WriteLine("Error: unable to locate server");
}
else
{
Console.WriteLine(obj.HelloWorld());
}
return 0;
}
}
}
</pre>
<h3>Test the Remoting Sample</h3>
<p>Once you have created the projects and successfully compiled each of them you are ready to try it out. Assuming you chose a free TCP/IP port for the service, start the server executable. After the server successfully starts it will result in a console window being displayed with the message "Press the enter key to exit". The server is listening so you are now ready to run the client. Executing the client should result in "Hello World!" being displayed in a separate console window. The client window will then close while the server remains open and available. </p>
<p>If you have multiple computers available to you on a network you could execute the server on one machine and the client on another just to prove to yourself that it really is remoting. In order to run on separate machines you would need to change the reference to localhost in the sample client to point to the appropriate location. </p>
<h3>Summary</h3>
<p>.NET Remoting is a powerful way to enable interprocess communication. It is more complicated to program against than Web services. You need to decide for yourself whether your standard architecture is to use .NET Remoting or Web services. </p>
<h3>Future Columns</h3>
<p>The next column will be on the use of encryption in the .NET framework. We'll take a look at some of the encryption algorithms available in the framework and ways to use them. If you have a particular topic in mind please email me at mstrawmyer@crowechizek.com</p>
<h3>About the Author</h3>
<p><strong>Mark Strawmyer</strong>, MCSD, MCSE (NT4/W2K), MCDBA is a Senior Architect of .NET applications for large and mid-size organizations. Mark is a technology leader with <a href="http://www.crowechizek.com/scg" target=new>Crowe Chizek</a> in Indianapolis, Indiana. He specializes in architecture, design and development of Microsoft-based solutions. You can reach Mark at <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#115;&#116;&#114;&#97;&#119;&#109;&#121;&#101;&#114;&#64;&#99;&#114;&#111;&#119;&#101;&#99;&#104;&#105;&#122;&#101;&#107;&#46;&#99;&#111;&#109;">mstrawmyer@crowechizek.com</a>.</p>
</pre>
<img src ="http://www.cppblog.com/twzheng/aggbug/24074.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-05-14 00:30 <a href="http://www.cppblog.com/twzheng/articles/24074.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于.net委托的一篇妙文</title><link>http://www.cppblog.com/twzheng/articles/delegate.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Sat, 12 May 2007 12:00:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/delegate.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/23997.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/delegate.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/23997.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/23997.html</trackback:ping><description><![CDATA[<p><strong>关于.net委托的一篇妙文</strong><br><br>作者：TomMax (笑望人生) 出处：csdn community </p>
<p>有许多人问的，.Net中的委托以及事件处理。我拿简单的例子说明一下，是现实中的例子：</p>
<p>比如说一个公司（场景），你是老板，手下有两个员工，小张和小王。<br>你命令小王，如果小张玩游戏，则小王扣去小张500元钱。</p>
<p>这就是现实中的委托。</p>
<p>实际上，在写程序中，程序员就是老板，小张和小王就是两个对象。小张玩游戏是一个方法，小张还有一个游戏事件，他玩游戏激发这个事件。而小王就是事件处理对象，他负责把小张的钱扣除500。</p>
<p>所以，委托有如下几个要素：<br>1 激发事件的对象--就是小张<br>2 处理对象事件的对象--就是小王<br>3 定义委托，就是你让小王监视小张。</p>
<p>如果这三个要素都满足的话，则你就写出了一个完整事件的处理。</p>
<p>下面有个例子：在vs.net2003 C#控制台应用程序编辑运行成功：<br>using System;</p>
<p>namespace CSharpConsole<br>{<br>&nbsp;public class 场景<br>&nbsp;{<br>&nbsp;&nbsp;[STAThread]<br>&nbsp;&nbsp;public static void Main(string[] args)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("场景开始了....");<br>&nbsp;&nbsp;&nbsp;// 生成小王<br>&nbsp;&nbsp;&nbsp;小王 w = new 小王();<br>&nbsp;&nbsp;&nbsp;// 生成小账<br>&nbsp;&nbsp;&nbsp;小张 z = new 小张();</p>
<p>&nbsp;&nbsp;&nbsp;// 指定监视<br>&nbsp;&nbsp;&nbsp;z.PlayGame += new PlayGameHandler(w.扣钱);</p>
<p>&nbsp;&nbsp;&nbsp;// 开始玩游戏<br>&nbsp;&nbsp;&nbsp;z.玩游戏();</p>
<p>&nbsp;&nbsp;&nbsp;console.writeline("场景结束...");<br>&nbsp;&nbsp;&nbsp;Console.ReadLine();<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p><br>&nbsp;// 负责扣钱的人<br>&nbsp;public class 小王<br>&nbsp;{<br>&nbsp;&nbsp;public 小王()<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("生成小王...");<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;public void 扣钱(object sender,EventArgs e)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("小王：好小子，上班时间胆敢玩游戏...");<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("小王：看看你小子有多少钱...");<br>&nbsp;&nbsp;&nbsp;小张 f = (小张)sender;<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("小张的钱： " + f.钱.ToString());<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("开始扣钱......");<br>&nbsp;&nbsp;&nbsp;System.Threading.Thread.Sleep(500);<br>&nbsp;&nbsp;&nbsp;f.钱 = f.钱 - 500;<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("扣完了....现在小张还剩下：" + f.钱.ToString());<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p>&nbsp;// 如果玩游戏，则引发事件<br>&nbsp;public class 小张<br>&nbsp;{<br>&nbsp;&nbsp;// 先定义一个事件，这个事件表示&#8220;小张&#8221;在玩游戏。<br>&nbsp;&nbsp;public event PlayGameHandler PlayGame;<br>&nbsp;&nbsp;// 保存小张钱的变量<br>&nbsp;&nbsp;private int m_Money;</p>
<p>&nbsp;&nbsp;public 小张()<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("生成小张....");<br>&nbsp;&nbsp;&nbsp;m_Money = 1000; // 构造函数，初始化小张的钱。<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;public int 钱 // 此属性可以操作小张的钱。<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;get<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;return m_Money;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;set<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;m_Money = value;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;public void 玩游戏()<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("小张开始玩游戏了.....");<br>&nbsp;&nbsp;&nbsp;Console.WriteLine("小张:CS好玩，哈哈哈！ 我玩.....");<br>&nbsp;&nbsp;&nbsp;System.Threading.Thread.Sleep(500);<br>&nbsp;&nbsp;&nbsp;System.EventArgs e = new EventArgs();<br>&nbsp;&nbsp;&nbsp;OnPlayGame(e);<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;protected virtual void OnPlayGame(EventArgs e)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;if(PlayGame != null)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;PlayGame(this,e);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p>&nbsp;// 定义委托处理程序<br>&nbsp;public delegate void PlayGameHandler(object sender,System.EventArgs e);</p>
<p>}<br></p>
<img src ="http://www.cppblog.com/twzheng/aggbug/23997.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-05-12 20:00 <a href="http://www.cppblog.com/twzheng/articles/delegate.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows函数错误处理</title><link>http://www.cppblog.com/twzheng/articles/20519.html</link><dc:creator>谭文政</dc:creator><author>谭文政</author><pubDate>Sat, 24 Mar 2007 03:04:00 GMT</pubDate><guid>http://www.cppblog.com/twzheng/articles/20519.html</guid><wfw:comment>http://www.cppblog.com/twzheng/comments/20519.html</wfw:comment><comments>http://www.cppblog.com/twzheng/articles/20519.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/twzheng/comments/commentRss/20519.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/twzheng/services/trackbacks/20519.html</trackback:ping><description><![CDATA[当调用一个Windows函数时，它首先要检验传递给它的各个参数的有效性，然后再设法执行任务.如果传递一个无效参数，或者由于某种原因无法执行这项操作，那么操作系统就会返回一个值，指明该函数在某种程度上运行失败了。<br>&nbsp;&nbsp;&nbsp;Windows函数常用的返回值类型:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOL:0,非0,TURE,FALSE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE:HANDLE,NULL,INVALID_HANDLE_VALID)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID:NULL,PVOID<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LONG/DWORD:具体函数而定<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br>&nbsp;&nbsp;&nbsp;Microsoft编译了一个所有可能的错误代码列表，并且为每个错误代码分配了一个32位的号码. WinError.h头文件(大约2万多行)包含了Micorsoft定义的错误代码列表.<br>&nbsp;&nbsp;&nbsp;当一个Windows函数检测到一个错误时，它会使用线程本地存储(thread-local storage)机制，将相应的错误代码号码与调用的线程关联起来.这将使线程能够互相独立的运行,而不会影响各自的错误代码.<br>&nbsp;&nbsp;&nbsp;当函数返回时，它的返回值就能指明是否有错误发生，若有且要确定是什么错误,就需要调用DWORD GetLastError()函数,它返回线程的32位错误代码.Visual Studio有一个Error Lookup程序可用将错误代码的号码换成相应文本描述.Windows还提供了一个函数FormatMessage可以将错误代码转换成它的文本描述.<br>DWORD FormatMessage(<br>&nbsp;&nbsp;DWORD dwFlags,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// source and processing options<br>&nbsp;&nbsp;LPCVOID lpSource,&nbsp;&nbsp;&nbsp;// message source<br>&nbsp;&nbsp;DWORD dwMessageId,&nbsp;&nbsp;// message identifier<br>&nbsp;&nbsp;DWORD dwLanguageId, // language identifier<br>&nbsp;&nbsp;LPTSTR lpBuffer,&nbsp;&nbsp;&nbsp;&nbsp;// message buffer<br>&nbsp;&nbsp;DWORD nSize,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// maximum size of message buffer<br>&nbsp;&nbsp;va_list *Arguments&nbsp;&nbsp;// array of message inserts<br>);<br>&nbsp;&nbsp;我们也可以在自己的函数中使用该机制,只需要使用VOID SetLastError(DWORD dwErrCode)函数即可,如果WinError.h中的任何代码都不能正确地反映该错误的性质，那么可以创建你自己的代码。错误代码的域的划分表:<br>位&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;31~30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;27~16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15~0<br>内容&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;严重性&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Microsoft/客户&nbsp;&nbsp;&nbsp;&nbsp;保留&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设备代码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;异常代码<br><br>含义&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0=成功&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0=MS定义的代码&nbsp;&nbsp;&nbsp;必顺是0&nbsp;&nbsp;&nbsp;由MS定义&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由MS或客户定义<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1=参考<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2=警告&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1=客户定义的代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3=错误<br><br>注:如果创建自己的错误代码，必顺使29位为1. 
<img src ="http://www.cppblog.com/twzheng/aggbug/20519.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/twzheng/" target="_blank">谭文政</a> 2007-03-24 11:04 <a href="http://www.cppblog.com/twzheng/articles/20519.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>