当前位置: 首页 > news >正文

C++/CLI

C++/CLI 仅在 Windows 上受支持。

C++/CLI 是微软在 C++ 的基础上发明的一个语言(相当于 C++ 的超集),它扩展了 C++ 以支持 .NET;同时还可用于 C# 与 C/C++ 互操作。

微软似乎不太建议新的项目使用 C++/CLI:

”对于新项目,我们建议探索现代第三方替代方案,例如 https://github.com/dotnet/ClangSharp 或 https://www.swig.org/,它们提供更大的灵活性并更好地与当前语言和运行时功能保持一致。“

摘自:使用 C++/CLI 进行 .NET 编程 |Microsoft Learn,由 Edge 翻译

相比 C++,C++/CLI 加了一堆乱七八糟的语法,用来和 CLR 打交道。本篇会详细介绍这些语法。

先决条件

使用 C++/CLI 前需要进行额外配置:

安装 Visual Studio C++ 工作负载时,默认情况下不安装 C++/CLI。 若要在安装 Visual Studio 后安装组件,请通过选择 Windows “开始”菜单并搜索 Visual Studio 安装程序打开 Visual Studio 安装程序。 选择安装的 Visual Studio 版本旁边的“修改”按钮。 选择“单个组件”选项卡。向下滚动到“编译器、生成工具和运行时”部分,然后选择“适用于 v143 生成工具的 C++/CLI 支持(最新版本)”。 选择“修改”以下载所需的文件并更新 Visual Studio。

摘自:使用 C++/CLI 进行 .NET 编程 | Microsoft Learn

配置完后,你应该会在 Visual Studio 的 “新建项目” 发现这些多出来的项目:

“CLR” 指的是 Common Language Runtime(公共语言运行时)。总之就是我们想要的 C++/CLI。

C++/CLI 中的 CLI 指的是 Common Language Infrastructure(公共语言基础设施)。不要和 Command-Line Interface(命令行界面)搞混了。

欲详细了解,可参考:.NET学习笔记 -- 那堆名词到底是啥(CLR、CLI、CTS、CLS、IL、JIT) - 红心李 - 博客园

  • 如果你只是想写一个程序,和 C# 没关系,就选 ”CLR 控制台应用”;
  • 如果你想要与 C# 交互,就选 “CLR 类库”;
  • 如果选择 “CLR 空项目”,你需要手动配置 “引用” 才能正常使用 .NET 功能(例如添加 mscorlibSystem 等)。

(另外还要注意 .NET 和 .NET Framework 的区别。)

C++/CLI 项目会启用编译指令 /clr。这可以在 “配置属性 > C/C++ > 常规 > 公共语言运行时支持” 中找到。

使用 BCL

在 C++/CLI 中使用 BCL 和 C# 十分类似,除了命名空间相关语法稍有不同:

using namespace System; // C# 中是 using System;
int main() {Console::WriteLine("Hello, world!");return 0;
}

定义托管类、托管结构体

这一节要介绍的内容实际上与下一节紧密相关。C++ 的类、结构体不能在 GC 堆上分配。为了在 GC 堆上分配,必须定义托管类、托管结构体。

语法与 C# 类似,这里仅举两个例子:

ref class MyRefClass {}; // C++ 是需要分号的
value class MyValueClass {};

使用 GC 堆

C++/CLI 支持了和 C# 类似的自动内存管理功能,允许我们愉快地使用 GC(Garbage Collection,垃圾回收器)。具体来说,我们会通过特定的语法在 GC 堆(Garbage Collected Heap)上申请内存。这样申请的对象,其会在引用计数归零后由 GC 自动回收。

让我们看两个例子吧:

int^ i = gcnew int;
MyRefClass ^c = gcnew MyRefClass();

我们用 C++/CLI 关键字 gcnew 在 GC 堆上分配内存,语法和 new 类似。在 GC 堆上分配内存的类型必须为托管类型,其包括:

  • 基础类型,如 int(实际上会这里会被隐式转换为 System.Int32);
  • ref classvalue class
  • ref structvalue struct

我们得到的这个 int^,称为 “句柄(handle)”。句柄的行为和指针类似(但不支持指针算术),请看这个例子:

using namespace System;
int main() {int^ i = gcnew int;Console::WriteLine(i);Console::WriteLine(*i);i = 13;Console::WriteLine(i);Console::WriteLine(*i);*i = 17;Console::WriteLine(i);Console::WriteLine(*i);return 0;
}

