Gibt es ein globales -#include dateiname-? Also ein include file, das in allen anderen Dateien "bekannt" ist, ohne es ausdrücklich in den anderen Dateien zu erwähnen?
Der Hintergrund meiner Frage: In einer Quelltextdatei SoftSerial.c ändern sich zwei Pin (TxD, RxD) je nach Projekt. Nun möchte ich in einer globalen hardware.h die Pins ablegen (z. B. #define TxD PORTB1). Wie kann ich das elegant lösen ohne SoftSerial.c zu verändern oder zu kopieren?
GCCUser schrieb: > Der Hintergrund meiner Frage: > > In einer Quelltextdatei SoftSerial.c ändern sich zwei Pin (TxD, RxD) je > nach Projekt. > > Nun möchte ich in einer globalen hardware.h die Pins ablegen (z. B. > #define TxD PORTB1). > > Wie kann ich das elegant lösen ohne SoftSerial.c zu verändern oder zu > kopieren? Warum solltest du das müssen? Du musst doch nur dein hardware.h ändern.
Du könntest es mit dem Compiler machen als Parameter -DTxD=PORTB1 beim gcc. In der Quelldatei dann noch sicherstellen, dass Txd definiert ist und einen Fehler ausgeben, wenn das nicht der Fall ist #ifndef TxD usw. So ist der Quellcode identisch und du kannst in den 2 Projekten über den Compiler das Verhalten ändern
So sieht es aus:
1 | Projekt: A Projekt: B |
2 | Verzeichnis: AV Verzeichnis: BV |
3 | |
4 | Datei: hardware.h in AV Datei: hardware.h in BV |
5 | ... ... |
6 | #define TxD PORTB0 #define TxD PORTC3
|
7 | ... ... |
8 | |
9 | Datei: SoftSerial.c |
10 | Datei: SoftSerial.h |
11 | Verzeichnis: driver/ |
12 | |
13 | |
14 | Datei: main.c in AV Datei: main.c in BV |
15 | |
16 | #include ? #include ?
|
17 | #include "driver/SoftSerial.h" #include "driver/SoftSerial.h" |
Es soll von SoftSerial.c die hardware.h des Projekts A oder des Projekts B genommen werden.
GCCUser schrieb: > #include ? #include "hardware.h" Ggf dann über den include-Pfad das richtige Verzeichnis einbinden.
Rolf Magnus schrieb: > GCCUser schrieb: >> #include ? > > #include "hardware.h" > > Ggf dann über den include-Pfad das richtige Verzeichnis einbinden. Dann kennt die main.c die Definitionen. SoftSerial.c bekommt davon nichts mit.
GCCUser schrieb: > Rolf Magnus schrieb: > GCCUser schrieb: > #include ? > > #include "hardware.h" > Ggf dann über den include-Pfad das richtige Verzeichnis einbinden. > > Dann kennt die main.c die Definitionen. SoftSerial.c bekommt davon > nichts mit. Darauf hatte ich gar nicht geachtet. Das include muss natürlich nicht in main.c, sondern in SoftSerial.c.
Rolf Magnus schrieb: > GCCUser schrieb: >> Rolf Magnus schrieb: >> GCCUser schrieb: >> #include ? >> >> #include "hardware.h" >> Ggf dann über den include-Pfad das richtige Verzeichnis einbinden. >> >> Dann kennt die main.c die Definitionen. SoftSerial.c bekommt davon >> nichts mit. > > Darauf hatte ich gar nicht geachtet. Das include muss natürlich nicht in > main.c, sondern in SoftSerial.c. Wie man oben sehen kann gibt es zwei (min.) hardware.h. Es soll immer die hardware.h aus dem aktuellen Projekt genommen werden.
Du gibst beim Aufruf des Compilers mit "-I" die Verzeichnisse an, in denen nach include-Dateien gesucht wird. Das ist dann halt je nach Projekt unterschiedlich. Du kannst auch, wie von Johann erwähnt, mit der Compileroption "-include" eine Datei in sämtliche Sourcen inkludieren. Das ist aber aus meiner Sicht die schlechtere Lösung, weil es dann eben überall inkludiert wird und nicht nur dort, wo man es braucht. Außerdem taucht der Name "hardware.h" dann nirgends es im Quelltext auf. Wenn sich das jemand anderes oder Du selber in ein paar Monaten wieder anschaut, geht erst mal die Sucherei los, was man denn alles zum Compilieren braucht ...
Hans schrieb: > Du gibst beim Aufruf des Compilers mit "-I" die Verzeichnisse an, in > denen nach include-Dateien gesucht wird. Das ist dann halt je nach > Projekt unterschiedlich. Vielen Dank für diesen auf Projekte bezogen Vorschlag. Werde ich einfach einmal ausprobieren, wie das in der Praxis so wirkt.
Übergebe dem Modul in seiner Init Funktion die notwendigen Informationen (port register, pin nummer, etc) Oder was ich auch manchmal mache sind Callback-funktionen, entweder dynamisch zur Laufzeit oder statisch zur Compilezeit, letzteres kann (und wird) von der LTO sogar geinlined werden, sogar über mehrere Aufrufebenen und mehrere Module hinweg.
> Außerdem taucht > der Name "hardware.h" dann nirgends es im Quelltext auf. Wenn sich das > jemand anderes oder Du selber in ein paar Monaten wieder anschaut, geht > erst mal die Sucherei los, Die "Sucherei" beginnt ganz geordnet im projektspezifischen Makefile: hier drin stehen alle "Meta"-Angaben wie das Projekt zu bauen ist, also auch "-D", "k -include" usw. Makefiles sind auch Bestandteil des Quellcodes. Wer auf nicht-klartext Projektbeschreibungen/Projektzusatzinfos verzichtet weil es $IDE ach-soooo-bequem über zig GUI-Dialoge/Reiter verstreut und über Versionen an anderen Orten verschiebt, verpasst einiges. Darunter: * die vollständige Übersicht dieser Zusatzinfos zu seinem Projekt * die "Versionierbarkeit" (oder wie schaut ein diff von XML-Projektdaten aus, wen die enthaltenen Elemente vllt. identisch, aber in anderer Ordnung drin stehen?)
I <3 makefiles schrieb: > Die "Sucherei" beginnt ganz geordnet im projektspezifischen Makefile: > hier drin stehen alle "Meta"-Angaben wie das Projekt zu bauen ist, also > auch "-D", "k > -include" usw. > Makefiles sind auch Bestandteil des Quellcodes. Allerdings sucht man (zumindest ich) in der Regel nicht unbedingt im Makefile nach inkludierten Headern - bzw. wundere mich, wenn z.B. beim Bauen eine C-Files ein Fehler in einem Header kommt, der auf den ersten Blick eigentlich gar nicht eingebunden ist.
Es gibt noch ne halbwegs elegante Möglichkeit das Problem auf pragmatisch-simple Weise zu lösen, ich mach das zum Beispiel so bei meinen Projekten: In jedem meiner Projekte existiert unter anderem immer (und das habe ich einfach mal so beschlossen und zum hausinternen Standard gemacht) ein "gpio.h", jedes andere Modul das irgendwas an der Hardware wackeln will kann und wird das includieren (und zwar ganz offiziell per #include, nicht hinten rum über die Kommandozeile) und kann davon ausgehen daß es auch tatsächlich existiert, in diesem gpio.h sind alle benutzten gpio-Pins mit sinnvollen Namen definiert, dort ist auch eine static inline gpio_init() Funktion die alle Pins und das pin-muxing initialisiert und und ebenso plaziere ich dort noch alle von der Pinbelegung abhängigen defines wie zum Beispiel benötigte ADC-Muxer-Kanäle, Timer-Kanäle, etc. mit sinnvollen Namen. Da brauch ich also keine Verrenkungen machen oder gar heimliche includes im Makefile verstecken, ich lege stattdessen einfach fest und dokumentiere dementsprechend daß eine Datei "gpio.h" vorhanden sein muss dort dieses und jenes definiert sein muss. Punkt aus. Das kann man auch sehen wenn man in den Code reinschaut, die wird da ganz hochoffiziell auf normalem Wege inkludiert, so daß man es sofort sehen kann. Wenn sie fehlt gibts aussagekräftige Fehlermeldungen, ebenso wenn ich vergessen habe dort irgendeinen benötigten Pin zu definieren.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.