Nur eine Python version für Bin2c, einem "Allesmögliche-zu-C"-Konverter.
Ich weiss nicht obs bereits eine in Python gibt, aber wenn nicht, gibts jetzt eine (Versionen in anderen sprachen gibts ja bereits mehr als genügend ;P). =)
Herunterladen kann man das ganze Hier.
EDIT: Kleine änderung, welche Dateinamen in C-kompatible variablen-namen konvertiert, falls notwendig.
EDIT2: die generierte Doku findet sich hier.
EDIT3: Jetzt wird zumindest schon Java, C, C++, und D unterstützt.
EDIT4: Da gist aus irgendeinem grund nicht den vollständigen Paste speichert, wird das skript jetzt Hier herunterladbar sein.
Bin2c
@stuhlbein: Warum bei `writefile()` der Modus 'w+'? Das '+' wird doch gar nicht verwendet.
Der Test ob ein Zeichen eine Ziffer ist, geht auch ohne `string.digits`, nämlich direkt auf der Zeichenkette selbst: ``if name[0].isdigit():``.
Das Umwandeln von `char` in `getchar()` und `datastring` in `gettemplate()` in Zeichenketten ist überflüssig -- das sind doch schon welche.
Die Ermittlung von `basename` funktioniert nicht, wenn der Dateiname mehr als einen '.' enthäht. Zum Trennen von Dateiname und Erweiterung gibt's `os.path.splitext()`. Man sollte IMHO das Ergebnis von `convert_name()` auch testen, ob da wirlich ein gültiger C-Bezeichner heraus kommt, denn Dateinamen können ja alles mögliche enthalten was in C nicht in einem Bezeichner erlaubt ist.
Das formatieren von Werten in Zeichenketten über Dictionaries finde ich hier ziemlich übertrieben, und mal machst Du es und mal nicht.
`gettemplate()` ist als Name falsch. Die Funktion gibt kein Template zurück.
Das ``position += 1`` hat keinen Effekt und kann ersatzlos gestrichen werden.
Zeichenketten in Schleifen mit ``+=`` aufbauen ist unpythonisch, weil das quadratische Laufzeit haben kann. Zeichenketten sind nicht veränderbar, also wird bei jedem ``+=`` eine neue Zeichenkette erzeugt und die beiden Anderen werden dafür im Speicher kopiert. Idiomatisch wäre das sammeln von Zeichenketten in einer Liste, die man dann am Ende mit `str.join()` zu einer Zeichenkette zusammenfasst. Ich hätte an der Stelle statt dem hantieren mit `position` die Eingabe in Blöcke zu 15 Zeichen zerlegt und die mit ``','.join(map(convert_char, block))`` zu einer Zeile zusammengesetzt und am Ende dann die ganzen Zeilen mit ``',\n'.join(lines)``.
Oder man könnte das Ganze auch als Datenstrom-orientierte Lösung schreiben, also nicht alles in den Speicher laden, sondern Vorspann rausschreiben, dann immer Blöcke von 15 Bytes aus der Eingabe lesen und konvertiert in die Ausgabedatei schreiben, und danach dann das kleine `main()` rausschreiben. Damit ist man relativ unabhängig vom Hauptspeicher und der Dateigrösse. Falls jemand mal ein DVD-Image in ein C-Programm einbetten möchte.
Erweiterungsvorschlag: Mehr als nur C unterstützen, Python fehlt zum Beispiel ganz offensichtlich , und auch verschiedene Formate bei den einzelnen Werten. Und die Optionen mit `optparse` verarbeiten.
Der Test ob ein Zeichen eine Ziffer ist, geht auch ohne `string.digits`, nämlich direkt auf der Zeichenkette selbst: ``if name[0].isdigit():``.
Das Umwandeln von `char` in `getchar()` und `datastring` in `gettemplate()` in Zeichenketten ist überflüssig -- das sind doch schon welche.
Die Ermittlung von `basename` funktioniert nicht, wenn der Dateiname mehr als einen '.' enthäht. Zum Trennen von Dateiname und Erweiterung gibt's `os.path.splitext()`. Man sollte IMHO das Ergebnis von `convert_name()` auch testen, ob da wirlich ein gültiger C-Bezeichner heraus kommt, denn Dateinamen können ja alles mögliche enthalten was in C nicht in einem Bezeichner erlaubt ist.
Das formatieren von Werten in Zeichenketten über Dictionaries finde ich hier ziemlich übertrieben, und mal machst Du es und mal nicht.
`gettemplate()` ist als Name falsch. Die Funktion gibt kein Template zurück.
Das ``position += 1`` hat keinen Effekt und kann ersatzlos gestrichen werden.
Zeichenketten in Schleifen mit ``+=`` aufbauen ist unpythonisch, weil das quadratische Laufzeit haben kann. Zeichenketten sind nicht veränderbar, also wird bei jedem ``+=`` eine neue Zeichenkette erzeugt und die beiden Anderen werden dafür im Speicher kopiert. Idiomatisch wäre das sammeln von Zeichenketten in einer Liste, die man dann am Ende mit `str.join()` zu einer Zeichenkette zusammenfasst. Ich hätte an der Stelle statt dem hantieren mit `position` die Eingabe in Blöcke zu 15 Zeichen zerlegt und die mit ``','.join(map(convert_char, block))`` zu einer Zeile zusammengesetzt und am Ende dann die ganzen Zeilen mit ``',\n'.join(lines)``.
Oder man könnte das Ganze auch als Datenstrom-orientierte Lösung schreiben, also nicht alles in den Speicher laden, sondern Vorspann rausschreiben, dann immer Blöcke von 15 Bytes aus der Eingabe lesen und konvertiert in die Ausgabedatei schreiben, und danach dann das kleine `main()` rausschreiben. Damit ist man relativ unabhängig vom Hauptspeicher und der Dateigrösse. Falls jemand mal ein DVD-Image in ein C-Programm einbetten möchte.
Erweiterungsvorschlag: Mehr als nur C unterstützen, Python fehlt zum Beispiel ganz offensichtlich , und auch verschiedene Formate bei den einzelnen Werten. Und die Optionen mit `optparse` verarbeiten.
Ich versteh nicht was du meinst? `w+` setzt den Zeiger auf den anfang der Datei (deswegen ja auch der Hinweis dass die datei überschrieben wird).BlackJack hat geschrieben:@stuhlbein: Warum bei `writefile()` der Modus 'w+'? Das '+' wird doch gar nicht verwendet.
gefixt in der neusten revision.Der Test ob ein Zeichen eine Ziffer ist, geht auch ohne `string.digits`, nämlich direkt auf der Zeichenkette selbst: ``if name[0].isdigit():``.
Das Umwandeln von `char` in `getchar()` und `datastring` in `gettemplate()` in Zeichenketten ist überflüssig -- das sind doch schon welche.
Die Ermittlung von `basename` funktioniert nicht, wenn der Dateiname mehr als einen '.' enthäht. Zum Trennen von Dateiname und Erweiterung gibt's `os.path.splitext()`.
Das formatieren von Werten in Zeichenketten über Dictionaries finde ich hier ziemlich übertrieben, und mal machst Du es und mal nicht.
Das ``position += 1`` hat keinen Effekt und kann ersatzlos gestrichen werden.
ich hab die funktion mit jeder denkabren art von Namen durchgetestet, und kann getrost behaupten dass sie valide C-bezeichner wiedergibt. wenn dir aber ein bug auffällt, kannst du ihn natürlich melden ;PMan sollte IMHO das Ergebnis von `convert_name()` auch testen, ob da wirlich ein gültiger C-Bezeichner heraus kommt, denn Dateinamen können ja alles mögliche enthalten was in C nicht in einem Bezeichner erlaubt ist.
stimmt, seh ich ein. Praktischerweise hab ich die funktion in `bin2c()` umbenannt`gettemplate()` ist als Name falsch. Die Funktion gibt kein Template zurück.
Ich denke ich versteh schon was du meinst, aber ein direktes problem seh ich nicht... Die idee das mit StringIO zu machen kam mir aber auch schon, und würde das persönlich auch einer Liste vorziehen.Zeichenketten in Schleifen mit ``+=`` aufbauen ist unpythonisch, weil das quadratische Laufzeit haben kann. Zeichenketten sind nicht veränderbar, also wird bei jedem ``+=`` eine neue Zeichenkette erzeugt und die beiden Anderen werden dafür im Speicher kopiert. Idiomatisch wäre das sammeln von Zeichenketten in einer Liste, die man dann am Ende mit `str.join()` zu einer Zeichenkette zusammenfasst. Ich hätte an der Stelle statt dem hantieren mit `position` die Eingabe in Blöcke zu 15 Zeichen zerlegt und die mit ``','.join(map(convert_char, block))`` zu einer Zeile zusammengesetzt und am Ende dann die ganzen Zeilen mit ``',\n'.join(lines)``.
Oder man könnte das Ganze auch als Datenstrom-orientierte Lösung schreiben, also nicht alles in den Speicher laden, sondern Vorspann rausschreiben, dann immer Blöcke von 15 Bytes aus der Eingabe lesen und konvertiert in die Ausgabedatei schreiben, und danach dann das kleine `main()` rausschreiben. Damit ist man relativ unabhängig vom Hauptspeicher und der Dateigrösse. Falls jemand mal ein DVD-Image in ein C-Programm einbetten möchte.
Mittlerweile unterstützt es C, C++, und D. Ich kenn mich leider nicht mit Java, BASIC, pascal oder Fortran aus um diese einzubauen, aber vielleicht les ich mich ja ein. ;PErweiterungsvorschlag: Mehr als nur C unterstützen, Python fehlt zum Beispiel ganz offensichtlich , und auch verschiedene Formate bei den einzelnen Werten. Und die Optionen mit `optparse` verarbeiten.
Und den tipp mit optparse hab ich selbstverständlich auch beachtet (selber link, neueste revision).
Auch "w" alleine setzt den Zeiger auf den Anfang der Datei. Lies mal in der Doku nach, was der tatsächliche Unterschied zwischen "w" und "w+" ist.
@stuhlbein: Ich denke bei der Mehrsprachenversion sollte man mit Templates arbeiten, also zum Beispiel mit `string.Template` und nicht mit einem ``if`` bzw. ``elif`` pro Sprache.
Ausserdem passt jetzt der Name der Funktion schon wieder nicht.
Ausserdem passt jetzt der Name der Funktion schon wieder nicht.
Ich versteh nicht inwiefern string.Template besser als ein paar if/elif zweige sein soll. Nicht jede Sprache auf diesem planeten hat C syntax.BlackJack hat geschrieben:@stuhlbein: Ich denke bei der Mehrsprachenversion sollte man mit Templates arbeiten, also zum Beispiel mit `string.Template` und nicht mit einem ``if`` bzw. ``elif`` pro Sprache.
Sag bloss dass bin2c() kein passender name für das Modul bin2c, dessen haupt-funktion bin2c() ist? hmm, nenn mich kleinkariert...Ausserdem passt jetzt der Name der Funktion schon wieder nicht.
@stuhlbein: Nein, nicht jede Sprache hat C-Syntax, aber was hat das damit zu tun? Es ist halt sauberer Daten und Code ein wenig zu trennen, dann lassen sich auch einfacher neue Sprachen hinzufügen. Im einfachsten Fall in dem man einfach ein neues Template und ein Sprachkürzel einem Dictionary hinzufügt. Und nicht wie jetzt, indem man einen Haufen Quelltext in einen neuen ``elif``-Zweig kopiert und anpasst.
`bin2c` ist auch ein unpassender Name für das Modul. Nenn mich kleinkariert, aber von so einem Modul würde ich nur erwarten, dass da C herauskommt. Für so eine allgemeine Funktion fänd' ich `bin2source()` halt passender und `bin2c()` zum generieren von D-Quelltext unpassend.
`bin2c` ist auch ein unpassender Name für das Modul. Nenn mich kleinkariert, aber von so einem Modul würde ich nur erwarten, dass da C herauskommt. Für so eine allgemeine Funktion fänd' ich `bin2source()` halt passender und `bin2c()` zum generieren von D-Quelltext unpassend.
gut, ist ein argument. Leider hab ich nur keine ahnung wie genau du das nun meinst. Beispiel?BlackJack hat geschrieben:@stuhlbein: Nein, nicht jede Sprache hat C-Syntax, aber was hat das damit zu tun? Es ist halt sauberer Daten und Code ein wenig zu trennen, dann lassen sich auch einfacher neue Sprachen hinzufügen. Im einfachsten Fall in dem man einfach ein neues Template und ein Sprachkürzel einem Dictionary hinzufügt. Und nicht wie jetzt, indem man einen Haufen Quelltext in einen neuen ``elif``-Zweig kopiert und anpasst.
Richtig, aber ich glaube, die meisten haben das programm einfach als bin2c im Kopf. und ohne jede sprach-angaben spuckt das programm ohnehin nur C code aus, weshalb ich mit dem namen durchaus leben kann. Die anderen sprach-varianten sind ohnehin mehr ein proof of concept, ich persönlich brauch zb nur die C, bzw, C++ variante. =)`bin2c` ist auch ein unpassender Name für das Modul. Nenn mich kleinkariert, aber von so einem Modul würde ich nur erwarten, dass da C herauskommt. Für so eine allgemeine Funktion fänd' ich `bin2source()` halt passender und `bin2c()` zum generieren von D-Quelltext unpassend.
Du könntest zb eine Klasse "Language" anlegen und alle Fälle, bei denen du etwas ersetzen musst, als string.Template Klassen übergeben lassen. Dann legst du ein (globales, konstantes) Dict an welches Sprachnamen zu Language Exemplaren zuordnet.
Stimmt. an sich auch eine gute idee. =)str1442 hat geschrieben:Du könntest zb eine Klasse "Language" anlegen und alle Fälle, bei denen du etwas ersetzen musst, als string.Template Klassen übergeben lassen. Dann legst du ein (globales, konstantes) Dict an welches Sprachnamen zu Language Exemplaren zuordnet.
Der wartbarkeit halber habe ich aber nun doch D und Java aus dem Code entfernt.
Zudem besitzen sowohl Java (durch JAR pakete) als auch D (die `import()` funktion) bereits native möglichkeiten, um Media dateien in der resultierenden ausführbaren datei einzubetten.