mikrocontroller.net

Forum: Compiler & IDEs Callback Funktionen und typedef


Autor: Dario C. (dario) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
  // Prototyp
  void do_action(void);
main.c:
 // Callback Funktion
 void do_action(void);
 {
     counter++;
 }

 // Main
 int main (void);
 {
     // Callback anmelden
     RTC_Init (do_action);
 }

rtc.h:
 // Typ der Callback Funktion
 typedef void (*rtc_callback_t) (void);
rtc.c:
 // Variable für Pointer auf die Callback Funktion
 rtc_callback_t RTC_DowTimerCallbackFunc;

 // Setzen der Callback Function
 void RTC_Init(rtc_callback_t pFunc)
 {
      RTC_CallbackFunc == pFunc;
      ...
 }

 // Aufruf irgendwo in rtc.c
 RTC_CallbackFunc();


Soweit so gut, was aber wenn ich der Callback Function
einen Parameter übergebn möchte, der ein typedef enum
ist, also sowas:
 typedef enum {
    MO, TU, WE, TH, FR, SA, SU, TIMER_ACTIVE
 } rtc_dow_t;

 RTC_CallbackFunc(rtc_dow_t dayofweek)

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.

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der typedef gehört ins rtc.h, und das wiederum per #include "rtc.h" ins 
main.c.

Oliver

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dario C. wrote:

>
>  typedef enum {
>     MO, TU, WE, TH, FR, SA, SU, TIMER_ACTIVE
>  } rtc_dow_t;
> 
>  RTC_CallbackFunc(rtc_dow_t dayofweek)
> 
>
> 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
typedef enum {
    MO, TU, WE, TH, FR, SA, SU, TIMER_ACTIVE
} rtc_dow_t;

 // Typ der Callback Funktion
 typedef void (*rtc_callback_t) (rtc_dow_t dayOfWeek);

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>// Setzen der Callback Function
> void RTC_Init(rtc_callback_t pFunc)
> {
>      RTC_CallbackFunc == pFunc;
                        ^^
>      ...
> }

ist das wirklich so gemeint?

MW

Autor: Dario C. (dario) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> rtc.h
 typedef enum {
     MO, TU, WE, TH, FR, SA, SU, TIMER_ACTIVE
 } rtc_dow_t;
 
  // Typ der Callback Funktion
  typedef void (*rtc_callback_t) (rtc_dow_t dayOfWeek);

Ja, aber die implemetierte Fuction in main.c muss ja doch so aussehen:

main.c
void ich_bin_die_callback_function (rtc_dow_t dayofweek)
{
  .. some code
}

Und der Prototyp dazu in der

main.h
void ich_bin_die_callback_function (rtc_dow_t);

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
RTC_CallbackFunc = pFunc;

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Dario C. (dario) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: OliverSo (Gast)
Datum:
Angehängte Dateien:
  • rtc.zip (976 Bytes, 174 Downloads)

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.