2014-09-09 7 views
5

Ist es möglich, eine C# -Working-Funktion von einem C++ - Aufruf in einer C# -App aufzurufen, so dass der C++ - Stapel ordnungsgemäß abgewickelt wird? Gibt es eine Dokumentation davon?Wie rufen Sie eine C# -Working-Funktion aus C++ in einer C# -App auf, so dass der C++ - Stapel ordnungsgemäß abgewickelt wird?

Zum Beispiel, beachten Sie bitte diesen C# -Code:

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

Zusammen mit diesem C++ Code:

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

Ich habe versucht, dies aus, und die C# Ausnahme wurde erfolgreich gefangen, aber releasesResourceOnDestruction didn‘ Ich habe es Destruktor genannt. Dies scheint darauf hinzuweisen, dass der C++ - Stack nicht richtig abgewickelt wird - ist es möglich, dass er hier richtig abläuft? Gibt es Dokumentation zu diesem Verhalten?

Für Kontext: Ich möchte manchmal eine C# Ausnahme von C++ - Code auslösen, so dass ich nicht jeden Aufruf von C# in C++ nachher überprüfen muss, um festzustellen, ob eine C# Ausnahme ausgelöst werden muss.

+0

Woher wissen Sie, dass der Destruktor von 'ReleasesResourceOnDestruction' nicht evoziert wurde? – 101010

+0

Sie müssen eine Optimierung deaktivieren, die der C++ - Compiler verwendet, wenn keine C++ - Ausnahme ausgelöst wird. Projekt + Eigenschaften, C/C++, Codegenerierung, C++ Ausnahmen aktivieren =/EHa. Um die Ausnahme abzufangen, müssen die nicht standardmäßigen __try/__-Schlüsselwörter verwendet werden. Es gibt * sehr * wenig vernünftig, was Sie tun können, alle Informationen, die zur Diagnose der Ausnahme benötigt werden, sind verloren gegangen. Das wird ein Support-Telefonanruf von einem abgehakten Benutzer sein, der schrecklich schwer zu beantworten ist. –

+0

40zwei: Ich habe dem Konstruktor und Destruktor von "ReleasesResourceOnDestruction" eine Druckanweisung hinzugefügt. Der Konstruktor druckt, aber der Destruktor tut es nie. – JDiMatteo

Antwort

2

Versuchen Sie, die strukturierte Ausnahmebehandlung in Ihrem C++ - Projekt zu aktivieren (Projekteigenschaften -> C/C++ -> Codegenerierung -> Ausnahmen C++ aktivieren -> "Ja mit SEH-Ausnahmen (/ EHa)"). Ohne SEH-Ausnahmen verfügt die an die C++ - Schicht zurückgegebene Ausnahme nicht über ausreichende Informationen, um den Stapel ordnungsgemäß aufzuwickeln.

+1

Es gibt mehrere Optionen unter C++ - Ausnahmen. Das "Ja mit SEH-Ausnahmen (/ EHa)" muss ausgewählt werden. – Velox

+1

Velox, sehen Sie mögliche Probleme mit diesem Ansatz? Die andere Antwort schlug vor, dass seltsame Dinge passieren würden, wenn die Ausnahme nicht aufgefangen würde. Denken Sie auch daran, Ihre Klarstellung zu "/ EHa" in Ihrem Kommentar zu Ihrer Antwort zu verschieben. – JDiMatteo

+1

Die Probleme, die ich mit diesem Ansatz sehe: 1 - Sie müssen eine Fangklausel haben, um die Ausnahme zu fangen, sonst wird Ihr Programm aufgrund der unbehandelten Ausnahme abstürzen. 2 - Da eine C# -Ausnahme ausgelöst wird, können Sie die genaue Ausnahme nicht abfangen. Sie werden wahrscheinlich einen 'catch (...)' brauchen, um die Ausnahme zu fangen. – Velox