其中 *i 可以看作是对句柄的解引用。此程序的输出:

0
0
13
13
17
17

从中可以发现使用 *ii 赋值是等价的。使用 .NET 相关方法时也是等价的,但对于标准 C++ 函数则不是,例如使用标准输出流:

std::cout << *i;

这是因为 i 的类型是 int^(句柄),STL 显然不支持,而 *i 就是 int,STL显然支持。

跟踪引用(Tracking Reference)

C++/CLI 引入了跟踪引用操作符(Tracking Reference Operator),即 %,Microsoft 给出的介绍如下:

跟踪引用有以下特征。

  • 将一个对象分配至跟踪引用将导致对象的引用计数增加。
  • 原生引用 (&) 是 * 解引用的结果。跟踪引用 (%) 是 ^ 解引用的结果。只要你有一个对象的 %(跟踪引用),此对象就会在内存中保持活动状态(stay alive)。
  • 成员访问符 (.) 用于访问成员。
  • 跟踪引用是对值类型和句柄有效的类型(例如 String^)。(注:这句话应该是说跟踪引用可以传参给值类型和句柄。)
  • 跟踪引用不能被分配为 nullptr。跟踪引用可以根据需要多次重新分配给另一个有效对象。
  • 跟踪引用不能用作一元获取地址运算符。

摘自:Tracking Reference Operator (C++/CLI and C++/CX) | Microsoft Learn,由笔者翻译

请看例子:

int^ i = gcnew int;
int% myRef = *i; // 将 i 解引用并赋给 myRef
int^% handleRef = i; // handleRef 是句柄的引用int^ j = %myRef;
// 这个可以这么理解,C++/CLI 新定义的运算符和原有运算符的对应关系:
// *(指针) <-> ^(句柄), &(引用) >-> %(跟踪引用)
// 那 int^ j = %myRef <-> int* j = &myRef
// 相当于把 % 当 "取句柄" 运算符使用 (乱猜)

参考

  • 使用 C++/CLI 进行 .NET 编程 | Microsoft Learn
  • 适用于 .NET 和 UWP 的组件扩展 | Microsoft Learn

微软真坑,居然把同样主题的内容放在两个地方。这两个文档互相引用,笔者查阅的时候很麻烦。

http://www.hskmm.com/?act=detail&tid=25167

相关文章:

  • uboot 2020版本下gpio命令的使用
  • 盛世华诞 举国同庆|热烈庆祝 LEWISAK 英勇重创消火栓 1 周年!
  • 完整教程:<el-table>构建树形结构
  • 如何在markdown中插入折叠框
  • wqs二分
  • markdown语法详解
  • CF2115 VP 记录
  • 2-SAT模板
  • lab5
  • lab4
  • NumPy广播:12个技巧替代循环,让数组计算快40倍
  • 某中心2026年推出1111个技术实习岗位
  • 川土微变频器应用分享
  • POLIR-Society-Philosophy- Hegels 形而上学System Philosophy Dialectics 系统化哲学辩证法: 自由意志+封闭的绝对精神
  • 解决VLC 无法解码格式“h264” (H264 - MPEG-4 AVC (part 10))
  • CF2115 总结
  • luogu P8816 [CSP-J 2022] 上升点列 题解
  • CF558C Amr and Chemistry BFS解
  • Atbash密码和摩斯密码
  • Redis 中如何保证缓存与数据库的内容一致性?
  • Payload CMS:开发者优先的Next.js原生开源解决优秀的方案,重新定义无头内容管理
  • 第一次写博客
  • 07. 自定义组件
  • python语法记录
  • 2025 年储罐厂家推荐最新公司权威排行榜榜单发布,深度解析衬四氟储罐 / 硫酸储罐 / 盐酸储罐工厂选购指南
  • UnicodeEncodeError: locale codec cant encode character \u5e74 in position 2: encoding error
  • 2025 年生物除臭设备厂家最新推荐排行榜:覆盖污水处理厂 / 垃圾中转站等多场景,助力企业精准挑选优质设备
  • 2025 年球墨铸铁管公司:重庆南恩物资全品类管材供应与市政工程适配解决方案解析
  • 2025生物除臭设备厂家最新品牌企业推荐排行榜揭晓:印染厂污水,食品厂污水,污水处理厂,污水泵站,污水站,餐厨垃圾,屠宰场,厨余垃圾生物除臭设备公司推荐
  • 2025 工业加热器选型必看:六大加热器实力厂家深度推荐,覆盖多场景加热设备解决方案