Forum: Mikrocontroller und Digitale Elektronik Headerdateien universal machen


von Jens (Gast)


Lesenswert?

Ich habe schon wieder ein Problem damit wie Headerdateien dynamisch 
verwendet werden sollten.

Angenommen ich habe eine Headerdatei header1.h. Diese ist projektbezogen 
und enhält generelle Definitionen, die keinen speziellen Peripherien 
zugeordnet werden können.
In dieser definiere ich zB
1
#ifndef DEF_H
2
#define DEF_H
3
#define ON                                      GPIO_PIN_SET
4
#define OFF                                      GPIO_PIN_RESET
5
#define NONE                                    0xFFFFFFFF 
6
#endif


Jetzt habe ich zB eine c-Datei datei1.c und eine h-Datei datei1.h davon. 
Jetzt habe ich zB in der c-Datei eine Funktion, die zB als Parameter OFF 
benötigt. Sie wird zB auch in der datei2.c in einer beliebigen Funktion 
ebenfalls als Parameter benötigt und sonst nirgends.

Jetzt muss ich in die jeweiligen Headerdateien datei1.h und datei2.h die 
header1.h einbinden.

Jetzt habe ich folgendes Problem.
Wenn nun datei1.c und datei2.h irgendwo als Vorlage dient und ich ein 
komplett anderes Programm schreibe, aber diese c-Datei benötige, muss 
ich doch ständig die projektbezogene Headerdatei mitziehen, obwohl diese 
mit dem neuen Programm nichts zu tun hat.

Denke ich da zu kompliziert?

von Jens (Gast)


Lesenswert?

im letzten Absatz meine ich datei1.c und datei1.h

von jois3 (Gast)


Lesenswert?

Hi Jens,

datei1 ist universell (also das Paar aus .c und .h), während header1.h 
projektbezogen ist? Wenn ja, dann ist das die falsche Reihenfolge des 
inkludierens bzw. der Abhängigkeiten. Du möchtest Deine 
projektspezifischen Dateien von allgemeinen abhängig halten, nicht 
umgekehrt.

Was Du tun kannst:
Gib das ON und OFF als Parameter an Deine universellen Code-Teile - oder 
allgemeiner, gib alles projektspezifische hinein (Parametrisierung).

Gruß, jois3

von Stefan F. (Gast)


Lesenswert?

Eine anderer Ansatz (der mir persönlich nicht gefällt) ist, solche 
Definitionen ins Build Script (bzw. Makefile) zu schreiben und dem 
Compiler als Parameter "-D" mit zu geben. Diese Definitionen sind dann 
im gesamten Projekt verfügbar ohne  irgend eine Datei zu inkludieren.

Ein Klassiker, wo das üblich ist: "-DF_CPU=16000000"

von Jens (Gast)


Lesenswert?

Stefanus F. schrieb:
> Eine anderer Ansatz (der mir persönlich nicht gefällt) ist, solche
> Definitionen ins Build Script (bzw. Makefile) zu schreiben und dem
> Compiler als Parameter "-D" mit zu geben. Diese Definitionen sind dann
> im gesamten Projekt verfügbar ohne  irgend eine Datei zu inkludieren.
>
> Ein Klassiker, wo das üblich ist: "-DF_CPU=16000000"

Das muss ich mir mal anschauen, auch wenn ich es vermutlich nicht 
brauchen werde. Es einfach zu wissen, schadet ja nie.

jois3 schrieb:
> Hi Jens,
>
> datei1 ist universell (also das Paar aus .c und .h), während header1.h
> projektbezogen ist? Wenn ja, dann ist das die falsche Reihenfolge des
> inkludierens bzw. der Abhängigkeiten. Du möchtest Deine
> projektspezifischen Dateien von allgemeinen abhängig halten, nicht
> umgekehrt.
>
> Was Du tun kannst:
> Gib das ON und OFF als Parameter an Deine universellen Code-Teile - oder
> allgemeiner, gib alles projektspezifische hinein (Parametrisierung).
>
> Gruß, jois3

Also das heisst, dass ich die folgende Definition
1
#ifndef DEF_H
2
#define DEF_H
3
#define ON                                      GPIO_PIN_SET
4
#define OFF                                      GPIO_PIN_RESET
5
#define NONE                                    0xFFFFFFFF 
6
#endif

