左眼水星

导航

使用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++代码,你可以单独使用它编写一个程序。

posted on 2022-12-30 17:01  左眼水星  阅读(43)  评论(0)    收藏  举报