??xml version="1.0" encoding="utf-8" standalone="yes"?>99久久精品费精品国产,国産精品久久久久久久,亚洲另类欧美综合久久图片区http://www.shnenglu.com/mzty/category/695.html<br/> <br/> <a href = "http://www.shnenglu.com/mzty/archive/2007/03/02/19109.html"><font size = 5 color ="#00FFFF">{C++ 基础}<font/></a> <a href = "http://www.shnenglu.com/mzty/archive/2007/08/13/29922.html"><font size = 5 color ="#00FFFF">{C++ 高}<font/></a> <a href = "http://www.shnenglu.com/mzty/archive/2008/07/18/56532.html"><font size = 5 color ="#00FFFF">{C++/CLI}<font/></a> <a href = "http://www.shnenglu.com/mzty/archive/2008/07/18/56533.html"><font size = 5 color ="#00FFFF">{VC Team中文}<font/></a> <a href = "http://www.shnenglu.com/mzty/archive/2007/04/16/22064.html"><font size = 5 color ="#00FFFF">{C#界面QC++核心法}<font/></a> <a href = "http://www.shnenglu.com/mzty/archive/2007/03/04/19163.html"><font size = 5 color ="#00FFFF">{设计模式}<font/></a> <a href = " http://www.shnenglu.com/mzty/archive/2007/03/04/19167.html"><font size = 5 color ="#FF0000">{C#基础}<font/></a> zh-cnSat, 19 Jul 2008 00:57:57 GMTSat, 19 Jul 2008 00:57:57 GMT60越 C++ 下一?C++ ?C++/CLI介(转蝲Q?/title><link>http://www.shnenglu.com/mzty/archive/2008/07/18/56536.html</link><dc:creator>梦在天</dc:creator><author>梦在天</author><pubDate>Fri, 18 Jul 2008 14:28:00 GMT</pubDate><guid>http://www.shnenglu.com/mzty/archive/2008/07/18/56536.html</guid><wfw:comment>http://www.shnenglu.com/mzty/comments/56536.html</wfw:comment><comments>http://www.shnenglu.com/mzty/archive/2008/07/18/56536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/mzty/comments/commentRss/56536.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/mzty/services/trackbacks/56536.html</trackback:ping><description><![CDATA[<span id="1ppfj79" class=a14c id=zoom> <br> <p><strong>一、A?/strong> <p>当微软推出VS.NET7实现了可扩展的托C++后,C++E序员们反映不一。尽大部分的程序员对于能够l箋使用C++感到很欣慎ͼ但几乎所有的人对于托C++提供的晦涩语法感到很痛苦。微软明显从反馈中感觉到托管C++不是那么成功? <p>2003q?0?日,ECMAQ欧z计机刉商协会Q宣布成立专家组Q负责结合ISO标准C++与通用语言Q开发一个可扩展语言的标准,q个新的可扩展语a被称为C++/CLI标准。这个标准将被VS.NET2005的C++~译器支持? <p><strong>二、老语法存在的问题</strong> <p>1、晦涩繁琐的语法和文?-q两?双重底线"问题加重了阅ȝ负担? <p>2、二的CLI支持--相对与C#与VB.NETQMC++使用不方便的工作区来提供CLI支持Q例如,它没有一个一一对应的结构来列D.NET的集合? <p>3、C++?NET_陋地结?-对于CLIcdQ你不能使用C++的特Ԍ例如模板Q同P对于C++cdQ你不能使用CLI的特Ԍ例如片帐集? <p>4、o人؜淆的指针--非托的C++的指针及托管的引用指针都使用*语法Q这非常令hhQ因?gc指针与托指针在本质和行Z完全不同? <p>5、MFC~译器不能生可校验的代码? <p><strong>三、C++/CLIl我们提供了什么?</strong> <p>1、优雅流畅的语法和文?-C++/CLI为C++开发h员书写托代码提供了一U非常自然的感觉Qƈ且它提供了非托管代码到托代码的qxq度。以前所谓的"双重底线"问题现在已经荡然无存? <p>2、一的CLI支持--CLI特色Q例如属性、碎片集合和属类得到了直接支持,此外QC++/CLIq准许将q些特色用于本地非托的cR? <p>3、一的C++cL?-C++特色Q例如模板和析构函数对于拖管和非拖管cȝl有效。实际上QC++/CLI是你可以"表面?在栈或C++本地堆上声明一?NETcd唯一?NET语言? <p>4、在.NET与C++之间的沟壑上架v了一座桥?-C++开发h员在抨击BCL时不再象d水的鱹{? <p>5、C++/CLI~译器生的可执行文件完全是可校验的? <p><strong>四?Hello World"程?/strong> <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>using namespace System; void _tmain() { Console::WriteLine("Hello World"); }</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>上述代码除了不需要引用mscorlib.dll库外Q与老的语法没有太大的区别,因ؓ无论你什么时候?clrq行~辑Q编译器都可以暗中进行引用(现在默认的是/clr:newSyntaxQ? <p><strong>五、句?/strong> <p>与老的语法主要的؜淆是我们习惯于?W号来声明拖引用或非拖指针,在C++/CLI里微软引入了句柄的概c? <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>void _tmain() { //The ^ punctuator represents a handle String^ str = "Hello World"; Console::WriteLine(str); }</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>^W号代表一个托对象(声明时看上去象个帽子Q,按照CLI的规定,句柄代表一个拖对象的引用。句柄在CLI中是新的语法Q相当于C++中的-gc指针。句柄与指针不再hQ在本质上两者完全不同? <p><strong>六、句柄与指针是怎样区分开来的Q?/strong> <p>1、指针声明时使用*W号Q而句柄用^W号? <p>2、句柄是针对拖管堆上对象的拖引用,而指针仅仅指向内存中的一个地址? <p>3、指针很E_QGC循环不会影响到它Q句柄在ZGC或内存紧张的情况下,可以指向不同的内存位|? <p>4、对于指针,E序开发h员必?昑ּ"地删除,否则会面临泄露的危险Q而对于句柄,是否q行昑ּ删除则完全根据程序h员的爱好了? <p>5、句柄一定要指向一个具体的cdQ即所谓的cd安全性,而指针明显不是这P你决不可以将一个句柄指向Void^cd? <p>6、正如new操作W返回一个指针一Pgcnewq回一个句柄? <p><strong>七、CLR对象CZ</strong> <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>void _tmain() { String^ str = gcnew String("Hello World"); Object^ o1 = gcnew Object(); Console::WriteLine(str); }</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>关键字gcnew用来实例化一个CLI对象Q而且它返回一个指向在CLR堆上的对象的句柄Qgcnew的优点在于它可以方便的让我们区分拖管和非拖管的实例对象? <p>大部分情况下Qgcnew关键字和^操作W提供了你用来进行BCL的一切手D,但是很明显你需要创建和声明属于自己的拖类和接口? <p><strong>八、声明类?</strong> <p>CLRcd有一个Ş容词前缀用来说明cd的种c,下面是C++/CLI中的cd声明CZQ? <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>1?CLR types o Reference types § ref class RefClass; § ref struct RefClass; 2?Value types § value class ValClass; § value struct ValClass; o Interfaces § interface class IType; § interface struct IType; o Enumerations § enum class Color; § enum struct Color; 3?Native types o class Native; o struct Native; CZQ? using namespace System; interface class IDog { void Bark(); }; ref class Dog : IDog { public: void Bark() { Console::WriteLine("Bow wow wow"); } }; void _tmain() { Dog^ d = gcnew Dog(); d->Bark(); }</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>上述E序中的代码与老的C++语言相比看上去非常简z,在以往的C++代码中,臛_要用?gc?interfaceq两个关键词? <p><strong>九、装?拆箱操作</strong> <p>在C++/CLI中,加箱是隐含的Q而且cd是安全的Q一个二q制的拷贝被执行q在CLR堆上形成一个对象,ȝ是显式的Q仅仅需要用reinterpret_cast操作W来解除引用? <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>void _tmain() { int z = 44; Object^ o = z; //implicit boxing int y = *reinterpret_cast<int^>(o); //unboxing Console::WriteLine(" ",o,z,y); z = 66; Console::WriteLine(" ",o,z,y); } // 输出l果如下Q? // 44 44 44 // 44 66 44</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>在上qC码中Q?o"对象是一个加q拯Q从W二个语句Console::WriteLine.的输出可以很明显地看刎ͼ它ƈ没有涉及到intcd的整数倹{? <p>当你对一U数值类型进行加操作时Q返回的对象C了最初的数值类型? <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>void _tmain() { int z = 44; float f = 33.567; Object^ o1 = z; Object^ o2 = f; Console::WriteLine(o1->GetType()); Console::WriteLine(o2->GetType()); } // Output // System.Int32 // System.Single</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>因此不能对不同类型的对象q行ȝ操作? <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>void _tmain() { int z = 44; float f = 33.567; Object^ o1 = z; Object^ o2 = f; int y = *reinterpret_cast<int^>(o2);//System.InvalidCastException float g = *reinterpret_cast<float^>(o1);//System.InvalidCastException }</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>如果你非试q么做,那么你将得到一个System.InvalidCastException。让我们来探讨一下完的cd安全性,如果你要看内部代码,你将看到微Y的内部箱在实际中的运用。例如: <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>void Box2() { float y=45; Object^ o1 = y; }</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>~译后的代码是: <p><ccid_nobr> <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <tbody> <tr> <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6> <pre><ccid_code>.maxstack 1 .locals (float32 V_0, object V_1) ldnull stloc.1 ldc.r4 45. stloc.0 ldloc.0 box [mscorlib]System.Single stloc.1 ret</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr> <p>Ҏ微Y的内部文档,操作将未加工的cd转换Z个具体类型的实例Q这工作的完成通过创徏一个新的对象ƈ数据拷贝到q个新分配的对象? <p><strong>十、写在后面的?/strong> <p>Z么很多h已经可以使用C、C++?NET来开发程序但q在U极学习C++/CLI呢,我想有四个方面的原因Q? <p>1、从~译器直到内层都q在支持C++代码Q? <p>2、C++/CLI对于其他标准来说无意是具有毁灭性地Q? <p>3、与生俱来的内部支持胜过所有其他CLI语言 <p>4、所有在MFC中出现的下划UK已不再存在?/p> </span><img src ="http://www.shnenglu.com/mzty/aggbug/56536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/mzty/" target="_blank">梦在天</a> 2008-07-18 22:28 <a href="http://www.shnenglu.com/mzty/archive/2008/07/18/56536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++/CLI 中文http://www.shnenglu.com/mzty/archive/2008/07/18/56532.html梦在天梦在天Fri, 18 Jul 2008 14:18:00 GMThttp://www.shnenglu.com/mzty/archive/2008/07/18/56532.htmlhttp://www.shnenglu.com/mzty/comments/56532.htmlhttp://www.shnenglu.com/mzty/archive/2008/07/18/56532.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/56532.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/56532.htmlC++/CLI中文文章Q?br>

一Q?br>
C++/CLIQ第一的CLI语言(转蝲)

二,

梦在天 2008-07-18 22:18 发表评论
]]>
C++/CLIQ第一的CLI语言(转蝲)http://www.shnenglu.com/mzty/archive/2008/07/18/56531.html梦在天梦在天Fri, 18 Jul 2008 14:12:00 GMThttp://www.shnenglu.com/mzty/archive/2008/07/18/56531.htmlhttp://www.shnenglu.com/mzty/comments/56531.htmlhttp://www.shnenglu.com/mzty/archive/2008/07/18/56531.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/56531.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/56531.html 

C++/CLIQ第一的CLI语言
2005-08-25 11:25 作者: 朱先忠编?出处Q?天极|?责Q~辑Q方?

1. ?br>
  本文q不是ؓ了奉承C++/CLI的辉煌,也不是ؓ了贬低其它如C#或者VB.NET{语aQ相反,q只是一个非官方的、以一个喜Ƣ这U语a的非微Y雇员w䆾来论证C++/CLI有它的自q唯一的角Ԍ可作为第一的.NET~程语言?br>
  一个不断在新闻l和技术论坛上出现的问题是Q当象C#和VB.NETq样的语a更适合于这U用途时Qؓ什么要使用C++来开?NET应用软g。通常q样一些问题后面的评论说是QC++语法是怎样的复杂和令h费解QC++现在是怎样一U过时的语言Q还有什么VS.NET设计者已不再像支持C#和VB.NET一Ll支持C++。其中一些猜疑是完全荒谬的,但有些说法部分正。希望本文有助于澄清所有这些围lC++/CLI语言及其在VS.NET语言层次中的C的疑惑,秘和不信Q。请CQ本作者既不ؓ微Y工作也没有从微Y那里取得报酬Q只是想从技术上对C++/CLI作一评判?br>
  2. 快速简z的本机interop

  除了P/Invoke机制可用在另外的象C#或VB.NETq样的语a外,C++提供了一U独有的interop机制Q称作C++ interop。C++ interop比P/Invoke直观得多Q因Z只是单地#include需要的头文Ӟq与需要的库进行链接就能象在本机C++中一栯用Q何函数。另外,它比P/Invoke速度?-q是很容易能证明的。现在,可争辩的是在实际应用软g的开发中Q经由C++ interop获得的性能好处与花在用h口交互、数据库存取?a class=bluekey target=_blank>|络数据转储、复杂数学算法等斚w的时间相比可以被忽略Q但是事实是在有些情况下Q甚至通过每次interop调用节省的几个纳U也能给全局应用E序性能/响应造成巨大影响Q这是绝对不能被忽视的。下面有两部分代码片?一个是使用P/Invoke机制的C#E序Q一个是使用C++ Interop机制的C++E序)Q我分别记录了其各自代码重复执行消耗的旉(毫秒)。不你如何解释q些数据Q不这会对你的应用E序产生什么媄响,全是你的事。我仅打事实性地指出QC++代码的执行速度要比C#(其中使用了较多的本机interop调用)快?br>
  1) C#E序(使用P/Invoke)

[SuppressUnmanagedCodeSecurity]
[DllImport("kernel32.dll")]
static extern uint GetTickCount();
[SuppressUnmanagedCodeSecurity]
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint GetWindowsDirectory(
[Out] StringBuilder lpBuffer, uint uSize);
static void Test(int x)
{
StringBuilder sb = new StringBuilder(512);
for (int i = 0; i < x; i++)
GetWindowsDirectory(sb, 511);
}
static void DoTest(int x)
{
uint init = GetTickCount();
Test(x);
uint tot = GetTickCount() - init;
Console.WriteLine("Took {0} milli-seconds for {1} iterations",tot, x);
}
static void Main(string[] args)
{
DoTest(50000);DoTest(500000);DoTest(1000000);DoTest(5000000);
Console.ReadKey(true);
}

  2) C++E序(使用C++ Interop)

