我正在一个大型非托管C ++库和一个大型C#库上开发一个瘦托管C ++包装器。我需要捕获源自该大型非托管C ++库的错误,并将它们重新抛出为Clr异常。非托管库抛出以下类的实例:
Error::Error(const std::string& file, long line,
const std::string& function,
const std::string& message) {
message_ = boost::shared_ptr<std::string>(new std::string(
format(file, line, function, message)));
}
const char* Error::what() const throw () {
return message_->c_str();
}
到目前为止,我已经想出了这个:
try{
// invoke some unmanaged code
}
catch(Object*)
{
throw gcnew System::Exception("something bad happened");
}
如何从Error类中提取消息并将其转换为Clr String类,以便将其传递给gcnew System :: Exception()构造函数? 如果非托管代码抛出其他内容,我的catch块是否会捕获它?
编辑:我使用的是catch(Object *),因为它是recommended in MCDN
答案 0 :(得分:9)
以下内容对您不起作用吗?
try
{
// invoke some unmanaged code
}
catch (Error const& err)
{
throw gcnew System::Exception(gcnew System::String(err.what()));
}
因为这对我来说当然有用:
#pragma managed(push, off)
#include <string>
struct Error
{
explicit Error(std::string const& message) : message_(message) { }
char const* what() const throw() { return message_.c_str(); }
private:
std::string message_;
};
void SomeFunc()
{
throw Error("message goes here");
}
#pragma managed(pop)
int main()
{
using namespace System;
try
{
try
{
SomeFunc();
}
catch (Error const& err)
{
throw gcnew Exception(gcnew String(err.what()));
}
}
catch (Exception^ ex)
{
Console::WriteLine(ex->ToString());
}
Console::ReadLine();
}
答案 1 :(得分:4)
我用
#include <exception>
#include <msclr\marshal.h>
using namespace System;
using namespace msclr::interop;
try
{
...
}
catch (const std::exception& e)
{
throw gcnew Exception(marshal_as<String^>(e.what()));
}
catch (...)
{
throw gcnew Exception("Unknown C++ exception");
}
您可能希望将其放入一对宏中,因为它们将在任何地方使用。
您可以使用catch
类添加自定义Error
块,但由于它似乎来自std::exception
,因此我向您展示的代码应该没问题。
您可能还想更具体地捕捉std::invalid_argument
并将其翻译为ArgumentException
等等,但我觉得这有点过分。
答案 2 :(得分:2)
我唯一可靠的方法来捕获大多数非托管异常是catch(...),它不会给你任何重新抛出的信息,但会阻止大多数崩溃。还有一些例外,即使没有崩溃指示器(应用程序只是消失),即使捕获(...)也不会捕获并且会使应用程序崩溃,就像一个写得不好的第三方应用程序使用SetJump / LongJump错误错误处理或线程协议。
如果您想尝试键入许多C ++异常,可以编写一系列很长的catch块,例如:
catch (int i)
{
// Rethrow managed with int data
}
catch (double d)
{
// Rethrow managed with double data
}
... etc
catch (...)
{
// Rethrow managed "I got a general exception" error
}