使用C++/CLI
认识C++/CLI
其实从这个名字就可以简单概括出C++/CLI的特点:首先它是一门C++语言,其次它遵循了CLI(Common Language Infrastructure)规范。简单来说CLI是微软提出的定义了一种可执行代码和编程模型的规范,它由CTS(Common Type System)、CLS(Common Language Specification)、IL(Intermediate Language)等几个部分组成。所以C++/CLI是一门用C++实现CLI规范的语言,而C#、VB等.NET语言也是CLI规范下的语言,因此这项技术使得C++与.NET语言之间的相互调用非常高效且自然。
为什么要使用C++/CLI
如果不使用C++/CLI,那么C++与.NET语言之间只能通过标准C接口的方式互相调用(P/Invoke)。这种方式本质是C语言和其它编程语言之间的调用方式,C/C++、C#、Java、Rust、Python等语言之间都可以通过导出C接口的方式互相调用。这是一种比较原始的技术,在C++和C#混合编程的场景下,并不是好的解决方案。
我总结了P/Invoke方式与C++/CLI方式之间几方面的对比:
| 特点 | P/Invoke | C++/CLI |
| 调用方式 | 必须先使用extern声明方法,再调用。且在声明时还需要标识DllImport、EntryPoint等调用信息 | 与调用自有方法一样,毫无跨语言调用的痕迹 |
| 数据类型 | 参数类型和返回类型只支持数值、字符等基本类型,因为本质是C语言接口 | 有CTS系统支撑,支持类、结构、枚举、事件等复杂数据结构 |
| 代码复用 | 只能调用方法。C是面向过程的,没有类的概念,自然也没有静态和实例的概念 | CLI是面向对象的,可以复用类,实例方法的。 |
C++/CLI入门
通过一个简单的示例来介绍一下C++/CLI
Employee.h
public ref class Employee
{
public:
Employee(System::String^ fullName);
Employee(System::String^ fullName, System::DateOnly hireDate);
System::String^ Department;
System::String^ FullName;
System::DateOnly HireDate;
/// <summary>
/// 获取工龄
/// </summary>
/// <returns></returns>
System::DateOnly GetServiceTime();
};
这就是一个简单的C++/CLI托管类。下面解释一下C++/CLI中特殊的语法:
1、ref(reference)标记该类是CLI规范下的托管类,ref标记是为了区分标准C++中的class
2、^标记表示对托管对象的引用,面向对象中的“引用”类似于C++中的“指针”。
3、System::String、System::DateOnly都是.NET中的类型,托管类中只能使用System中的类型,不能使用指针、wchar_t等C++类型。
因为托管类的内存由垃圾回收机制处理,非System中的类型不能被正确处理,且托管类是与.NET之间相互使用的类,.NET是不认识C++中的类型的。
4、System::DateOnly是值类型,所以不需要使用^,在CLI中值类型的传递规则是复制一份相同的数据。当然也可以加^,表示对值类型对象的引用。
Employee.cpp
Employee::Employee(System::String^ fullName, System::DateOnly hireDate) {
FullName = fullName;
HireDate = hireDate;
}
Employee::Employee(System::String^ fullName) {
FullName = fullName;
Department = gcnew System::String("临时");
}
gcnew是为了区分new引入的,专门用来创建托管对象。gcnew创建对象然后^的应用指向该对象。
C++/CLI中的概念对于熟悉.NET的人来说不难理解。
在.NET中所有对象都可以分为引用类型和值类型,值类型包括基础的数字(int,double等)、字符(char)、枚举、结构(struct)、true/false。除此之外的类(class)、字符串(string)、数组(arrary)、委托(delegate)等都是引用类型。值对象的创建直接通过=赋值即可,引用类型对象只能通过new创建。参数传递时引用对象传递引用,值对象复制一份相同数据到栈。
在C++/CLI中你可以使用ref class,也可以使用原本的class,但是与.NET交互的类只能是ref class。
不只是胶水语言
很多人把C++/CLI只看成是连接C++和.NET的胶水语言,其实不然。
应该把它看成一门独立的语言,在C++/CLI中你既可以编写托管代码,也可以编写标准C++代码,你可以单独使用它编写一个程序。
浙公网安备 33010602011771号