void Test(int x)
{
TCHAR buff[512];
for(int i=0; i<x; i++)
GetWindowsDirectory(buff, 511);
}
void DoTest(int x)
{
DWORD init = GetTickCount();
Test(x);
DWORD tot = GetTickCount() - init;
Console::WriteLine("Took {0} milli-seconds for {1} iterations",tot, x);
}
int main(array<System::String ^> ^args)
{
DoTest(50000);DoTest(500000);DoTest(1000000);DoTest(5000000);
Console::ReadKey(true);
return 0;
}

  3) 速度比较

重复ơ数 C# E序 C++E序
50,000 61 10
500,000 600 70
1,000,000 1162 140
5,000,000 6369 721
  
  其性能差别真是令h惊愕Q这的确是说明ؓ什么要使用C++/CLI的一个好理由Q如果你在用本机interopq行开发,那么性能Q完全由于性能Q我将被迫借助本机interop来实现ƈ非基于web?NET应用E序。当ӞZ么我惌使用.NET来开发需要大量本机interop技术的应用E序完全是另外一个问题?br>
  如果你仍怀疑这U性能优势Q有另外的理由来说明你ؓ什么不得不使用C++/CLI而不是C#或VB.NET——源码膨胀Q下面是一个C++函数的例子,它用了IP帮助者API来枚举一台机器上的网l适配器ƈ且列Z每个适配器相联系的所有IP地址?br>
  4) 枚Dn/w适配器的C++代码

void ShowAdapInfo()
{
PIP_ADAPTER_INFO pAdapterInfo = NULL;
ULONG OutBufLen = 0;
//得到需要的~冲区大?br>if(GetAdaptersInfo(NULL,&OutBufLen)==ERROR_BUFFER_OVERFLOW)
{
int divisor = sizeof IP_ADAPTER_INFO;
#if _MSC_VER >= 1400
if( sizeof time_t == 8 ) divisor -= 8;
#endif
pAdapterInfo = new IP_ADAPTER_INFO[OutBufLen/divisor];
//取得适配器信?br>if( GetAdaptersInfo(pAdapterInfo, &OutBufLen) != ERROR_SUCCESS )
{//调用p| }
else
{
int index = 0;
while(pAdapterInfo)
{
Console::WriteLine(gcnew String(pAdapterInfo->Description));
Console::WriteLine("IP Address list : ");
PIP_ADDR_STRING pIpStr = &pAdapterInfo->IpAddressList;
while(pIpStr)
{
Console::WriteLine(gcnew tring(pIpStr->IpAddress.String));
pIpStr = pIpStr->Next;
}
pAdapterInfo = pAdapterInfo->Next;
Console::WriteLine();
}
}
delete[] pAdapterInfo;
}
}

  现在让我们看一个用P/Invoke的C#版本?br>
  5) 使用P/Invoke技术的C#版本

const int MAX_ADAPTER_NAME_LENGTH = 256;
const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
const int ERROR_BUFFER_OVERFLOW = 111;
const int ERROR_SUCCESS = 0;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADDRESS_STRING
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Address;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADDR_STRING
{
public IntPtr Next;
public IP_ADDRESS_STRING IpAddress;
public IP_ADDRESS_STRING Mask;
public Int32 Context;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADAPTER_INFO
{
public IntPtr Next;
public Int32 ComboIndex;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = MAX_ADAPTER_NAME_LENGTH + 4)]
public string AdapterName;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
public string AdapterDescription;
public UInt32 AddressLength;
[MarshalAs(UnmanagedType.ByValArray,
SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
public byte[] Address;
public Int32 Index;
public UInt32 Type;
public UInt32 DhcpEnabled;
public IntPtr CurrentIpAddress;
public IP_ADDR_STRING IpAddressList;
public IP_ADDR_STRING GatewayList;
public IP_ADDR_STRING DhcpServer;
public bool HaveWins;
public IP_ADDR_STRING PrimaryWinsServer;
public IP_ADDR_STRING SecondaryWinsServer;
public Int32 LeaseObtained;
public Int32 LeaseExpires;
}
[DllImport("iphlpapi.dll", CharSet = CharSet.Ansi)]
public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref int pBufOutLen);
static void ShowAdapInfo()
{
int OutBufLen = 0;
//得到需要的~冲区大?br>if( GetAdaptersInfo(IntPtr.Zero, ref OutBufLen) ==
ERROR_BUFFER_OVERFLOW )
{
IntPtr pAdapterInfo = Marshal.AllocHGlobal(OutBufLen);
//取得适配器信?br>if( GetAdaptersInfo(pAdapterInfo, ref OutBufLen) != ERROR_SUCCESS )
{ //调用p|?}
else{
while(pAdapterInfo != IntPtr.Zero)
{
IP_ADAPTER_INFO adapinfo =
(IP_ADAPTER_INFO)Marshal.PtrToStructure(
pAdapterInfo, typeof(IP_ADAPTER_INFO));
Console.WriteLine(adapinfo.AdapterDescription);
Console.WriteLine("IP Address list : ");
IP_ADDR_STRING pIpStr = adapinfo.IpAddressList;
while (true){
Console.WriteLine(pIpStr.IpAddress.Address);
IntPtr pNext = pIpStr.Next;
if (pNext == IntPtr.Zero)
break;
pIpStr = (IP_ADDR_STRING)Marshal.PtrToStructure(
pNext, typeof(IP_ADDR_STRING));
}
pAdapterInfo = adapinfo.Next;
Console.WriteLine();
}
}
Marshal.FreeHGlobal(pAdapterInfo);
}
}


3. 栈语义和定性的析构

  C++l由栈语义模仿给了我们确定性的析构。简a之,栈语义是Dispose模式的良好的语法替代品。但是它在语义上比C# using块语法更直观些。请看下列的C#和C++代码D(都做一L事情-q接两个文g的内容ƈ把它写到W三个文件中Q?br>
  1) C#代码--使用块语?br>
public static void ConcatFilestoFile(String file1, String file2, String outfile)
{
String str;
try{
using (StreamReader tr1 = new StreamReader(file1))
{
using (StreamReader tr2 = new StreamReader(file2))
{
using (StreamWriter sw = new StreamWriter(outfile))
{
while ((str = tr1.ReadLine()) != null)
sw.WriteLine(str);
while ((str = tr2.ReadLine()) != null)
sw.WriteLine(str);
}
}
}
}
catch (Exception e)
{ Console.WriteLine(e.Message); }
}

  2) C++代码--栈语?br>
static void ConcatFilestoFile(String^ file1, String^ file2, String^ outfile)
{
String^ str;
try{
StreamReader tr1(file1);
StreamReader tr2(file2);
StreamWriter sw(outfile);
while(str = tr1.ReadLine())
sw.WriteLine(str);
while(str = tr2.ReadLine())
sw.WriteLine(str);
}
catch(Exception^ e)
{ Console::WriteLine(e->Message); }
}

  C#代码与相{的C++ 代码相比不仅免不了冗长,而且using块语法让E序员自己明地指定他想在哪儿调用DisposeQusing块的l束处)Q而用C++/CLI的栈语义Q只需让编译器使用常规的范围规则来处理它即可。事实上Q这使得在C#中修改代码比在C++中更乏味-作ؓ一实例Q让我们修改q些代码以便即仅存在一个输入文件也能创出文件。请看下面修改后的C#和C++代码?br>
  3) 修改后的C#代码

public static void ConcatFilestoFile(String file1, String file2, String outfile)
{
String str;
try{
using (StreamWriter sw = new StreamWriter(outfile))
{
try{
using (StreamReader tr1 = new StreamReader(file1))
{
while ((str = tr1.ReadLine()) != null)
sw.WriteLine(str);
}
}
catch (Exception) { }
using (StreamReader tr2 = new StreamReader(file2))
{
while ((str = tr2.ReadLine()) != null)
sw.WriteLine(str);
}
}
}
catch (Exception e){ }
}

  把针对StreamWriter的using块放到顶层需要重新调整using块结?-q在上面情况下显然不是个大问题,但是对于实际开发中的修改,q可能是相当模糊的且易导致逻辑错误的?br>
  4) 修改后的C++代码

static void ConcatFilestoFile(String^ file1, String^ file2, String^ outfile)
{
String^ str;
try{
StreamWriter sw(outfile);
try{
StreamReader tr1(file1);
while(str = tr1.ReadLine())
sw.WriteLine(str);
}
catch(Exception^){}
StreamReader tr2(file2);
while(str = tr2.ReadLine())
sw.WriteLine(str);
}
catch(Exception^){}
}

  q样不是比在C#中的做更Ҏ些吗Q我恰好把StreamWriter声明Ud了顶部ƈ增加了一个额外的try块,p些。甚臛_于象在我的示例代码片断中的琐事情,如果所涉及的复杂性在C++中大大减,那么Q当你工作于更大的工E时你能惌使用栈语义对你的~码效率千万的媄响?br>
  q不信Q好Q让我们看一下成员对象和它们的析构吧。Imagine CLI GCcR1和R2Q二者都实现了Idisposable接口且都有函数F()Q还有一个CLI GCcRQ它有R1和R2成员和一个函数F()-它内部地调用R1和R2上的F()成员函数。让我们先看C#实现?br>
  5) 一个disposablecȝ承层ơ的C#实现

