Ho un progetto C che è progettato per essere portabile su varie piattaforme (PC e embedded).Come si digita una struct definita dall'implementazione in un'intestazione generica?
Il codice dell'applicazione utilizzerà varie chiamate che avranno implementazioni specifiche della piattaforma, ma condivideranno un'API (generica) comune per facilitare la portabilità. Sto cercando di stabilire il modo più appropriato per dichiarare la funzione prototipi e strutture.
Ecco cosa mi è venuta in mente finora:
main.c:
#include "generic.h"
int main (int argc, char *argv[]) {
int ret;
gen_t *data;
ret = foo(data);
...
}
generic.h: (indipendente dalla piattaforma includono)
typedef struct impl_t gen_t;
int foo (gen_t *data);
impl.h: (dichiarazione specifica piattaforma)
#include "generic.h"
typedef struct impl_t {
/* ... */
} gen_t;
impl.c: (implementazione specifica della piattaforma)
int foo (gen_t *data) {
...
}
Corporatura:
gcc -c -fPIC -o platform.o impl.c
gcc -o app main.c platform.o
Ora, questo sembra funzionare ... nel senso che compila OK. Tuttavia, di solito non taggato le mie strutture poiché non sono mai accessibili al di fuori dell'alias typedef
. È un piccolo pignolo, ma mi chiedo se c'è un modo per ottenere lo stesso effetto con le strutture anonime?
sto anche chiedendo per i posteri, dal momento che ho cercato per un po 'e la risposta più vicina che ho trovato è stato questo: (Link)
Nel mio caso, non sarebbe l'approccio giusto, come l'applicazione nello specifico non dovrebbe mai includere direttamente le intestazioni di implementazione - l'intero punto è disaccoppiare il programma dalla piattaforma.
vedo un paio di altri meno-che-ideale modi per risolvere questo, ad esempio:
generic.h:
#ifdef PLATFORM_X
#include "platform_x/impl.h"
#endif
/* or */
int foo (struct impl_t *data);
Nessuno di questi sembra particolarmente interessante, e sicuramente non il mio stile. Anche se non voglio nuotare controcorrente, non voglio nemmeno uno stile conflittuale quando potrebbe esserci un modo migliore per implementare esattamente ciò che avevo in mente. Quindi penso che la soluzione typedef sia sulla strada giusta, ed è solo il bagaglio tag struct che mi rimane.
Pensieri?
Si potrebbe semplicemente rendere 'gen_t' un tipo di puntatore (un handle). Quindi i client dovrebbero usare la tua API per inizializzarla/usarla/distruggerla. O una leggera variazione, rendi la tua struttura esposta pubblicamente con un puntatore opaco all'attuale implementazione. altrimenti, non c'è molto altro che puoi fare. È necessario creare un oggetto o tracciamento del percorso che il cliente dovrà conoscere. –
c'è un problema nel fatto che il generic.h viene incluso PRIMA di impl.h Ma generico.h fa riferimento alla struttura definita in impl.h I.E. un riferimento futuro. (probabilmente non verrà compilato) molto meglio avere generic.h include impl.h (dove impl.h è specifico della piattaforma) Quindi la struttura sarà già definita quando generic.h prova ad usarlo. – user3629249
è molto meglio definire una struttura come: struct tagname {;;; }; quindi riferiscilo sempre come "struct tagname myname;" ci sono un certo numero di ragioni per questo: 1) le strutture nominate è un formato deprecato 2) i debugger usano il nome del tag per i campi di riferimento, ecc. 3) usando typedef su una struct è (in generale) la cattiva pratica di programmazione – user3629249