Hallo, gibt es einen offiziellen Weg folgendes in C zu realisieren? Ich habe mehrere Hardwarekomponenten (UART, USB, ...). Alle können Datenströme senden und empfangen. D.h. für jede Hardwarekomponente gibt es ein struct, welches die Komponente verwaltet. Nun haben diese structs gemeinsamme Elemente. Z.B. verfügt jede Hardwarekomponente über einen Send- und Empfangspuffer + dazugehörige Pointer. Diese sind für alle Hardwarekomponentet/structs gleich. Nun möchte ich eine C-Funktion schreiben, der ich jede dieser verschiedenen structs übergeben kann. Wichtig wäre da aber, daß z.B. der RxBuffer in allenen structs den gleichen Offset hat. In C++ würde man da ja z.B. eine struct/class entwerfen, die dieses gemeinsammen Elemente enthält. Alle speziellen structs/classes würden dann von dieser erben. Somit könnte man der Funktion einen Pointer vom Typ Basisklasse übergeben und man kann sicher sein, daß die in der Basisklasse deklarieretn Elemente für alle Hardwarekomponenten an der gleichen stelle liegt. Wie macht man das in C?
Eklige Variante: cast Bessere Variante: die gemeinsamen Komponenten in einer Unter-Struct zusammenfassen, von der dann eine Instanz in jeder Haupt-Struct ist. Der Programmteil, der keine Unterscheidungen macht, bekommt dann einen Zeiger auf diese Unter-struct.
Habe ich mir schon gedacht. Ich hatte aber gehofft, daß ich die doppelte Indirektion umgehen kann. Kann man ich eigentlich darauf verlassen, daß die oberen struct-Member in verschiedenen structs, wenn sie gleich sind, immer den gleichen Offset haben?
Du definierst ein Struct, als CPP define z.B. und verwendest es. Nicht elegant, aber portable. #define HW_CLASS \ int size; \ int used; char* head; \ char* foot; \ char buff[0] Wenn der/die Compiler alle unnamed structures unterstützt, dann definiere eine Struct, und instanziere es, das ist sauberer, aber nicht portabel.
@chris: Was meinst Du mit "als CPP define"? Und was meinst Du mit "sauber, aber nicht portabel"? Solange es die Compiler unterstützen und ich den Datenblock nicht blind auf ein anderes System übertrage, sollte es doch gehen, oder?
Die einzelnen IO-Typen (oder Zeiger darauf) in eine Union stopfen?
1 | #include "usb.h" |
2 | #include "uart.h" |
3 | #include "i2c.h" |
4 | ...
|
5 | |
6 | enum
|
7 | {
|
8 | IO_USB, |
9 | IO_UART, |
10 | IO_I2C, |
11 | ...
|
12 | |
13 | IO_NIL
|
14 | };
|
15 | |
16 | typedef union |
17 | {
|
18 | int id; |
19 | |
20 | struct
|
21 | {
|
22 | int id; |
23 | usb_t data; |
24 | } usb; |
25 | |
26 | struct
|
27 | {
|
28 | int id; |
29 | uart_t data; |
30 | } uart; |
31 | |
32 | ...
|
33 | |
34 | } io_t; |
35 | |
36 | void handle_io (io_t * io) |
37 | {
|
38 | switch (io->id) |
39 | {
|
40 | case IO_USB: |
41 | io->usb.data.buffer[0] = '0'; |
42 | break; |
43 | |
44 | case IO_UART: |
45 | io->uart.data.buffer[0] = '0'; |
46 | break; |
47 | |
48 | ...
|
49 | |
50 | default:
|
51 | fatal_error(); |
52 | break; |
53 | }
|
54 | }
|
Das ist keine Verebung, aber es gibt dir verschiedene Sichten auf dein io-Objekt. Und in uart.h:
1 | #include "buffer.h" // extern char buf[]; |
2 | |
3 | typedef struct |
4 | {
|
5 | ...
|
6 | char * buffer; |
7 | ...
|
8 | } uart_t; |
9 | |
10 | void uart_init (uart_t * uart) |
11 | {
|
12 | uart->buffer = buf; |
13 | ...
|
14 | }
|
>Was meinst Du mit "als CPP define"? einfach eine preprozessor define, habe dir ein Beispiel dort gemacht. struct hw_serial { HW_CLASS; char dummy[100]; } hw_serial1,hw_serial2; >Und was meinst Du mit "sauber, aber nicht portabel"? Solange es die >Compiler unterstützen und ich den Datenblock nicht blind auf ein anderes >System übertrage, sollte es doch gehen, oder? Ja, wenn es deine Compiler unterstützen. Z.B. struct hw_base { int size; char *head; char*tail; ... }; struct hw_rs232 { struct hw_base; int port; ... } serial1, serial2; dann kannst du im Code z.B. serial1.size usw benutzen, als hättest du sie in hw_rs232 declariert. Bei neueren Branches des GCC kann es sein, daß du -fms-extensions als Kommandozeile übergeben mußt, damit er das macht, früher konnter es es auch ohne.
Johann L. schrieb: > Das ist keine Vererbung, aber es gibt dir verschiedene Sichten auf dein > io-Objekt. Und in uart.h: .uart.data.buffer und .usb.data.buffer liegen nicht notwendig an der gleichen Adresse (was auch nicht nötig ist) aber sie zeigen auf die gleiche Adresse, wenn diese Zeiger richtig initialisiert wurden (siehe unten). Beachte, daß das dann nicht reentrant-fähig ist.
So, so,.. ... und da sag noch einer, für Microcontroller brauche man kein C++. Dabei könnte das Leben doch so einfach sein. Dann fang ich mal an mir eine Lösung zu stricken ;-)
Was hindert dich daran, den mikrocontroller in c++ zu programmieren ?
> Habe ich mir schon gedacht. Ich hatte aber gehofft, daß ich die doppelte > Indirektion umgehen kann. Ein CPP-Compiler macht bei Vererbung nix anderes. Aus
1 | class Dings : public class Bums { |
2 | int some_field; |
3 | };
|
4 | |
5 | ...
|
6 | Dings d; |
7 | Bums *b = &d; |
wird
1 | struct Dings { |
2 | struct Bums _base; |
3 | int some_field; |
4 | };
|
5 | |
6 | ...
|
7 | struct Dings d; |
8 | struct Bums *b = &(d._base); |
Da bei Einfachvererbung das Basisobjekt an den Anfang des Gesamt-Structs gepackt wird, ist diese Indirektion übrigens im Maschinencode recht trivial ;-) Und, wie schon von den Vorpostern genannt: Nimm nen C++-Compiler. Du musst ja außerhalb dieser Stelle keine C++-Features nutzen, von daher hat dies auf die Codegröße keine negativen Auswirkungen.
pic32 sowie pic18 Compiler ist GCC (Gnu C Compiler), man bekommt auch die Sourcen. Klar kann der C++. Bei pic24 sowie pic3x weiß ich nicht, ob das GCC ist, oder nicht. Warscheinlich.
der gcc ist ein c compiler der g++ ist ein c++ compiler der c18 ist KEIN gcc, der pic24 aka c30 ist ein gcc derivat die anderen angaben stimmen irgendwie verwaschen das thema, auf jedenfall ist der c18, c30 und c32 KEIN C++ compiler
Hier ein Thread mit Beispielprogramm am Schluss über das objektorientierte Programmieren in C: Beitrag "Objekte in C"
> der gcc ist ein c compiler > der g++ ist ein c++ compiler und die GCC ist alles zusammen (Gnu Compiler Collection)
na dann anders ausgedrückt, die gcc die microchip liefert kann kein c++ :)
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.