如何将C#返回的System::Array转换为C++兼容数据类型
在C++/CLI中转换C#结构体数组为原生C++类型的方案
首先得提一个关键细节:你C#里的PJSONInfo结构体字段都是私有的,C++/CLI根本访问不到这些值,所以第一步要先修正C#代码,把字段改成public(或者添加public属性),不然后续转换无从谈起。
步骤1:修正C#结构体的访问权限
把PJSONInfo的字段改为public,让C++/CLI能读取这些字段的值:
namespace JSON { public struct PJSONInfo { public string sSetting; public double dMinVal; public double dMaxVal; public string sUnits; } public interface iCalFunction { PJSONInfo[] ReadJSON(); } public class JSONReaderClass : iCalFunction { public PJSONInfo[] ReadJSON() { IList<PJSONInfo> JSONList = new List<PJSONInfo>(); // 保留你的填充逻辑 PJSONInfo[] ReturningJSONArray = JSONList.ToArray(); return ReturningJSONArray ; } } }
步骤2:定义原生C++结构体
在C++代码里定义一个和C#结构体字段一一对应的原生结构体,方便存入vector:
// 原生C++结构体,匹配C#的PJSONInfo struct NativeJSONInfo { std::wstring sSetting; // C# string是UTF-16,用wstring对应最直接 double dMinVal; double dMaxVal; std::wstring sUnits; };
步骤3:实现托管数组到原生vector的转换
利用C++/CLI提供的封送工具,把System::Array里的每个元素逐个转换为原生结构体,存入vector。记得要包含封送相关的头文件:
首先添加必要的头文件:
#include <vector> #include <string> #include <msclr/marshal_cppstd.h>
然后修改你的读取函数:
class CReadingClass { public: msclr::auto_gcroot<JSON::JSONReaderClass^> pJSONClass; }; int ReadJSONFromJSONReader() { CReadingClass* pReadClass = new CReadingClass(); pReadClass->pJSONClass = gcnew JSON::JSONReaderClass(); System::Array^ JSONSetting = pReadClass->pJSONClass->ReadJSON(); // 用于存储原生C++结构体的vector std::vector<NativeJSONInfo> nativeJSONList; // 遍历托管数组的每个元素 for each (JSON::PJSONInfo item in JSONSetting) { NativeJSONInfo nativeItem; // 封送字符串:System::String^ 转 std::wstring nativeItem.sSetting = msclr::interop::marshal_as<std::wstring>(item.sSetting); // 数值类型可以直接赋值,因为都是值类型 nativeItem.dMinVal = item.dMinVal; nativeItem.dMaxVal = item.dMaxVal; nativeItem.sUnits = msclr::interop::marshal_as<std::wstring>(item.sUnits); nativeJSONList.push_back(nativeItem); } // 现在nativeJSONList就是纯原生C++可以直接使用的结构体集合了 // 在这里添加你的后续业务逻辑即可... // 记得释放手动分配的原生内存 delete pReadClass; return 1; }
一些注意事项
- 字符串编码:如果你的原生代码需要用
std::string而不是std::wstring,可以把marshal_as的目标改成std::string,默认会把UTF-16的C#字符串转成UTF-8的std::string,如果有特殊编码需求需要额外处理。 - 内存管理:
CReadingClass是用new分配的原生对象,一定要记得delete;而托管对象(比如JSONReaderClass^)由CLR垃圾回收机制处理,不用手动释放。 - 替代方案:如果你的后续逻辑还是在C++/CLI环境中运行,其实可以直接使用
System::Array或者转换为System::Collections::Generic::List<JSON::PJSONInfo>,不需要转成原生vector——只有当需要和纯原生C++代码交互时,才需要做这种封送转换。
内容的提问来源于stack exchange,提问作者Bharath V
相关产品推荐
相关产品推荐

