MoinMoin, ich habe da mal eine C-Problem, welches mich gerade beschäftigt, wobei ich aber nicht weis, ob es dafür eine Lösung gibt, vielleicht hat ja hier jemand eine Idee: Man kann ja, nach der bekannten Methode, Funktionen über Pointer aufrufen. Bei der Typ-Deklaration solcher Funktionspointer muss man, wenn diese Funktionen Parameter haben, laut "Lehrbuch", die Typen der Übergabeparameter mit deklarieren. Soweit so gut und kein Problem, wenn die so verpackten Funktionen alle die gleiche Anzahl von Übergabeparametern haben und die Typen ebenfalls gleich sind. Damit kann man dann ja auch, wie ich das auch möchte, eine schicke Tabelle mit allen Funktionspointern usw. aufbauen.... Mein Problem: die Anzahl der Übergabeparameter und deren Typ ist bei mir nicht gleich! Erschwerend kommt dazu, dass ich nicht in jeder Funktionen eine Mimik ala va_list, va_start, va_arg, va_end einbauen möchte, also ich sie unverändert lassen möchte (weil sie halt gegeben sind und u.U. im Programm auch ohne Funktionspointer aufgerufen werden sollen usw.). Frage, gibt es einen Weg dieses Problem irgendwie doch zu lösen! Grüße & Danke Uwe
Gast
#1717971
Dann mach wrapper-Funktionen mit va_.
Uwe Berger schrieb: > Mein Problem: die Anzahl der Übergabeparameter und deren Typ ist bei mir > nicht gleich! Dann hast du ein Problem > Erschwerend kommt dazu, dass ich nicht in jeder Funktionen > eine Mimik ala va_list, va_start, va_arg, va_end einbauen möchte, musst du auch nicht. main() weiß auch nicht, wieviele Argumente es bekommt und hat trotzdem einen Mechanismus wie es eine variable Argumentliste bekommt. > also > ich sie unverändert lassen möchte (weil sie halt gegeben sind und u.U. > im Programm auch ohne Funktionspointer aufgerufen werden sollen usw.). Du könntest * Zwischenwrapper einbauen. Also Funktionen, die alle die gleiche Argumentliste haben. Ihre einzige Aufgabe ist es, sich aus der fixen Argumentliste die benötigten herauszuholen und damit die eigentlichen Funktionen aufzurufen * Casten was das Zeug hält. Zu deinen Funktionspointern kommt noch ein zusätzliches Attribut dazu, das dir sagt, von welchem konkretem Typ der Funktionspointer ist. (Du hast also einen Vorrat an verschiedenen Funktionspointer- Datentypen und dieser Eintrag sagt dir welcher der richtige ist) Dort siehst du nach, castest den Pointer zurecht und rufst die Funktion auf. Der erste Weg ist der saubere Weg. Insbesondere mit einem argc/argv Mechanismus wie ihn main() auch verwendet, ist das eine saubere Sache. Hat man nicht zuviele verschiedene Argumentlisten spricht auch nichts dagegen, einfach den 'größten gemeinsamen Nenner' aller Argumentlisten zu ermitteln und die Wrapperfunktionen damit aufzurufen. Der zweite weg ist der dirty Weg, der in solchen Fällen meistens gar nicht so quick ist. Insbesondere wenn es viele verschiedene Argumentlisten, artet das in eine switch-case Schlacht aus. Und Pointer-Casten ist generell etwas, was immer einen anrüchigen Beigeschmack haben sollte.
Nobody schrieb: > Dann mach wrapper-Funktionen mit va_. > wie müsste das ungefähr aussehen? (eine solche ungefähre Idee schwirrt auch in meinem Gehirn rum, aber der Ansatz fehlt bisher...) ... bzw. meinst du für jede Funktion eine eigene Wrapper-Funktion? Könnte man das noch irgendwie verallgemeinern, um nur eine Wrapper-Funktion zu haben? Grüße & Danke Uwe
Karl heinz Buchegger schrieb: > * Casten was das Zeug hält. > Zu deinen Funktionspointern kommt noch ein zusätzliches Attribut dazu, > das dir sagt, von welchem konkretem Typ der Funktionspointer ist. > (Du hast also einen Vorrat an verschiedenen Funktionspointer- > Datentypen und dieser Eintrag sagt dir welcher der richtige ist) > Dort siehst du nach, castest den Pointer zurecht und rufst die > Funktion auf. ... ungefähr kann ich mir dunkel vorstellen, was du meinst... hast du ein kleines Beispiel? Grüße & Danke Uwe
Uwe Berger schrieb: > ... bzw. meinst du für jede Funktion eine eigene Wrapper-Funktion? Kann man machen. Man kann aber auch einfach nur für jede Funktionsklasse einen entsprechenden Wrapper bauen > Könnte man das noch irgendwie verallgemeinern, um nur eine > Wrapper-Funktion zu haben? Auch das könnte man machen. Um casten kommt man nicht rum, solange man nicht für jede einzelne Funktion einen eigenen Wrapper schreibt.
Gast
#1717999
Falls du beim Aufruf einer Funktion nicht weißt, welche Funktion da tatsächlich aufgerufen wird, und du damit auch nicht weißt, welche Parameter diese benötigt, hast du ein Problem. Wenn es für die fehlenden Parameter sinnvolle default-Werte gibt, geht das über var args, oder eine standardisierte Maximal-Parameterliste. Wenn nicht, geht es gar nicht. Wenn du das vor dem Aufruf schon weißt, was du aufrufst, reicht ein einfacher cast des Funktionspointers. Oliver
Gast
#1718001
Uwe Berger schrieb: > ... bzw. meinst du für jede Funktion eine eigene Wrapper-Funktion? Ja. > Könnte man das noch irgendwie verallgemeinern, um nur eine > Wrapper-Funktion zu haben? Sorry, aber es geht entweder va_ innerhalb der Funktion oder ausserhalb. Die Wrapper-Funktion muss ja wissen wieviele Parameter sie auspacken soll. Das geht aber nur aus der Parameterliste hervor. Für Metaprogramming dann mal LISP oder Smalltalk andenken. Praktisch verallgemeinern kannst Du das mit einem Perl-Script der Dir zu einer gegebenen Deklaration einen Wrapper schreibt.
Gast
#1718006
Karl heinz Buchegger schrieb: >> Könnte man das noch irgendwie verallgemeinern, um nur eine >> Wrapper-Funktion zu haben? > > Auch das könnte man machen. Um casten kommt man nicht rum, solange man > nicht für jede einzelne Funktion einen eigenen Wrapper schreibt. Du meinst dann beim Aufruf des Wrappers?
Uwe Berger schrieb: > > ... ungefähr kann ich mir dunkel vorstellen, was du meinst... hast du > ein kleines Beispiel? Keine Phantasie :-)
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
ungetesteter Code. Es kann sein, dass man den Compiler an der einen oder anderen Stelle mit noch einem Cast davon überzeugen muss, dass ich schon weiß was ich tue. Die Sache mit der variablen Argumentliste und deren Einbau in den Wrapper darfst du machen. Und überprüfe lieber doppelt und dreifach, ob die Einträge im Functions Array auch mit den tatsächlichen Gegebenheiten übereinstimmen. Zuwiderhandlungen werden mit Debugsitzungen nicht unter 3 Stunden bestraft.
Ich glaube mich zu erinnern (finde die Stelle aber gerade nicht im Standard), dass eine Konvertierung eines beliebigen Funktionszeigers auf einen anderen und wieder zurück durch den Standard abgedeckt ist. Damit kann man sich einen "generischen Funktionszeigertypen" bauen, mit dem der Zeiger selbst in einer Tabelle o. ä. untergebracht wird, und der dann per typecast vor dem Aufruf in einen Funktionszeiger mit der korrekten Parameterliste gewandelt wird (der Aufrufer sollte sich natürlich sehr sicher sein, welche und wie viele Argumente zu über- geben sind, aber sonst hat er sowieso ein Problem ;-). Was jedoch nicht vom Standard abgedeckt ist, ist die Wandlung eines Funktionszeigers in einen Objektzeiger (also z. B. "void *") und zurück; es kann Architekturen geben, bei denen die Darstellung beider Adressräume nicht verlustfrei ineinander überführt werden kann. (Dafür muss man gar nicht so weit laufen: bereits der AVR ist eine derartige Architektur, lediglich der GCC handhabt sie nicht als solche, weil er innerhalb einer Architektur-Portierung nur eine einzige Zeigergröße kennt.) p.s.: Genau das macht Karl Heinz aber gerade. ;-)
Jörg Wunsch schrieb: > Was jedoch nicht vom Standard abgedeckt ist, ist die Wandlung eines > Funktionszeigers in einen Objektzeiger (also z. B. "void *") und > zurück; es kann Architekturen geben, bei denen die Darstellung beider > Adressräume nicht verlustfrei ineinander überführt werden kann. AH. Ich wusste nicht mehr, ob man auf einen void* gehen darf oder nicht. Ist aber kein Beinbruch, dann nimmt man anstelle des void* einfach einen der Funktionspointer her und definiert den als den 'Standardfall' in den alle anderen gecastet werden um im Array Platz nehmen zu können und aus dem dann wieder herausgecastet wird. Bei der bisher angerichteten Schweinerei kommts auf eine mehr oder weniger auch nicht mehr an :-) Gegen die C-Version einer Smith&Wesson hat der Compiler keine Chance.
ok, danke für die Anregungen..., da habe ich erst mal eine ganze Menge Stoff zum Nachdenken und rumexperimentieren! Falls ich nicht klar kommen sollte, kann ich mich ja nochmal melden. Grüße Uwe
Karl heinz Buchegger schrieb: > Ist > aber kein Beinbruch, dann nimmt man anstelle des void* einfach einen der > Funktionspointer her und definiert den als den 'Standardfall' Oder halt
1 | |
...ich nochmal zu dem Thema, nachdem ich über die gezeigten Ansätze geschlafen habe: Ist es, um sich ein wildes Rumcasten zusparen, auch möglich, die Deklaration des Funktionspointers in der Tabelle mittels union zu überlagern? In der Wrapper-Funktion spricht man dann, so wie Karl Heinz es vorgeschlagen hat, an Hand des in der Tabelle mit abgelegten Zeiger-Typs die Variable mit dem entsprechenden Typ an... Grüße & Danke Uwe
Uwe Berger schrieb: > Ist es, um sich ein wildes Rumcasten zusparen, auch möglich, die > Deklaration des Funktionspointers in der Tabelle mittels union zu > überlagern? Ja, die Idee kam mir auch schon.
Ist die union dann eleganter als wildes Rumcasten?
...naja, da könnte man sich drüber streiten. Impliziet läuft es auf das gleiche hinaus. Aber ich bin der Meinung, dass es zumindestens transparender ist (und damit vielleicht einige Fehlerfallen weniger in sich verbirgt). Grüße Uwe
Wenn der Compiler noch die alte per-ANSI-Syntax ohne Prototyping von
Funktionen beherrscht, dann geht das recht einfach. Natürlich schaufelt
man sich so das eigene Grab - aber wer darauf Lust hat, der möge es
probieren.
Also
void (*fptr)();
void f1(a) { ... }
void f2(a,b) double a; { ... }
und
fptr = f2;
fptr(3.14, 1);
fptr = f1;
fptr(0);
Wahrscheinlich muss man allerdings ein paar Warnungen des wohlmeinenden
Compilers standhaft ignorieren.
Das ist Leichenfledderei. Leidest du unter Nekrophilie? :-)
Klaus Wachtler schrieb: > Leidest du unter Nekrophilie? :-) Wieso "leiden"? ;-) Ohnehin hat die Fragestellung an sich schon einen Hang zu "gothic", da passt das doch prima rein.
Dann viel Spaß! Brrrr...
A. K. schrieb: > Ohnehin hat die Fragestellung an sich schon einen Hang zu "gothic", da > passt das doch prima rein. > :-) könnte stimmen, beim (privaten) Rumprogrammieren höre ich die entsprechend düstere Musik am liebsten. Grüße Uwe
Sowas höre ich nicht mal beim Rumtrinken.
Uwe Berger schrieb: > Aber ich bin der Meinung, dass es zumindestens transparender ist (und > damit vielleicht einige Fehlerfallen weniger in sich verbirgt). Nicht wirklich. Die Fehleranfälligkeit ist ja nicht der Cast an sich. Die potentielle Falle steckt hier:
1 | |
2 | |
3 | |
4 | |
5 | |
Du kannst hier wild Funktionspointer mit falschen Signaturkennungen versehen, ohne das dich irgendein Compiler der Welt davor schützen könnte Blödsinn zu machen. An dieser Stelle wird der Typprüfungsmechanismus ausgehebelt. Hier ist der Programmierer zu 100% in der Pflicht, das ohne Compilerunterstützung korrekt hinzukriegen und vor allen Dingen: auch in der Zukunft, wenn sich zb Funktionssignaturen verändern, hier auch nachzuziehen. Der Compiler wird dich nicht darauf aufmerksam machen, dass du hier ebenfalls nachbessern musst. Alles Weitere sind dann nur noch syntaktische Varianten der Auswertung eben dieser Datenstruktur. Aber dieses Array muss stimmen. Wenn es nicht korrekt aufgebaut wurde, dann krachts. Egal wie du es auswertest.
Ja. Das Problem ist, daß der TE unbedingt seine Funktionen nicht ändern will. Für jede elegante und sauebre Lösung müsste er aber genau das tun. Es ist ein legitimer Wunsch, das nicht zu tun, aber dann muß man zwangsläufig mit Murks leben und hat noch die Wahl, ein möglichst kleines Übel zu nehmen.
Klaus Wachtler schrieb: > Das Problem ist, daß der TE unbedingt seine Funktionen nicht > ändern will. Für jede elegante und sauebre Lösung müsste er > aber genau das tun. Meine Erfahrung ist: Solche vermeintlich schnell durchgeführte Krücken fallen einem immer irgendwann auf den Schädel. Vielleicht nicht heute, vielleicht nicht morgen. Aber irgendwann kommt der Boomerang. Und dann ist in der Zwischenzeit alles noch viel schlimmer geworden. Diese Krücke hat noch andere Krücken hervorgebracht, wirkt sich u.U auf Dateiformate aus, Kunden haben mitlerweile Unmengen an Daten mit diesem Dateiformat, etc. Kurz und gut: Ganz am Anfang der Geschichte hätte man alles noch einfach in den Griff kriegen können. Da ging es nur um ein paar Stunden Arbeit, die investiert werden müssten. Durch die Verschleppung ist man dann aber in der Situation, dass man die Krücke nicht einfach ausbauen und ersetzen kann. Zuviel anderes Zeugs hängt davon ab. Und dann sitzt man erst so richtig in der Sch... > Es ist ein legitimer Wunsch, das nicht zu tun, aber dann muß > man zwangsläufig mit Murks leben und hat noch die Wahl, ein > möglichst kleines Übel zu nehmen. Pest oder Cholera :-)
Nochmal Hallo zusammen..., so ungefähr würde ich mir das mit union vorstellen (ohne den Wrapper, der je nach Typ und Anzahl der Parameter, die Parameter setzt und den entsprechenden Funktionspointer aufruft). Ist da jetzt ein eklatanter Fehler enthalten?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
@Karl Heinz: mir ist klar, dass die Initialisierung der Tabelle callfunct[] kritisch ist und in meiner Verantwortung ist. In dem Zusammenhang verstehe ich auch die beiden Warnings, die der Compiler bei der Initialisierung der zweiten und dritten Tabellenzeile schmeisst: warning: initialization from incompatible pointer type (Ich kann das Programm gerade nicht auf der Zielplattform (ein AVR, sonst hätte ich nicht hier gefragt ;-)...) ausprobieren, da ich sie nicht bei der Hand habe.) Eine Frage noch: Warum warnt der Compiler bei der Initialisierung der Tabelle mit dem Spruch "warning: missing braces around initializer", wenn ich die Funktionsnamen nicht in {} schreibe? Steckt da noch Unverständnis meinerseits dahinter? Grüße & Danke Uwe PS.: achso, warum eigentlich diese ganze Geschichte? Ich habe ja vor einigen Tagen angefangen einen Basic-Interpreter zu schreiben/weiterzuentwickeln, der auf einem AVR läuft (siehe auch entsprechender Thread im Unterforum "Codesammlung"). Um diesen Interpreter im Funktionsumfang drastisch zu erweitern möchte ich einen Basic-Befehl "call funct, p1, p2, ..." implementieren, der bestehende C-Routinen z.B. aus irgend einer Lib aufrufen kann.
Uwe Berger schrieb: > Eine Frage noch: Warum warnt der Compiler... Weil du einen einfachen Wert (Zeiger) angibst, wo eigentlich ein Aggregattyp (union) verlangt wird.
Uwe Berger schrieb: > Eine Frage noch: Warum warnt der Compiler bei der Initialisierung der > Tabelle mit dem Spruch "warning: missing braces around initializer", > wenn ich die Funktionsnamen nicht in {} schreibe? Steckt da noch > Unverständnis meinerseits dahinter? Weil innerhalb der struct noch eine union steckt. Du brauchst für jedes Aggregat (struct oder union) eine {} > Interpreter im Funktionsumfang drastisch zu erweitern möchte ich einen > Basic-Befehl "call funct, p1, p2, ..." implementieren, der bestehende > C-Routinen z.B. aus irgend einer Lib aufrufen kann. Speziell dann würde ich mir auf jeden Fall etwas völlig anderes überlegen. Da ist Tür und Tor für Fehler offen. Merke: Wann immer du eine Benutzerinteraktion hast, und für einen BASCIC-Compiler ist nun mal das zu compilierende Programm seine 'Benutzerinteraktion', kannst du nie genügend vorsichtig sein. Vertrauen dass der Benutzer schon das richtige eingeben wird, ist naiv (verzeih den Ausdruck)
Uwe Berger schrieb: > entsprechenden Funktionspointer aufruft). Ist da jetzt ein eklatanter > Fehler enthalten? Auf die Schnelle hab ich nichts gesehen. Ich seh aber auch nicht, wie die union da irgendetwas vereinfachen würde. Denn das hier > int main(void) { > callfunct[0].funct_ptr.VoidFuncVoid(); > callfunct[1].funct_ptr.VoidFuncInt(1); > callfunct[2].funct_ptr.VoidFuncIntInt(1, 2); Ist ja nicht die reale Anwendung. In der realen Anwendung weißt du ja nicht, dass an callfunct[0] ein VoidFuncVoid Pointer steckt.
In C99 kann man angeben, welches Element einer union initialisiert wird:
callfunct_t callfunct[] = {
{"a", .funct_ptr.VoidFuncVoid = a, FUNC_VOID_VOID, 0},
{"b", .funct_ptr.VoidFuncInt = b, FUNC_VOID_INT, 1},
{"c", .funct_ptr.VoidFuncIntInt = c, FUNC_VOID_INT_INT, 2}
};
Gast
#1718914
Das mit den unions ist ja schon ganz nett, aber wie sieht es mit folgender Idee aus? Statt Funktionen mit verschiedenen Parametern (und einer verschiedenen Anzahl Parameter) kann man die Funktionen allesamt so umschreiben, dass sie nur einen einzigen Parameter bekommen - eben eine Union aller moeglichen Parameter der verschiedenen Funktionen. Jede Funktion holt sich dann aus der Union ihre jeweiligen Argumente heraus, diese sind ja fuer jede Funktion bekannt. Damit sind die Signaturen aller Funktionen gleich (je ein Parameter - die o.g. union) und Aufrufe ueber function pointer sind harmlos. Dies scheint mir im Vergleich der einfachste Ansatz zu sein. Murkser
Naja, das ist eine von mehreren sauberen Möglichkeiten. Der TE möchte aber seine Funktionen nicht ändern - was zwar m.E. fragwürdig ist, aber des Menschen Wille sei sein Himmelreich.
Gast
#1718925
Ob jetzt
1 | |
oder
1 | |
weniger "gothic" ist, ist wohl eher Geschmackssache. Oliver
Klaus Wachtler schrieb: > Naja, das ist eine von mehreren sauberen Möglichkeiten. > Der TE möchte aber seine Funktionen nicht ändern - was > zwar m.E. fragwürdig ist, aber des Menschen Wille sei > sein Himmelreich. Yepp. Das mindeste was ich tun würde: Vor die eigentlichen und vorhandenen Funktionen einen Wrapper setzen. Der Wrapper kriegt die vereinheitlichte Argumentliste (wie auch immer die aussieht, union finde ich nicht so gut (*)), holt sich die für die Funktion relevanten Argumente dort heraus, macht meinetwegen noch ein paar Prüfungen darauf und ruft dann die eigentliche Funktion auf. Die vorhandene Funktion muss nicht geändert werden, lediglich der Wrapper ist zu schreiben. Da es aber nicht unendlich viele unterschiedliche Argumentlisten geben wird, kann man sich da ein paar Hilfen bauen, so dass in weiterer Folge so ein Wrapper eine Frage von ein paar Minuten wird. (*) Da das ganze offenbar sowieso in eine Runtime-virtuelle CPU eingebaut wird, ist das sogar noch viel einfacher: Die virtuelle CPU legt die Argumente auf den Callstack, schreibt noch die Anzahl an Argumenten auf den Stack und die Wrapperfunktionen holen sich das dann von dort wieder, Prüfen die Anzahl, holen die Argumente etc. Das ganze läuft also darauf hinaus, der virtuellen CPU beizubringen mit variablen Argumentlisten umzugehen.
> Vor die eigentlichen und vorhandenen Funktionen einen Wrapper setzen.
Dann kann man aber mit dem gleichen Aufwand auch gleich die Funktionen
sinnvoll ändern. Aber jeder wie er will...
Wie sagte mein Bruder mal so schön: "Meine Katze mag die Mäuse roh,
ich mag sie nicht mal gekocht."
Klaus Wachtler schrieb: >> Vor die eigentlichen und vorhandenen Funktionen einen Wrapper setzen. > > Dann kann man aber mit dem gleichen Aufwand auch gleich die Funktionen > sinnvoll ändern. Aber jeder wie er will... Ich meinte nur: Dann braucht er die eigentlichen Funktionen in den anderen Libraries nicht ändern. Das mag unter Umständen auch gar nicht so einfach sein, weil es noch andere Projekte gibt, die die Funktionen genau so haben wollen.
Jo, das mag sein. Ich habe aber eher den stillen Verdacht, daß die eh alle von ihm sind und er nur keine Lust hat... Wenn es um inneren Schweinehund geht, weiß ich, wovon ich rede!
Klaus Wachtler schrieb: > Wenn es um inneren Schweinehund geht, weiß ich, wovon ich rede! <verlegen mit der Fusspitze im Sand scharren> Schnell weg :-)
Klaus Wachtler schrieb: > Ich habe aber eher den stillen Verdacht, daß die eh alle von ihm > sind und er nur keine Lust hat... > nein, sind sie erst mal nicht. Wenn es so wäre, würde ich wahrscheinlich die Sache "richtiger" machen und stimme euren Bedenken zu! Die Idee zu dem call-Basic-Befehl kam mir, als ich jemanden, der relativ aktiv im c't-Bot-Projekt (http://de.wikipedia.org/wiki/C%E2%80%99t-Bot) ist, von dem AVR-Basic-Interpreter erzählt habe. Er meinte, dass ein solcher Interpreter eine interessante Sache wäre, um Fahrverhalten, Grundfunktionen, keine Ahnung was noch und die als gegebene C-Funktionen vorliegen, nachladbar auf SD-Card zu haben und bei Bedarf ausführen zu können. Wenn man das etwas allgemeiner betrachtet, bietet ein solcher call-Befehl fast unendliche Möglichkeiten im Hinblick auf den Funktionsumfang und die Anpassbarkeit des Interpreters für den jeweiligen Anwendungsfall. Von der Sache wäre es dann möglich, irgend eine bestehende, fremde, tausendmal bewährte Lib einzubinden und die Funktionen dem call-Befehl bekannt zu machen. Warum soll ich z.B. die Initialisierung und Ausgabe auf ein LCD für den Basic-Interpreter neu schreiben, wenn es dafür bewährte Libs gibt? Es ist doch viel einfacher eine dieser Libs (unmodifiziert) einzubinden, um später im Basic-Programm schreiben zu können:
1 | |
2 | |
3 | |
4 | |
Grüße Uwe PS.: es ist ein echter Interpreter, kein Compiler der Zwischen- oder Pseudocode vorproduziert. Das Basic-Programm wird im "Klartetxt" auf den AVR geladen und dann schrittweise analysiert und entsprechend ausgeführt. So ist der Ansatz...
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.