2015-02-06 18 views
10

Per prima cosa, non sto cercando uno strumento che produrrà un codice C non gestibile da una base di codice cpp esistente. È un requisito di un cliente, quindi non posso usare solo il codice CPP stesso.Flusso di lavoro da C++ a C

Sto cercando di elaborare un flusso di lavoro, in modo da poter convertire il codice-base da CPP a C in modo incrementale senza rompere il codice. Ho pensato un paio di cose che utilizzano il metodo "extern C"

  1. Classi per Structs
  2. funzioni membro della Le lezioni saranno convertiti in formato Struct_name_FunctionName.
  3. Nel caso in cui una funzione venga riutilizzata da 2 classi, ho intenzione di utilizzare i puntatori di funzione.
  4. Sostituisce gli operatori sovraccarichi come +, - etc con le funzioni effettive. Ad esempio, Add_, Sub_ etc

Riesci a aggiungere? e segnalare potenziali buche? Non posso condividere il code-base a causa della NDA. La base del codice non è enorme in sé. Ha circa 50 file cpp, ha visto circa 100 classi dispari.

Grazie in anticipo.

P.s Ho ricevuto altre domande simili. Ma in realtà non hanno il flusso di lavoro che sto cercando.

[Closing]: Anche se il post è stato messo in attesa perché è troppo ampio, molti dei commenti erano effettivamente utili. Sono più chiaro su ciò che deve essere fatto rispetto a prima. Grazie.

+10

Ho già fatto qualcosa di simile. Per avere un buon risultato ogni classe deve essere un nuovo file .c con classname.c. Ogni metodo privato deve essere statico. Ogni metodo pubblico deve essere esternalizzato nel file classname.h. Tutto ciò che hai scritto è un buon modo per farlo. – LPs

+14

Non pensare di * convertire * il codice in C, ma di * riscrivere * nuovo codice in C. C++ e C sono * diverse * lingue. –

+0

E i sovraccarichi? – Deduplicator

risposta

9

Bene, c'è una lista molto lunga che dovrete affrontare. Senza la pretesa di essere completa, è inoltre necessario:

  1. sostegno di funzione virtuale (non incredibilmente difficile, puntatore a funzione tabella)
  2. Costruttori e distruttori (mappatura ragionevole alle funzioni ordinarie, tanto lavoro)
  3. eccezioni e impilare svolgimento (estremamente difficile)
  4. mancante funzioni C++ biblioteca e le classi (molto lavoro)

Ma non illuderti. std::map<std::string, std::pair<int, int>> è una classe molto semplice che memorizza due int per ogni stringa. La traduzione C di quella classe è un vero casino. MyMap["five,three"] = std::make_pair(5,3) può facilmente diventare 100+ linee di codice C.

+0

Solo per aggiungere un'altra cosa, i modelli sono la prima cosa che mi è venuta in mente: se si dispone di una funzione basata su modelli che utilizza un operatore sovraccarico sul tipo di modello, solo "Add_whatever" non lo taglierà. – Random832

+0

@ Random832: Non è davvero un grosso problema. Quando si traduce C++ in C, sarà necessario creare manualmente un'istanza di ogni modello. Puoi/devi cercare tutti gli "overload" corretti nel processo. – MSalters

4

Se il codice C++ fa ampio uso di costrutti OO - in particolare ereditarietà e polimorfismo - si potrebbe desiderare di guardare alcune librerie C che lo imitano in C. qobject (dall'albero dei sorgenti qemu) è una che conosco bene, ma più noto (a quasi tutti i bar mi) è http://en.wikipedia.org/wiki/GObject che proviene da glib. Al giorno d'oggi, questo non è legato al codice GUI.

Il vantaggio qui è che è possibile modificare la lingua in uso senza apportare troppe modifiche al flusso del programma.

glib fornisce anche un buon numero di altri costrutti di libreria utili.

2

Seguendo il consiglio di prendere il GObject come un esempio di come C++ - codice come è fatto in C, c'è una cosa che si può provare:

  1. Tradurre il codice C++ per Vala
  2. Genera codice C dal compilatore Vala.

Vala è un linguaggio simile a C#; eccetto che dovrai ripetere "public" o "private" in ogni firma di funzione, oltre a sbarazzarti di pointer-star nei tipi di classe in uso, non ci sono molte cose che devi fare.

Ovviamente, il codice C generato avrà lo stesso aspetto degli altri generatori, ma almeno ci sono alcuni modi per renderlo un codice "manutenibile" (il problema principale è che ogni oggetto creato in Vala risultati in incrementare il contatore di riferimento nel codice C, che non è sempre necessario).

Il modello GObject può essere una buona istruzione/esempio su come tradurre i costrutti C++ nello stesso in C. Se non si utilizzano eccezioni (Vala fa! :)), non ci dovrebbero essere problemi con questo. Naturalmente le linee guida principali sono:

  1. Metodi normali: utilizzare il puntatore dell'oggetto come primo argomento. Il nome della funzione è NAMESPACE_CLASSNAME_METHODNAME.
  2. Metodi virtuali: è necessario creare un "oggetto caratteristico", indicato dall'oggetto "oggetto" di quella classe, che contiene i puntatori alle funzioni. Gli oggetti caratteristici della classe vengono in genere creati in GObject in funzioni che restituiscono puntatore a quell'oggetto - l'oggetto stesso viene creato e salvato pigramente in una variabile locale statica.
  3. SOVRACCARICO: add name-distinguising parti (Vala non supporta sovraccarico, anche nei costruttori - costruttori utilizzano sintassi speciale per chiamare i costruttori di nome)
  4. Modelli: espandere a posto :)
  5. Derivazione: unico singolo di derivazione (come anche in Vala), rendere il primo campo della struttura di "classe derivata" il campo di tipo della struttura di "classe base".
  6. Chiamare i metodi dalle classi base: utilizzare il cast di C. Se segui il punto 5, devi semplicemente trasmettere la struttura dell'oggetto classe derivata alla struttura della classe base.
+0

Al punto 6: Se usi una convenzione per chiamare suboboject 'super' di base class in tutti i casi, puoi semplicemente scrivere' & me-> super' invece di '(* BaseClass) me'. Mentre entrambe le espressioni vengono compilate sullo stesso codice assembler (vale a dire nessuna), la prima consente al compilatore di verificare se la conversione del tipo è appropriata. Hai solo bisogno di cast per downcasting come in C++. – cmaster

+0

Non se avete una classe derivata dalla seconda, nel qual caso avete '& me-> super-> super' o terza derivata ecc. - mentre il cast alla base ha sempre la stessa sintassi. E il fatto che tu abbia un controllo di tipo è insignificante in C (non avresti un errore, ma solo un avvertimento), specialmente che in C devi eseguire il cast se fai cose avanzate. Il "downcasting" è in realtà un caso raro in C++. Il GObject fa davvero un buon lavoro per fornire un modello di programmazione OO abbastanza buono, ma dimostra anche che scegliere C per quell'attività è raramente una buona idea (a meno che non si abbia scelta). – Ethouris

+0

So solo un po 'di Vala, ma questo non ti lascerà con il codice scritto in Vala, piuttosto che il codice scritto in C? – abligh