2014-10-05 20 views
5

Sto lavorando su un grande progetto in C, e voglio organizzarlo usando i file di interfaccia (.h) e di implementazione (.c), simili a molti linguaggi orientati agli oggetti come Objective -C o Java. Ho familiarità con la creazione di librerie statiche in C, ma penso che farlo per il mio progetto sia inutilmente complesso. Come posso implementare un paradigma di interfaccia/implementazione in ANSI C? Sto principalmente utilizzando GCC per la compilazione, ma sto puntando a una stretta aderenza a ANSI C e alla compatibilità cross-compiler. Grazie!Interfaccia/implementazione in ANSI C

+0

Stai parlando di OOP in C? –

+0

No, sono fondamentalmente alla ricerca di un modo per separare le definizioni di funzione dai meccanismi interni di tali funzioni e anche un metodo per raggruppare funzioni correlate e tali insieme (come math.h, ad esempio). Non voglio utilizzare una libreria perché non riusciamo a riutilizzare le funzioni in altri programmi e potrebbe anche essere necessario apportare modifiche frequenti alla funzionalità. – user2105505

+0

Rendi statica la funzione nel file .h, e sarebbe visibile solo nel file .c; –

risposta

5

Sembra che tu sei già fare la cosa giusta: buon codice C anche organizza interfacce in .h-files e le implementazioni in .c-files.

Esempio di file ah:

void f(int a); 

Esempio file di AC:

#include "a.h" 
static void helper(void) {...} 
void f(int a) {... use helper()...} 

Esempio di file main.c:

#include "a.h" 
int main(void) { f(123); return 0; } 

Si ottiene modularità perché helper-funzioni non sono dichiarati in le intestazioni in modo che gli altri moduli non ne siano a conoscenza (è possibile dichiararle nella parte superiore dello .c file se vuoi). Questa modularità riduce il numero di ricompilazioni necessarie e riduce la quantità di che deve essere ricompilata. (Il collegamento al deve essere eseguito ogni volta). Si noti che se non si dichiarano le funzioni di aiuto nell'intestazione, si è già abbastanza sicuri, tuttavia avere il static davanti a loro li nasconde anche da altri moduli durante il collegamento, quindi non c'è conflitto se più moduli utilizzano la stessa funzione di supporto -names.

Se si lavora solo con tipi primitivi, questo è tutto ciò che è necessario sapere e è possibile interrompere la lettura qui. Tuttavia, se il tuo modulo ha bisogno di lavorare con una struct, diventa un po 'più complicato.

problematico esempio intestazione b.h:

typedef struct Obj { 
    int data; 
}*Obj; 
Obj make(void); 
void work(Obj o); 

Il modulo vuole passare gli oggetti dentro e fuori. Il problema qui è che gli interni sono trapelati ad altri moduli che dipendono da questa intestazione. Se la rappresentazione viene modificata in float data, tutti i moduli che utilizzano devono ricompilare. Un modo per risolvere questo problema è utilizzare solo void*. Questo è il modo in cui molti programmi lo fanno. Tuttavia questo è ingombrante perché ogni funzione che riceve l'argomento void* deve inoltrarla a Obj. Un altro modo è quello di fare questo:

Header ch:

typedef struct Obj*Obj; 
Obj make(void); 
void work(Obj); 

Attuazione cc:

#include "c.h" 
typedef struct Obj { 
    int data; 
}*Obj; 

Il motivo per cui questo funziona è che Obj è un puntatore (al contrario di una struttura da valore/copy). Altri moduli che dipendono da questo modulo hanno solo bisogno di sapere che un puntatore viene passato dentro e fuori, non a cosa punta.

+0

Grazie per la tua risposta chiara. Questo può essere fatto con un comando in GCC? Basta chiamare "gcc main.c" per ottenere un errore di simboli non definiti. – user2105505

+0

Dovresti chiamare 'gcc -c nomefile.c' per ogni c-file. Ognuno di loro genera un file .o (modulo). Alla fine chiami 'gcc * .o' che li collega tutti insieme. Se hai cambiato solo 'b.c', allora deve solo essere ricompilato (' b.o') e tu dovrai riconnetterti. (i file c non modificati non devono essere nuovamente compilati) –

+0

@ user2105505 inoltre, questo è normalmente automatizzato da un makefile. con questo è sufficiente digitare "make" sulla riga di comando e sceglierà quale c-file da ricompilare e quindi collegherà il programma insieme. –

1

È necessario leggere qualcosa su OOP con non OOL come http://www.cs.rit.edu/~ats/books/ooc.pdf. Ma, facendo questo non avrai mai una forte digitazione OOP.

+1

Inoltre, così facendo ti farà impazzire;) –

+0

Questo è un po 'esagerato ma avrai bisogno di una disciplina almeno forte (che potrebbe farti impazzire). –

+2

"Mi sono divertito a scoprire che ANSI-C è un linguaggio orientato agli oggetti su vasta scala" - ha smesso di leggerlo. Divertente. Sì, si può SEMPLIFICARE i modelli OOP con uno sforzo MASSIVO ma questo è praticamente insensato e inefficiente, anche: in pratica sarebbe stato reinventare una ruota. Non c'è bisogno di schemi OO in C. C è praticamente un linguaggio di basso livello, forzare l'OO in esso provocherà solo problemi - ecco perché è stato inventato Obj-C. – specializt