2014-04-23 15 views
5

Quando scriviamo un programma in C, è possibile che chiameremo alcune librerie che sono state scritte in C++ ma con un'interfaccia C. Quindi può capitare che quando chiamiamo queste librerie, si verificherà un'eccezione C++. Quindi la mia domanda è come possiamo gestire questa situazione. Sono più interessato a questo problema dalla prospettiva di uno sviluppatore C++. Supponiamo che sto sviluppando una libreria C++ che verrà invocata da un programma C, dovrei smettere di usare l'eccezione e invece restituire i codici di errore? Un'altra situazione è che se ho già una libreria C++ completamente sviluppata che utilizza l'eccezione, come posso trasferire questa libreria in un modo rapido che utilizzerà solo il metodo di ritorno degli errori?Gestione delle eccezioni C++ nei codici C

+2

Questo non è un duplicato perché non risponde alla domanda su cosa fare con le eccezioni. C'è solo una risposta che dice "fai attenzione alle eccezioni" senza alcuna soluzione fornita. – Lundin

+4

@Lundin, non penso che ci sia una soluzione universale qui. I possibili sarebbero riscrivere il codice senza usare eccezioni o creare wrapper in modo tale che le eccezioni non lascino il codice della libreria, suppongo? – SingerOfTheFall

+0

@SingerOfTheFall Non lo so nemmeno io, probabilmente mi farei incazzare qualcosa di simile. Ma sono curioso di sapere se c'è qualche pratica raccomandata o forse qualche caratteristica del linguaggio C++ che è utile. E poiché quell'altra domanda non è stata utile nel fornire risposte per questo, per favore non chiudere questo. – Lundin

risposta

9

Devi prendere tutte le eccezioni sul lato C++ e convertirli in adeguata ritorni di errore in C, che possono includere specifici codici di errore, ove appropriato. Questo non significa che tu smetta di usare le eccezioni - puoi ancora usarle in C++ - ma non puoi esporle a C, diventano un dettaglio di implementazione.

Un tipico involucro può essere strutturato come segue:

// thingy-wrapper.h, typically included from C code: 

#ifdef __cplusplus 
extern "C" { 
#endif 

// create a typedef visible to C that doesn't expose the layout of 
// the implementation. 
typedef void *thingy_t; 

// wrapper for std::string Thingy::get_name() 
char *thingy_get_name(thingy_t t); 

#ifdef __cplusplus 
} 
#endif 

// thingy-wrapper.cpp, implements the wrapper, compiled with C++: 

#include <thingy-wrapper.h> 
#include <thingy.hpp>   // declares Thingy class 

char *thingy_get_name(thingy_t t_) 
{ 
    try { 
    Thingy& t = *static_cast<Thingy*>(t_); 
    std::string name = t.get_name(); 
    return strdup(name.c_str()); 
    } 
    catch(...) { 
    return NULL; 
    } 
} 

In questo semplice esempio, il chiamante di thingy_get_name può rilevare che si è verificato un errore, ma non può scoprire i dettagli dell'errore. Un esempio più realistico rileva eccezioni specifiche e imposta una variabile last_error su un codice di errore o un messaggio prima di restituire NULL. ... verrà catturato solo come ultima risorsa e imposterà last_error in un valore generico UNKNOWN_ERROR. Un'API separata per l'interrogazione dell'ultimo errore, ad esempio thingy_last_error(), sarebbe disponibile per i chiamanti più attenti di thingy_get_name().

La separazione tra i risultati di errore e non errore consente al codice che non si preoccupa della causa degli errori di controllare semplicemente se ha ricevuto NULL, consentendo al codice più coscienzioso di propagare correttamente o segnalare l'errore. Se la libreria è multithreading, assicurarsi che last_error utilizzi la memorizzazione locale dei thread.

1

Le eccezioni non vengono catturate in C quindi, se si desidera catturarle, nel codice C o nel codice C++ è necessario scrivere molto attentamente i wrapper.

fare in modo che nel vostro C++ funzioni avete le funzioni dichiarato anche:

extern "C" 

Si può anche verificare How to mix C and C++

4

Quindi può succedere che quando chiamiamo queste librerie, si verificherà un'eccezione C++. Quindi la mia domanda è come possiamo gestire questa situazione.

Il codice C non può gestire questa situazione. Il codice C non può gestire eccezioni C++.

Supponiamo che stia sviluppando una libreria C++ che verrà invocata da un programma C, dovrei interrompere l'utilizzo dell'eccezione e restituire invece i codici di errore?

No. Se si desidera che la libreria C++ venga utilizzata dal codice C++, è necessario utilizzare la gestione degli errori C++ nativa. Il che significa eccezioni.

Tuttavia, l'interfaccia che si espone al codice C non deve generare eccezioni. In genere questo significa scrivere un livello dell'adattatore che cattura le eccezioni generate dalla libreria C++ e le converte in codici di errore che devono essere utilizzati dal codice C.

Un'altra situazione è che se ho già una libreria C++ completamente sviluppata che utilizza un'eccezione, come posso trasferire questa libreria in modo rapido che utilizzerà solo il metodo di ritorno degli errori?

Non c'è davvero alcuna scorciatoia qui. Devi scrivere l'adattatore che converte le eccezioni C++ in codici di errore C. Scriverai comunque un adattatore se vuoi che la libreria esponga le interfacce per i consumatori sia C che C++. Quindi l'aspetto della gestione degli errori è solo un'altra cosa di cui occuparsi con questo adattatore.