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

C++调用C# DLL时字符串传递乱码问题求助

问题根源与解决步骤

核心问题

C#与C++的字符串确实存在本质差异:

  • C#的string是UTF-16编码的宽字符序列(对应C++的wchar_t*)
  • C++的char*/std::string是ANSI编码的窄字符序列(单字节,编码取决于系统区域设置)
    此外你的代码还存在函数签名不匹配、路径转义错误、调用约定不一致的问题,共同导致了乱码。

具体修复步骤

1. 修正C#的DllExport属性

明确指定字符集和调用约定,让C#导出的函数能正确识别C++传递的字符串类型:

using System.Runtime.InteropServices;
using System.IO;

public class YourClass
{
    // 方案1:接受ANSI窄字符串(对应C++的const char*)
    [DllExport(CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static int AntiMacro([MarshalAs(UnmanagedType.LPStr)] string filepath)
    {
        Console.WriteLine(filepath);
        bool isFolder = false;
        string fullpath = "";
        try
        {
            fullpath = Path.GetFullPath(filepath);
            Console.WriteLine(fullpath);
        }
        catch (Exception)
        {
            Console.WriteLine(fullpath);
            Console.WriteLine("Invalid path 1");
            return 1;
        }
        // 补充你的其他逻辑
        return 0;
    }

    // 方案2:接受Unicode宽字符串(对应C++的const wchar_t*,推荐)
    // [DllExport(CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
    // public static int AntiMacro([MarshalAs(UnmanagedType.LPWStr)] string filepath)
    // {
    //     // 逻辑同上
    // }
}

2. 修正C++代码的函数签名与字符串处理

  • 不能用std::string作为导出函数的参数(C#无法识别C++类类型),必须用C兼容的指针类型
  • 修正路径字符串的转义问题(\要写成\\,或者用C++11的原始字符串)
  • 确保调用约定与C#端一致(这里用__cdecl,和C#的设置匹配)

方案1(对应C#的ANSI版本):

#include "pch.h"
#include <stdio.h>
#include <Windows.h>
#include <string>

int main()
{
    // 修正路径转义:用双反斜杠
    const char* pemodule = "C:\\Users\\source\\repos\\ClassLibrary2\\ClassLibrary2\\bin\\Debug\\ClassLibrary2.dll";
    HMODULE hlib = LoadLibraryA(pemodule);
    if (!hlib) {
        printf("Failed to load DLL\n");
        return 1;
    }

    // 函数签名改为接受const char*,调用约定__cdecl
    typedef int(__cdecl* AntiMacro)(const char* path);
    auto pAntiMacro = (AntiMacro)GetProcAddress(hlib, "AntiMacro");
    if (!pAntiMacro) {
        printf("Failed to get proc address\n");
        FreeLibrary(hlib);
        return 1;
    }

    // 修正路径转义
    const char* path = "C:\\macro\\test";
    int a = pAntiMacro(path);
    printf("%d\n", a);

    FreeLibrary(hlib);
    return 0;
}

方案2(对应C#的Unicode版本,推荐,避免编码依赖):

C#端用CharSet.Unicode和LPWStr,C++代码改为:

#include "pch.h"
#include <stdio.h>
#include <Windows.h>
#include <wchar.h>

int main()
{
    const wchar_t* pemodule = L"C:\\Users\\source\\repos\\ClassLibrary2\\ClassLibrary2\\bin\\Debug\\ClassLibrary2.dll";
    HMODULE hlib = LoadLibraryW(pemodule);
    if (!hlib) {
        wprintf(L"Failed to load DLL\n");
        return 1;
    }

    typedef int(__cdecl* AntiMacro)(const wchar_t* path);
    auto pAntiMacro = (AntiMacro)GetProcAddress(hlib, "AntiMacro");
    if (!pAntiMacro) {
        wprintf(L"Failed to get proc address\n");
        FreeLibrary(hlib);
        return 1;
    }

    const wchar_t* path = L"C:\\macro\\test";
    int a = pAntiMacro(path);
    wprintf(L"%d\n", a);

    FreeLibrary(hlib);
    return 0;
}

3. 额外注意事项

  • 确保C# DLL编译时的平台(x86/x64)与C++程序一致,否则会加载失败
  • 如果使用DllExport库,要确保版本正确,且已正确配置导出设置
  • 路径中的转义字符必须处理,否则会被解析为特殊字符(比如\t是制表符,\U是Unicode转义)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:45:08