Как отловить неуправляемое исключение C ++ в управляемом C ++ - PullRequest
11 голосов
/ 27 июля 2011

Я разрабатываю тонкую управляемую оболочку 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 это?

Ответы [ 3 ]

9 голосов
/ 28 июля 2011

Вам не подходит следующее?

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();
}
4 голосов
/ 28 июля 2011

Я использую

#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 голосов
/ 27 июля 2011

Единственный надежный способ обнаружения большинства неуправляемых исключений - это catch (...), который не даст вам никакой информации для повторного выброса, но предотвратит большинство сбоев. Есть все еще некоторые исключения, которые даже catch (...) не поймают и будут вызывать сбой вашего приложения, даже без индикатора сбоя (приложение просто исчезает), например, если плохо написанное стороннее приложение использует SetJump / LongJump с неправильным обработка ошибок или протоколы потоков.

Вы можете написать длинную серию блоков catch, если хотите попытаться напечатать много исключений C ++, например:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...