2016-12-10 12 views
1

Ich bin auf der Suche durch eine Basis jemand anderen Code und ich sehe diese Funktion Prototyp:Wie wird dieses Strukturelement zu einer Funktion ohne Klammern ausgewertet?

void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); 

Und es definiert ist, wie folgt:

void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) 
{ 
    Radio.Sleep(); 
    BufferSize = size; 
    memcpy(Buffer, payload, BufferSize); 
    RssiValue = rssi; 
    SnrValue = snr; 
    State = RX; 
} 

Aber, es später in der Super-Schleife aufgerufen

RadioEvents.RxDone = OnRxDone;

wie auf der Erde, dass legal ist: von main wie hier gezeigt? Diese Funktion erwartet einen Zeichenzeiger und drei Ints, aber es geht nichts und das funktioniert gut. Was geht hier vor sich?

+0

Aktualisiert die Frage. – testname123

+0

zurückgerollt. Sobald Sie eine Antwort erhalten haben, sollten Sie die Frage nicht ändern! Wir sind kein Diskussionsforum. Wenn Sie eine neue Frage haben, öffnen Sie eine neue Frage! Aber am besten wäre es, diese Grundlagen aus einem guten C-Buch zu bekommen. Bestimmte Fragen oder unstrukturierte Tutorials oder Youtube-Videos geben nicht das ganze Bild, wenn es nötig ist. – Olaf

Antwort

7

RadioEvents.RxDone = OnRxDone;

Dies ruft nicht Funktion OnRxDone. Stattdessen weist es den Zeiger auf die Funktion OnRxDone einem anderen Funktionszeiger zu, der ein Mitglied von RadioEvents ist. Hier wird der Funktionsname als Zeiger auf diese Funktion verwendet. Später kann es mit dem Funktionszeiger RadioEvents.RxDone mit den erforderlichen Parametern aufgerufen werden.

Edit: nach der Bearbeitung in der Frage scheint es, dass OP nach den Details des Funktionszeigers fragt. Googeln "c Funktionszeiger" gibt diese Frage als erstes Ergebnis zurück: How do function pointers in C work?

2

RadioEvents.RxDone = OnRxDone;

Es scheint RadioEvents ein struct von Funktionszeigern ist, und RxDone ist einer von ihnen, und so die Zuordnung gültig ist.


Nach der Frage bearbeiten:

Wie erwähnt, liegt die Antwort in der Struktur von RadioEvents, aber dies stellt klar, nur dies, wenn Sie verstehen, was eine Struktur von Funktionszeigern tut. Kann jemand näher erläutern, wie das alles zusammenhängt und was die ganze Geschichte damit ist?

Die Geschichte dahinter ist, dass Struktur RadioEvents eine Schnittstelle definiert. Zum Beispiel definiert der Linux-Kernel eine solche Schnittstelle, so dass alle drahtlosen Treiber folgen müssen. Der Kernel muss nicht die Implementierungsdetails jedes Treibers kennen, er muss lediglich die Funktionen implementieren, die in dieser Struktur RadioEvents definiert sind.

Jeder Treiber hat eine andere Implementierung der Funktion RxDone - die Implementierungsdetails können hardwarespezifisch sein. Aber solange der Treiber diesen Prototyp implementiert, kann er in den Kernel gesteckt werden.

Sie können die genaue Übereinstimmung zwischen der Funktion API RxDone in RadioEvents beachten:

void (*RxDone)(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); 

und die OnRxDone:

void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); 

Dies wird manchmal als Polymorphismus im Kernel.

2

RadioEvents.RxDone ist eine variable von funktions pointer Typ. Sie kann auf jede Funktion mit einem bestimmten Parameter und einer Rückgabetypsignatur verweisen, die durch ihre Typdefinition definiert wird. In diesem Fall wird das Strukturelement RxDone so definiert:

void (*RxDone)(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); 

anzeigt, dass es auf eine Funktion bezieht sich void zurückkehren und vier Argumente der Typen uint8_t*, uint16_t, int16_t und int8_t bzw. Einnahme. Die Parameternamen in dieser Erklärung sind optional und es könnte equelly sein:

void (*RxDone)(uint8_t*, uint16_t, int16_t, int8_t); 

oder sogar

tRxDone RxDone ; 

wo tRxDone definiert somit ist:

typedef (*tRxDone)(uint8_t*, uint16_t, int16_t, int8_t); 

Die Funktion RadioEvents.RxDone zugeordnet sein kann, wird anschließend aufgerufen (nicht in Ihrem Codefragment gezeigt):

RadioEvents.RxDone(data, data_length, rssi, snr) ; 

Der Zweck einen Zeiger auf eine Funktion ist, dass es die Unterstützung für vorgesehen späte Bindung wo die Funktion aufgerufen wird, wird, anstatt hart zu Laufzeit bestimmt, kodiert durch den Linker und Zeit aufzubauen. Es wird oft für Callbacks verwendet, wo einige Bibliothekscode eine benutzerdefinierte Funktion aufrufen wird, um das Verhalten anzupassen und anzupassen. Im Gegenzug werden Callbacks oft für Event-Handler verwendet, was in Ihrem Beispiel so aussieht.

Was die Zuordnung von RadioEvents.RxDone hat im Wesentlichen der Bibliothek * sagen wird „wenn ein Ereignis Rx kompletter nennen geschieht meine Funktion OnRxDone“ *.

Verwandte Themen