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"
#include <string>
using namespace System;
using namespace System::Text;
<p>// 托管函数:返回托管字符串
String^ BuildHelloWorld() {
StringBuilder^ sb = gcnew StringBuilder();
sb->Append("Hello");
sb->Append(" ");
sb->Append("World");
return sb->ToString();
}</p><p>// 原生C++可调用的包装函数(返回C风格字符串)
const char<em> GetHelloWorldNative() {
String^ managedStr = BuildHelloWorld();
// 将托管字符串转为UTF8原生字符串
array<byte>^ bytes = System::Text::Encoding::UTF8->GetBytes(managedStr);
pin_ptr<unsigned char> pinned = &bytes[0];
static std::string cachedResult;
cachedResult.assign(reinterpret_cast<char</em>>(pinned), bytes->Length);
return cachedResult.c_str();
}</p>注意: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;
<p>public ref class MathWrapper {
public:
static double Add(double a, double b) {
return ::Add(a, b); // 直接调用原生函数
}
};</p>C#中即可这样使用:
// C# 代码 var result = MathWrapper.Add(3.5, 4.2); // 输出 7.7
传递复杂数据(如List)
C++/CLI可双向转换原生容器与.NET集合:
#include <vector>
using namespace System::Collections::Generic;
<p>// 原生vector → .NET List<int>
List<int>^ ToDotNetList(const std::vector<int>& v) {
auto list = gcnew List<int>(v.size());
for (size_t i = 0; i < v.size(); ++i) {
list->Add(v[i]);
}
return list;
}</p><p>// .NET List<int> → 原生vector
std::vector<int> ToStdVector(List<int>^ list) {
std::vector<int> v(list->Count);
for (int i = 0; i < list->Count; ++i) {
v[i] = list[i];
}
return v;
}</p>注意:避免在循环中频繁访问 list[i](.NET索引器有开销),可用 list->ToArray() + pin_ptr 批量复制提升性能。
不复杂但容易忽略:C++/CLI项目必须引用对应.NET Framework版本(如v4.7.2),且所有依赖的DLL需在运行时路径中;调试时混合堆栈可见,但托管异常需用 try/catch (System::Exception^) 捕获,不能用原生 try/catch。









