Ich habe ein C-Projekt, das auf verschiedene Plattformen (PC und Embedded) portierbar ist.Wie tippe ich eine implementierungsdefinierte Struktur in einem generischen Header ein?
Der Anwendungscode wird verschiedene Aufrufe verwenden, die plattformspezifische Implementierungen haben, aber eine gemeinsame (generische) API zur Unterstützung der Portabilität verwenden. Ich versuche, den am besten geeigneten Weg zu finden, die Funktionsprototypen und Strukturen zu deklarieren.
Hier ist, was ich mit so weit habe kommen:
main.c:
#include "generic.h"
int main (int argc, char *argv[]) {
int ret;
gen_t *data;
ret = foo(data);
...
}
generic.h: (plattformunabhängig sind)
typedef struct impl_t gen_t;
int foo (gen_t *data);
impl.h: (Plattformspezifische Deklaration)
#include "generic.h"
typedef struct impl_t {
/* ... */
} gen_t;
impl.c: (plattformspezifische Implementierung)
int foo (gen_t *data) {
...
}
Körperbau:
gcc -c -fPIC -o platform.o impl.c
gcc -o app main.c platform.o
Nun, dies ... in zu arbeiten scheint, dass es kompiliert OK. Normalerweise markiere ich meine Strukturen jedoch nicht, da sie nie außerhalb des typedef
'd Alias aufgerufen werden. Es ist ein kleiner Schwachpunkt, aber ich frage mich, ob es eine Möglichkeit gibt, den gleichen Effekt mit anonymen Strukturen zu erreichen?
Ich bin auch für die Nachwelt zu fragen, da ich für eine Weile gesucht und die nächste Antwort fand ich, war dies: (Link)
In meinem Fall, das wäre der richtige Ansatz nicht sein, da die Anwendung Insbesondere sollten die Implementierungsköpfe niemals direkt enthalten sein - der einzige Punkt ist, das Programm von der Plattform zu entkoppeln.
Ich sehe ein paar anderen, weniger als ideale Möglichkeiten, dies zu lösen, zum Beispiel:
generic.h:
#ifdef PLATFORM_X
#include "platform_x/impl.h"
#endif
/* or */
int foo (struct impl_t *data);
Keines dieser besonders attraktiv scheint, und auf jeden Fall nicht mein Stil. Obwohl ich nicht stromaufwärts schwimmen möchte, möchte ich auch keinen widersprüchlichen Stil, wenn es eine schönere Möglichkeit gibt, genau das umzusetzen, was ich mir vorgestellt habe. Also denke ich, dass die typedef-Lösung auf dem richtigen Weg ist, und es ist nur das struct-tag-Gepäck, das mir geblieben ist.
Gedanken?
Sie könnten einfach 'gen_t' einen Zeigertyp (ein Handle) machen. Dann müssten Clients Ihre API verwenden, um sie zu initialisieren/zu verwenden/zu zerstören. Oder eine kleine Variation, lassen Sie Ihre öffentlich exponierte Struktur einen opaken Zeiger auf die tatsächliche Implementierung enthalten. Ansonsten kann man sonst nicht viel tun. Ein Objekt oder eine Wegstrecke muss erstellt werden, über die der Client Bescheid wissen muss. –
gibt es ein Problem, dass das generic.h vor impl.h enthalten ist. Aber, generic.h verweist auf die in impl.h I.E. eine Vorwärtsreferenz. (wird wahrscheinlich nicht kompilieren) viel besser zu haben generic.h include impl.h (wo impl.h plattformspezifisch ist) Dann wird die Struktur bereits definiert, wenn generic.h versucht, sie zu benutzen. – user3629249
ist es viel besser, eine Struktur wie folgt zu definieren: struct Tagname {;;; }; dann referenziere es immer als 'struct tagname myname;' Es gibt eine Reihe von Gründen dafür: 1) benannte Strukturen ist ein abgeschriebenes Format 2) Debugger verwenden den Tag-Namen, um Felder, usw. Referenz 3) mit typedef auf einer Struktur ist (im Allgemeinen) schlechte Programmierpraxis – user3629249