2011-07-27 9 views
11

Estoy desarrollando un contenedor de C++ administrado fino sobre una gran biblioteca de C++ no administrada y una gran biblioteca de C#. Necesito detectar los errores que se originan en esa gran biblioteca C++ no administrada, y volver a lanzarlos como excepciones Clr. La biblioteca no administrado lanza instancias de la clase siguiente:Cómo atrapar la excepción de C++ no administrada en C++ administrado

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

Hasta aquí he llegado con esto:

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

¿Cómo extraer el mensaje de la clase de error y la convierten en la clase Clr Cadena , para poder pasarlo al nuevo constructor System :: Exception()? Si el código no administrado arroja algo más, ¿atrapará mi captura?

Editar: Estoy utilizando la captura (Object *), ya que es recommended in MCDN

+0

Si se lanzan instancias de 'Error', ¿por qué atrapa' Objeto * '? ¿Y qué es 'Object' en este contexto de todos modos? – ildjarn

+0

@ildjarn: este objeto * se notificó en MSDN –

+0

Esto es relevante para las Extensiones administradas para C++, no para C++/CLI. Dos idiomas diferentes, y dado que está usando 'gcnew', está usando C++/CLI. – ildjarn

Respuesta

9

¿El siguiente trabajo no para usted?

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

Debido a esto ciertamente funciona para mí:

#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

La única manera confiable que he llegado con más de atrapar excepciones sin gestionar es la captura (...), que no le dará cualquier información para volver a lanzar, pero evitará la mayoría de los bloqueos. Todavía hay algunas excepciones que incluso detectan (...) no detectarán y bloquearán su aplicación, incluso sin un indicador de bloqueo (la aplicación simplemente desaparece), como si una aplicación de terceros mal escrita utilizara SetJump/LongJump con el error. manejo de errores o protocolos de hilos.

podría escribir una larga serie de bloques de captura si se quería tratar de escribir muchas excepciones de C++, como:

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

utilizo

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

Es posible que desee poner esto en un par de macros ya que va a ser utilizado por todas partes.

se puede añadir un bloque personalizado catch con su clase Error, pero ya que parece derivar de std::exception, el código muestro debe estar bien.

También podría querer atrapar más específicamente std::invalid_argument y traducirlo a ArgumentException, etc. pero me parece excesivo.

Cuestiones relacionadas