2011-07-27 25 views
11

大規模なアンマネージドC++ライブラリと大きなC#ライブラリで、シンマネージドC++ラッパーを開発しています。私はその大きなアンマネージドC++ライブラリに由来するエラーを捕らえ、それらをClr例外として再現する必要があります。私は、エラー・クラスからメッセージを抽出とCLR Stringクラスに変換するにはどうすればよい管理対象C++でアンマネージC++例外をキャッチする方法

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

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

は、これまでのところ、私はこれが出ている:非管理ライブラリーでは、以下のクラスのインスタンスをスローします、私はそれをgcnew System :: Exception()コンストラクタに渡すことができますか? アンマネージドコードが何かをスローした場合、私のcatchブロックはそれをキャッチしますか?

編集:それは私が最も管理されていない例外をキャッチするために作ってみたrecommended in MCDN

+0

'Error'のインスタンスがスローされている場合、なぜあなたは' Object * 'をキャッチしていますか?とにかくこの文脈では 'Object'とは何ですか? – ildjarn

+0

@ildjarn:このオブジェクト*はMSDN –

+0

でアドバイスされました。これはManaged Extensions for C++、C++/CLIには関係ありません。 2つの異なる言語で、 'gcnew'を使っているなら、C++/CLIを使っています。 – ildjarn

答えて

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

唯一の信頼できる方法であるので、私はキャッチ(オブジェクト*)を使用していますが、あなたに与えることはありませんキャッチ(...)ですすべての情報を元に戻しますが、ほとんどのクラッシュを防止します。まだ間違って書かれたサードパーティのアプリケーションが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 
} 
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"); 
} 
を使用しています。

Errorクラスでカスタムcatchブロックを追加することはできますが、std::exceptionから派生しているようだから、コードはOKであることがわかります。

さらに具体的にはstd::invalid_argumentをキャッチしてArgumentExceptionなどに翻訳したいと思うかもしれませんが、私はこの過剰を見つけることができます。