技术开发 频道

C++/CLI:第一流的CLI语言(1)

【IT168 技术文档】

  简介
 
  本文并不是为了奉承C++/CLI的辉煌,也不是为了贬低其它如C#或者VB.net等语言,相反,这只是一个非官方的、以一个喜欢这种语言的非微软雇员身份来论证C++/CLI有它的自己的唯一的角色,可作为第一流的.NET编程语言。
 
  一个不断在新闻组和技术论坛上出现的问题是,当象C#和VB.net这样的语言更适合于这种用途时,为什么要使用C++来开发.NET应用软件。通常这样一些问题后面的评论说是,C++语法是怎样的复杂和令人费解,C++现在是怎样一种过时的语言,还有什么VS.net设计者已不再像支持C#和VB.NET一样继续支持C++。其中一些猜疑是完全荒谬的,但有些说法部分正确。希望本文有助于澄清所有这些围绕C++/CLI语言及其在VS.NET语言层次中的地位的疑惑,神秘和不信任。请记住,本作者既不为微软工作也没有从微软那里取得报酬,只是想从技术上对C++/CLI作一评判。
 
  快速简洁的本机interop
 
  除了P/Invoke机制可用在另外的象C#或VB.NET这样的语言外,C++提供了一种独有的interop机制,称作C++ interop。C++ interop比P/Invoke直观得多,因为你只是简单地#include需要的头文件,并与需要的库进行链接就能象在本机C++中一样调用任何函数。另外,它比P/Invoke速度快--这是很容易能证明的。现在,可争辩的是在实际应用软件的开发中,经由C++ interop获得的性能好处与花在用户接口交互、数据库存取、网络数据转储、复杂数学算法等方面的时间相比可以被忽略,但是事实是在有些情况下,甚至通过每次interop调用节省的几个纳秒也能给全局应用程序性能/响应造成巨大影响,这是绝对不能被忽视的。下面有两部分代码片断(一个是使用P/Invoke机制的C#程序,一个是使用C++ Interop机制的C++程序),我分别记录了其各自代码重复执行消耗的时间(毫秒)。不管你如何解释这些数据,不管这会对你的应用程序产生什么影响,全是你的事。我仅打算事实性地指出,C++代码的执行速度要比C#(其中使用了较多的本机interop调用)快。

  1) C#程序(使用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++程序(使用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#程序
C++程序
50,000
61
10
500,000
600
70
1,000,000
1,162
140
5,000,000
6,369
721
 
  其性能差别真是令人惊愕!这的确是说明为什么要使用C++/CLI的一个好理由,如果你在使用本机interop进行开发,那么性能!完全由于性能,我就将被迫借助本机interop来实现并非基于Web的.NET应用程序。当然,为什么我想要使用.NET来开发需要大量本机interop技术的应用程序完全是另外一个问题。
 
  如果你仍怀疑这种性能优势,有另外的理由来说明你为什么不得不使用C++/CLI而不是C#或VB.NET——源码膨胀!下面是一个C++函数的例子,它使用了IP帮助者API来枚举一台机器上的网络适配器并且列出与每个适配器相联系的所有IP地址。
 
  4) 枚举n/w适配器的C++代码
void ShowAdapInfo() { PIP_ADAPTER_INFO pAdapterInfo = NULL; ULONG OutBufLen = 0; //得到需要的缓冲区大小 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]; //取得适配器信息 if( GetAdaptersInfo(pAdapterInfo, &OutBufLen) != ERROR_SUCCESS ) {//调用失败 } 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#版本。

 

 

0
相关文章