使用 dllexport 传递 std::string

Passing std::string with dllexport

我正在尝试制作某种 C++ "bridge" 以将一端的非托管 C++ dll(不修改其代码)连接到使用 DllImport 进行各种导入的 C# Wrapper。

我能够使用 char 指针将 C# 字符串传递到我的桥,但是接收 Dll 需要接收 std::string,所以我尝试使用 std::string(foo); 但没有成功,它总是被转换变成奇怪的角色。

结构如下:

C# 包装器

[DllImport(@"Bridge.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void initDetector(string foo, int something = 0);

C++ 桥

extern "C" __declspec(dllexport) void initCppClass(char* foo, int something)
{
    std::string bar = std::string(foo);
    std::cout << bar << std::endl; //Returns "foo"
    instance = new CppClass(bar, something);
}

C++导入的DLL(此处不允许更改代码)

CppClass::CppClass(std::string foo, int something)
{
    std::cout << foo << std::endl; //Returns garbage
}

请注意,此构造函数仅用于演示目的,因为我不能透露原始代码。

我最初尝试将 char* 直接传递给构造函数,但这也没有用。我在这里遗漏了什么吗?

我认为问题是不同的字符串编码。

尝试在 C# 中添加 CharSet = CharSet.Ansi,如下所示:

[DllImport(@"Bridge.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]

但是,请阅读该 C++ dll 的文档 API。许多 C++ 代码,尤其是 cross-platform 代码,需要 UTF8 编码的字符串。如果是这种情况,请将桥更改为

extern "C" __declspec(dllexport) void initCppClass(const wchar_t* foo, int something)

并编写代码将字符串从 UTF16 编码的 C 指针转换为 UTF8 编码的 std::string,参见 this answer 示例。

更新:另一个可能的原因是不同的STL,或者不同的CRT。当您跨 DLL 边界传递 std::string 或任何其他 STL 对象对象时,您必须使用相同的编译器和相同的版本,相同的构建设置(例如 VC++,std::string s 内存布局在调试和发布版本之间不同),并且两个 DLL 都必须 link 动态地进行 CRT。,例如Multi-threaded DLL (/MD)