如何在托管C ++中捕获非托管C ++exception

我正在一个大型非托管C ++库和一个大型C#库上开发一个瘦托管C ++包装器。 我需要捕获源自大型非托管C ++库的错误,并将它们重新抛出为Clrexception。 非托管库抛出以下类的实例:

Error::Error(const std::string& file, long line, const std::string& function, const std::string& message) { message_ = boost::shared_ptr(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 *),因为在MCDN中建议使用它

以下不适合您吗?

 try { // invoke some unmanaged code } catch (Error const& err) { throw gcnew System::Exception(gcnew System::String(err.what())); } 

因为这对我来说当然有用:

 #pragma managed(push, off) #include  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(); } 

我用

 #include  #include  using namespace System; using namespace msclr::interop; try { ... } catch (const std::exception& e) { throw gcnew Exception(marshal_as(e.what())); } catch (...) { throw gcnew Exception("Unknown C++ exception"); } 

您可能希望将其放入一对宏中,因为它们将在任何地方使用。

您可以使用Error类添加自定义catch块,但由于它似乎派生自std::exception ,因此我向您展示的代码应该没问题。

您可能还想更具体地捕获std::invalid_argument并将其转换为ArgumentException等,但我发现这有点过分。

我想出来捕获大多数非托管exception的唯一可靠方法是catch(…),它不会给你任何重新抛出的信息,但会阻止大多数崩溃。 甚至还有一些例外,即使没有崩溃指示器(应用程序只是消失),即使捕获(…)也不会捕获并且会使应用程序崩溃,就像一个写得不好的第三方应用程序使用SetJump / LongJump错误error handling或线程协议。

如果你想尝试输入许多C ++exception,你可以写一长串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 }