class R1 : IDisposable{
public void Dispose() { }
public void F() { }
}
class R2 : IDisposable{
public void Dispose() { }
public void F() { }
}
class R : IDisposable{
R1 m_r1 = new R1();
R2 m_r2 = new R2();
public void Dispose()
{
m_r1.Dispose();
m_r2.Dispose();
}
public void F()
{
m_r1.F();
m_r2.F();
}
public static void CallR()
{
using(R r = new R())
{r.F();}
}
}

  q里有几件事情要做:必须为每个disposable cL工实现IDisposable接口Q对于具有成员R1和R2的类RQDisposeҎ也需要调用成员类上的Dispose。现在让我们分析上面几个cȝC++实现?br>
  6) {h的C++实现

ref class R1
{
public:
~R1(){}
void F(){}
};
ref class R2
{
public:
~R2(){}
void F(){}
};
ref class R
{
R1 m_r1;
R2 m_r2;
public:
~R(){}
void F()
{
m_r1.F();
m_r2.F();
}
static void CallR()
{
R r;
r.F();
}
};

  注意Q这里不再有手工的Idisposable接口实现(我们的类中仅建立了析构器)而且最好的部分--cR的析构器(DisposeҎ)q没有在该类可能含有的可释放的成员上调用Dispose-它没有必要这样做Q编译器自动Z生成所有的代码Q?

4. 混合cd

  我们知道QC++支持本机cd-L如此QC++支持CLIcd-本文正是特别q一点;它还支持混合cd-hCLI成员的本机类型和h本机成员的CLIcdQ请管考虑所有你能的可能需求?br>
  注意Q谈到WhidbeyQ؜合类型实现还不完_我从BrandonQHerb和Ronald发表的材料的理解得知Q存在这U相当酷的类?-l一模型Q它在Orcas中实?-你能够在本机C++堆上new/delete CLIcdQ而且也能够在CLI堆上gcnew/delete本机cd。但既然q是Whidbey以后的东西,本文不讨论统一模型?br>
  在我谈论你何时用؜合类型以前,我想向你说明什么是混合cd。如果你理解混合cdQ请跌下面几段。这里引用Brandon Bray的说法:"一U؜合类型,或者是本机crefc(需要有对象成员Q,或者是通过声明或承被分配在垃圑֛收堆或本机堆上的?因此如果你有一个托类型或者有一个有托管成员的本机类型,你就有了一个؜合类型。VC++ Whidbey不直接支持؜合类?l一cd模型是一UWhidbey之后的概?Q但是它l我们划定了实现混合cd的条件。让我们开始讨论包含托成员的本机cd?br>
ref class R
{
public:
void F(){}
//假定 non-trivial ctor/dtor
R(){}
~R(){}
};

  在我的例子中Q设惌托管cdR有一个non-trivial构造器和一个non-trivial析构器?br>
class Native
{
private:
gcroot<R^> m_ref;
public:
Native():
m_ref(gcnew R()){}
~Native()
{ delete m_ref; }
void DoF()
{ m_ref->F(); }
};

  既然Q我不能在我的类中拥有一个R成员Q我使用了gcroot模板c?在gcroot.h中声明,但是你要?#include vcclr.h")Q它包装了System::Runtime::InteropServices::GCHandlel构。它是个象类一L灉|指针Q它重蝲了运符->以返回用作模板参数的托管cd。因此在上面cMQ我可以使用m_refQ就好象我已l声明它是R^Q而且你能在DoF函数中看到这正在起作用。实际上你可以节省deleteQ这可以通过使用auto_gcroot(cM于std::auto_ptrQ在msclr\auto_gcroot.h文g中声?代替gcroot来实现。下面是一个更好些的用auto_gcroot的实现?br>
class NativeEx
{
private:
msclr::auto_gcroot<R^> m_ref;
public:
NativeEx() : m_ref(gcnew R()){}
void DoF()
{ m_ref->F(); }
};

  下面让我们看相反的情形:一个CLIcȝ本机成员?br>
ref class Managed
{
private:
Native* m_nat;
public:
Managed():m_nat(new Native()){ }
~Managed()
{ delete m_nat; }
!Managed()
{ delete m_nat;
#ifdef _DEBUG
throw gcnew Exception("Oh, finalizer got called!");
#endif
}
void DoF()
{ m_nat->DoF(); }
};

  我不能定义一个Native对象来作Z个refcL员,因此需要用一个Native*对象来代ѝ我在构造器中new该Native对象Q然后在析构器和finalizer中delete它。如果你q行该工E的调试版,在执行到finalizer时将抛出一个异? 因此开发者可以马上添加一个对delete的调用或Z的CLIcd使用栈语义技术。奇怪的是,库开发小l没有徏立一个gcroot的反向实?但这不是个大问题Q我们可以自己写?br>
template<typename T> ref class nativeroot
{
T* m_t;
public:
nativeroot():m_t(new T){}
nativeroot(T* t):m_t(t){}
T* operator->()
{ return m_t; }
protected:
~nativeroot()
{ delete m_t; }
!nativeroot()
{
delete m_t;
#ifdef _DEBUG
throw gcnew Exception("Uh oh, finalizer got called!");
#endif
}
};

  q仅是个相当单的灉|指针实现Q就象一个负责本机对象分?回收的refcR不怎样Q借助nativeroot模板c,我们可以如下修改托管c:

ref class ManagedEx
{
private:
nativeroot<Native> m_nat;
public:
void DoF()
{ m_nat->DoF(); }
};

  好,关于混合cd的最大问题是什么呢Q你可能问。最大问题是Q现在你能؜合用你的MFC、ATL、WTL、STL代码仓库?NET框架Qƈ用可能的最直接的方?只需写你的؜合模式代码ƈ~译实现!你可以徏立在一个DLL库中建立MFC c,然后建立一?NET应用E序来调用这个DLLQ还需要把.NETcL员添加到你的MFCc(也实现可以相反的情况Q?br>
  作ؓ一例,设想你有一MFC对话?-它通过一个多行的~辑框接受来自用L数据-现在Q你有一新的要求-昄一个只ȝ辑框Q它显C当前在该多行编辑框中文本的md5哈希l果。你的队友正在悲叹他们将必须p几个时ȝcrypto APIQ而你的上司在担忧你们可能必须要买一个第三方加密库;那正是你在他们面前树立Ş象的时候,你宣布你在15分钟内做完这Q务。下面是解决的办法:

  d一个新的编辑框C的对话框资源中,q且d相应的DDX变量。选择/clr~译模式q且d下列代码C的对话框的头文g中:

#include <msclr\auto_gcroot.h>
using namespace System::Security::Cryptography;

  使用auto_gcroot模板来声明一个MD5CryptoServiceProvider成员Q?br>
protected:
msclr::auto_gcroot<MD5CryptoServiceProvider^> md5;

  在OnInitDialogq程中,gcnew MD5CryptoServiceProvider成员?br>
md5 = gcnew MD5CryptoServiceProvider();

  q且为多行编辑框d一个EN_CHANGE处理器:

void CXxxxxxDlg::OnEnChangeEdit1()
{
using namespace System;
CString str;
m_mesgedit.GetWindowText(str);
array<Byte>^ data = gcnew array<Byte>(str.GetLength());
for(int i=0; i<str.GetLength(); i++)
data[i] = static_cast<Byte>(str[i]);
array<Byte>^ hash = md5->ComputeHash(data);
CString strhash;
for each(Byte b in hash)
{
str.Format(_T("%2X "),b);
strhash += str;
}
m_md5edit.SetWindowText(strhash);
}

  q里使用了؜合类型:一个本机Cdialogzc,该类含有一个MD5CryptoServiceProvider成员(CLIcd)。你可以L地试验相反的情况Q如早期的代码片断已昄的)——可以徏立一个Windows表单应用E序而且可能惛_用一个本机类?-q不成问题,使用上面定义的模板nativeroot卛_?br>
5. 托管模板

  也许你对泛型的概念已很清楚了Q它帮助你避免进入C++的模板梦,它是实现模板的最x式,{等。好Q假设这些全部正,C++/CLI支持泛型pM其它CLI语言一?但是它有而其它一些CLI语言q没有的是它q支持托模?也就是模板化的ref和valuecR如果你以前从未使用q模板,你不能一下欣赏这么多优点Q但是如果你有模板用背景而且你已发现了泛型中存在的可能限制你~码的方式,托管模板会大大减轻你的负担。你能联合用泛型和模板- 事实上有可能用一个托类型的模板参数来实例化一个泛型类?管相反的情形是不可能的Q因行时d例化由泛型所?。STL.NET (或STL/CLR)以后讨论Q请很好地利用泛型和托管模板的؜合编E吧?br>
  泛型使用的子cdU束机制防止你写出下面的代码:

generic<typename T> T Add(T t1, T t2)
{ return t1 + t2; }

  ~译错误Q?br>
error C2676: binary ’+’ : ’T’ does not define this operator or a conversion to a type acceptable to the predefined operator

  现在L相应的模板版本:

template<typename T> T Add(T t1, T t2)
{ return t1 + t2; }

  那么可以这样做Q?br>
int x1 = 10, x2 = 20;
int xsum = Add<int>(x1, x2);

  q可以这样做Q?br>
ref class R
{
int x;
public:
R(int n):x(n){}
R^ operator+(R^ r)
{ return gcnew R(x + r->x); }
};
//...
R^ r1 = gcnew R(10);
R^ r2 = gcnew R(20);
R^ rsum = Add<R^>(r1, r2);

  q在一个象int的本机类型以及一个refcd(只要refcd有一?q算W?情况下都能工作良好。这个泛型缺点不是一个调试错误或~陷-它是设计造成的。泛型的实例化是在运行时通过调用配g集实现的Q因此编译器不能知一特定操作能被施行于一个泛型参敎ͼ除非它匹配一个子cdU束Q因此编译器在定义泛型时解决q个问题。当你用泛型时的另外一个妨是Q它不会允许你用非cd参数。下列泛型类定义不会~译Q?br>
generic<typename T, int x> ref class G{};

  ~译错:

error C2978: syntax error : expected ’typename’ or ’class’; found type ’int’; non-type parameters are not supported in generics

  与托模板相比较Q?br>
template<typename T, int x = 0> ref class R{};

  如果你开始感ȀC++向你提供了泛型和托管模板Q那么请看下面这一个例子:

template<typename T> ref class R{
public:
void F()
{ Console::WriteLine("hey"); }
};
template<> ref class R<int>
{
public:
void F()
{ Console::WriteLine("int"); }
};

  你不能用泛型q样~码Q否则,生:

  ~译错:error C2979: explicit specializations are not supported in generics

  但可以在l承链中混合使用模板和泛型:

generic<typename T> ref class Base
{
public:
void F1(T){}
};
template<typename T> ref class Derived : Base<T>
{
public:
void F2(T){}
};
//...
Derived<int> d;
d.F1(10);
d.F2(10);

  最后,你不能从一个泛型参数类型派生一个泛型类?br>
  下列代码不会成功~译Q?br>
generic<typename T> ref class R : T
{};

  error C3234: a generic class may not derive from a generic type parameter

  模板让你q样?好像你还不知道这?Q?br>
ref class Base{
public:
void F(){}
};
generic<typename T> ref class R : T
{};
//...
R<Base> r1;
r1.F();

  q样Q当你下ơ遇到对泛型的贬谤时Q你q道该怎么做了?br>
  6. STL/CLR

  当大量用STL的C++开发者{?NET1/1.1时一定感觉非常别扭,他们中的许多可能会放弃ƈ转回到原来的本机~码。从技术上Ԍ你能l合.NETcd(using gcroot)使用本机STLQ但是生的l果代码可能相当低效Q更不用说是丑陋了:

std::vector< gcroot<IntPtr> >* m_vec_hglobal;
//...
for each(gcroot<IntPtr> ptr in *m_vec_hglobal)
{ Marshal::FreeHGlobal(ptr);}

  大概VC++组考虑Cq些q决定在Whidbey以后Q他们会提供STL.NETQ或STL/CLRQƈ可以单独从网上下载?br>
  你可能问Z么?Stan LippmanQ在他的MSDN文章(STL.NET Primer)中给Z3条原因:

  ·可扩展?-STL设计把算法和容器隔离到自q应用I间-也就是你可以有一l容器和一l算法,q且你能在Q何一个容器上使用q些法Q同时你能在M一个算法中使用q些容器。因此,如果你添加一U新的算法,你能在Q何一U容器中使用它;同样Q一个新的容器也可以与现有算法配合用?br>
  ·l一?-所有核心C++开发者集中在一P汇集起他们精妙的STL专长Q再使用他们的专长则轻R熟\。要较好C用STL需要花Ҏ?然而一旦你掌握了它Q你有了在.NET世界中用你的技巧的明显优势。不是吗Q?br>
  ·性能--STL.NET通过使用实现泛型接口的托模板实现。ƈ且既然它的核心已用C++和托模板编码,可以期盼它比在BCL上用的泛型容器更具有性能优势?br>
  使用qSTL的h不需要Q何示范,所以下面代码有益于以前没有使用qSTL的h?br>
vector<String^> vecstr;
vecstr.push_back("wally");
vecstr.push_back("nish");
vecstr.push_back("smitha");
vecstr.push_back("nivi");
deque<String^> deqstr;
deqstr.push_back("wally");
deqstr.push_back("nish");
deqstr.push_back("smitha");
deqstr.push_back("nivi");

  我用了两个STL.NET容器-vector和dequeQƈ装满两个容器Q其看h相同(在两个容器中都用了push_back)。现在,我将在两个容器上使用replace法-我们再次看到Q这些代码是很相同的?br>
replace(vecstr.begin(), vecstr.end(),
gcnew String("nish"), gcnew String("jambo"));
replace(deqstr.begin(), deqstr.end(),
gcnew String("nish"), gcnew String("chris"));

  q里特别要注意的是我使用?同样"的算?-replaceq在两个不同STL容器上用相同的函数调用。这是当Stan谈及"可扩展?时的意思。下面我用一个简单函数来证明Q?br>
template<typename ForwardIterator> void Capitalize(
ForwardIterator firstQForwardIterator end)
{
for(ForwardIterator it = first; it < end; it++)
*it = (*it)->ToUpper();
}

  它遍历一个System::String^容器q把其中的每个字W串转化为大写?br>
Capitalize(vecstr.begin(), vecstr.end());
Capitalize(deqstr.begin(), deqstr.end());
for(vector<String^>::iterator it = vecstr.begin();
it < vecstr.end(); it++)
Console::WriteLine(*it);
Console::WriteLine();
for(deque<String^>::iterator it = deqstr.begin();
it < deqstr.end(); it++)
Console::WriteLine(*it);

  上面我的法能够与vector和deque容器工作良好。至此,不再l谈Q否则,guru站上的STL爱好者们会对我群h击,而非STL人可能感到厌烦。如果你q没使用qSTLQ可以参考有兌料?br>
7. 熟悉的语?br>
  开发者经常迷恋他们所用的~程语言Q而很是Z实用的目的。还记得当微软宣布不再ؓVB6提供官方支持ӞVB6人的反抗吗?非VB6人对此可能非帔R惊,而老道的VB6人早已ؓ他们的语a作好葬礼准备了。事实上Q如果VB.NET从来没被发明Q多数VB6人将会离开.NETQ因为C#会对他们非帔R生,而它的祖先就是C++。如今,许多VB.NET人可能已l{向了C#Q但是他们不会从VB6直接转向C#QVB.NET起到一个桥梁作用让他们的思想q开原来VB6思想。相应地Q如果微软仅发行VB.NET(而没有C#)Q那?NET可能成ؓ了新的面向对象VBQ且带有一个更大的cd-C++C֛的h可能Ҏ嗤之以E-他们甚至不会ȝ地检?NET基础cd。ؓ什么Q何用一U特定语a的开发者会对另外一个团体的使用另外开发语a的开发者嗤之以鼻?q不是我要回{的问题?-要回{该问题也许要先回答Z么有的h喜欢威士忌,有的人喜Ƣ可口可乐,而还有h喜欢牛奶。所有我要说的是Q对开发者来_语法家族是个大问题?br>
  你认为对于一个具有C++背景的hQ下面的代码h怎样的直觉性?

char[] arr =new char[128];

  ?她可能回{的W一件事是,Ҏh错了位置。下面这句又如何Q?br>
int y=arr.Length;

  "呀!"-最可能的反映。现在把下面与前面相比较Q?br>
char natarr[128];
array<char>^ refarr=gcnew array<char>(128);
int y=refarr->Length;

  h意声明一个本机数l和一个托数l时的语法区别。这里不同的模板形式的语法可视化地告诫开发者这一事实--refarrq不是典型的C++数组而且它可能是某种CLIcȝz?事实上确是如?Q所以极有可能可以把Ҏ和属性应用于它?br>
  C#的finalizer语法最有可能引赯{向C#的C++E序员的h。请看见下列C#代码Q?br>
class R
{ ~R(){} }

  好,q样~R看v来象一个析构器但实际是个finalizer。ؓ什么?请与下面的C++代码比较Q?br>
ref class R
{
~R(){ }
!R(){ }
};

  q里~R是析构器Q实际上{h于一个析构器的Dispose模式-但对C++人员来说Q这它的行ؓ象个析构器)而新?R语法是ؓfinalizer建立?q样׃再有h而且语法看上M与本机C++相匹配?br>
  L一下C#泛型语法Q?br>
class R<T>{};

  再请看一下C++的语法:

generic<typename T> ref class R{};

  曄使用q模板的人马上就看出q种C++语法Q而C#语法不能保证其没有؜淆性且也不直观。我的观ҎQ如果你以前hC++背景QC++/CLI语法最贴近于你以前所用。C#(以及J#)看上去象C++Q但是还有相当多的极Z人烦火的奇怪语义差别而且如果你没有完全放弃C++Q语法差别将永远不停地带l你混ؕ和挫折。从q种意义上说Q我认ؓVB.NET更好些,臛_它有自己唯一的语法,所以那些共用C++和VB.NET的h不会产生语法混ؕ?br>
  8. l论

  最后,至于你用什么语a~程Q这可能依赖许多因素——如Q你在学校学习的是什么语aQ你是用什么语a开发的现有代码仓库Q是否你的客户对你有具体的语a要求{。本文的主要目的是帮助你定使用C++/CLI的几个明的场所--q里Q它比另外CLI语言更具有明显优ѝ如果你开发的应用E序?0%的用时间是涉及本机interopQؓ何还要考虑使用另外的而不是C++Q如果你惛_发一个通用集合Qؓ什么仅把你自己限制在泛型上Q而不是结合泛型和模板的优势呢Q如果你已经用C++工作Qؓ什么还要学习一U新的语a?我常觉得象C#和VB.NETq样的语aL量向开发者隐藏CLRQ而C++不仅让你品味CLRQ甚臛_以让你去亲吻CLR! 



梦在天 2008-07-18 22:12 发表评论
]]>
CLI与C#比较http://www.shnenglu.com/mzty/archive/2008/06/02/51878.html梦在天梦在天Mon, 02 Jun 2008 06:17:00 GMThttp://www.shnenglu.com/mzty/archive/2008/06/02/51878.htmlhttp://www.shnenglu.com/mzty/comments/51878.htmlhttp://www.shnenglu.com/mzty/archive/2008/06/02/51878.html#Feedback2http://www.shnenglu.com/mzty/comments/commentRss/51878.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/51878.html来自QThe Most Powerful Language for .NET Framework Programming 

            http://msdn.microsoft.com/en-us/library/ms379617(VS.80).aspx


比较Q?br>
Description C++/CLI C#
Allocate reference type ReferenceType^ h = gcnew ReferenceType; ReferenceType h = new ReferenceType();
Allocate value type ValueType v(3, 4); ValueType v = new ValueType(3, 4);
Reference type, stack semantics ReferenceType h; N/A
Calling Dispose method ReferenceType^ h = gcnew ReferenceType;

delete h;

ReferenceType h = new ReferenceType();

((IDisposable)h).Dispose();

Implementing Dispose method ~TypeName() {} void IDisposable.Dispose() {}
Implementing Finalize method !TypeName() {} ~TypeName() {}
Boxing int^ h = 123; object h = 123;
Unboxing int^ hi = 123;

int c = *hi;

object h = 123;

int i = (int) h;

Reference type definition ref class ReferenceType {};

ref struct ReferenceType {};

class ReferenceType {}
Value type definition value class ValueType {};

value struct ValueType {};

struct ValueType {}
Using properties h.Prop = 123;

int v = h.Prop;

h.Prop = 123;

int v = h.Prop;

Property definition property String^ Name
{
    String^ get()
    {
        return m_value;
    }
    void set(String^ value)
    {
        m_value = value;
    }
}
string Name
{
    get
    {
        return m_name;
    }
    set
    {
        m_name = value;
    }
}

thanks

梦在天 2008-06-02 14:17 发表评论
]]>
CLI中native的string和System::String转化http://www.shnenglu.com/mzty/archive/2008/03/12/44280.html梦在天梦在天Wed, 12 Mar 2008 08:47:00 GMThttp://www.shnenglu.com/mzty/archive/2008/03/12/44280.htmlhttp://www.shnenglu.com/mzty/comments/44280.htmlhttp://www.shnenglu.com/mzty/archive/2008/03/12/44280.html#Feedback4http://www.shnenglu.com/mzty/comments/commentRss/44280.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/44280.html阅读全文

梦在天 2008-03-12 16:47 发表评论
]]>
C#的Form通过CLI调用C++的DLLhttp://www.shnenglu.com/mzty/archive/2007/12/25/39610.html梦在天梦在天Tue, 25 Dec 2007 11:14:00 GMThttp://www.shnenglu.com/mzty/archive/2007/12/25/39610.htmlhttp://www.shnenglu.com/mzty/comments/39610.htmlhttp://www.shnenglu.com/mzty/archive/2007/12/25/39610.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/39610.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/39610.html阅读全文

