You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用带C包装层的C++ DLL传递字符串乱码问题求助

解决C#调用C++ DLL时字符串传递的乱码问题

这个乱码问题我之前也碰到过,核心原因是C#与C/C++之间的字符串编码不匹配——C#的string默认是UTF-16(双字节Unicode),但你的C/C++代码用的是char*(单字节ANSI编码),跨边界传递时没有做正确的编码转换,导致内存解析错误,就出现了那些乱码字符。下面给你几个可行的解决方案:

方案一:修改C#端的编码匹配(最快解决)

直接在DllImport中指定字符集为ANSI,让C#自动把UTF-16字符串转换成ANSI编码的char*传递给DLL,完美匹配你的现有C/C++代码:

[DllImport(DllName, CallingConvention = DllCallingConvention, CharSet = CharSet.Ansi)]
public static extern IntPtr AllocateHandle(string filename);

这样修改后,C#会自动处理编码转换,你的C++构造函数里直接把char*赋值给std::string就不会有乱码了。

方案二:改用Unicode宽字符(推荐,支持多语言)

如果你的程序需要支持中文、日文等非ASCII字符,推荐改用宽字符方案,从根本上避免编码问题:

  1. 修改C包装层代码:把char*换成wchar_t*
LPVOID SAMPLEDLL_API CALLCONV_API AllocateHandle(wchar_t* filename);
  1. 修改C++类构造函数:用std::wstring存储宽字符
#include <string>
CustomData::CustomData(wchar_t* filename) {
    _filename = std::wstring(filename); // 改为std::wstring类型存储
}
  1. 修改C#端的DllImport:指定Unicode字符集(其实C#默认就是Unicode,明确写出来更清晰)
[DllImport(DllName, CallingConvention = DllCallingConvention, CharSet = CharSet.Unicode)]
public static extern IntPtr AllocateHandle(string filename);

如果之后需要把宽字符串转成窄字符串输出到文件,可以用C++11的std::wstring_convert,或者Windows API的WideCharToMultiByte来做转换。

方案三:手动在C#端转换编码(不修改DLL时用)

如果暂时不想改动DLL代码,可以在C#端手动把字符串转成ANSI字节数组,再传递指针给DLL:

public static IntPtr AllocateHandle(string filename)
{
    // 把字符串转成ANSI编码的字节数组,必须加上'\0'终止符
    byte[] ansiBytes = System.Text.Encoding.Default.GetBytes(filename + '\0');
    // 分配非托管内存
    IntPtr ptr = Marshal.AllocHGlobal(ansiBytes.Length);
    Marshal.Copy(ansiBytes, 0, ptr, ansiBytes.Length);
    
    try
    {
        // 调用原生DLL函数
        return NativeAllocateHandle(ptr);
    }
    finally
    {
        // 必须释放非托管内存,避免内存泄漏
        Marshal.FreeHGlobal(ptr);
    }
}

// 内部调用的原生函数,参数为IntPtr
[DllImport(DllName, CallingConvention = DllCallingConvention)]
private static extern IntPtr NativeAllocateHandle(IntPtr filename);

额外注意事项

  • 不管用哪种方案,都要确保传递的字符串是以\0(空字符)终止的——C/C++的char*/wchar_t*依赖空终止符来识别字符串长度。
  • 保存_filename到文件时,要匹配存储的字符串类型:比如用std::string就用普通的fopen/printf输出;用std::wstring则需要用_wfopen/fwprintf这类宽字符输出函数。

内容的提问来源于stack exchange,提问作者Mathieu Gauquelin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:49:26