Frage Cross-Platfrom design?
-
@SeppJ sagte in Frage Cross-Platfrom design?:
Stimmt. Für @SoIntMan : Das nennt sich PIMPL bzw. Opaque Pointer und das macht das nochmals viel besser (Auch allgemein, nicht nur für plattformabhängigen Code). https://en.wikipedia.org/wiki/Opaque_pointer
ja kenn ich benutzt ich an andere stellen;) in diesem platform context hab ich das mal außen or gelassen..
danke
-
@SoIntMan sagte in Frage Cross-Platfrom design?:
@SeppJ sagte in Frage Cross-Platfrom design?:
Stimmt. Für @SoIntMan : Das nennt sich PIMPL bzw. Opaque Pointer und das macht das nochmals viel besser (Auch allgemein, nicht nur für plattformabhängigen Code). https://en.wikipedia.org/wiki/Opaque_pointer
ja kenn ich benutzt ich an andere stellen;) in diesem platform context hab ich das mal außen or gelassen..
PIMPL würd ich auf jeden Fall empfehlen, falls z.B. lediglich für einen Datentyp irgendwo
<windows.h>
und Konsorten in einem Header mit inkludiert werden müssten. Sonst holt man sich ganz schnell die Krätze ins Haus. In dem Kontext würde ich dann auch den anderen Namen für PIMPL verwenden: compilation firewall(Sorry, das musste sein. Die oben erwähnten
HANDLE
,HWND
undFILE
haben mich getriggert)
-
@Finnegan sagte in Frage Cross-Platfrom design?:
PIMPL würd ich auf jeden Fall empfehlen, falls z.B. lediglich für einen Datentyp irgendwo <windows.h> und Konsorten in einem Header mit inkludiert werden müssten. Sonst holt man sich ganz schnell die Krätze ins Haus. In dem Kontext würde ich dann auch den anderen Namen für PIMPL verwenden: compilation firewall
(Sorry, das musste sein. Die oben erwähnten HANDLE, HWND und FILE haben mich getriggert )gibt es auch ein art Opaque typedef, analog zu struct?;)
-
@SoIntMan sagte in Frage Cross-Platfrom design?:
gibt es auch ein art Opaque typedef, analog zu struct?;)
Ich verstehe die Frage nicht ganz.
Ziel ist es doch Implementierungsdetails zu verbergen. Und solange du dies beherzigst, kannst du Handles frei nach Herzenslust definieren.
Das kann ein Pointer sein, ein Index, ein Bitfeld, ein Typedef, ein Struct,... sein.
Hauptsache die Implementierungsdetails sind nach außen nicht sichtbar.
-
@SoIntMan sagte in Frage Cross-Platfrom design?:
gibt es auch ein art Opaque typedef, analog zu struct?;)
Nein, aber z.B. bei Windows-Typen mache ich das dann meistens so oder ähnlich:
// public header struct os_data_t; class Window { ... private: os_data_t* os_data; }; // os_a.c #include <windows.h> struct os_data_t { HWND hwnd; }; ...
Wichtig ist halt, im Header das
#include <windows.h>
zu vermeiden, damit man sich nicht so übles Zeug wie z.B.#define min ...
in seinen gesamten Code reinzieht und dann bei jedemstd::min(a, b)
einen Heidenspaß bekommt... es gibt zwar
#define NOMINMAX
für speziell dieses Problem, aber die Header haben auch noch ne Menge anderer Makros, die für Überraschungen sorgen können (z.B.near
/far
und solche Dinge).
-
@Finnegan sagte in Frage Cross-Platfrom design?:
Wichtig ist halt, im Header das #include <windows.h> zu vermeiden, damit man sich nicht so übles Zeug wie z.B. #define min ... in seinen gesamten Code reinzieht und dann bei jedem std::min(a, b) einen Heidenspaß bekommt
Spaßig ist auch
winsock2.h
.
-
@Quiche-Lorraine sagte in Frage Cross-Platfrom design?:
Spaßig ist auch
winsock2.h
.Nicht viel mit der gemacht, aber beim groben Überfliegen fallen mir schon ein paar ungünstige Makros auf:
SOCKET_ERROR
,NO_ADDRESS
,NO_DATA
,HOST_NOT_FOUND
,BIGENDIAN
,LITTLEENDIAN
(Kollision mit eigenenenum
s),. Überhaupt, viel zu viele Makros. Ich denke du meinst sowas, oder?
-
Probiere doch mal folgendes aus:
#include <Windows.h> #include <winsock2.h>
Unter meinem VS 2019 kommt da eine Reihe von Fehler (C2143, C2059, C4430,...) und Warnungen über Makro Neudefinitionen. Dreht man die include Reihenfolge um, so funktioniert alles.
-
@Quiche-Lorraine sagte in Frage Cross-Platfrom design?:
Ich verstehe die Frage nicht ganz.
Ziel ist es doch Implementierungsdetails zu verbergen. Und solange du dies beherzigst, kannst du Handles frei nach Herzenslust definieren.
Das kann ein Pointer sein, ein Index, ein Bitfeld, ein Typedef, ein Struct,... sein.
Hauptsache die Implementierungsdetails sind nach außen nicht sichtbar.ich meins ein art konzept dass ich ein primitver Typ bekannt mache, aber ihn erst durch eine Deklaration definiert. wie eben ne struktur:
so irgendwie:
typedef struct X X; typedef MyInt32 <placeholder>
Module.c
struct X {...} <placeholder> os_32int
-
@SoIntMan sagte in Frage Cross-Platfrom design?:
so irgendwie:
typedef struct X X; typedef MyInt32 <placeholder>
Module.c
struct X {...} <placeholder> os_32int
Das funktioniert in C nicht. Du kannst nur Zeiger auf den struct X definieren, und damit wird die eigentliche Implementation nicht verborgen. In anderen Programmiersprachen geht das.
Mit dem Pimpl-Idiom hast Du ein äußeren struct und Funktionen, der die API definiert und intern nutzt dieser struct einen Zeiger auf die eigentliche Datenstruktur. Dadurch wird in C die Linkabhängigkeit durchbrochen. Sprich man kann die Implementation z.B. in einer Library ändern, ohne dass man die Programme neu übersetzen muss. Es muss nur die Library neu gebaut werden.
// API.h struct X { void* impl_; } void X_init(struct X *self); int X_foo(struct X *self); // API.c #include "X_impl.h" void X_init (struct X *self) { impl_ = malloc(sizeof(struct X_impl)); } int X_foo(struct X *self) { struct X_impl *p = (struct X_impl*)impl_; return X_impl_foo(p); }
-
Mache dir bitte etwas bewusst, du bist hier im Bereich der Schnittstellen-Definition. Also etwas, wo es manchmal heißt: Einmal Schnittstelle definieren, niemals mehr verändern, nur noch anfügen.
Und generell dienen dir alle Definitionen der Schnittstelle nur als Abstraktionsebene zu der Implementierung.
Dein
MyInt32
ist also erstmal nicht ein 32 Bit Integer von Betriebssystem XYZ, sondern ein 32 Bit Integer auf allen Betriebssystemen.MyInt32
ist also unabhängig von irgentwelchen Betriebssystemen.BTW: Das Beispiel ist nicht gut, da wir hier von einem primitiven Datentyp bzw.
int32_t
reden.
-
@Quiche-Lorraine sagte in Frage Cross-Platfrom design?:
BTW: Das Beispiel ist nicht gut, da wir hier von einem primitiven Datentyp bzw. int32_t reden.
ja das habe ich auch erkannt , war bissel zu arg im over-engineering...:)
ich werde jetzt die Standard typen c11 also in dem int32_t verwenden;)