Hallo miteinander, habe nun mein erstes C-Projekt fast fertig. Da ich das ganze im "Learning-by-doing"-Verfahren gemacht habe, fehlt mir offenbar noch ein wenig Verständnis. Folgender Sachverhalt: Ich habe das Projekt in "Module" gegliedert. Module in dem Sinn, dass ich ein C-File habe, welches z.B. die serielle Kommunikation abwickelt, ein Modul für die Display-Steuerung usw. (Nebenbei, ich rede von C für Mikrocontroller, aber C ist C). Okay, so weit so gut. Als Beispiel nehme ich jetzt mal das RS232-Modul. Dort habe ich einen Verweis auf eine externe Routine, welche prüft, ob das übergebene Zeichen ein ASCII-Hex-Zeichen (also "0" - "9" und "A" bis "F") ist. Daher muss ich ja im RS232-Modul einen #include Verweis auf das Modul machen, welches die Prüf-Routine enthält, richtig? Mein Problem ist, dass ich nicht direkt auf eine Routine in einem bestimmten Modul verweisen möchte (was ja durch das #include zwangsläufig passiert), sondern ich möchte nur den Namen der entsprechenden Routine verwenden. Das sichert mir die Unabhängigkeit der einzelnen Module voneinander. Ist das machbar und/oder sinnvoll? Oder habe ich ein größeres Verständnis-Problem, als ich dachte? ;-) Dass ich in einigen Modulen zwangsläufig auf andere verweisen muss, ist mir klar, aber ich möchte u.a. auch folgendes Problem lösen: Da ich es wie bereits erwähnt bevorzuge, einzelne Module zu verwenden, welche ein bestimmtes "Thema" abdecken, möchte ich erreichen, dass diese Module (welche ja so eine Art "Treiber" darstellen), völlig unabhängig voneinander funktionieren (also ohne Verweis auf ein bestimmtes anderes Modul). Hoffe, ich konnte mein Problem verständlich rüberbringen. Gruß Ralf PS: Vielleicht hat ja auch jemand einen Link, wo die Lösung solcher Probleme angegangen wurde?
ähm... also zu allererst.. dir ist hoffentlich klar das du im include nur .h files einbinden solltest... den code darf der compiler sich selbst aus der .c generieren (darum gibst ja auch in der makefile deine .c files an ;) ich habe mir übrigeds eine tool-lib gebastelt...auf die haben alle meine libs einen include stehn und die .c wird auch überall reingelinkt (so heisst das übrigends wenn man aus den .obj/.o/... files die der compiler produziert eine schöne ausführbare file macht ;) wo ist also das genaue problem ?? willst du deine treiber von diesem (in meinem fall tool-lib) tool-modul unabhängig machen ??? weil dann hilft nur copy-past von allem funktionen die du brauchst... aber das macht wieder probs weil am schluss der linker mäckern wird weil ein und die selbe funktion an mehrerern orten definiert ist wenn du sie in mehrern modulen reintust 73
Mit der Include-Datei machst Du dem "Modul" den Prototyp einer Funktion bekannt. Die Funktion selbst kann in einem ganz anderen "Modul" implementiert (in Code ausformuliert) sein. In deinem Beispiel hättest Du die Funktionen für die serielle Kommunikation in das Modul SERIELL13.C gesteckt und die für die Displayansteuerung in das Modul DISPLAY45.C Ich gehe ab jetzt davon aus, dass Du die Vorteile von Prototypen kennst und NICHT darauf verzichten möchtest ;-) Du kannst jetzt die Prototypen der Funktionen aus SERIELL13.C in der Includedatei SERIELL.H halten und die für DISPLAY45.C in der Includedatei DISPLAY.H. Will eine Funktion aus SERIELL13.C eine Funktion aus DISPLAY45.C benutzen, ist kann der Prototyp der Funktion durch ein #include DISPLAY.H in SERIELL13.C bekannt gemacht werden. Mehr als der Name, die Parameterübergabe (!!!) und der Rückgabetyp (!!!) ist dem aufrufenden Modul nicht bekannt. Wie die Funktion dann in dem anderen Modul implementiert (codiert) ist, sieht die aufrufende Funktion nicht. Meinst Du das mit Unabhängigkeit? Wenn es Dich nervt, mit vielen Includedateien umzugehen, kannst Du mehrere Includedateien zusammenfassen. Zum Beispiel könntest Du alle Prototypen von selbstprogrammierten Funktionen in RALF.H reinstecken und diese Datei in allen Modulen mit #include RALF.H einbinden. Aber schön ist das nicht. Wenn es noch unabhängiger sein soll, kannst Du in jedem Deiner Module ein Feld von Funktionszeigern einrichten. Ein Supervisormodul (z.B. Dein Hauptprogramm) füllt die Funktionszeiger am Anfang auf und die Module greifen auf andere Module zu, in dem sie die Funktionen über die Funktionszeiger aufrufen statt direkt. Aber Vorsicht: Nicht dass Du uns zu den objektorientierten Sprachen entfleuchst ;-)
Danke für die Antworten. Und dann muss ich sagen: UUPS, natürlich arbeite ich mit Prototypen, und die habe ich auch schön brav in den H-Files angegeben, und ich habe natürlich auch nur die H-Files included. Sorry, war keine Absicht, solch eine Verwirrung zu stiften ;-) Vielleicht lässt sich mein Problem anders etwas verständlicher ausdrücken: Durch das #include bin ich immer an eine bestimmte Modul-Datei gebunden. Ich suche eine Möglichkeit, eine Funktion unabhängig vom Modul, in der sie enthalten ist, bekannt zu machen. Sagen wir als Beispiel, ich habe im Projekt A im Modul "RS232" eine Routine "GET_ASC_HEX", die aus dem übergebenen ASCII-HEX-Zeichen einen Hex-Wert generiert. Jetzt erstelle ich Projekt B, das die gleiche Funktion braucht, aber das RS232-Geraffel nicht. Statt dessen brauche ich die Funktion "GET_ASC_HEX" im Modul "DISPLAY" von Projekt B. Was ich nun als Lösung machen könnte, wäre die "GET_ASC_HEX" in ein anderes Modul zu schreiben, z.B. Modul "HEX". Auf dieses Modul kann ich in A von "RS232" aus mit #include "HEX.h" zugreifen. Das gleiche gilt für Projekt B mit einem #include in "DISPLAY". Jetzt geht es aber schon los, das werden ja zig Module! Und ich bin wieder bei meinem Problem, ich habe wieder eine Abhängigkeit zu einem anderen Modul. Das will ich aber für die TREIBER-Module VERHINDERN! Dass das nötig ist für die eigentliche Applikation, ist klar, aber in den Treiber Modulen möchte ich das eben verhindern. Dort möchte ich nur sagen können, es gibt die Funktion in einem anderen Modul, aber ohne zu sagen, in welchem Modul, was aber durch das #include nicht möglich ist, denn ich muss ja den Modulnamen angeben. Damit müsste sich doch die von mir gewünschte "Unabhängigkeit" der Treiber erreichen lassen, oder? Vielleicht ist diese Umschreibung verständlicher ;-) ODER: Sind solche "Treiber-Module" immer stand-alone-fähig geschrieben, d.h. ich kopiere den verwendeten Code immer direkt in das Modul und verwende keinen Code aus anderen Modulen? NOCH EIN ODER: Ist in Bezug auf das Schreiben solcher Treiber-Module meine Vorgehensweise falsch? Gruß Ralf BTW: Ich habe gerade einen Blick in die bei C mitgelieferten H-Files geworfen (stdio.h). Dort sind die Prototypen mit extern deklariert. Ist das Schlüsselwort "extern" evtl. die Lösung für mein Problem? Oder sagt das dem Compiler nur, dass er in einer Bibliothek zu suchen hat?
Das Einbinden des Maschinencodes für eine Funktion in ein Programm macht der Linker. Dazu werden binäre Objektdateien oder binäre Librarydateien zum Hauptprogramm dazugebunden. An der Stelle haben die Includedateien ihre Aufgabe längst getan. Die Includedateien mit den Prototypen wurden vom Präprozessor benutzt, um z.B. Typkontrollen durchzuführen. Du kannst Millionen von Prototypen in eine Includedatei packen. Der Präprozessor fischt sich nur die notwendigen (= die im Programm benutzten) raus. Dein eigentliches Problem hat mit den Includedateien nichts zu tun. Du musst Dir überlegen, welche Funktionen Du sinnvoll in den verschiedenen Libraries bzw. Quelltextdateien für einzelne Objektdateien zusammenfasst. Du kannst Dich an an dem Aufbau der Standard-C-Libraries orientieren. Dein Beispiel mit HEX.C ist schon OK. Die Vielzahl der Module wird üblicherweise reduziert, indem man mit einem Librarian die kleinen Objektdateien der Module in einer Library zusammenfasst und der Linker sich die benötigten herausfischt. Und weil der Präprozessor auch angeln kann, legt man nicht für jede Funktion eine einzelne Includedatei an, sondern fasst viele zusammen. Im Extremfall packt man alle Windows Prototypen in eine fette windows.h ;)
Ja, das "extern" zeigt dem Compiler, dass die Funktion nicht in dem Quelltext implementiert (= in Code ausformuliert) wird, der gerade bearbeitet wird. Trifft der Compiler im Quelltext auf einen Funktionsaufruf einer externen Funktion, wird er in der Objektdatei vermerken, dass der Linker später da was aus einer weiteren Objektdatei oder einer Library dazubinden muss.
Hi Stefan, danke für die Hilfe. In meinem C-Buch wird "extern" nämlich nur in Verbindung mit dem Benkanntmachen von Variablen in anderen Modulen verwendet, daher war ich mir unsicher, ob man es auch mit den Prototypen bzw. Funktionen verwenden kann. Demnach müsste "extern" mein Problem lösen können. Gruß Ralf
Bei Funktionsprototypen ist "extern" implizit und kann daher ohne irgendwelche Auswirkungen weggelassen werden.
Hi Rufus, dass würde dann bedeuten, ich muss nicht die H-Datei einbinden, sondern kann die Prototypen aus der H-Datei des externen, "fremden" Moduls verwenden. Das ist auch nicht schlecht ;-) Gruß Ralf
> dass würde dann bedeuten, ich muss nicht die H-Datei einbinden, > sondern kann die Prototypen aus der H-Datei des externen, > "fremden" Moduls verwenden. Hmm, was meinst du mit letzterem? Du weißt doch bestimmt, dass das "Einbinden" mittels #include vom Präprozessor erledigt wird, sodass es für den Compiler absolut keine Rolle mehr spielt, wie die Prototypen in den Code gelangt sind?
Hi Chris, eben genau das ist es ja, was ich suche. Ich wollte ja unabhängig von dem Modul sein, in dem die externe Funktion steht. Über einen #include bin ich jedoch immer von einem bestimmten Modul abhängig, da ich ja den Namen der H-Datei angeben muss. Über die Sache mit dem extern ist es egal, WO in welchem Modul die Funktion steht. Gruß Ralf
Nein, es ist völlig wurscht, wie die Headerdatei heisst, in der die Prototypen deklariert sind. Es ist lediglich eine sinnvolle Konvention, die Headerdatei genauso zu nennen wie das zugehörige Sourcemodul. Daher kannst Du Dein "Treiberkonzept" beispielsweise so realisieren: In einer Headerdatei namens "treiber.h" deklarierst Du die Prototypen // treiber.h int machdies(char* womit); void machjenes(int warum); int machnix(void) Und in jedem einzelnen Treibermodul implementierst Du diese Funktionen mit exakt demselben Namen: // Turboblaster.c #include "treiber.h" int machdies(char* womit) { return (0); } // ... etc. // Gurkenhobel.c #include "treiber.h" int machdies(char* womit) { return (1); } // ... etc. In Deiner Projektverwaltung oder Deinem Makefile darfst Du nur genau eine der Treiberimplementierungsdateien einbinden, also entweder turboblaster.c oder gurkenhobel.c
Hallo Ralf, bin grad auch dabei C für microcontroller anzuwenden. Da du auch damit grad angefangen hast, wollt ich nachfragen ob du Irgendwelche gute Tutorials /links zu dem Thema zusammen getragen hast. Würde mich sehr auf eine Antwort freuen
Hi Rainer, ich suche halt immer mal wieder das Forum ab, auch das Internet bleibt nicht verschont. Ansonsten gucke ich auch auf www.c51.de, dort ist ebenfalls ein Forum und Code-Beispiele gibt es dort auch. Von C51.de habe ich mir die beiden Bücher für den Keil C51 Compiler gekauft. Und ein paar Bücher über C allgemein habe ich auch schon. Das ist alles was du brauchst (Aus meiner Sicht). Der Rest ist Hirn benutzen und üben, üben, üben. Sicher wird ein Profi vielleicht die Hände über dem Kopf zusammenschlagen, wenn er meinen Schreib-Stil sieht, aber ES FUNKTIONIERT grins Wenn du ein Problem hast, kannst mir ja mailen, vielleicht kann ich dir helfen. Gruß Ralf
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.