C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#与C++字符串互操作

C#与C++字符串互操作的三种常见问题及解决方案

作者:你一身傲骨怎能输

这篇文章主要为大家详细介绍了C++与C#互操作时处理字符串的三种常见问题及解决方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

本文总结了C++与C#互操作时处理字符串的三种常见问题及解决方案。针对内存布局不同,推荐使用C风格字符串(char*)作为桥梁;生命周期管理可采用调用方负责分配/释放或只传递数据所有权的方案;编码问题建议统一使用UTF-8或UTF-16。核心原则是:C++接口只暴露C风格字符串,C#通过P/Invoke配合Marshal类进行转换,并明确内存管理责任。这种模式能有效解决跨语言字符串传递的兼容性问题。

1. 内存布局不同的应对方法

方案:使用C风格字符串(char)作为桥梁*

示例

C++侧:

extern "C" __declspec(dllexport) void PrintMessage(const char* msg) {
    printf("C++ received: %s\n", msg);
}

C#侧:

[DllImport("mylib.dll", CharSet = CharSet.Ansi)]
public static extern void PrintMessage(string msg);

PrintMessage("Hello from C#");

说明:这样C#的string会被自动转换为C风格字符串,C++端用const char*接收,避免了内存布局不兼容的问题。

2. 生命周期不同的应对方法

方案A:由调用方负责分配和释放内存

C++返回的字符串用malloc分配,C#用完后调用C++提供的释放函数。

示例

C++侧:

extern "C" __declspec(dllexport) char* GetMessage() {
    const char* msg = "Hello from C++";
    char* buffer = (char*)malloc(strlen(msg) + 1);
    strcpy(buffer, msg);
    return buffer;
}

extern "C" __declspec(dllexport) void FreeMessage(char* ptr) {
    free(ptr);
}

C#侧:

[DllImport("mylib.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetMessage();

[DllImport("mylib.dll", CharSet = CharSet.Ansi)]
public static extern void FreeMessage(IntPtr ptr);

IntPtr ptr = GetMessage();
string msg = Marshal.PtrToStringAnsi(ptr);
Console.WriteLine(msg);
FreeMessage(ptr); // 释放内存

方案B:只传递数据,不传递所有权

只在C++内部用std::string,导出接口时用const char*,不让C#负责释放。

3. 编码不同的应对方法

方案A:统一使用UTF-8编码

C++用UTF-8字符串,C#用CharSet = CharSet.AnsiCharSet = CharSet.Unicode,并用Marshal类做编码转换。

示例

C++侧:

extern "C" __declspec(dllexport) const char* GetUtf8Message() {
    return u8"你好,世界!"; // UTF-8字符串
}

C#侧:

[DllImport("mylib.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetUtf8Message();

IntPtr ptr = GetUtf8Message();
string msg = Marshal.PtrToStringUTF8(ptr); // .NET 5+ 支持
Console.WriteLine(msg);

如果用.NET Framework,可以用第三方库或手动转换。

方案B:C#传递UTF-16,C++用wchar_t*接收

C++接口用wchar_t*,C#用CharSet = CharSet.Unicode

示例

C++侧:

extern "C" __declspec(dllexport) void PrintWideMessage(const wchar_t* msg) {
    wprintf(L"C++ received: %ls\n", msg);
}

C#侧:

[DllImport("mylib.dll", CharSet = CharSet.Unicode)]
public static extern void PrintWideMessage(string msg);

PrintWideMessage("你好,世界!");

总结

推荐的通用模式

C++接口只用C风格字符串(char 或 wchar_t),不暴露std::string。**

C#用P/Invoke声明,配合Marshal类做编码转换。

涉及内存分配时,C++提供释放函数,C#用完后主动释放。

到此这篇关于C#与C++字符串互操作的三种常见问题及解决方案的文章就介绍到这了,更多相关C#与C++字符串互操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文