C#托管向C++非托管传递结构体数组并获取修改结果求助
解决C#托管与C++非托管结构体数组互传并获取修改值的问题
嘿,我帮你搞定这个问题!你当前的代码核心卡点在于字符串类型的封送映射和数组的双向修改权限配置,直接按下面的修正代码来就能正常工作:
一、修正后的C++非托管代码
先保留你的逻辑,注意如果后续要使用动态分配的字符串,得额外做内存管理(目前用常量字符串没问题):
struct CPT { const char* Value1; const char* Value2; }; extern "C" __declspec(dllexport) int ToError(CPT* cpts, const int length) { for (int i = 0; i < length; i++) { cpts[i].Value1 = "a"; cpts[i].Value2 = "b"; } return length; }
二、修正后的C#托管代码
这里重点要给结构体字段指定正确的封送类型,同时确保数组能被非托管代码修改后同步回托管端:
using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct CPT { // 把C#字符串封送为C++的const char*,匹配ANSI编码 [MarshalAs(UnmanagedType.LPStr)] public string Value1; [MarshalAs(UnmanagedType.LPStr)] public string Value2; } class Program { // 导入DLL函数,[In, Out]属性确保数组能双向传递修改 [DllImport("你的C++生成的DLL文件名.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int ToError([In, Out] CPT[] cpts, int length); static void Main(string[] args) { // 初始化结构体数组,比如长度设为3 CPT[] cptArray = new CPT[3]; // 调用非托管函数 int modifiedCount = ToError(cptArray, cptArray.Length); // 输出修改后的结果 for (int i = 0; i < modifiedCount; i++) { Console.WriteLine($"第{i+1}个结构体:Value1={cptArray[i].Value1}, Value2={cptArray[i].Value2}"); } } }
三、必须注意的几个关键点
- 结构体布局对齐:
LayoutKind.Sequential保证C#结构体和C结构体的内存布局完全一致,CharSet.Ansi匹配C默认的char编码(如果C++用宽字符,要改成CharSet.Unicode和LPCWSTR)。 - 字符串封送规则:
[MarshalAs(UnmanagedType.LPStr)]是核心,它告诉CLR把C#的string转换成C++能识别的const char*,反之亦然。 - 数组双向修改权限:默认情况下,C#传递给非托管的数组可能只作为输入,添加
[In, Out]属性后,非托管代码对数组的修改会被同步回托管内存。 - 内存管理提醒:如果你的C后续要动态分配字符串(比如用
malloc),千万不能让C#直接接管这块内存,必须在C里写一个释放函数,然后C#调用它来释放,否则会导致内存泄漏。如果是像你现在用的常量字符串,就不用操心这个问题,因为它们存在全局内存中。
内容的提问来源于stack exchange,提问作者Vy Phan
相关产品推荐
相关产品推荐

