2014-09-09 7 views
5

Czy można wywołać funkcję rzucania C# z wywołania C++ w aplikacji C#, tak aby stos C++ został odpowiednio rozwinięty? Czy jest jakaś dokumentacja tego?Jak wywołać funkcję C# z C++ w aplikacji C#, tak aby stos C++ został odpowiednio rozwinięty?

Na przykład, należy rozważyć ten kod C#:

using System; 

public class Test 
{ 
    public static void CalledFromCpp() 
    { 
     throw new Exception("Is this safe? Is C++ stack unwound properly?"); 
    } 

    public static void Main() 
    { 
     try { 
      CppFunc(CalledFromCpp); 
     } 
     catch(Exception e) 
     { 
      Console.Writeline("Exception e: {0}", e); 
     } 
    } 

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    delegate void CsFuncToBeCalledFromCpp(); 

    [DllImport("CppApp", CallingConvention = CallingConvention.Cdecl)] 
    private static extern void 
    CppFunc(CsFuncToBeCalledFromCpp callback); 
} 

Wraz z tym C++ Kod:

void CppFunc(void (*handler)) 
{ 
    SomeResourceWrappingClass releasesResourceOnDestruction(); 
    handler(); 
} 

Próbowałem to uwagę, a C# wyjątek został złapany pomyślnie, ale releasesResourceOnDestruction nie zrobił” t ma wywoływany destruktor. Wydaje się to wskazywać, że stos C++ nie jest odpowiednio rozwijany - czy można go tutaj odpowiednio odpiąć? Czy istnieje dokumentacja dotycząca tego zachowania?

Dla kontekstu: Chcę czasami wyzwalać wyjątek C# z kodu C++, jeśli to możliwe, tak, że nie potrzebuję każdego wywołania z C# do C++, muszę coś sprawdzić później, aby sprawdzić, czy wyjątek C# musi zostać zgłoszony.

+0

Skąd wiesz, że destruktor 'releasesResourceOnDestruction' nie został wywołany? – 101010

+0

Konieczne będzie wyłączenie optymalizacji używanej przez kompilator C++, gdy nie zostanie wyświetlony wyjątek C++. Project + Properties, C/C++, Generowanie kodu, Włącz C++ Exceptions =/EHa. Faktycznie wychwycenie wyjątku wymaga użycia niestandardowego __try/__ oprócz słów kluczowych. Jest * bardzo * mało sensowne, co możesz zrobić, wszystkie informacje potrzebne do zdiagnozowania wyjątku zostały utracone. To będzie pomocna rozmowa telefoniczna od użytkownika, który jest ciężko odpowiedzieć. –

+0

40two: Dodałem instrukcję drukowania zarówno do konstruktora, jak i destruktora wydaniaResourceOnDestruction. Contructor drukuje, ale destruktor nigdy tego nie robi. – JDiMatteo

Odpowiedz

2

Spróbuj włączyć Structured Exception Handling w swoim projekcie C++ (Właściwości projektu -> C/C++ -> Generowanie kodu -> Włącz wyjątki C++ -> "Tak z wyjątkami SEH (/ EHa)"). Bez wyjątków SEH wyjątek zwracany do warstwy C++ nie ma wystarczających informacji, aby odpowiednio rozwinąć stos.

+1

Istnieje wiele opcji w wyjątkach C++. Należy wybrać "Tak z SEH Exceptions (/ EHa)". – Velox

+1

Velox, czy widzisz potencjalne problemy z tym podejściem? Druga odpowiedź sugerowała, że ​​dziwne rzeczy mogłyby się zdarzyć, gdyby wyjątek nie został złapany. Należy również rozważyć przeniesienie wyjaśnienia dotyczącego "/ EHa" w komentarzu do odpowiedzi. – JDiMatteo

+1

Problemy, które widzę z tym podejściem: 1 - Będziesz musiał mieć klauzulę catch, aby złapać wyjątek, albo twój program ulegnie awarii z powodu nieobsługiwanego wyjątku. 2 - Ponieważ jest to wyjątek C#, będziesz miał problem ze złapaniem tego wyjątku. Prawdopodobnie będziesz potrzebować 'catch (...)', aby wychwycić wyjątek. – Velox