2014-09-09 7 views
5

È possibile chiamare una funzione di lancio C# da una chiamata C++ in un'app C# in modo tale che lo stack C++ sia svolto correttamente? C'è qualche documentazione di questo?Come chiamare una funzione di lancio C# da C++ in un'app C# in modo tale che lo stack C++ sia svolto correttamente?

Per esempio, perche questo codice 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); 
} 

Insieme a questo codice C++:

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

ho provato questo fuori, e il C# eccezione è stato catturato con successo, ma releasesResourceOnDestruction didn' Ho chiamato il distruttore. Questo sembra indicare che lo stack C++ non viene svolto correttamente - è possibile farlo svolgersi correttamente qui? C'è qualche documentazione su questo comportamento?

per il contesto: voglio innescare a volte un'eccezione C# da codice C, se possibile, in modo che non ho bisogno di ogni chiamata da C# in C++ deve controllare qualcosa in seguito per vedere se un C# un'eccezione deve essere gettato ++.

+0

Come fai a sapere che il distruttore di "releasesResourceOnDestruction" non è stato evocato? – 101010

+0

Dovrai disabilitare l'ottimizzazione che il compilatore C++ usa quando non vede lanciata un'eccezione C++. Progetto + Proprietà, C/C++, Generazione codice, Abilita eccezioni C++ =/EHa. In realtà, la cattura dell'eccezione richiede l'utilizzo di __try/__ non standard tranne le parole chiave. C'è * molto * poco ragionevole che puoi fare, tutte le informazioni necessarie per diagnosticare l'eccezione sono andate perse. Sarà una telefonata di supporto da parte di un utente spuntato che è terribilmente difficile rispondere. –

+0

40due: ho aggiunto una dichiarazione di stampa sia al costruttore che al distruttore di releasesResourceOnDestruction. Il contructor stampa ma il distruttore non lo fa mai. – JDiMatteo

risposta

2

Provare ad abilitare Structured Exception Handling nel progetto C++ (Proprietà progetto -> C/C++ -> Generazione codice -> Abilita eccezioni C++ -> "Sì con Eccezioni SEH (/ EHa)"). Senza eccezioni SEH, l'eccezione che viene restituita al livello C++ non dispone di informazioni sufficienti per svolgere correttamente lo stack.

+1

Esistono più opzioni in Eccezioni C++. È necessario selezionare "Sì con Eccezioni SEH (/ EHa)". – Velox

+1

Velox, vedi qualche potenziale problema con questo approccio? L'altra risposta suggeriva che sarebbero accadute cose strane se non fosse stata rilevata l'eccezione. Inoltre, ti preghiamo di prendere in considerazione la possibilità di spostare il tuo commento su "/ EHa" nel tuo commento alla tua risposta. – JDiMatteo

+1

I problemi che vedo con questo approccio: 1 - Dovrai avere una clausola catch per catturare l'eccezione, altrimenti il ​​tuo programma si bloccherà a causa dell'eccezione non gestita. 2 - Dal momento che si tratta di un'eccezione C#, si avranno problemi ad individuare l'eccezione esatta. Probabilmente avrai bisogno di un 'catch (...)' per catturare l'eccezione. – Velox