2013-12-16 13 views
5

Używam niezarządzanego DLL z funkcją, która rzuca std::exception.Złap niezarządzanego dll wyjątku w .NET

Używam wrapper .NET DLL, aby można go było rozpowszechniać w programach .NET.

Chciałbym móc złapać się komunikat z natywnym wyjątkiem ale jestem coraz to System.Runtime.InteropServices.SEHException("External component has thrown an exception.")

Czy istnieje jakiś sposób, aby propagować szczegóły wyjątek? Może powinienem wyeksportować niestandardowy wyjątek z macierzystej biblioteki DLL? Jak to zrobić?

Dzięki

rodzimy DLL:

__declspec(dllexport) void __stdcall W32DLLFunc(int param) { 
    if (param < 0) { 
    throw new exception("Error: param must be > 0"); 
    } 
    ... 
} 

.net DLL:

[DllImport("nw32.dll", CharSet = CharSet::Auto)] 
static void W32DLLFunc(int param); 

Program vb.net:

Try 
    W32DLLFunc(-1) 
Catch ex As Exception 
    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) 
End Try 

Odpowiedz

2

wyjątki macierzystym C++ wyjątki macierzystym C++. Nie działają z rzeczami, które nie są w C++. Nawet nie działają między różnymi wersjami C++.

Natywne wyjątki C++ nie są dobre dla interoperacyjności.

Standardowym mechanizmem zwracania informacji o błędzie z bibliotek DLL jest zwrócenie wartości wskazującej na sukces lub niepowodzenie oraz użycie SetLastError i w celu przekazania kodu błędu, jeśli funkcja nie działa.

Jeśli chcesz, aby standardowy mechanizm zwracał więcej informacji niż kod błędu, musisz sprawdzić COM, który ma IErrorInfo.

Ale byłoby prostsze po prostu zdefiniować niektóre kody błędów.

Jeśli to możliwe, zmieniłbym oryginalną bibliotekę DLL, aby nie powodowała żadnych wyjątków. Jeśli jest to niemożliwe, ponieważ istniejący klient C++ zależy od bieżącego projektu, dodałbym równoległy interfejs API: nową wersję każdej wyeksportowanej funkcji, która wywołuje oryginał, przechwytuje wyjątki i zwraca kody błędów. To wszystko, co można ukryć w makrach. Jeśli nie możesz dotknąć biblioteki DLL, dodaję rodzime opakowanie do tłumaczenia wyjątków.

Aktualizacja

Jak sugeruje IInspectable, innym rozwiązaniem jest stworzenie zespołu w trybie mieszanym.

Dodaj klasę .Net do istniejącej biblioteki C++. Powinno to zapewnić opakowanie dla każdej funkcji API, która wywołuje oryginalny interfejs API, przechwytuje każdy wyjątek, kopiuje szczegóły do ​​wyjątku .Net i generuje wyjątek .Net.

Utrzymując wszystkie natywne procedury obsługi wyjątków w bibliotece DLL, unika się problemów z wyjątkami C++ przekraczającymi granice DLL. Zapakowane wyjątki mogą być używane w dowolnym języku .Net bez potrzeby tworzenia deklaracji dla wyeksportowanych funkcji. Jedyną wadą jest to, że potrzebujesz dodatkowego API do współdziałania z innym natywnym kodem.

+0

To prawda, słynny wyjątek "E msc". Usuwam moje komentarze w zamian za przegłosowanie.Nadal można dodać notatkę o pisaniu wrappera C++/CLI do tłumaczenia wyjątków C++ do wyjątków .NET, który wydaje się być najczystszym rozwiązaniem. Zestaw złożony w trybie mieszanym może być używany zarówno przez kod rodzimy, jak i zarządzany. – IInspectable

+0

Pozdrawiam. Pojawiło się opakowanie C++/CLI, ale nie wiedziałem od razu jak natywne wyjątki współdziałają z C++/CLR. [Ten artykuł] (http://msdn.microsoft.com/en-us/library/df24ysb6.aspx) prawie sugeruje, że to zadziała, więc dałem mu wolną rękę i tak jest. Zaktualizowałem swoją odpowiedź. – arx