C++/CLI:第一流的CLI语言

简介:
1. 简介

  本文并不是为了奉承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作一 评判。

   2. 快速简洁的本机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 1162 140
5,000,000 6369 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#版本。

  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; 
//得到需要的缓冲区大小
if( GetAdaptersInfo(IntPtr.Zero, ref OutBufLen) == 
ERROR_BUFFER_OVERFLOW )
{
IntPtr pAdapterInfo = Marshal.AllocHGlobal(OutBufLen); 
//取得适配器信息
if( GetAdaptersInfo(pAdapterInfo, ref OutBufLen) != ERROR_SUCCESS )
{ //调用失败了 }
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);
}

}















本文转自朱先忠老师51CTO博客,原文链接:http://blog.51cto.com/zhuxianzhong/59841 ,如需转载请自行联系原作者



相关文章
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
239 2
|
3月前
|
存储 C++
C++语言中指针变量int和取值操作ptr详细说明。
总结起来,在 C++ 中正确理解和运用 int 类型地址及其相关取值、设定等操纵至关重要且基础性强:定义 int 类型 pointer 需加星号;初始化 pointer 需配合 & 取址;读写 pointer 执向之处需配合 * 解引用操纵进行。
374 12
|
8月前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
248 15
|
8月前
|
存储 算法 安全
企业员工数据泄露防范策略:基于 C++ 语言的布隆过滤器算法剖析[如何防止员工泄密]
企业运营过程中,防范员工泄密是信息安全领域的核心议题。员工泄密可能致使企业核心数据、商业机密等关键资产的流失,进而给企业造成严重损失。为应对这一挑战,借助恰当的数据结构与算法成为强化信息防护的有效路径。本文专注于 C++ 语言中的布隆过滤器算法,深入探究其在防范员工泄密场景中的应用。
187 8
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
249 0
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
305 5
|
存储 编译器 C语言
深入计算机语言之C++:类与对象(上)
深入计算机语言之C++:类与对象(上)
147 0
|
存储 分布式计算 编译器
深入计算机语言之C++:C到C++的过度-2
深入计算机语言之C++:C到C++的过度-2
113 0
|
编译器 Linux C语言
深入计算机语言之C++:C到C++的过度-1
深入计算机语言之C++:C到C++的过度-1
157 0
|
编译器 C++ 容器
C++语言的基本语法
想掌握一门编程语言,第一步就是需要熟悉基本的环境,然后就是最重要的语法知识。 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。 完整关键字
276 2