梦在天 2007-12-25 19:14 发表评论
]]>
NativeC++通过CLI调用C#的Formhttp://www.shnenglu.com/mzty/archive/2007/12/25/39555.html梦在天梦在天Tue, 25 Dec 2007 02:51:00 GMThttp://www.shnenglu.com/mzty/archive/2007/12/25/39555.htmlhttp://www.shnenglu.com/mzty/comments/39555.htmlhttp://www.shnenglu.com/mzty/archive/2007/12/25/39555.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/39555.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/39555.html一 调用Ҏ

      Native C++的project调用C#的DLLQ一般有3中方法:
      1Q通过COM装
      2Q通过CLI/C++的Wrapper
      3)  在VS中可以直接修改NativeC++的project或是部分文gZ用CLR来调用C#的DLL

?实例
1QC#的一个MyFormc,有public函数ShowMyFormQ)
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace CsharpDLL
{
    
public class MyForm : Form
    
{
        
private Button button1;

        
public void ShowMyForm()
        
{
            
this.ShowDialog();
        }

        
public MyForm()
        
{
            InitializeComponent();
            
this.Text = "MyForm";
            
this.StartPosition = FormStartPosition.CenterScreen;
        }

        
private void InitializeComponent()
        
{
            
this.button1 = new System.Windows.Forms.Button();
            
this.SuspendLayout();
            
// 
            
// button1
            
// 
            this.button1.Location = new System.Drawing.Point(11074);
            
this.button1.Name = "button1";
            
this.button1.Size = new System.Drawing.Size(7523);
            
this.button1.TabIndex = 0;
            
this.button1.Text = "TestMessageBox";
            
this.button1.UseVisualStyleBackColor = true;
            
this.button1.Click += new System.EventHandler(this.button1_Click);
            
// 
            
// MyForm
            
// 
            this.ClientSize = new System.Drawing.Size(292266);
            
this.Controls.Add(this.button1);
            
this.Name = "MyForm";
            
this.ResumeLayout(false);

        }


        
private void button1_Click(object sender, EventArgs e)
        
{
            MessageBox.Show(
"Hello, i am a Csharp Form!");
        }

    }

}


2QC#的exe调用
using System;
using System.Collections.Generic;
using System.Text;

namespace CsharpTest
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            System.Console.WriteLine(
"Csharp main funtion start:");
            CsharpDLL.MyForm myForm 
= new CsharpDLL.MyForm();
            myForm.ShowMyForm();
            System.Console.WriteLine(
"Csharp main function end!");
        }

    }

}


3QCLI/C++的warpperQDLLexport函数CallCsharpFormQ)Q此函数中调用C#的MyForm
CPPCLIPROXYDLLFORCSHARPDLL_API void CallCsharpForm();

#
using "../debug/CsharpDll.dll"

CPPCLIPROXYDLLFORCSHARPDLL_API 
void CallCsharpForm()
{
    CsharpDLL::MyForm
^ myForm = gcnew CsharpDLL::MyForm();
    myForm
->ShowMyForm();
}

4QNativeC++的exe调用CLI的Wrapper来间接的调用MyForm
#include "stdafx.h"
#include 
<iostream>
#pragma comment(lib, 
"../debug/CppCLIProxyDLLForCsharpDLL.lib")

void CallCsharpForm();

int _tmain(int argc, _TCHAR* argv[])
{
    std::cout
<<" Cpp Main function start:"<<std::endl;
    CallCsharpForm();
    std::cout
<<" Cpp Main function end!"<<std::endl;
    
return 0;
}


要调试最好修改编译选项为Mixed?br>
代码下蝲Q?http://www.shnenglu.com/Files/mzty/CppCallCsharpByCLI.rar


梦在天 2007-12-25 10:51 发表评论
]]>
CLI/C++中؜合类的?/title><link>http://www.shnenglu.com/mzty/archive/2007/12/24/39517.html</link><dc:creator>梦在天</dc:creator><author>梦在天</author><pubDate>Mon, 24 Dec 2007 09:47:00 GMT</pubDate><guid>http://www.shnenglu.com/mzty/archive/2007/12/24/39517.html</guid><wfw:comment>http://www.shnenglu.com/mzty/comments/39517.html</wfw:comment><comments>http://www.shnenglu.com/mzty/archive/2007/12/24/39517.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/mzty/comments/commentRss/39517.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/mzty/services/trackbacks/39517.html</trackback:ping><description><![CDATA[     摘要: 一 混合cL谓؜合类是指CLI/C++中native的Class中可以包含CLR对象QCLR的class也可以包含Naitve的对象?1Qnative的class中包含CLR对象Q必通过gcroot<>或auto_gcroot<>?QCLR中的class中包含native的对象,必须是指针,也可以用高手写的CAutoNativePtr指针?注意QC#中不?..  <a href='http://www.shnenglu.com/mzty/archive/2007/12/24/39517.html'>阅读全文</a><img src ="http://www.shnenglu.com/mzty/aggbug/39517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/mzty/" target="_blank">梦在天</a> 2007-12-24 17:47 <a href="http://www.shnenglu.com/mzty/archive/2007/12/24/39517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个CLI/C++的DLL同时被C#的exe和NativeC++的exe调用http://www.shnenglu.com/mzty/archive/2007/12/20/39165.html梦在天梦在天Thu, 20 Dec 2007 14:47:00 GMThttp://www.shnenglu.com/mzty/archive/2007/12/20/39165.htmlhttp://www.shnenglu.com/mzty/comments/39165.htmlhttp://www.shnenglu.com/mzty/archive/2007/12/20/39165.html#Feedback4http://www.shnenglu.com/mzty/comments/commentRss/39165.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/39165.html 一 引子

      1Q用VS2005QNative C++QC#QCLI/C++?br>      2Q主要介lCLI/C++和Native C++, C#的交互,最总能够实CCLI/C++Z介的Native C++与C#的互调?br>
 ?实例
      
      1Q实C个CLI/C++的DllQ在此Dll中包含一个RefClass能够被C#的exe调用。(实现q程Q在VS中徏立C++ CLR Class library 的一个ProjectQ然后增加一个类RefClassQ代码如下:

      refclass.h文gQ?br>      
#pragma once 

namespace ClrCppDll 
{
    
public ref class RefClass
    
{
    
public:
        RefClass()
{}
        RefClass(
int _x, int _y) : x(_x), y(_y)
        
{
        }

        
void PrintSelf();
    
    
private:
        
int x;
        
int y;
    }
;
}

      refclass.cpp文gQ?br>
#include "stdafx.h"
#include 
"refclass.h"

using namespace System;
using namespace ClrCppDll;

void RefClass::PrintSelf()
{
    System::Console::WriteLine(
"hello, i am a ref cpp class");
    System::Console::WriteLine(
"x is {0}",x);
    System::Console::WriteLine(
"y is {0}",y);
}

      2Q能够调用上面第1Q步中的CLI/C++的Dll中class的C#的exe。(实现q程Q在VS建立C#的console ApplicationQ然后reference 前面?)生成的DllQ代码如下:

         Program.cs文gQ?br>
using System;
using System.Collections.Generic;
using System.Text;

namespace CsharpTest
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            ClrCppDll.RefClass refClass 
= new ClrCppDll.RefClass(2,4);
            refClass.PrintSelf();
        }

    }

}

            上面2步的代码下蝲Q?a href="http://www.shnenglu.com/Files/mzty/CSharpCPPCLI1.rar">http://www.shnenglu.com/Files/mzty/CSharpCPPCLI1.rar Q实现CLI/C++的dll能够被C#调用Q?br>


     3Q对1Q实现的CLI/C++的Dll中增加能够被Native C++调用的NativeClass。代码如下:

      NativeClass.h文gQ?br>
#pragma once

namespace ClrCppDll
{
    
public class NativeClass
    
{        
        
public:
            NativeClass()
{}
            NativeClass(
int _x, int _y) : x(_x), y(_y)
            
{}

            
void printSelf();

        
private:
            
int x;
            
int y;    
    }
;
}

      NativeClass.cpp文gQ?br>
#include "stdafx.h"
#include 
<iostream>
#include 
"nativeclass.h"

using namespace ClrCppDll;

void NativeClass::printSelf()
{
    std::cout
<<"hello,i am a native cpp class!"<<std::endl;
    std::cout
<<"x is "<<x<<std::endl;
    std::cout
<<"y is "<<y<<std::endl;                
}


      问题Q?/span> 如果我们直接在NativeC++的exe调用上面CLI/C++中的NativeClassQ会有问题,Error 1 error C3381: 'CppClrDll::NativeClass' : assembly access specifiers are only available in code compiled with a /clr option d:\cppandcsharpinteractivetest\csharpcppcli\clrcppdll\nativeclass.h 8Q这是ؓ什么那Q我们想x们一般的Native C++的DLL的调用,都要要被调用的Class或funtion导出才可以调用,惛_q里我们也对我们的NativeClassq行导出。(怎么导出可以看下面的代码Q但是当增加了对NativeClass的导出,调用的时候仍然有上面的errorQError 1 error C3381: 'CppClrDll::NativeClass' : assembly access specifiers are only available in code compiled with a /clr option d:\cppandcsharpinteractivetest\csharpcppcli\clrcppdll\nativeclass.h 9Q最后只有查找资料(没有扑ֈQ问别hQ没有问刎ͼQ最后想C用导出函数试试,一试果然可行啊Q哈哈哈Qso HappyQ?span style="COLOR: #00ccff">其实后来发现是我加的导出__declspec(dllexport)的位|不对,应该是在class关键字后面,M导出cM是可以的?/span>导出cȝ代码可以下蝲新的sampleQ增加导出和导出的函C码如下:

      (导出不久需要下面的2文gQ还的定义宏 CLR_CPP_DLL在编译选项中,或直接写在文件中)
      clrcppdll.h
// ClrCppDll.h

#pragma once

#ifdef CLR_CPP_DLL
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP
#endif

namespace ClrCppDll 
{
    DLLIMPEXP 
void  CallNativeClassPrintSelf();    
}

      clrcppdll.cpp文gQ?br>
// This is the main DLL file.

#include 
"stdafx.h"
#include 
"NativeClass.h"
#include 
"ClrCppDll.h"

DLLIMPEXP 
void  ClrCppDll::CallNativeClassPrintSelf()
{
    ClrCppDll::NativeClass test(
10,20);
    test.printSelf();
}

      4Q徏立一个NativeC++的exe来调?Q生成的CLI/C++的Dll中的3Q增加的NativeClassQ实现过E:建立一个Native C++的console applicationQ代码如下:

       cpptest.cpp文gQ(l过上一步问题的反复折磨Q终于搞定)Q同时别忘了要在~译选项中指定lib和lib的\径)
// CppTest.cpp : Defines the entry point for the console application.
//

#include 
"stdafx.h"
#include 
"../ClrCppDll/clrcppdll.h"

int _tmain(int argc, _TCHAR* argv[])
{
    
/*ClrCppDll::NativeClass test(5,6);
    test.PrintSelf();
*/


    ClrCppDll::CallNativeClassPrintSelf();
    
return 0;
}


   上面四步M码下载:http://www.shnenglu.com/Files/mzty/CSharpCPPCLI2.rar Q实现CLI/C++的dll同时被Native C++和C#的调用)

      5Q扩展,增加在NativeClass中调用RefClass的funtion, 和RefClass中调用NativeClass的function?br>
      代码下蝲Q?a href="http://www.shnenglu.com/Files/mzty/CSharpCPPCLI3.rar">http://www.shnenglu.com/Files/mzty/CSharpCPPCLI3.rar Q最后代码下载,包含NativeClass与RefClass的互调)
                           http://www.shnenglu.com/Files/mzty/CSharpCPPCLI32.zip Q包含native class的导Z调用Q?br>

      ?ȝ

      1) CLI/C++中如果想导出让NativeC++使用Q则最好导出函?也可以导出类?br>      2) CLI/C++的DLL可以没有像一般的NativeC++的Dll中的DllMainQ)函数?br>      3) CLI/C++如果惛_C#使用Q则一般是ref class?br>








梦在天 2007-12-20 22:47 发表评论
]]>
C#通过C++/CLI调用C++DLLhttp://www.shnenglu.com/mzty/archive/2007/06/04/25524.html梦在天梦在天Mon, 04 Jun 2007 14:59:00 GMThttp://www.shnenglu.com/mzty/archive/2007/06/04/25524.htmlhttp://www.shnenglu.com/mzty/comments/25524.htmlhttp://www.shnenglu.com/mzty/archive/2007/06/04/25524.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/25524.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/25524.html只要你会C++/CLI比较容易哦Q或者说只要你会C++和C#学v来也是很快的哦!?br>


大家可以先参考,以后有时间加再写哦~


参考:http://www.codeproject.com/csharp/marshalCPPclass.asp




梦在天 2007-06-04 22:59 发表评论
]]>
C++?NET中基cd的对应及转化http://www.shnenglu.com/mzty/archive/2007/05/29/25062.html梦在天梦在天Tue, 29 May 2007 05:55:00 GMThttp://www.shnenglu.com/mzty/archive/2007/05/29/25062.htmlhttp://www.shnenglu.com/mzty/comments/25062.htmlhttp://www.shnenglu.com/mzty/archive/2007/05/29/25062.html#Feedback3http://www.shnenglu.com/mzty/comments/commentRss/25062.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/25062.html阅读全文

