C#调用C++ DLL返回unsigned char拼接字符串出现乱码如何解决?
错误原因
- C++返回了栈内存地址:你在函数内定义的
unsigned char c[20]是栈上的局部变量,函数执行结束后这块内存会被系统自动回收,返回的指针指向无效内存,访问时自然出现乱码。 - 拼接结果无字符串结束符:C/C++中字符串以
\0作为结束标识,你拼接完成后没有添加该标识,读取逻辑无法判断字符串的结束位置。 - C#端编码不匹配:
Marshal.PtrToStringAuto默认按Unicode(UTF-16)编码读取内存,但是C++中存储的是ASCII编码的字节,编码不一致也会导致乱码。
修复方案
C++端修改
改用堆内存存储拼接结果,添加结束符,同时配套提供内存释放函数避免内存泄漏:
#include <malloc.h> // 拼接函数 _declspec(dllexport) unsigned char * concat_fun(unsigned char a[], unsigned char b[], int d, int e) { int i, ind = 0; // 堆上分配内存,长度为两个数组长度之和+1(存储结束符) unsigned char* c = (unsigned char*)malloc(d + e + 1); for (i = 0; i < d; i++) { c[ind] = a[i]; ind++; } for (i = 0; i < e; i++) { c[ind] = b[i]; ind++; } // 添加字符串结束符 c[ind] = '\0'; return c; } // 配套释放内存的函数 _declspec(dllexport) void free_buffer(unsigned char* buf) { if (buf != NULL) { free(buf); } }
C#端修改
导入内存释放函数,使用对应ASCII编码的方法读取字符串,读取完成后释放C++分配的堆内存:
using System; using System.Runtime.InteropServices; using System.Text; class HelloWorld { [DllImport("cpp_func.dll")] public static extern IntPtr concat_fun(byte[] a,byte[] b, int c, int d); // 导入内存释放函数 [DllImport("cpp_func.dll")] public static extern void free_buffer(IntPtr buf); static void Main() { string hello = "hello", world = "world", final; byte[] hel = Encoding.ASCII.GetBytes(hello); byte[] wor = Encoding.ASCII.GetBytes(world); IntPtr return_value = concat_fun(hel, wor, hel.Length, wor.Length); // 按ASCII编码读取字符串 final = Marshal.PtrToStringAnsi(return_value); Console.WriteLine("Concatenated string:" +final); // 释放C++分配的堆内存,避免泄漏 free_buffer(return_value); Console.Read(); } }
内容的提问来源于stack exchange,提问作者Tespildox
相关产品推荐
相关产品推荐

