Werte GCC Freaks,
ich habe da mal ein Problem:
Doch zuerst die Eckdaten: AVRLIB 1.6.0 (WinAVR)
Ich habe zwei Module main.c und rtc.c
RTC hat eine Uhr und die soll zu bestimmten Zeiten eine Funktion
aus main.c aufrufen. Das habe ich wie folgt gedacht:
main.h:
1
// Prototyp
2
voiddo_action(void);
main.c:
1
// Callback Funktion
2
voiddo_action(void);
3
{
4
counter++;
5
}
6
7
// Main
8
intmain(void);
9
{
10
// Callback anmelden
11
RTC_Init(do_action);
12
}
rtc.h:
1
// Typ der Callback Funktion
2
typedefvoid(*rtc_callback_t)(void);
rtc.c:
1
// Variable für Pointer auf die Callback Funktion
2
rtc_callback_tRTC_DowTimerCallbackFunc;
3
4
// Setzen der Callback Function
5
voidRTC_Init(rtc_callback_tpFunc)
6
{
7
RTC_CallbackFunc==pFunc;
8
...
9
}
10
11
// Aufruf irgendwo in rtc.c
12
RTC_CallbackFunc();
Soweit so gut, was aber wenn ich der Callback Function
einen Parameter übergebn möchte, der ein typedef enum
ist, also sowas:
1
typedefenum{
2
MO,TU,WE,TH,FR,SA,SU,TIMER_ACTIVE
3
}rtc_dow_t;
4
5
RTC_CallbackFunc(rtc_dow_tdayofweek)
WO muss das typedef hin?
Es ist ja eigentlich ein Bestandteil von rtc,
hat also in main.h nix verlohren, oder?
Aber in der main.h muss der bekannt sein,
sonst gehr der Prototype nicht.
>> WO muss das typedef hin?> Es ist ja eigentlich ein Bestandteil von rtc,> hat also in main.h nix verlohren, oder?
Du meinst rtc.h, nicht main.h
Doch, der muss ins rtc.h
Wie soll denn sonst die aufgerufene Funktion diesen
Parameter auswerten, wenn sie nicht weiss was ihr da
als Argument übergeben wird?
rtc.h
Und jetzt muss ich ja in der main.c zuerst die rtc.h includen
und danach erst die main.h, sonst kennt die main.h den typen rtc_dow_t
ja noch nicht.
Das kann es doch nicht sein, oder?
Und in der rtc.c muss ich die main.h vor der rtc.h includen,
weil mir sonst die defines (z.B.:) F_CPU fehlen. Und spätestens
da bekomme ich Probleme.
Dario
PS:
@ Michael Wilhelm (Gast):
>> RTC_CallbackFunc == pFunc;> ^^^^> ist das wirklich so gemeint?
Tippfehler, selbstverständlich muss es heissen
> Und der Prototyp dazu in der main.h>> void ich_bin_die_callback_function (rtc_dow_t);
Was soll der da? Diese Funktion wird nur innerhalb von main.c verwendet,
also genügt es, den Prototypen in main.c anzulegen.
Und das machst Du halt nach der üblichen #include-Orgie.
Das heisst:
ich packe in die Header Datei ausschließlich die Funktionen,
die von extern mit ihrem Namen aufgeruden werden müssen?
Also nicht die, die über einen Pointer aufgerufen werden,
den ich vorher übergeben habe.
Sehe ich das richtig so?
Ist die Funktion deren Pointer ich dann übergebe static?
Dario.
Anbei ein Beispiel, wie du es machen könntest.
Ich würde allerdings F_CPU gar nicht im headerfile, sondern mit -DF_CPU
im makefile als Compileroption definieren. Damit bekommmts du mehr
Sicherheit, daß wirklich alle Dateien den selben Wert sehen.
Oliver
Dario C. wrote:
> Das heisst:>> ich packe in die Header Datei ausschließlich die Funktionen,> die von extern mit ihrem Namen aufgeruden werden müssen?
Richtig!
>> Also nicht die, die über einen Pointer aufgerufen werden,> den ich vorher übergeben habe.
Wozu soll die rtc Funktion denn den Namen der Funktion
benötigen. Sie hat ja einen Pointer darauf und macht den
Aufruf über den Pointer.
> Sehe ich das richtig so?>> Ist die Funktion deren Pointer ich dann übergebe static?
Nein. Das eine hat mit dem anderen nichts zu tun.
Es ist einfach so, dass die aufrufende Funktion den Namen
der Funktion gar nicht kennen braucht, weil: Sie hat ja
die Startadresse der Funktion. Und über diese Startadresse
wird die Funktion gestartet. Wie auch immer sie heissen mag.
Solange sich nur Aufrufer und aufgerufene Funktion darüber einig
sind, welche Argumente übergeben werden und welcher returntyp
zurückgegeben werden muss, ist doch alles paletti.
Und hier kommt das rtc.h Header File ins Spiel.
In diesem File ist dokumentiert wie sich der Code in rtc.c
den Aufruf so vorstellt. Die Funktion in main.c muss sich nur
an diese Vorgaben halten.
> Ist die Funktion deren Pointer ich dann übergebe static?
Ist sie zwar nicht, aber es ergäbe keinen funktionalen Unterschied, wenn
sie es wäre.
Der einzige Unterschied zwischen einer statischen und einer
nichtstatischen Funktion ist in C der, daß bei einer statischen Funktion
kein für den Linker verwendbarer Symbolname erzeugt wird.
Das hat zur Folge, daß a) diese Funktion wirklich nur von Code aus dem
die Funktion enthaltenen Modul aufgerufen werden kann und daß b) in
anderen Modulen Funktionen mit exakt demselben Namen vorhanden sein
können.
Der Aufruf der Funktion über einen Funktionspointer funktioniert auch
aus anderen Modulen heraus, sofern der Wert des Funktionspointers in dem
Modul bestimmt wird, in dem die betreffende Funktion enthalten ist.