C#调用C DLL:Marshal含字符串数组的返回结构体时崩溃求助
解决C#调用C DLL时Marshal返回结构体的崩溃问题
我来帮你搞定这个问题!你怀疑指针偏移计算出错完全找对了方向,咱们一步步拆解问题根源:
核心问题:size_t的类型映射错误导致指针偏移失效
C语言里的size_t是平台相关的无符号整数类型——32位系统下占4字节,64位系统下占8字节。你用ulong对应它,再通过Marshal.SizeOf(typeof(ulong))计算偏移,这在32位平台下直接踩坑:ulong在C#里固定是8字节,而实际size_t只占4字节,导致指针被多偏移了4字节,指向错误的内存区域,读取char**时自然会崩溃。
正确的解决方案步骤
1. 定义与C结构体严格匹配的C#结构体
首先要确保C#侧的结构体和C侧内存布局完全一致,用IntPtr对应size_t(IntPtr大小会自动适配32/64位平台):
假设你的C结构体定义是:
typedef struct { size_t string_count; char** string_array; } ConfigStruct;
对应的C#结构体应该这样写:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct ConfigStruct { // 用IntPtr对应C的size_t,自动适配平台指针大小 public IntPtr StringCount; // 对应C的char** public IntPtr StringArrayPtr; }
2. 正确解析返回的结构体指针
不要手动计算字段偏移,直接用Marshal.PtrToStructure把C返回的结构体指针解析成C#结构体实例,彻底避免手动偏移的错误:
public Dictionary<string, string> ConvertConfigStructToDict(IntPtr structPtr) { // 直接把C的结构体指针marshal成C#结构体对象 ConfigStruct config = Marshal.PtrToStructure<ConfigStruct>(structPtr); // 把IntPtr类型的count转成整数(自动适配平台) int count = (int)config.StringCount; // 获取char**的指针 IntPtr stringsPtr = config.StringArrayPtr; // 调用你的ConvertStringArray方法处理字符串数组 string[] stringArray = ConvertStringArray(stringsPtr, count); // 假设字符串数组是键值对形式,转成字典 var configDict = new Dictionary<string, string>(); for (int i = 0; i < count; i += 2) { if (i + 1 < count) configDict[stringArray[i]] = stringArray[i + 1]; } return configDict; }
3. 确保ConvertStringArray的逻辑正确
你的ConvertStringArray单独测试char**时正常,但结合结构体使用时要注意:每个元素是char*的指针,需要先读取指针地址再转成字符串:
public string[] ConvertStringArray(IntPtr arrayPtr, int count) { string[] result = new string[count]; for (int i = 0; i < count; i++) { // 读取第i个char*的指针地址(每个指针占IntPtr.Size字节) IntPtr strPtr = Marshal.ReadIntPtr(arrayPtr, i * IntPtr.Size); // 把C的char*转成C#字符串 result[i] = Marshal.PtrToStringAnsi(strPtr); // 注意:如果C DLL分配了字符串内存,一定要调用DLL提供的释放函数,避免内存泄漏 } return result; }
额外注意事项
- 平台一致性:确保你的C DLL和C#程序同为32位或64位,否则指针大小不匹配会引发各种内存错误。
- 内存释放:如果C DLL返回的结构体和字符串数组是动态分配的,务必调用DLL提供的释放函数。
- 调用约定:在
DllImport时指定正确的CallingConvention(比如Cdecl),和C DLL的编译约定保持一致。
内容的提问来源于stack exchange,提问作者KrissCode
相关产品推荐
相关产品推荐

