使用 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)
我正在尝试制作某种 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)