2013-07-10 3 views
8

Ist es legal eine struct als C- structdefinieren vorwärts erklärt C-Struktur als C++ - <code>struct</code>, dh als nicht-POD - struct

// api.h 
#ifdef __cplusplus 
extern "C" { 
#endif 

    typedef struct handle_tag handle_t; 

    handle_t *construct(); 
    void destruct(handle_t *h); 

    void func(handle_t *h); 

#ifdef __cplusplus 
} 
#endif 

und anschließend definieren es als eine C++ zu zukunfts erklären Art?

// api.cpp 
struct handle_tag { 
    void func(); 
    std::string member; 
}; 

void func(handle_t *h) { 
    h->func(); 
} 

Die allgemeine Absicht ist, über eine C-Schnittstelle einen von außen zugänglichen opaken Typ handle_t zu erhalten, die intern als C++ Datentyp implementiert ist.

+4

Übrigens ist PODness nicht verwandt mit C vs. C++ - Verknüpfung. C++ - Namen werden unabhängig davon, ob es sich um PODs handelt, verfälscht. –

+0

@KonradRudolph Diese Struktur ist nicht POD –

+1

@ BЈовић Nun ja, niemand behauptete, es zu sein, nicht wahr? –

Antwort

9

Ja, das so lange gut funktioniert wie der C-Code nie zu sehen „innerhalb“ der handle_tag Struktur benötigt, und die entsprechende C++ Bau/Zerstörung wird durch die C++ Code ausgeführt (was ich die construct und destruct preseume sind für).

Alles, was der C-Code benötigt, ist ein Zeiger auf eine Datenstruktur - es wird nicht wissen, was der Inhalt ist, so dass der Inhalt alles sein kann, wie Sie es wünschen, einschließlich Konstruktor/Destruktor-abhängigen Daten.

Edit: ich, dass dies darauf hinweisen, oder Verfahren, ähnlich wie es (zB ein void * mit der Adresse eines Objekts für den C Abschnitt hold aufzuzeichnen), ist eine ziemlich gängige Methode C-Code-Schnittstelle zu C++ Funktionalität.

Edit2: Es ist wichtig, dass der aufgerufene C++ - Code keine Ausnahmen in den C-Code "leckt". Das ist ein undefinierbares Verhalten, das sehr wahrscheinlich Abstürze verursacht oder schlimmere "komische Dinge", die nicht abstürzen ... Es sei denn, der Code garantiert keine Ausnahmen (und std::string ist zum Beispiel dafür verantwortlich, bad_alloc zu werfen von niedrigem Speicher), ist es erforderlich, einen try/catch Block in Code wie construct anf func in der C++ Seite zu verwenden.

+2

Bist du sicher, dass das funktioniert? Wird die Objektdatei für 'api.cpp' einen nicht-entstellten Namen für' handle_tag' exportieren? –

+1

@KonradRudolph: Normalerweise manifestieren sich nur Variablen und Funktionen als exportierte Namen, nur ein Typ selbst hat keinen verfälschten Namen. – PlasmaHH

+0

Solange Sie den exportierten Typedef nur als Zeiger verwenden, haben Sie kein Problem damit.Das C muss die Größe der Struktur nicht kennen, um die Größe eines Zeigers zu dieser Struktur zu kennen. –

2

Funktioniert nicht ganz so wie es ist, aber das Konzept ist in Ordnung. Wenn die Funktionen definiert sind, müssen Sie auch sicherstellen, dass die Namen nicht gemangelt werden, damit der C-Code sie finden kann. Das bedeutet, dass #include "api.h" auf Ihrer api.cpp-Datei hinzugefügt werden sollte.

+0

Sie haben Recht, ich habe einige Details weggelassen ... – phlipsy