梦在天 2007-05-29 13:55 发表评论
]]>
C++/CLIhttp://www.shnenglu.com/mzty/archive/2007/05/29/25059.html梦在天梦在天Tue, 29 May 2007 05:38:00 GMThttp://www.shnenglu.com/mzty/archive/2007/05/29/25059.htmlhttp://www.shnenglu.com/mzty/comments/25059.htmlhttp://www.shnenglu.com/mzty/archive/2007/05/29/25059.html#Feedback1http://www.shnenglu.com/mzty/comments/commentRss/25059.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/25059.html阅读全文

梦在天 2007-05-29 13:38 发表评论
]]>
C#界面QC++法http://www.shnenglu.com/mzty/archive/2007/04/16/22064.html梦在天梦在天Mon, 16 Apr 2007 14:41:00 GMThttp://www.shnenglu.com/mzty/archive/2007/04/16/22064.htmlhttp://www.shnenglu.com/mzty/comments/22064.htmlhttp://www.shnenglu.com/mzty/archive/2007/04/16/22064.html#Feedback16http://www.shnenglu.com/mzty/comments/commentRss/22064.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/22064.html阅读全文

梦在天 2007-04-16 22:41 发表评论
]]>
Managed c++与c++\CLI的区?实例)http://www.shnenglu.com/mzty/archive/2006/08/18/11397.html梦在天梦在天Fri, 18 Aug 2006 02:58:00 GMThttp://www.shnenglu.com/mzty/archive/2006/08/18/11397.htmlhttp://www.shnenglu.com/mzty/comments/11397.htmlhttp://www.shnenglu.com/mzty/archive/2006/08/18/11397.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/11397.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/11397.html阅读全文