in der datei1.h und datei2.h einfügen muss.
Dann existiert in der header.h die Definition einfach nicht, wenn sie 
sonst auch im Projekt nirgends benötigt wird. Richtig?

von jois3 (Gast)


Lesenswert?

Hi Jens,

> Also das heisst, dass ich die folgende Definition
[...]
> in der datei1.h und datei2.h einfügen muss.
> Dann existiert in der header.h die Definition einfach nicht, wenn sie
> sonst auch im Projekt nirgends benötigt wird. Richtig?

Naja, eine nicht-existierende Definition führt freundlichstenfalls zu 
einer aussagekräftigen Fehlermeldung des Compilers...

Ist jetzt natürlich ohne konkreten Quelltext ziemlich abstrakt, aber 
mein Vorschlag zielt eher in Richtung ganz expliziter Parameterübergabe.
Also sprich, Du hast im projektspezifischen Code z.B. eine Prozedur 
namens "SetRedLEDOn", die dann eine "SetGPIO" im allgemeinen Teil 
aufruft, und dabei die Konstanten (die in projektspezifischen Teilen 
definiert sind) als Aufrufparameter übergeben. Während SetRedLEDOn dann 
z.B. SetGPIO(ON) aufruft, kann eine SetRedLEDOff dann eben SetGPIO(OFF) 
aufrufen. Ist etwas mehr Quelltext, dafür hat's sprechende Namen und 
eine feste Schicht, an der fachliches (Rote LED schalten) in technisches 
(GPIO-Wert setzen) übergeht.

Gruß, jois3

von Axel S. (a-za-z0-9)


Lesenswert?

Jens schrieb:
> Jetzt muss ich in die jeweiligen Headerdateien datei1.c und datei1.h die
> header1.h einbinden.

Ja. Wenn du Definitionen aus header1.h benötigst, dann mußt du header1.h 
#includen.

> Jetzt habe ich folgendes Problem.
> Wenn nun datei1.c und datei1.h irgendwo als Vorlage dient und ich ein
> komplett anderes Programm schreibe, aber diese c-Datei benötige, muss
> ich doch ständig die projektbezogene Headerdatei (header1.h) mitziehen,

Ja.

> obwohl diese mit dem neuen Programm nichts zu tun hat.

Nein. Wenn datei1.c oder datei1.h irgendwelche Definitionen aus 
header1.h benötigen, dann haben sie offensichtlich etwas damit zu tun. 
Deswegen kann header1.h nicht als "nicht dazu gehörig" betrachtet 
werden.

Ich glaube dein Fehler passiert viel eher:

Jens schrieb:
> Angenommen ich habe eine Headerdatei header1.h. Diese ist projektbezogen
> und enhält generelle Definitionen

"projektbezogen" und "generell" beißt sich. Es kann doch eigentlich nur 
entweder das eine oder das andere sein. Trenne diese beiden. Allgemeine 
Definitionen wirst du mehr oder weniger immer mitziehen müssen, 
projektbezogene Definitionen aber höchstwahrscheinlich nie.

Unabhängig von deiner konkreten Frage komme ich nicht umhin zu bemerken, 
daß du für meinen Geschmack viel zu viel versuchst, durch Makros 
wegzukapseln oder zu abstrahieren. Indirektion ist ein nützliches 
Hilfsmittel. Aber zuviel davon kann die Übersichtlichkeit des Codes auch 
wieder verschlimmern.

Immer dann, wenn du Makros in andere Makros verpackst, solltest du dich 
fragen, ob das sinnvoll ist. Immer dann, wenn du ein Makro nur an einer 
einzigen Stelle im Code verwendest, dito. Dein früheres Makro mit clock 
enable fällt genau in diese Kategorie. Typischerweise macht man das 
genau einmal im Programm und packt dann diesen Code auch in eine passend 
benannte Funktion wie z.B. hardware_init(void). Diese Funktion ist ganz 
klar projektspezifisch und es reicht vollkommen, wenn du da drin die 
Clocks der diversen Peripherieinheiten anschaltest; vielleicht jeweils 
noch mit einem Kommentar, warum.

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
Noch kein Account? Hier anmelden.