C接口 中文字符问题
- [1. C接口字符串传递](#1. C接口字符串传递)
- [2. 示例代码](#2. 示例代码)
-
- [2.1. 基本C接口字符传递(不支持中文)](#2.1. 基本C接口字符传递(不支持中文))
- [2.2. C接口中文字符传递(支持中文)](#2.2. C接口中文字符传递(支持中文))
1. C接口字符串传递
在使用 C/C++ 编写 DLL 并通过 C# 调用时,常见的跨语言字符串传递方式是通过 const char*。但在涉及中文路径或文件名等含有非 ASCII 字符的情况时,如果编码方式处理不当,可能会出现乱码或崩溃问题。
本篇文章将详细讲解如何通过 const char* 实现 UTF-8 编码的中文字符传递,适配中英文路径,并在 C# 和 C++ 之间安全传参。
主要问题汇总:
问题 | 错误做法 | 正确做法 |
---|---|---|
中文乱码 | 直接传 string / char* |
使用 UTF-8 编码 + 手动传递 IntPtr |
编码不统一 | 使用默认编码(如 ANSI) | 明确使用 UTF-8 编码 |
控制台乱码 | 默认编码输出中文 | 设置 SetConsoleOutputCP(CP_UTF8) |
2. 示例代码
2.1. 基本C接口字符传递(不支持中文)
以char*作为字符串之间的传递
cpp
#define DLL_EXPORT __declspec(dllexport)
#define DLL_IMPORT __declspec(dllimport)
extern "C" {
DLL_EXPORT int SetFile(const char* filePath) {
std::cout << "filePath:" << filePath << std::endl;
}
} // extern "C"
2.2. C接口中文字符传递(支持中文)
为了支持中文字符,我们需要:
- 保证 C# 传入的是 UTF-8 编码的字节流
- 在 C++ 端以 UTF-8 的方式接收和处理
cpp
#define DLL_EXPORT __declspec(dllexport)
#define DLL_IMPORT __declspec(dllimport)
extern "C" {
DLL_EXPORT int SetFile(const char* filePath) {
std::string utf8_path(stpPath);
std::cout << "filePath:" << utf8_path<< std::endl;
}
} // extern "C"
C#端调用示例
csharp
using System;
using System.Text;
using System.Runtime.InteropServices;
class Program
{
// 指定调用约定和 ANSI 编码,但我们传入的是 UTF-8 字节,所以用 IntPtr 更安全
[DllImport("YourDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SetFile(IntPtr filePath);
static void Main()
{
string filePath = "C:\\测试\\文件.txt";
// 编码为 UTF-8 字节数组(带末尾 null 终止符)
byte[] utf8Bytes = Encoding.UTF8.GetBytes(filePath + "\0");
// 分配非托管内存
IntPtr unmanagedPtr = Marshal.AllocHGlobal(utf8Bytes.Length);
try
{
Marshal.Copy(utf8Bytes, 0, unmanagedPtr, utf8Bytes.Length);
// 调用 C 接口
SetFile(unmanagedPtr);
}
finally
{
Marshal.FreeHGlobal(unmanagedPtr); // 释放内存
}
}
}
✅ 说明:
- 使用 Encoding.UTF8.GetBytes() 确保传入的是 UTF-8 编码。
- 自行添加 \0 终止符,防止 C++ 接口访问越界。
- 使用 IntPtr 而不是 string,避免编码转换的干扰。