梦在天 2006-08-18 10:58 发表评论
]]>
Visual C++ .NET~程Q托C++概述http://www.shnenglu.com/mzty/archive/2006/08/18/11393.html梦在天梦在天Fri, 18 Aug 2006 02:18:00 GMThttp://www.shnenglu.com/mzty/archive/2006/08/18/11393.htmlhttp://www.shnenglu.com/mzty/comments/11393.htmlhttp://www.shnenglu.com/mzty/archive/2006/08/18/11393.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/11393.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/11393.html
  Microsoft?NET战略意味着QMicrosoft以及在Microsoftq_上的开发者将会制造服务,而不是制造Y件。在未来几年之内QMicrosoft陆l发布有?NET的^台和工具Q用于在因特|上开发Web服务。那Ӟ工作?NET上的用户、开发h员和IT工作人员都不再购买Y件、安装Y件和l护软g。取而代之的是,他们定制服务,软g会自动安装,所有的l护和升U也会通过互联|进行。“Microsoft.NET 代表了一个集合、一个环境、一个可以作为^台支持下一代Internet的可~程l构。”这是鲍尔默对.NET的描q?br />

  作ؓ.NET的最新特性组成部分,Microsoft .NET Framework是一个用于构建,部v和运行Web服务及应用程序的q_。它为将现有投资与下一代应用程序和服务的集成提供了高的,Z标准的,多语a环境Q同时它q用于解决InternetU应用程序的部v和操作问题?NET框架包含三个主要部分Q通用语言q行Ӟ一l层ơ化的统一的类库,及组件化版本的动态服务器主页(UCؓASP.NET)?br />
  用于开?NET Framework的语a有Visual C#、VB.NET和C++托管扩展(Managed Extensions for C++)。其中C#是开?NET的元语言Q而C++托管扩展是在C++基础上徏立v来的Q用来ؓVisual C++E序员开?NET框架应用E序而设计。ؓ叙述方便Q我们将C++托管扩展q之ؓ“托C++”?br />Z帮助C/C++以及Visual C++E序员或爱好者快速用托C++开?NET FrameworkE序Q我们将陆箋推出相关的一pd文章?br />
  本篇“托C++概述”主要讲qC什么是托管C++、开?NET Framework(框架)的项目类型以及与标准C++之间的区别?br />
  1、什么是托管C++Q?/font>

  在回{这个问题,首先要搞清楚什么是“托?Managed)。托是.NET的一个专门概念,它是融于通用语言q行?CLR)中的一U新的编E理念,因此我们完全可以把“托”视为?NET”。那么什么是“通用语言q行时”?通用语言q行时是.NET 框架应用E序的执行引挚。它提供了许多服务,其中包括Q代码管?装入和执?、类型安全性验证、元数据(高cd信息)讉K、ؓ理对象理内存、管理代码,COM对象和预生成的DLLs(非管理代码和数据)的交互操作性、对开发h员服务的支持{等?br />
  也就是说Q用托C++意味着Q我们的代码可以被CLR所理Qƈ能开发出h最新特性如垃圾自动攉、程序间怺讉K{的.NET框架应用E序?br />
  由托概忉|引发的C++应用E序包括托管代码、托数据和托管cM个组成部分。  

  (1) 托管代码Q?Net环境提供了许多核心的q行(RUNTIME)服务Q比如异常处理和安全{略。ؓ了能使用q些服务Q必要l运行环境提供一些信息代?元数?Q这U代码就是托代码。所有的C#、VB.NET、JScript.NET默认旉是托的Q但Visual C++默认时不是托的Q必d~译器中使用命o行选项(/CLR)才能产生托管代码?br />
  (2) 托管数据Q与托管代码密切相关的是托管数据。托数据是由公paq行的垃圑֛收器q行分配和释攄数据。默认情况下QC#、Visual Basic ?JScript.NET 数据是托数据。不q,通过使用Ҏ的关键字QC# 数据可以被标Cؓ非托数据。Visual C++数据在默认情况下是非托管数据Q即使在使用 /CLR 开x也不是托的?br />
  (3) 托管c?/b>Q尽Visual C++数据在默认情况下是非托管数据Q但是在使用C++的托扩展时Q可以用“__gc”关键字类标记为托类。就像该名称所昄的那P它表C类实例的内存由垃圾回收器管理。另外,一个托类也完全可以成?.NET 框架的成员,由此可以带来的好处是Q它可以与其他语a~写的类正确地进行相互操作,如托的C++cd以从Visual Basiccȝ承等。但同时也有一些限Ӟ如托类只能从一个基cȝ承等。需要说明的是,在托C++应用E序中既可用托类也可以用非托管cR这里的非托类不是指标准C++c,而是使用托管C++语言中的__nogc关键字的cR?br />
2、用托管C++可以开?NET框架的项目类?br />
  使用托管C++应该是C++E序员编?NET框架应用E序最好的一U选择Q通过集成在Visual Studio.NET开发环境的托管C++向导Q我们可以创Z下几U开?NET框架的项目类型:

  (1) 托管C++应用E序:用来创徏一个支持托扩展的单独C++应用E序Q用它q可创徏Mcd的应用程序,包括.NET框架客户应用E序?br />
  (2) 托管C++cd:用来创徏一个支持托扩展的C++DLLQ用它可以生成一个能?NET框架应用E序调用的托类型的lg?br />
  (3) 托管C++I项目:用来创徏一个空的托项目,该项目只含有支持托管扩展的正编译和链接的开关选项。用它能将一个已有的C++源文件进入到一个托环境中?br />
  (4) 托管C++ Web服务Q用于创Z个项目,一个是C++托管扩展目Q另一个是部v目?br />
  3、托C++与标准C++的主要区?/font>

  管托管C++是从标准C++建立而来的,但它与标准C++有着本质上的区别Q这主要体现在以下几个方面:

  (1) q泛采用“名U空间?namespace)

  名称I间是类型的一U逻辑命名ҎQ?NET使用该命名方案用于将cd按相兛_能的逻辑cdq行分组Q利用名U空间可以开发h员更Ҏ在代码中览和引用类型。当Ӟ我们也可名U空间理解成是一个“类库名”?

  管很早Microsoft在Visual C++中支持名U空间的~程方式Q但是很引起Visual C++E序员的普遍x。现在在托管C++E序中,我们必须使用q一方式Q即使用#using和using关键字。例如下面的单程序代码是在控制台上输出“Hello World”:

#using
using namespace System;
int main(void)
{
Console::WriteLine(S"Hello World");
return 0;
}

  代码中,#using是用来将一个元数据文g输入到托C++E序中,q些文g可以是包含托数据和l构的MSIL (Microsoft intermediate languageQ微软中间语a)文gQ如DLL、EXE、OBJ文g{。mscorlib.dll?NET框架的一个核心类库,包含主要的名U空间System。程序的W二行代码“using namespace System;”用来用System名称I间。System?NET框架根名U空_包含最基本的类型,如用于数据流的输?输出的System::IO{?br />
  在对托管C++E序开发的不断深入Q我们不久就会发玎ͼ许多cd的引用都要在E序的前面?using和using来进行?br />
  (2) 基本数据cd的变?/b>

  我们知道Q标准C++语言的数据类型是非常丰富的。而托C++的数据类型更加丰富,不仅包含了标准C++中的数据cdQ而且新增了__int64(64位整?、Decimal(96位十q制?、String*(字符串类?和Object*(对象cd){类型,?-1列出它们各自数据cd?br />
cd描述标准C++cd?/td>托管C++cd?/td>长度(?
布尔?/td>boolbool8
字符?/td>charsigned char8
无符号字W型unsigned charchar8
短整?/td>short [int]short16
无符L整型unsigned short [int]unsigned short16
整型intint ?long32
无符h?/td>unsigned [int]unsigned int ?long32
长整?/td>long [int]long32
无符号长整型unsigned long [int]unsigned long32
单精度Q点型floatfloat32
双精度Q点型doubledouble64
长双_ֺ点?/td>long double--64
Unicode字符--wchar_t16
64位整?/td>--__int6464
无符?4位整?/td>--unsigned __int6464
96位十q制?/td>--Decimal96
对象cd--Object*32
字符串类?/td>--String*--


  需要注意的是,String和Object在定义一个变量时Q注意要有星???Q但q个变量不是指针变量Q这与标准C++的含义是不一L。例如上面的代码可以改ؓQ?br />
#using
using namespace System;
int main(void)
{
String* hello = S"Hello World";
Console::WriteLine(hello);
return 0;
}
 (3) 新增三个托管C++cdQ__gc class、__value class和__gc interface

  一个__gccLl构意味着该类或结构的生命周期是由.NET开发^台自动管理及垃圾自动攉Q用户不必自已去调用delete来删除。定义一个__gccLl构和标准C++基本怼Q所不同的是在class或struct前加上__gcQ例如下面的代码Q?br />
__gc class G {
public:
int k;
int sum(int);
};

G::sum(int i) {return i*(i + 1)/2;}
int main()
{
G * g = new G;
Console::WriteLine(g->sum(4)); // l果输出10
return 0;
}

  但要注意Q?/font>

  A. 一个__gccM能从一个非托管cMl承Q且不能包含从它z的非托管cR但一个__gccL多可以从一个托类中ѝ?br />
  B. 一个__gccM能定义成一个友元类或包含一个友元成员函数。所谓友元函敎ͼ是用来让外部函数讉KcM的私有和保护cd成员?br />
  C. 一个__gccM能声明或定义以及重蝲new或delete操作以及不能包含using{声明?br />
  __valuecL用来使用h短生命期的小型数据项Q它不同于__gccR__gccL据分配在CLR堆中Q而__valuecd象是在运行栈或称为NDP(.NET Developer PlatformQ?NET开发者^?堆中创徏的,从而避免了垃圾回收器不断分配和释放I间而带来的开销。一个__valuecd以声明成Z个局部变量、参数和q回|也可嵌入C个__gccM或是作ؓ一个静态变量或在C++堆中分配的变量。例如下面的代码Q?br />
#using
using namespace System;
__value struct V { int i; };
__gc struct G { V v; }; // 嵌入到__gccM
V f(V v) { // 定义一个全局函数Q其值存储在q行栈中
v.i += 1; // 不媄响原来Ş参v的?br />return v; // q回Vl构cd的?br />}
int main(void)
{
V v1 = {10}; // 在运行栈中声明ƈ初始?br />V v2 = f(v1); // 调用f函数Q此时v1中的i?0Q而v2中的i?1
G *pG = new G; // 为G实例分配堆空?br />pG->v = v1; // pG的v中的i?0
pG->v.i += v2.i; // pG的v中的i?0+11=21
Console::WriteLine(v1.i); // 输出l果?0
Console::WriteLine(v2.i); // 输出l果?1
Console::WriteLine(pG->v.i); // 输出l果?1
return 0;
}

  除此之外Q所有的__gc对象都是从类System::Objectz而来Q因而能够很Ҏ使用作用在__gccM的集合和映射功能。然而__valuecdq没有与q个基类所׃nQ因而不能直接将__value作ؓ函数中的Object*实参。ؓ了解册个问题,.NET允许我们使用__box关键字将一个__valuecd视ؓ一个__gc对象。此时__valuecd被封装成一个__gccL?Stub)Qƈ被复制到NDP堆中。由于在托管C++中,box不具备隐式{换的功能Q因此在转换时必L明{换的cd?br />
  托管C++中的__gc接口最能体现COM接口的思想Q它的定义和声明是非常简单的Q它除了关键字不同外Q与一个__gccȝ声明极ؓ怼。例如下面的代码定义了一个接口IMyBaseQ其中包含了一个f的方法:

__gc __interface Ibase {
void f();
};

  需要说明的是,接口中所有的Ҏ默认旉是纯虚的且都是公有的Q我们不需要在Ҏ之前使用virtual关键字或在方法之后加上? 0”。其ơ,在一个__gc接口中不能包含数据成员以及静态成员,也不能包含Q何类的声明。下面D一个示例来说明__gc接口的用:

#using
using namespace System;

__gc __interface Ibase1 {
int f(int);
};
__gc __interface Ibase2 {
int f(int);
};
__gc struct C: Ibase1, Ibase2 {
int f(int i) { // 接口Ҏ的实?br />return 2*i-1;
};
};

int main(void){
C* c = new C;
Console::WriteLine((c -> f(1)).ToString()); // 输出l果?
Console::WriteLine((__try_cast (c)->f(2)).ToString());
// 输出l果?

Console::WriteLine((__try_cast (c)->f(3)).ToString());
// 输出l果?

return 0;
}

  代码中,__try_cast用来某个对象{换成一个指定类型,q当cd转换p|时自动处理由此生的异常。ToString用来对象描q成一个字W串?br />(4) 化属性操?br />
  在__gccM可以使用.NET的属性,q个属性简化了属性函数的调用操作Q这与标准C++中的属性不一栗在标准C++中分别通过get_和put_成员函数来设|或获取相关属性的倹{现在,托管C++中的属性操作就好比是对一个属性变量进行操作,例如下列代码Q?br />
#using
using namespace System;

__gc class G {
public:
__property int get_Size() {
Console::WriteLine(S"get_属?);
return nSize;
};
__property void set_Size(int i) {
Console::WriteLine(S"set_属?);
nSize = i;
};
private:
int nSize;
};

int main() {
G * pG = new G;
pG->Size = 10; // 调用set_Size
int i = pG->Size; // 调用get_Size
Console::WriteLine(i);
}

  E序l果为:

   set_属?br />
   get_属?br />
   10

  需要说明的是,托管C++使用__property关键字来定义一个属性的成员函数。从代码中可以看|和获取属性的成员函数名称中分别用了set_和get_Q这L译器会自动生成一个伪成员变量SizeQ这个变量名是set_和get_成员函数后面的名U。注意不要再在get_成员函数代码中用这个伪成员变量SizeQ它会引赯函数的递归调用?br />
  (5) 托管C++的委z?/b>

  在C/C++中,一个函数的地址是内存地址。这个地址不会带有M其它附加信息Q如函数的参C数、参数类型、函数的q回值类型以及这个函数的调用规范{。MQC/C++的回调函C具备cd安全性。?NET框架在回调函数的基础增加了提供类型安全的机制Q称为委z?br />
  托管C++的委z方法不像C#那么复杂Q它化了委派l大部分的内部机Ӟ因而得它的用变成非常简单容易。例如下面的代码Q?br />
#using
using namespace System;

__delegate int GetDayOfWeek(); // 委派Ҏ的声?br />__gc class MyCalendar
{
public:
MyCalendar() : m_nDayOfWeek(4) {}
int MyGetDayOfWeek() {
Console::WriteLine("非静态方?);
return m_nDayOfWeek;
}
static int MyStaticGetDayOfWeek() {
Console::WriteLine("静态方?);
return 6;
}
private:
int m_nDayOfWeek;
};

int main(void)
{
GetDayOfWeek * pGetDayOfWeek; // 声明委派cd变量
int nDayOfWeek;

// 类的静态方法MyStaticGetDayOfWeekl定成委z?br />pGetDayOfWeek = new GetDayOfWeek(0, &MyCalendar::MyStaticGetDayOfWeek);
nDayOfWeek = pGetDayOfWeek->Invoke(); // 委派的调?br />Console::WriteLine(nDayOfWeek);

// 一个类的实例绑定成委派
MyCalendar * pcal = new MyCalendar();
pGetDayOfWeek =
static_cast(Delegate::Combine(pGetDayOfWeek,
new GetDayOfWeek(pcal, &MyCalendar::MyGetDayOfWeek)));
nDayOfWeek = pGetDayOfWeek->Invoke();
Console::WriteLine(nDayOfWeek);

// 删除l定委派的类实例
pGetDayOfWeek =
static_cast(Delegate::Remove(pGetDayOfWeek,
new GetDayOfWeek(pcal, &MyCalendar::MyGetDayOfWeek)));

return 0;
}

  输出l果是:

   静态方?br />  
   6

   静态方?br />
   非静态方?br />
   4

  4、结速语

  MQ用托C++是C++E序员编?NET框架应用E序最好的一U选择Q在充分理解.NET框架基础上,避免了用其他语a如C#、VB.NET所带来的额外开销?br />

梦在天 2006-08-18 10:18 发表评论
]]>
c++\CLI与c#http://www.shnenglu.com/mzty/archive/2006/08/17/11358.html梦在天梦在天Thu, 17 Aug 2006 08:46:00 GMThttp://www.shnenglu.com/mzty/archive/2006/08/17/11358.htmlhttp://www.shnenglu.com/mzty/comments/11358.htmlhttp://www.shnenglu.com/mzty/archive/2006/08/17/11358.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/11358.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/11358.html Description C++/CLI C# Allocate reference type ReferenceType^ h = gcnew ReferenceType; ReferenceType h = new ReferenceType(); Allocate value type ValueType v(3, 4); ValueType v = new ValueType(3, 4); Reference type, stack semantics ReferenceType h; N/A Calling Dispose method ReferenceType^ h = gcnew ReferenceType;

delete h;

ReferenceType h = new ReferenceType();

((IDisposable)h).Dispose();

Implementing Dispose method ~TypeName() {} void IDisposable.Dispose() {} Implementing Finalize method !TypeName() {} ~TypeName() {} Boxing int^ h = 123; object h = 123; Unboxing int^ hi = 123;

int c = *hi;

object h = 123;

int i = (int) h;

Reference type definition ref class ReferenceType {};

ref struct ReferenceType {};

class ReferenceType {} Value type definition value class ValueType {};

value struct ValueType {};

struct ValueType {} Using properties h.Prop = 123;

int v = h.Prop;

h.Prop = 123;

int v = h.Prop;

Property definition property String^ Name
{
    String^ get()
    {
        return m_value;
    }
    void set(String^ value)
    {
        m_value = value;
    }
}
string Name
{
    get
    {
        return m_name;
    }
    set
    {
        m_name = value;
    }


梦在天 2006-08-17 16:46 发表评论
]]>
Native c++ 和Managed ?interophttp://www.shnenglu.com/mzty/archive/2006/08/17/11354.html梦在天梦在天Thu, 17 Aug 2006 08:26:00 GMThttp://www.shnenglu.com/mzty/archive/2006/08/17/11354.htmlhttp://www.shnenglu.com/mzty/comments/11354.htmlhttp://www.shnenglu.com/mzty/archive/2006/08/17/11354.html#Feedback5http://www.shnenglu.com/mzty/comments/commentRss/11354.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/11354.html4U方?

There are four main ways to do interop in .NET between the managed and native worlds. COM interop can be accomplished using Runtime Callable Wrappers (RCW) and COM Callable Wrappers (CCW). The common language runtime (CLR) is responsible for type marshaling (except in the rare scenarios where a custom marshaler is used) and the cost of these calls can be expensive. You need to be careful that the interfaces are not too chatty; otherwise a large performance penalty could result. You also need to ensure that the wrappers are kept up to date with the underlying component. That said, COM interop is very useful for simple interop scenarios where you are attempting to bring in a large amount of native COM code.

The second option for interop is to use P/Invoke. This is accomplished using the DllImport attribute, specifying the attribute on the method declaration for the function you want to import. Marshaling is handled according to how it has been specified in the declaration. However, DllImport is only useful if you have code that exposes the required functions through a DLL export.

When you need to call managed code from native code, CLR hosting is an option. In such a scenario, the native application has to drive all of the execution: setting up the host, binding to the runtime, starting the host, retrieving the appropriate AppDomain, setting up the invocation context, locating the desired assembly and class, and invoking the operation on the desired class. This is definitely one of the most robust solutions in terms of control over what and when things happen, but it is also incredibly tedious and requires a lot of custom code.

The fourth option, and quite possibly the easiest and the most performant, is to use the interop capabilities in C++. By throwing the /clr switch, the compiler generates MSIL instead of native machine code. The only code that is generated as native machine code is code that just can't be compiled to MSIL, including functions with inline asm blocks and operations that use CPU-specific intrinsics such as Streaming SIMD Extensions (SSE). The /clr switch is how the Quake II port to .NET was accomplished. The Vertigo software team spent a day porting the original C code for the game to code that successfully compiled as C++ and then threw the /clr switch. In no time they were up and running on the .NET Framework. Without adding any additional binaries and simply by including the appropriate header files, managed C++ and native C++ can call each other without any additional work on the part of the developer. The compiler handles the creation of the appropriate thunks to go back and forth between the two worlds.



梦在天 2006-08-17 16:26 发表评论
]]>
Visual C++ ~译器选项http://www.shnenglu.com/mzty/archive/2006/08/17/11336.html梦在天梦在天Thu, 17 Aug 2006 04:16:00 GMThttp://www.shnenglu.com/mzty/archive/2006/08/17/11336.htmlhttp://www.shnenglu.com/mzty/comments/11336.htmlhttp://www.shnenglu.com/mzty/archive/2006/08/17/11336.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/11336.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/11336.html 来自msdn:http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/vccore/html/_core_compiler_options_listed_by_category.asp

优化

/O1 创徏代?/td>
/O2 创徏快速代?/td>
/Oa 假设没有别名
/Ob 控制内联展开
/Od 用优化
/Og 使用全局优化
/Oi 生成内部函数
/Op 改善点C致?/td>
/Os 代码大小优先
/Ot 代码速度优先
/Ow 假定在函数调用中使用别名
/Ox 使用最大优?(/Ob2gity /Gs)
/Oy 省略框架指针

代码生成

/arch 使用 SSE ?SSE2 指o生成代码
/clr 启用 C++ 的托扩展ƈ产生在公paq行库上q行的输出文?/td>
/EH 指定异常处理模型
/G3 优化代码以优?386 处理器。在 Visual C++ 5.0 中已l停用,~译器将忽略此选项
/G4 优化代码以优?486 处理器。在 Visual C++ 5.0 中已l停用,~译器将忽略此选项
/G5 优化代码以优?Pentium
/G6 优化代码以优?Pentium Pro、Pentium II ?Pentium III 处理?/td>
/G7 针对 Pentium 4 ?Athlon 优化代码?/td>
/GB ?/G6 {效Q将 _M_IX86 的D|ؓ 600
/Gd 使用 __cdecl 调用U定
/Ge Ȁzd栈探?/td>
/GF
/Gf
启用字符串池
/Gh 调用挂钩函数 _penter
/GH 调用挂钩函数 _pexit
/GL 启用全程序优?/td>
/Gm 启用最重新生?/td>
/GR 启用q行时类型信?(RTTI)
/Gr 使用 __fastcall 调用U定
/Gs 控制堆栈探测
/GT 支持使用静态线E本地存储区分配的数据的U程安全
/GX 启用同步异常处理
/Gy 启用函数U链?/td>
/Gz 使用 __stdcall 调用U定
/MD 使用 MSVCRT.lib 创徏多线E?DLL
/MDd 使用 MSVCRTD.lib 创徏调试多线E?DLL
/ML 使用 LIBC.lib 创徏单线E可执行文g
/MLd 使用 LIBCD.lib 创徏调试单线E可执行文g
/MT 使用 LIBCMT.lib 创徏多线E可执行文g
/MTd 使用 LIBCMTD.lib 创徏调试多线E可执行文g

输出文g

/FA
/Fa
创徏列表文g
讄列表文g?/td>
/Fd 重命名程序数据库文g
/Fe 重命名可执行文g
/Fm 创徏映射文g
/Fo 创徏对象文g
/Fp 指定预编译头文g?/td>
/FR
/FR
生成览器文?/td>
/Fx 插入的代码与源文g合ƈ

调试

/GS ~冲区安全检?/td>
/GZ ?/RTC1 相同
/RTC 启用q行旉误检?/td>
/Wp64 ?64 位可UL性问?/td>
/Yd 完整的调试信息攑֜所有对象文件中
/Yl 创徏调试库时插入 PCH 引用
/Z7 生成?C 7.0 兼容的调试信?/td>
/Zd 生成行号
/Zi 生成完整的调试信?/td>

预处理器

/AI 指定在解析传递到 #using 指o的文件引用时搜烦的目?/td>
/C 在预处理期间保留注释
/D 定义常数和宏
/E 预处理器输出复制到标准输出
/EP 预处理器输出复制到标准输出
/Fl 预处理指定的包含文g
/FU 强制使用文g名,像它已被传递到 #using 指o一?/td>
/I 在目录中搜烦包含文g
/P 预处理器输出写入文?/td>
/U U除预定义宏
/u U除所有的预定义宏
/X 忽略标准包含目录
/ZI 调试信息包含在与“编辑ƈl箋”兼容的E序数据库中

语言

/vd 取消或启用隐藏的 vtordisp cL?/td>
/vmb Ҏ向成员的指针使用最佳的?/td>
/vmg Ҏ向成员的指针使用完全一般?/td>
/vmm 声明多重l承
/vms 声明单一l承
/vmv 声明虚拟l承
/Za 用语言扩展
/Zc ?/Ze 下指定标准行?/td>
/Ze 启用语言扩展
/Zg 生成函数原型
/Zl ?.obj 文g中移除默认库?/td>
/Zp n 装l构成员
/Zs 只检查语?/td>

链接

/F 讄堆栈大小
/LD 创徏动态链接库
/LDd 创徏调试动态链接库
/link 指定的选项传递给 LINK
/MD 使用 MSVCRT.lib ~译以创建多U程 DLL
/MDd 使用 MSVCRTD.lib ~译以创试多U程 DLL
/ML 使用 LIBC.lib ~译以创建单U程可执行文?/td>
/MLd 使用 LIBCD.lib ~译以创试单U程可执行文?/td>
/MT 使用 LIBCMT.lib ~译以创建多U程可执行文?/td>
/MTd 使用 LIBCMTD.lib ~译以创试多U程可执行文?/td>

预编译头

/Y- 忽略当前生成中的所有其他预~译头编译器选项
/Yc 创徏预编译头文g
/Yd 完整的调试信息攑֜所有对象文件中
/Yu 在生成期间用预~译头文?/td>
/YX 自动处理预编译头

杂项

@ 指定响应文g
/? 列出~译器选项
/c ~译但不链接
/H 限制外部Q公共)名称的长?/td>
/HELP 列出~译器选项
/J 更改默认?char cd
/nologo 取消昄d版权标志
/QI0f 保 Pentium 0F 指o没有问题
/QIfdiv FDIV、FPREM、FPTAN ?FPATAN 指o有缺L Intel Pentium 微处理器的变通方?/td>
QIfist 当需要从点cd转换为整型时取消 Helper 函数 _ftol 的调?/td>
/showIncludes 在编译期间显C所有包含文件的列表
/Tc
/TC
指定 C 源文?/td>
/Tp
/TP
指定 C++ 源文?/td>
/V 讄版本字符?/td>
/W 讄警告{
/w 用所有警?/td>
/Wall 启用所有警告,包括默认情况下禁用的警告
/WL 在从命o行编?C++ 源代码时启用错误信息和警告消息的单行诊断
/Zm 指定预编译头内存分配限制

请参?/h4>

C/C++ 生成参?/a> | ~译器选项 | 讄~译器选项



梦在天 2006-08-17 12:16 发表评论
]]>非托的vc工程中部分文件?Net Framworkhttp://www.shnenglu.com/mzty/archive/2006/08/17/11334.html梦在天梦在天Thu, 17 Aug 2006 04:05:00 GMThttp://www.shnenglu.com/mzty/archive/2006/08/17/11334.htmlhttp://www.shnenglu.com/mzty/comments/11334.htmlhttp://www.shnenglu.com/mzty/archive/2006/08/17/11334.html#Feedback2http://www.shnenglu.com/mzty/comments/commentRss/11334.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/11334.html使用vs2005?/font> ?,且工E不使用与编译头文gstdafx.h.(保证可以,不可以来找我!)

一,建立一般的c++的console32的project ,name: Test ,工程setting使用默认,不改?如下:
r_testclass.jpg
?add header file: ManagedCppClass.h
#pragma  once

class ManagedCppClass
{
public:
    
void PrintString();
    
}
;

?add cpp file: ManagedCppClass.cpp
#using <mscorlib.dll> 
using namespace System;

#include 
"ManagedCppClass.h"

void ManagedCppClass::PrintString()
{
    Console::WriteLine(S
"Hello, i am a Managed cpp class ");
}
?main函数如下:
#include "stdafx.h"
#include 
"ManagedCppClass.h"

int _tmain(int argc, _TCHAR* argv[])
{
    ManagedCppClass test;
    test.PrintString();
    
return 0;
}
?修改Managedcppclass.cpp文g的property setting,
r_managedcppclass.jpg
next
o_managedcppclass2.jpg
?compile->link->run ,it is ok!

梦在天 2006-08-17 12:05 发表评论
]]>
使用c++\CLI实现c++托管与非托管混合~程http://www.shnenglu.com/mzty/archive/2006/08/16/11288.html梦在天梦在天Wed, 16 Aug 2006 06:23:00 GMThttp://www.shnenglu.com/mzty/archive/2006/08/16/11288.htmlhttp://www.shnenglu.com/mzty/comments/11288.htmlhttp://www.shnenglu.com/mzty/archive/2006/08/16/11288.html#Feedback0http://www.shnenglu.com/mzty/comments/commentRss/11288.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/11288.htmlMixing Native and Managed Types in C++

Wow, its turning into a busy month. I just haven’t had any time to blog despite having a number of interesting topics to cover. I’ll try to get a few of them written soon. Here’s a topic from one of my regular readers.

The CLR naturally supports mixing managed and native method calls allowing you to easily call native functions from managed functions (which are of course natively compiled before execution) and visa versa. This is all largely transparent in C++. What’s not as transparent is how to mix managed and native types. The reason is that there is a greater distinction between native and managed types compared with function calls. Beside obvious differences such as those introduced by different calling conventions and virtual invocation, function calls aren’t all that different. Types however require a bit more help from the programmer/compiler since native and managed types can have very different characteristics. This is very evident in C# as you often need to decorate native type definitions with all kinds of attributes to control memory layout and marshalling. Fortunately for the C++ programmer the compiler takes care of much of this when you define or include native type definitions such as those found in the various Windows header files, but the programmer is still responsible for telling the compiler just how those types are to be used.

Visual C++ provides many of the building blocks for mixing native and managed types but in some cases you need to write a little code to help it along. Fortunately C++/CLI is very capable. Let’s consider a few different scenarios.

Embed Simple Managed Type in Native Type

Since the CLR needs to keep track of every single instance of a managed type in a process, storing some kind of reference/pointer/handle to a managed object in a native type is not directly supported since instances of native types can be allocated in any region of memory and cast to all kinds of foreign data types that would be completely opaque to the CLR and its services. Instead you need to register such occurrences with the CLR so that it is aware of these “native?references to managed types. This is achieved with the use of the GCHandle type. Internally GCHandle manages a static table of (native) pointers that are used to lookup the objects in the managed heap. Of course using GCHandle directly from C++ can be quite tedious. It’s a CLS compliant value type which means native pointers are represented by IntPtr values. It also does not preserve static type information so static_casts are inevitable. Fortunately Visual C++ ships with the gcroot native template class that provides a strongly-typed interface over the GCHandle type.

#include <vcclr.h>
 
ref struct ManagedType
{
    void HelloDotNet()
    {
        Console::WriteLine("Hello .NET");
    }
};
 
struct NativeType
{
    ManagedType m1;          // Error!
   
    ManagedType^ m2;         // Error!
   
    gcroot<ManagedType^> m3; // OK
};
 
void main()
{
    NativeType native;
    native.m3 = gcnew ManagedType;
 
    native.m3->HelloDotNet();
}

As you can see, gcroot provides a “smart?pointer for storing handles in native types. It may be smart but it does not provide automatic cleanup of resources. Specifically, the gcroot destructor makes no attempt to dispose of the managed object’s resources.

Embed Managed Resource in Native Type

Enter the auto_gcroot class. This native template class wraps a gcroot and provides transfer-of-ownership semantics for managed objects stored in native types. If you’re looking for a point of reference, think of the auto_ptr template class from the Standard C++ Library which does the same thing for native pointers. The auto_gcroot destructor takes care of “deleting?the handle which results in the object’s IDisposable::Dispose method (if any) being called.

#include <msclr\auto_gcroot.h>
 
ref struct ManagedType
{
    void HelloDotNet()
    {
        Console::WriteLine("Hello .NET");
    }
 
    ~ManagedType()
    {
        Console::WriteLine("dtor");

        // Compiler implements Dispose pattern...
    }
};
 
struct NativeType
{
    msclr::auto_gcroot<ManagedType^> m3; // OK
};
 
void main()
{
    NativeType native;
    native.m3 = gcnew ManagedType;
 
    native.m3->HelloDotNet();
}

The NativeType destructor (provided by the compiler) will automatically call the auto_gcroot destructor which will delete the managed object resulting in its destructor being called through its compiler generated Dispose method.

Embed Native Type in Managed Type

Now let’s turn things around. Let’s say we want to store a native type as a member of a managed type. The challenge is that the only native type the CLR really supports within managed types is a native pointer. C# programmers use IntPtr but that is only because IntPtr is the CLS compliant way of representing a native pointer and C# tries really hard to remain CLS compliant. The CLR fully supports storing native pointers without losing type information.

struct NativeType
{
};
 
ref struct ManagedType
{
    NativeType n1; // Error!

    NativeType* n2; // OK
};

That’s great except that now we have a resource management issue. Recall that C++ does not have the separation of memory and resource management evident in the CLR. The native object pointed to by the ManagedType member needs to be deleted. Here is one solution.

ref struct ManagedType
{
    NativeType* n2; // OK
 
    ~ManagedType()
    {
        if (0 != n2)
        {
            delete n2;
            n2 = 0;
        }
    }
};

Now the ManagedType has a Dispose implementation that will faithfully delete the native object. But this can become tedious and error prone very quickly. A better solution is to use some kind of “automatic?approach. Fortunately C++/CLI support by-value semantics for members so all we need is a managed auto-pointer template class. With such a class the ManagedType becomes really simple.

ref struct ManagedType
{
    AutoPtr<NativeType> n2; // OK
};

ManagedType stores a pointer to a native object and its destructor automatically deletes the object. Woohoo!

The C++ compiler really takes care of a lot of boilerplate code. If you’re not sure just how much code the compiler is taking care of for you then take a look at the compiled assembly in a disassembler.

Although Visual C++ does not provide a managed AutoPtr class, it is reasonably simple to write one. Here is a basic implementation.

template <typename T>
ref struct AutoPtr
{
    AutoPtr() : m_ptr(0)
    {
        // Do nothing
    }
    AutoPtr(T* ptr) : m_ptr(ptr)
    {
        // Do nothing
    }
    AutoPtr(AutoPtr<T>% right) : m_ptr(right.Release())
    {
        // Do nothing
    }
    ~AutoPtr()
    {
        if (0 != m_ptr)
        {
            delete m_ptr;
            m_ptr = 0;
        }
    }
    T& operator*()
    {
        return *m_ptr;
    }
    T* operator->()
    {
        return m_ptr;
    }
    T* Get()
    {
        return m_ptr;
    }
    T* Release()
    {
        T* released = m_ptr;
        m_ptr = 0;
        return released;
    }
    void Reset()
    {
        Reset(0);
    }
    void Reset(T* ptr)
    {
        if (0 != m_ptr)
        {
            delete m_ptr;
        }
        m_ptr = ptr;
    }
private:
    T* m_ptr;
};

In a future post I may provide a few realistic examples of mixing native and managed code, but I hope this introduction has given you a few ideas on how to mix native and managed code and types effectively in C++.


来自: http://weblogs.asp.net/kennykerr/archive/2005/07/12/Mixing-Native-and-Managed-Types-in-C_2B002B00_.aspx



梦在天 2006-08-16 14:23 发表评论
]]>
A first look at C++/CLI(C++的管理扩?http://www.shnenglu.com/mzty/archive/2005/12/29/2240.html梦在天梦在天Thu, 29 Dec 2005 07:14:00 GMThttp://www.shnenglu.com/mzty/archive/2005/12/29/2240.htmlhttp://www.shnenglu.com/mzty/comments/2240.htmlhttp://www.shnenglu.com/mzty/archive/2005/12/29/2240.html#Feedback2http://www.shnenglu.com/mzty/comments/commentRss/2240.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/2240.htmlIntroduction

When Microsoft brought out the Managed Extensions to C++ with VS.NET 7, C++ programmers accepted it with mixed reactions. While most people were happy that they could continue using C++, nearly everyone was unhappy with the ugly and twisted syntax offered by Managed C++. Microsoft obviously took the feedback it got very seriously and they decided that the MC++ syntax wasn't going to be much of a success.

On October 6th 2003, the ECMA announced the creation of a new task group to oversee development of a standard set of language extensions to create a binding between the ISO standard C++ programming language and Common Language Infrastructure (CLI). It was also made known that this new set of language extensions will be known as the C++/CLI standard, which will be supported by the VC++ compiler starting with the Whidbey release (VS.NET 2005).

Problems with the old syntax

  • Ugly and twisted syntax and grammar - All those double underscores weren't exactly pleasing to the eye.
  • Second class CLI support - Compared to C# and VB.NET, MC++ used contorted workarounds to provide CLI support, for e.g. it didn't have a for-each construct to enumerate .NET collections.
  • Poor integration of C++ and .NET - You couldn’t use C++ features like templates on CLI types and you couldn’t use CLI features like garbage collection on C++ types.
  • Confusing pointer usage - Both unmanaged C++ pointers and managed reference pointers used the same * based syntax which was quite confusing because __gc pointers were totally different in nature and behavior from unmanaged pointers.
  • The MC++ compiler could not produce verifiable code

What C++/CLI gives us?

  • Elegant syntax and grammar -This gave a natural feel for C++ developers writing managed code and allowed a smooth transition from unmanaged coding to managed coding. All those ugly double underscores are gone now.
  • First class CLI support - CLI features like properties, garbage collection and generics are supported directly. And what's more, C++/CLI allows jus to use these features on native unmanaged classes too.
  • First class C++ support - C++ features like templates and deterministic destructors work on both managed and unmanaged classes. In fact C++/CLI is the only .NET language where you can *seemingly* declare a .NET type on the stack or on the native C++ heap.
  • Bridges the gap between .NET and C++ - C++ programmers won't feel like a fish out of water when they attack the BCL
  • The executable generated by the C++/CLI compiler is now fully verifiable.

Hello World

				using
				namespace System;

void _tmain()
{
    Console::WriteLine("Hello World");
}

Well, that doesn't look a lot different from old syntax, except that now you don't need to add a reference to mscorlib.dll because the Whidbey compiler implicitly references it whenever you compile with /clr (which now defaults to /clr:newSyntax).

Handles

One major confusion in the old syntax was that we used the * punctuator with unmanaged pointers and with managed references. In C++/CLI Microsoft introduces the concept of handles.

				void _tmain()
{
    //The ^ punctuator represents a handle
    String^ str = "Hello World";
    Console::WriteLine(str);
}

The ^ punctuator (pronounced as cap) represents a handle to a managed object. According to the CLI specification a handle is a managed object reference. Handles are the new-syntax equivalent of __gc pointers in the MC++ syntax. Handles are not to be confused with pointers and are totally different in nature from pointers.

How handles differ from pointers?

  • Pointers are denoted using the * punctuator while handles are denoted using the ^ punctuator.
  • Handles are managed references to objects on the managed heap, pointers just point to a memory address.
  • Pointers are stable and GC cycles do not affect them, handles might keep pointing to different memory locations based on GC and memory compactions.
  • For pointers, the programmer must deleteexplicitly or else suffer a leak. For handles delete is optional.
  • Handles are type-safe while pointers are most definitely not. You cannot cast a handle to a void^.
  • Just as a new returns a pointer, a gcnew returns a handle.

Instantiating CLR objects

				void _tmain()
{
    String^ str = gcnew String("Hello World");
    Object^ o1 = gcnew Object();
    Console::WriteLine(str);
}

The gcnew keyword is used to instantiate CLR objects and it returns a handle to the object on the CLR heap. The good thing about gcnew is that it allows us to easily differentiate between managed and unmanaged instantiations.

Basically, the gcnew keyword and the ^ operator offer just about everything you need to access the BCL. But obviously you'd need to create and declare your own managed classes and interfaces.

Declaring types

CLR types are prefixed with an adjective that describes what sort of type it is. The following are examples of type declarations in C++/CLI :-

  • CLR types
    • Reference types
      • refclass RefClass{...};
      • refstruct RefClass{...};
    • Value types
      • value class ValClass{...};
      • value struct ValClass{...};
    • Interfaces
      • interfaceclass IType{...};
      • interfacestruct IType{...};
    • Enumerations
      • enumclass Color{...};
      • enumstruct Color{...};
  • Native types
    • class Native{...};
    • struct Native{...};
				using
				namespace System;

interfaceclass IDog
{
    void Bark();
};

refclass Dog : IDog
{
public:
    void Bark()
    {
        Console::WriteLine("Bow wow wow");
    }
};

void _tmain()
{
    Dog^ d = gcnew Dog();
    d->Bark();
}

There, the syntax is now so much more neater to look at than the old-syntax where the above code would have been strewn with double-underscored
 keywords like __gc and __interface.

Boxing/Unboxing

Boxing is implicit (yaay!) and type-safe. A bit-wise copy is performed and an Object is created on the CLR heap. Unboxing is explicit - just do a reinterpret_cast and then dereference.

				void _tmain()
{
    int z = 44;
    Object^ o = z; //implicit boxingint y = *reinterpret_cast<int^>(o); //unboxing

    Console::WriteLine("{0} {1} {2}",o,z,y);

    z = 66; 
    Console::WriteLine("{0} {1} {2}",o,z,y);
}

// Output// 44 44 44// 44 66 44

The Objecto is a boxed copy and does not actually refer the int value-type which is obvious from the output of the second Console::WriteLine.

When you box a value-type, the returned object remembers the original value type.

				void _tmain()
{
    int z = 44;
    float f = 33.567;

    Object^ o1 = z; 
    Object^ o2 = f; 

    Console::WriteLine(o1->GetType());
    Console::WriteLine(o2->GetType());    
}

// Output// System.Int32// System.Single

Thus you cannot try and unbox to a different type.

				void _tmain()
{
    int z = 44;
    float f = 33.567;

    Object^ o1 = z; 
    Object^ o2 = f;

    int y = *reinterpret_cast<int^>(o2);//System.InvalidCastExceptionfloat g = *reinterpret_cast<float^>(o1);
//System.InvalidCastException }

If you do attempt to do so, you'll get a System.InvalidCastException. Talk about perfect type-safety! If you look at the IL generated, you'll see the MSIL box instruction in action. For example :-

				void Box2()
{
    float y=45;
    Object^ o1 = y;
}

gets compiled to :-

.maxstack  1
.locals (float32 V_0, object V_1)

  ldnull
  stloc.1ldc.r4     45.
  stloc.0ldloc.0
  box   [mscorlib]System.Single
  stloc.1ret

According to the MSIL docs, "The box instruction converts the ‘raw?valueType (an unboxed value type) into an instance of type Object (of type O). This is accomplished by creating a new object and copying the data from valueType into the newly allocated object."

Further reading

Conclusion

Alright, so why would anyone want to use C++/CLI when they can use C#, J# and that VB thingie for writing .NET code? Here are the four reasons I gave during my talk at DevCon 2003 in Trivandrum (Dec 2003).

  • Compile existing C++ code to IL (/clr magic)
  • Deterministic destruction
  • Native interop support that outmatches anything other CLI languages can offer
  • All those underscores in MC++ are gone ;-)

About Nishant Sivakumar



Editor
Site Builder
Nish is a real nice guy living in Toronto who has been coding since 1990, when he was 13 years old. Originally from sunny Trivandrum in India, he has moved to Toronto so he can enjoy the cold winter and get to play in some snow.

He works for The Code Project and handles the Dundas MFC products Ultimate Toolbox, Ultimate Grid and Ultimate TCP/IP that are sold exclusively through The Code Project Storefront. He frequents the CP discussion forums when he is not coding, reading or writing. Nish hopes to visit at least three dozen countries before his human biological mechanism stops working (euphemism used to avoid the use of the d-word here), and regrets that he hasn't ever seen snow until now (will be rectified this December). Oh btw, it must be mentioned that normally Nish is not inclined to speak about himself in the 3rd person.

Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com

Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book ?Extending MFC applications with the .NET Framework.

Click here to view Nishant Sivakumar's online profile.



 

C++的管理扩?/h1>

?/b>

C++理扩展是一l语a扩展Q它帮助Microsoft Visual C++开发h员ؓ微Y.NET~写应用E序?

理扩展是有用的Q如果你Q?

  • 希望提高开发h员用C++~写.NET应用E序的生产率
  • 要分阶段地将一大段代码从非理C++中移植到.NETq_?
  • 想从.NET Framework应用E序中用已有的非管理C++lg?
  • 想从非管理C++中?NET Frameworklg
  • 在同一应用E序中؜合非理C++代码?NET代码

C++理扩展为开发h员定?NET Framework提供了无比的灉|性。传l的非管理C++和管理C++代码可以自由地؜合在一?br />应用E序中。用理扩展~写的应用程序可以利用两U代码的优点。用管理扩展,现有lg可以方便地封装到.NETlg中,
在与.NET集成的同时保留原有投资?

什么是理扩展?
扩展允许你在C++中编写在.NET Framework控制下运行的理Q或.NETQ类。(非管理C++c运行在传统的微软基于Windows?
的环境中。)一个管理类是一个内|的.NETc,可以完全利用.NET Framework?

理扩展是Visual C++开发系l的新关键字和属性。它们允许开发h员决定哪些类或函数编译ؓ理或非理代码?br />q些部分然后可以^滑地与其它部分或外部库交互?

理扩展也用于在C++源代码中表示.NETcd和概c这允许开发h员容易地~写.NET应用E序Q而无需~写额外代码?

主要使用环境

  • 现有代码^滑地UL?.NET
    如果你在C++代码上有大量投资Q管理扩展将帮你它们^滑地转移?NETq_中。因Z可以在一个应用程?-
  • 甚至是同一文g中؜合管理和非管理代码,你可以用很长旉转移代码Q一个组件接一个组件地转换?NET中?
  • 或你可以l箋在非理C++中编写组Ӟ以利用该语言的强大功能和灉|性,只用理扩展~写量的高性能?
  • 装器(它你的代码可以?NETlg中调用)?
  • ?.NET语言中访问C++lg
    理扩展允许你从M.NET语言中调用C++cR你需要用扩展~写单的装器,它将你的C++cdҎ暴露?
  • 理cR封装器是完全的理c,可以从Q?NET语言中调用。封装器cL作ؓ了管理类与非理C++c间?
  • 映射层。它单地方法调用直接传递到非管理类中。管理扩展可用于调用M内置的动态链接库QDLLQ及
  • 内置cR?
  • 从内|代码中讉K.NET c?
    使用理扩展Q你可以创徏q从C++代码中直接调?NETcR你可以~写?NETlg当作M其它理C++cȝ
  • C++代码。你可以使用.NET Framework中内|的COM调用.NETcR你使用COMq是使用理扩展讉K.NETlg
  • 要依赖于你的工程。在一些情况下Q利用现有的COM支持是最好的选择。在另一些情况下Q用管理扩展可?
  • 会增加性能和开发者的生率?
  • 在同一可执行文件中的管理和内置代码
    Visual C++~译器能在管理和非管理上下文中自动而透明的翻译数据、指针和指o。这个过E是允许理扩展
  • 无缝C非管理代码交互的q程。开发h员能够控制什么样的数据和代码可以理。选择每个cL函数是管?
  • q是非管理的能力为开发h员提供了更大的灵zL。一些代码或数据cd在非理环境中执行得要比较好?
  • 另一斚wQ管理代码由于如片攉和类库等Ҏ,它提高了开发h员的生率。现有非理代码可以一?
  • 一部分地{化ؓ理代码Q因此保留了已有的投资?/li>



梦在天 2005-12-29 15:14 发表评论
]]>Managed, Unmanaged, Native: What Kind of Code Is This?Q{Q?/title><link>http://www.shnenglu.com/mzty/archive/2005/11/21/1213.html</link><dc:creator>梦在天</dc:creator><author>梦在天</author><pubDate>Mon, 21 Nov 2005 02:47:00 GMT</pubDate><guid>http://www.shnenglu.com/mzty/archive/2005/11/21/1213.html</guid><wfw:comment>http://www.shnenglu.com/mzty/comments/1213.html</wfw:comment><comments>http://www.shnenglu.com/mzty/archive/2005/11/21/1213.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/mzty/comments/commentRss/1213.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/mzty/services/trackbacks/1213.html</trackback:ping><description><![CDATA[     摘要: Managed, Unmanaged, Native: What Kind of Code Is This?  <a href='http://www.shnenglu.com/mzty/archive/2005/11/21/1213.html'>阅读全文</a><img src ="http://www.shnenglu.com/mzty/aggbug/1213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/mzty/" target="_blank">梦在天</a> 2005-11-21 10:47 <a href="http://www.shnenglu.com/mzty/archive/2005/11/21/1213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>泛型~程 Q知多少Q?/title><link>http://www.shnenglu.com/mzty/archive/2005/11/18/1188.html</link><dc:creator>梦在天</dc:creator><author>梦在天</author><pubDate>Fri, 18 Nov 2005 05:51:00 GMT</pubDate><guid>http://www.shnenglu.com/mzty/archive/2005/11/18/1188.html</guid><wfw:comment>http://www.shnenglu.com/mzty/comments/1188.html</wfw:comment><comments>http://www.shnenglu.com/mzty/archive/2005/11/18/1188.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/mzty/comments/commentRss/1188.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/mzty/services/trackbacks/1188.html</trackback:ping><description><![CDATA[     摘要: 归纳hQ泛型比非泛型具有下面两个优点: 1?nbsp; 更加安全 在非泛型~程中,虽然所有的东西都可以作为Object传递,但是在传递的q程中免不了要进行类型{换。而类型{换在q行时是不安全的。用泛型编E将可以减少不必要的cd转换Q从而提高安全性?2?nbsp; 效率更高 在非泛型~程中,简单类型作为Object传递时会引起Boxing和Unboxing操作Q这两个q程都是h...  <a href='http://www.shnenglu.com/mzty/archive/2005/11/18/1188.html'>阅读全文</a><img src ="http://www.shnenglu.com/mzty/aggbug/1188.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/mzty/" target="_blank">梦在天</a> 2005-11-18 13:51 <a href="http://www.shnenglu.com/mzty/archive/2005/11/18/1188.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于 “托与非托??大家都知道那些,来说_http://www.shnenglu.com/mzty/archive/2005/11/18/1186.html梦在天梦在天Fri, 18 Nov 2005 05:36:00 GMThttp://www.shnenglu.com/mzty/archive/2005/11/18/1186.htmlhttp://www.shnenglu.com/mzty/comments/1186.htmlhttp://www.shnenglu.com/mzty/archive/2005/11/18/1186.html#Feedback1http://www.shnenglu.com/mzty/comments/commentRss/1186.htmlhttp://www.shnenglu.com/mzty/services/trackbacks/1186.html与非托管代码互操?

Z使得现存的非.NET代码都可用,微Y的设计得CLR可以在应用程序里同时包含托管和非托管代码。CLR支持三种互操作:

托管代码调用DLLQ就是我们说的动态链接库Q中的非托管函数

托管代码使用现存的COMl徏Q非托管l徏作ؓCOM服务器)

非托代码用托类型(托管cd作ؓCOM服务器)


互操作?BR>是否可以?.NET 框架E序中?COM 对象Q?BR>是。您现在部v的Q?COM lg都可以在托管代码中用。通常情况下,所需的调整是完全自动q行的?/P>

特别是,可以使用q行时可调用包装 (RCW) ?.NET 框架讉K COM lg。此包装?COM lg提供?COM 接口转换Z .NET 框架兼容的接口。对?OLE 自动化接口,RCW 可以从类型库中自动生成;对于?OLE 自动化接口,开发h员可以编写自定义 RCWQ手动将 COM 接口提供的类型映ؓ?.NET 框架兼容的类型?/P>

是否可以?COM E序中?.NET 框架lgQ?BR>是。您现在创徏的托类型都可以通过 COM 讉K。通常情况下,所需的配|是完全自动q行的。托开发环境的某些新特性不能在 COM 中访问。例如,不能?COM 中用静态方法和参数化构造函数。一般,提前定l定cd所针对的用h一U较好的办法。如果类型需要在 COM 中用,您将被限制在使用 COM 可访问的Ҏ?/P>

默认情况下,托管cd可能是可见的Q也可能是不可见的,q由用于~写托管cd的语a军_?/P>

特别是,可以使用 COM 可调用包?(CCW) ?COM 讉K .NET 框架lg。这?RCWQ请参阅上一个问题)怼Q但它们的方向相反。同P如果 .NET 框架开发工具不能自动生成包装,或者如果自动方式不是您所需要的Q则可以开发自定义?CCW?/P>

 是否可以?.NET 框架E序中?Win32 APIQ?BR>是。?P/InvokeQ?NET 框架E序可以通过静?DLL 入口点的方式来访问本Z码库?/P>

下面?C# 调用 Win32 MessageBox 函数的示例:

using System;
using System.Runtime.InteropServices;

class MainApp
{
    [DllImport("user32.dll", EntryPoint="MessageBox")]
    public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);

    public static void Main()
    {
        MessageBox( 0, "您好Q这?PInvokeQ?, ".NET", 0 );
    }
}

-----------------------------------------------------------------------------
什么是托管代码和托数据?

托管代码是ؓ面向公共语言q行库的服务~写的代码(请参阅“什么是公共语言q行库?”)。ؓ了面向这些服务,该代码必dq行库提供最低别的信息Q元数据Q。默认情况下Q所?C#、Visual Basic .NET ?JScript .NET 代码都受托管。默认情况下QVisual Studio .NET C++ 代码不受托管Q但~译器可以通过指定命o行开?(/CLR) 来生托代码?
与托代码密切相关的是托数据(由公paq行库的垃圾回收器分配和释放的数据)。默认情况下QC#、Visual Basic ?JScript .NET 数据受托。然而,通过使用Ҏ的关键字可以?C# 数据标记为非托管。默认情况下QVisual Studio .NET C++ 数据不受托管Q即使在使用 /CLR 开xQ,但在使用 C++ 托管扩展Ӟ可以通过使用 __gc 关键字将cLCؓ托管。正如名U所暗示的,q意味着用于cd例的内存受垃圑֛收器的托。另外,cL?.NET 框架C֌的一名完全参与的成员Q这既带来了好处Q也带来了限制。其中一个好处是与用其他语言~写的类的正互操作性(例如Q托?C++ cd以从 Visual Basic cȝ承)。其中一个限制是托管cd能从基类l承?/P>

--------------------------------------------------------------------------------
什么是公共语言q行?(CLR)Q?BR>公共语言q行时是 .NET 框架应用E序的执行引擎?/P>

它提供许多服务,包括Q?/P>

代码理Q加载和执行Q?/P>


应用E序内存隔离


cd安全验证


IL 到本Z码的转换


元数据(增强的类型信息)讉K


为托对象管理内?/P>


强制代码讉K安全


异常处理Q包括跨语言异常


托管代码、COM 对象和现?DLLQ非托管代码和数据)之间的互操作


自动q行对象布局


对开发h员服务(配置、调试等Q的支持

什么是公共cdpȝ (CTS)Q?BR>公共cdpȝ是多信息cdpȝQ它被内|在公共语言q行时中Q支持大多数~程语言中的cd和操作。公q型系l支持大量编E语a的完全实现?/P>

 

什么是公共语言规范 (CLS)Q?BR>公共语言规范是一l结构和限制Q用作库~写者和~译器编写者的指南。它使Q何支?CLS 的语a都可以完全用库Qƈ且ɘq些语言可以怺集成。公pa规范是公q型系l的子集。对于那些需要编写代码供其他开发h员用的应用E序开发h员,公共语言规范也非帔R要。如果开发h员遵?CLS 规则来设计公p问的 APIQ那么就可以在支持公paq行时的M其他~程语言中很ҎC用这?API?/P>

 

什么是 Microsoft 中间语言 (MSIL)Q?BR>MSIL 是与 CPU 无关的指令集?NET 框架E序被编译成 MSIL。它包含加蝲、存储、初始化和调用对象方法的指o?/P>

与元数据和公q型系l结合,MSIL 允许真正的跨语言集成?/P>

MSIL 在执行前被{换ؓ机器代码Q而不是一边解释一Ҏ行?/P>

 

 



梦在天 2005-11-18 13:36 发表评论
]]>
Ʒþþþþ| Ļþ| Ʒþþþþþ| ھƷþþþþ99| ձƷþþþĻ8| 91þ㽶Ů߿| þþþƷר| ŷ޹Ʒþ| þҹɫƷ鶹| ղþøŷһ| 99þùѸ| Ʒ˾þþ| Ʒþþþ| þۺ77777| VۺVŷþ| þþƷһӰԺ| AëƬþþþƷëƬ| þ99Ʒ| Ʒľþþþþþ| 91Ʒþþþþio| þþþùɫAVѿͼƬ| AVþþƷ| Ʒþˬۺ| ҹҹݺݾþAV| þ91ᆱƷ2020| ۺϾþĻӰ| ŷ þ | þóСƵ| þþƷ۲ӰԺ| պþþþþ| þܳ| þۺɫһ| ˾þ뾫ƷĻ| þõӰ| þùɫAVѹۿ| þ99ù龫Ʒ66 | þþƷþ˼˼| ɫۺϾþþþۺ99| 97þþƷˬ| þþƷ鶹ҹҹ| պŷۺϾþ|