我在C#调用的标准C++库周围有一个C++-CLR包装器。为了从库中接收状态消息,我通过Marshal::GetFunctionPointerForDelegate在C++代码中使用了一个分配给回调的委托。
这花了我相当多的时间才开始工作,我非常,非常接近(我认为)。调用了C#委托,但字符串未正确传递到边界。
当我从C++代码中调用TakesCallback(“测试字符串”)时,在C#函数中得到的只是垃圾。
-原始C++类和回调函数
class Solver
{
private:
std::string TakesCallback(const std::string message)
{
return cb(message);
}
public:
// Declare an unmanaged function type that takes a string
typedef std::string (__stdcall* ANSWERCB)(const std::string);
ANSWERCB cb;
};-从托管包装设置回调的函数
// Set the delegate callback
void ManagedSolver::SetMessageCallback(SendMessageDelegate^ sendMessageDelegate)
{
_sendMessage = sendMessageDelegate;
// Use GetFunctionPointerForDelegate to get the pointer for delegate callback
IntPtr ip = Marshal::GetFunctionPointerForDelegate(sendMessageDelegate);
_solver->cb = static_cast<Solver::ANSWERCB>(ip.ToPointer());
} -传递给C++ \ CLR包装器SetMessageCallBack的C#函数
private void Message(string message)
{
XtraMessageBox.Show(message, "Done", MessageBoxButtons.OK);
}发布于 2011-04-26 09:29:04
C++ std::string和.NET System::String不可互换。C#不能使用第一个,本机C++代码也不能使用第二个。您需要的是一个接受std::string并在调用委托之前将其转换为System::String^的C++/CLI函数。
发布于 2011-04-26 09:00:17
我已经使用the code from this page好几个月了,我发现它非常好用。它只是一个可以跨项目复制的头文件,它可以快速而干净地完成这项工作。
您可以使用例如
std::wstring s = clix::marshalString<E_UNICODE>(myCliString);或
System::String^ s = clix::marshalString<E_ANSI>(mystdstring);它可以双向工作,让你指定你想要的编码方式(ANSI、UTF8或Windows-实际上是UTF16)。
发布于 2011-04-26 08:47:09
通常,不能将标准c++类编组到C#中,也不能将其编组出c++。如果您将C++代码构建为Unicode,我建议您将代码更改为以下代码:
C++
// Declare an unmanaged function type that takes a string
typedef int (__stdcall* ANSWERCB)(LPCTSTR);C#
private void Message([MarshalAs(UnmanagedType.LPWStr)]string message)
{
XtraMessageBox.Show(message, "Done", MessageBoxButtons.OK);
}看一下下面的example from MSDN
https://stackoverflow.com/questions/5784571
复制相似问题