C++/CLI是微软提供的混合编程语言扩展,支持原生C++与.NET双向调用,编译生成托管IL和原生机器码,由CLR统一管理;需启用/clr选项,仅支持.NET Framework或.NET 6+桌面场景。

使用C++/CLI可以在原生C++代码中直接调用.NET类库,也能让.NET代码调用C++逻辑。它不是单纯的“桥接工具”,而是微软提供的混合编程语言扩展,编译后生成托管IL代码(对.NET部分)和原生机器码(对native部分),由CLR统一管理。
启用C++/CLI支持
在Visual Studio中创建项目时需选择“CLR空项目”或手动修改项目属性:
- 项目属性 → 配置属性 → 常规 → “公共语言运行时支持”设为“/clr”
- 确保目标平台与引用的.NET程序集一致(如x64或x86,.NET Core/.NET 5+暂不支持C++/CLI,仅支持.NET Framework或.NET 6+的“带运行时”的桌面场景)
从C++/CLI调用.NET类(托管代码)
以下示例在C++/CLI中创建一个.NET StringBuilder,拼接字符串并返回结果:
#include "stdafx.h" #includeusing namespace System; using namespace System::Text; // 托管函数:返回托管字符串 String^ BuildHelloWorld() { StringBuilder^ sb = gcnew StringBuilder(); sb->Append("Hello"); sb->Append(" "); sb->Append("World"); return sb->ToString(); }
// 原生C++可调用的包装函数(返回C风格字符串) const char GetHelloWorldNative() { String^ managedStr = BuildHelloWorld(); // 将托管字符串转为UTF8原生字符串 array
^ bytes = System::Text::Encoding::UTF8->GetBytes(managedStr); pin_ptr pinned = &bytes[0]; static std::string cachedResult; cachedResult.assign(reinterpret_cast >(pinned), bytes->Length); return cachedResult.c_str(); }
注意:gcnew分配托管对象,pin_ptr防止GC移动内存,避免指针失效;static std::string用于缓存转换结果(因返回const char*需保证生命周期)。
立即学习“C++免费学习笔记(深入)”;
从.NET调用原生C++函数
先写一个纯原生C++函数(放在 .cpp 文件中,不带 /clr 编译):
JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互。本文将快速讲解 JSON 格式,并通过代码示例演示如何分别在客户端和服务器端进行 JSON 格式数据的处理。
// native_math.cpp(不启用/clr)
extern "C" __declspec(dllexport) double Add(double a, double b) {
return a + b;
}
再在C++/CLI中封装为托管接口供C#调用:
// wrapper.h #pragma once #include "native_math.h" using namespace System;public ref class MathWrapper { public: static double Add(double a, double b) { return ::Add(a, b); // 直接调用原生函数 } };
C#中即可这样使用:
// C# 代码 var result = MathWrapper.Add(3.5, 4.2); // 输出 7.7
传递复杂数据(如List)
C++/CLI可双向转换原生容器与.NET集合:
#includeusing namespace System::Collections::Generic; // 原生vector → .NET List
List ^ ToDotNetList(const std::vector & v) { auto list = gcnew List (v.size()); for (size_t i = 0; i < v.size(); ++i) { list->Add(v[i]); } return list; } // .NET List
→ 原生vector std::vector ToStdVector(List ^ list) { std::vector v(list->Count); for (int i = 0; i < list->Count; ++i) { v[i] = list[i]; } return v; }
注意:避免在循环中频繁访问 list[i](.NET索引器有开销),可用 list->ToArray() + pin_ptr 批量复制提升性能。
不复杂但容易忽略:C++/CLI项目必须引用对应.NET Framework版本(如v4.7.2),且所有依赖的DLL需在运行时路径中;调试时混合堆栈可见,但托管异常需用 try/catch (System::Exception^) 捕获,不能用原生 try/catch。









