C# 如何转换C++/CLI字符串到常量字符* 我有一个C++/CLI DLL,我打算用它作为C++的一个适配器和本地C++客户端之间的适配器。我需要在两个方向传递字符串。适配器是用VS2013编译的,但需要支持用VS2008构建的客户端,所以我在API中使用const char*。但即使两个都是VS2013构建的,我得到的也不起作用
在别处,我找到了使用msclr\marshal.h的建议,因此我创建了:C# 如何转换C++/CLI字符串到常量字符* 我有一个C++/CLI DLL,我打算用它作为C++的一个适配器和本地C++客户端之间的适配器。我需要在两个方向传递字符串。适配器是用VS2013编译的,但需要支持用VS2008构建的客户端,所以我在API中使用const char*。但即使两个都是VS2013构建的,我得到的也不起作用,c#,c++,c,dll,C#,C++,C,Dll,在别处,我找到了使用msclr\marshal.h的建议,因此我创建了: using namespace msclr::interop; System::String^ ToCliString(const char* s) { System::String ^result = marshal_as<System::String^>(s); return result; } const char* ToCppString(System::String^ s) {
using namespace msclr::interop;
System::String^ ToCliString(const char* s)
{
System::String ^result = marshal_as<System::String^>(s);
return result;
}
const char* ToCppString(System::String^ s)
{
msclr::interop::marshal_context context;
const char* result = context.marshal_as<const char*>(s);
return result;
}
当本地C++客户端调用FO(“abc”)时,第一个消息被显示,“返回的其他消息”被显示,客户端接收到垃圾邮件。看来我的第二次转换不起作用了
更新 这是我使用的最终解决方案 我使用zneaks的建议将marshall改为std::string,并使用PaulMcKenzie的建议将调用方分配的char*传递给调用方,而不是返回const char*。谢谢你们两位void ToCppString(System::String^ input, char* output)
{
std::string temp= marshal_as<std::string>(input);
strcpy(output, temp.c_str());
}
void Foo(const char* input, char* output)
{
System::String^ cli = ::ToCliString(input);
::ToCppString(cli, output);
}
void tocpstring(系统::String^输入,char*输出)
{
std::string temp=marshal_as(输入);
strcpy(输出,温度c_str());
}
void Foo(常量字符*输入,字符*输出)
{
系统::字符串^cli=::ToCliString(输入);
::tocpString(cli,输出);
}
问题在于封送上下文
拥有您获得的字符指针,因此:
此示例创建一个上下文,用于从System::String封送到const char*变量类型。在删除上下文的行之后,转换的数据将无效
考虑改用,因为允许字符串在
封送\u上下文
之外存在,请注意VC++2008 express不包含封送头文件(marshal.h和其他文件),因此您必须使用VC++2008 pro或更高版本。看起来,自从VS2010以来,这些头文件都包含在Express版本中。你返回一个指向本地变量的指针<代码> cSt2,这是未定义的行为。@ PulcMcKeZi]因此,将一个字符串从C ^传递到本地C++客户端,客户端需要通过一个字符适配器适配器“填充”,这是通常的方式。客户端提供缓冲区,C++代码将缓冲区填充到数据中。@ PulcMcKeZee客户端是否需要调用Delphi来防止内存泄漏?我想他们可以分配一次缓冲区,在我的API中调用许多函数,并在完成后删除。所以我的API应该包含另一个parm,这样他们就可以告诉我可以返回的最大消息大小了?或者更适合让属性客户端可以查询以确定我的最大消息长度?客户端负责正确维护缓冲区。它可能被分配了new[]/delete[]
,它甚至可能是一个std::vector
,您正在传递std::vector::data()
,等等。我刚刚尝试用std::string result=context.marshal_as替换tocpstring的最后两行;返回result.c_str();但同样的结果。我想知道,既然本地std::string超出了作用域,那么它的c_str()函数返回的值是否仍然有效?明白了,现在在新参数中使用strcpy。稍后将发布我的解决方案。@JimC,是的,c_str()
返回的指针归字符串所有,并在函数返回时解除分配,因此您基本上又遇到了相同的问题。不过,您可以返回一个std::string
。我可以,但这只是在踢罐子,因为我无法将std::string全部返回到应用程序(我必须支持使用不同版本的Visual Studio构建的应用程序)。请小心自己删除字符串。
void ToCppString(System::String^ input, char* output)
{
std::string temp= marshal_as<std::string>(input);
strcpy(output, temp.c_str());
}
void Foo(const char* input, char* output)
{
System::String^ cli = ::ToCliString(input);
::ToCppString(cli, output);
}