Frage Cross-Platfrom design?
-
Hallo Leute,
was ist das best-practise Design Pattern für Cross-Platfrom code?
So ganz pragmatisch:
//plattform.h void Foo();
c- module
//platform.c #ifdef OS_A void Foo(){...} #elseif OS_B void Foo(){...} #else #error "Error no OS Selected" #endif
aber wie mache ich das bissel modularer?
Idee:
module osa.c
//os_a.c #if defined(OS_A) && ! defined(OS_B) void Foo(){...} #else #error "Error no OS Selected" #endif
module osb.c
//os_b.c #if defined(OS_B) && ! defined(OS_A) void Foo(){...} #else #error "Error no OS Selected" #endif
oder lieg ich komplett daneben ? macht es hier vll. auch sind extern func def zu verwenden oder is das dann ehr schlecht?
Vielen Dank
-
Wenn man ein buildsystem wie z.b. cmake nutzt dann könnte man die platform spezifischen source files (in deinem beispiel *.c) nur dann in dem build hinzufügen, wenn für die entsprechende Platform gebaut werden soll.
-
Präprozessormagie würde ich benutzen, um Schnittstellen anzugleichen. So hast du nur eine Stelle im Programm, die sich mit unterschiedlichen Arten und Weisen auskennen muss, wie der plattformabhängige Code aufgerufen wird. In deinem Beispiel ist schon alles eine einheitliche Schnittstelle (
void Foo()
), aber du kannst dir sicher leicht Erweiterungen vorstellen, wo beispielsweise plattformabhängige Datentypen auftauchen, die hinter Präprozessormakros verborgen werden können.Die eigentlichen plattformabhängigen Codeteile würde ich überhaupt gar nicht mit dem Präprozessor trennen. Das gehört ins Builscript. Wenn du für OS_A übersetzt werden eben andere Dateien übersetzt als für OS_B.
-
@SeppJ sagte in Frage Cross-Platfrom design?:
Die eigentlichen plattformabhängigen Codeteile würde ich überhaupt gar nicht mit dem Präprozessor trennen. Das gehört ins Builscript. Wenn du für OS_A übersetzt werden eben andere Dateien übersetzt als für OS_B.
Da schließe ich mich an.
os_a.c
undos_b.c
sind eine gute Idee und m.E. gängige Praxis, aber das Präprozessor-Zeug würde ich nur machen, wenn es sich absolut nicht vermieden lässt - z.B. in einem gemeinsamen Header. Das erzeugt sonst nur unnötiges Code-Rauschen und schadet der Lesbarkeit. Wenn die falsche Datei für das OS kompiliert wird, dann läuft das eben vor die Wand. Genau so wie wenn eine notwendige Bibliothek nicht installiert ist oder der falsche Compiler verwendet wird.Eine Ausnahme würde ich allerdings bei feingranularen Unterschieden machen, die zu wenige sind um eine eigene C-Datei zu rechtfertigen oder die sich nur schlecht aus dem Code herauslösen lassen, so dass der Code drumherum ansonsten doppelt vorhanden müsste. Z.B. sowas hier:
// os_a.c void Foo() { ... #if OS_A_VERSION >= 200 moderne_os_funktion(); #else legacy_os_funktion(); #endif ... }
Wenn diese Unterschiede aber zu viele werden, kann man auch hier überlegen, ob man den entsprechenden Code nicht in eine eigene Funktion in einer separaten Datei auslagert und auf die Präprozessor-Direktiven verzichtet.
-
@Finnegan sagte in Frage Cross-Platfrom design?:
@SeppJ sagte in Frage Cross-Platfrom design?:
Die eigentlichen plattformabhängigen Codeteile würde ich überhaupt gar nicht mit dem Präprozessor trennen. Das gehört ins Builscript. Wenn du für OS_A übersetzt werden eben andere Dateien übersetzt als für OS_B.
Da schließe ich mich an.
os_a.c
undos_b.c
sind eine gute Idee und m.E. gängige Praxis, aber das Präprozessor-Zeug würde ich nur machen, wenn es sich absolut nicht vermieden lässt - z.B. in einem gemeinsamen Header. Das erzeugt sonst nur unnötiges Code-Rauschen und schadet der Lesbarkeit. Wenn die falsche Datei für das OS kompiliert wird, dann läuft das eben vor die Wand. Genau so wie wenn eine notwendige Bibliothek nicht installiert ist oder der falsche Compiler verwendet wird.Eine Ausnahme würde ich allerdings bei feingranularen Unterschieden machen, die zu wenige sind um eine eigene C-Datei zu rechtfertigen oder die sich nur schlecht aus dem Code herauslösen lassen, so dass der Code drumherum ansonsten doppelt vorhanden müsste. Z.B. sowas hier:
// os_a.c void Foo() { ... #if OS_A_VERSION >= 200 moderne_os_funktion(); #else legacy_os_funktion(); #endif ... }
Wenn diese Unterschiede aber zu viele werden, kann man auch hier überlegen, ob man den entsprechenden Code nicht in eine eigene Funktion in einer separaten Datei auslagert und auf die Präprozessor-Direktiven verzichtet.
ja der code wird in cmake und auch mit msvc vs gebaut.. würde gehen.
@Finnegan sagte in Frage Cross-Platfrom design?:
@SeppJ sagte in Frage Cross-Platfrom design?:
Die eigentlichen plattformabhängigen Codeteile würde ich überhaupt gar nicht mit dem Präprozessor trennen. Das gehört ins Builscript. Wenn du für OS_A übersetzt werden eben andere Dateien übersetzt als für OS_B.
Da schließe ich mich an.
os_a.c
undos_b.c
sind eine gute Idee und m.E. gängige Praxis, aber das Präprozessor-Zeug würde ich nur machen, wenn es sich absolut nicht vermieden lässt - z.B. in einem gemeinsamen Header. Das erzeugt sonst nur unnötiges Code-Rauschen und schadet der Lesbarkeit. Wenn die falsche Datei für das OS kompiliert wird, dann läuft das eben vor die Wand. Genau so wie wenn eine notwendige Bibliothek nicht installiert ist oder der falsche Compiler verwendet wird.Eine Ausnahme würde ich allerdings bei feingranularen Unterschieden machen, die zu wenige sind um eine eigene C-Datei zu rechtfertigen oder die sich nur schlecht aus dem Code herauslösen lassen, so dass der Code drumherum ansonsten doppelt vorhanden müsste. Z.B. sowas hier:
// os_a.c void Foo() { ... #if OS_A_VERSION >= 200 moderne_os_funktion(); #else legacy_os_funktion(); #endif ... }
Wenn diese Unterschiede aber zu viele werden, kann man auch hier überlegen, ob man den entsprechenden Code nicht in eine eigene Funktion in einer separaten Datei auslagert und auf die Präprozessor-Direktiven verzichtet.
also ohne präprocesseor in den code differenziert in verschieden c module die dann je nach build setup kompliert werden... wie auch firefly meinte?
wie sieht es dann mit typedefs aus?
//OS_A typedef Int16 osAint16 //OS_B typedef Int16 osBint16
müsste ich diese dann in jeweilige 2 header tun und die auch je nach build setup includen!?