2011-07-27 16 views
11

Zajmuję się tworzeniem cienkiego zarządzanego opakowania C++ w dużej niezarządzanej bibliotece C++ i dużej biblioteki C#. Muszę złapać błędy pochodzące z tej dużej niezarządzanej biblioteki C++ i ponownie je zgłosić jako wyjątki Clr. Niezarządzanego biblioteki rzuca instancji następujących klas:Jak wychwycić niezarządzanego wyjątek C++ w zarządzanym C++

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(); 
} 

tej pory mają pochodzić z tego:

try{ 
// invoke some unmanaged code 
} 
catch(Object*) 
{ 
throw gcnew System::Exception("something bad happened"); 
} 

Jak wyodrębnić wiadomości z klasy Error i przekształcić ją w klasie Clr String , aby przekazać go do gcnew Konstruktor System :: Exception()? Jeśli niezarządzany kod rzuca coś innego, czy mój blok catch go złapie?

Edycja: używam catch (Object *), ponieważ jest to recommended in MCDN

+0

Jeśli są zgłaszane instancje 'Error', dlaczego łapiesz' Object * '? A czym właściwie jest "Object" w tym kontekście? – ildjarn

+0

@ildjarn: ten obiekt * był zalecany na MSDN –

+0

Jest to istotne dla Managed Extensions dla C++, nie C++/CLI. Dwa różne języki i biorąc pod uwagę, że używasz 'gcnew', używasz C++/CLI. – ildjarn

Odpowiedz

9

Czy nie następuje pracować dla Ciebie?

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

Bo to na pewno działa na mnie:

#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(); 
} 
2

Jedynym niezawodnym sposobem mam wymyślić złapać najbardziej niezarządzanymi wyjątki to catch (...), który nie daje wszelkie informacje do ponownego wrzucenia, ale zapobiegną większości wypadków. Nadal istnieją pewne wyjątki, które nawet złapią (...) nie złapią i spowodują awarię aplikacji, nawet bez wskaźnika awarii (aplikacja po prostu znika), tak jakby źle napisana aplikacja innej firmy używała SetJump/LongJump z błędem obsługa błędów lub protokoły wątków.

można napisać długą serię bloków catch jeśli chciał spróbować wpisać wiele wyjątków C++, jak:

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 
} 
4

używam

#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"); 
} 

Możesz umieścić to w parę makr ponieważ zostaną one wykorzystane wszędzie.

Możesz dodać niestandardowy blok z klasą Error, ale ponieważ wydaje się, że pochodzi z std::exception, kod, który pokazuję powinien być w porządku.

Możesz również chcieć złapać bardziej szczegółowo std::invalid_argument i przetłumaczyć go na ArgumentException itp., Ale uważam, że jest to przesada.

Powiązane problemy