Python vs C++ vs C# vs Java für Software Entwicklung und Embedded?

4 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Alle genannten Sprachen verfügen über exzellent ausgearbeitete Features und mächtige (Standard-) Bibliotheken, aber für µC wäre es auch heutzutage ratsam, sich mit C und Assembler auseinander zu setzen.

Assembler allein schon deshalb, weil du dein Kompilat damit disassemblieren, und die Funktionsweise prüfen kannst. Gerade bei Embedded-Sachen finden sich dort z. B. auch gerne mal richtige Compiler-Fehler wider, bei denen man sich ohne Assemblerkenntnisse totgesucht hätte.

Ansonsten ist C sehr schlank und mit vernünftigen Herangehensweisen auch sehr sicher und effizient zu programmieren. Auf großen Rechnern bevorzuge ich C++, aber gerade im Embedded-Bereich fehlen dir u. U. sehr sehr sehr viele Features, die du von C++ her kennst (keine Exceptions, keine dynamische Speicherreservierung, es fehlt ein großer Teil der Standardbibliothek, usw.).

C++ kannst du nutzen, wenn du dicke fette Mikrocontroller nutzt, aber vor allem die kleineren und günstigeren von TI, Atmel, ehemals Microchip, usw. usf. sind oft viel zu schwachbrüstig, um darauf "richtigen" C++ Code ausführen zu können.

Wenn aber überhaupt erst mal ein C++ Compiler für deine Plattform existiert, und du dich aber mit einer sehr kleinen Teilmenge der gängigen C++ Features zufrieden geben kannst, können gerade moderne C++ Compiler wunderbar effizienten Code erzeugen, der deutlich effizienter ist und weniger Speicher benötigt, als vergleichbarer C-Code. (Dafür brauchst du aber nach Möglichkeit MINDESTENS einen C++11 Compiler, IDEAL wäre aber ein C++17 Compiler, evtl. bereits teilweise mit features von C++20.)

Alle anderen genannten Sprachen (Python, C# und Java) sind für eingebettete Systeme nicht geeignet und Spezialfälle für C# oder Java konnten sich in den letzten Jahrzehnten nicht durchsetzen und dümpeln seitdem vor sich hin, bzw. sind schon relativ frühzeitig ausgestorben.

Allerdings ist Python quasi DIE Standardsprache um einige gängige Debugger zu steuern bzw. zu automatisieren, und zusammen mit einem ISP kannst du z. B. den GDB damit in die mächtigste "Debugmaschine" verwandeln, die man sich vorstellen kann.

Für Java und C# sehe ich hier keine Anwendungsmöglichkeiten, aber das ist auch nicht weiter schlimm, da diese Sprachen für andere Dinge konzipiert wurden.

Falls du etwas zu viel Zeit und ausreichend Lust hast, solltest du dir diese beiden aber ebenfalls mal ansehen, da diese eine extrem große Standardbibliothek mitbringen, die unvergleichbar mächtiger ist, als das, was standardmäßig mit C oder gar C++ kommt. Allein Python kommt hier in die Nähe ... aber wie gesagt, vergleichen kann man diese ganzen Sprachen eigentlich nicht, da sie einfach zu unterschiedlich sind.

Fazit: Wenn du Embeddedkram machen willst, dann lerne auf jeden Fall C! Da wirst du nicht drum herum kommen, egal für welchen Mikrocontroller du dich entscheidest. C ist in dem Bereich einfach die ungeschlagene Nummer Eins.

Falls es sich um einen relativ mächtigen µC handelt, guck dir an, ob sich C++ sinnvoll einsetzen lässt. Und damit du überhaupt weißt, was intern passiert, und nicht bei jedem Fehler im Netz fragen musst, lerne auf jeden Fall auch die Architektur und den Assembler-Dialekt deiner Plattform.

(Die Programmierung von eingebetteten Systemen funktioniert etwas anders, als Desktop-Programme. Falls dein Englisch ausreicht, besorge dir mal das Buch "Making Embedded Systems" vom O'Reilly Verlag ... aber lerne vorher erst mal richtig C, damit du überhaupt weißt, worum es in dem Buch geht.)

Und wenn du dich irgendwann mal eingefummelt hast, könntest du Python nebenbei lernen, um deine Entwicklungswerkzeuge zu automatisieren, aber das ist jetzt kein Primärziel.

C# und Java brauchst du dabei vorläufig erst mal nicht, zumindest nicht in deinem Falle für das ganze Embedded-Zeug. Trotzdem kannst / solltest du die auch mal irgendwann lernen, weil dich Kenntnisse darin allgemein weiterbringen werden und es einfach praktisch ist, gewisse Anforderungen in Java / C# zu erschlagen, für die diese Sprachen einfach das beste Werkzeug darstellen.

Viel Spaß! :)

Tarustyle 
Fragesteller
 17.04.2018, 20:45

Um aber zum Beispiel ein Microcontroller mit einer App zu verbinden/ steuern ? Da lohnt es sich aber schon die App mit Java oder C# programmieren zu können oder ?

1
TeeTier  17.04.2018, 20:49
@Tarustyle

Ja, in diesem Falle würde ich eine Android-App in jedem Falle mit Java schreiben, da hast du völlig Recht! :)

Für iOS würde ich hingegen Apples Swift nehmen.

Früher wurden Windows-Phone Apps mit C# geschrieben, aber Windows-Phone ist tot, also fällt das weg. :)

0

Die Frage ist immer, wie groß "embedded" ist und wie komplex die zu entwickelnde Anwendung ist.

Ich habe hier beispielsweise ein Newsblog-System laufen, was in C++ als Monolith implementiert ist und wo das Binary (inklusive HTTP-Server, also komplett von vorn bis DB alles in einem Prozess) gerade mal gut 2 MB groß ist. Läuft wunderbar auf einem Raspberry Pi, könnte man auf einer Hardware sogar ein Dutzend Instanzen von betreiben.

Auf einen ESP32, ESP8266 oder ähnliches könnte man sowas aber nicht draufpacken, weil's dafür schon wieder viel zu fett und overfeatured ist.

Auf den wirklich kleinen Kisten (bzw. SoC) sollte man besser Standard-C (ohne "plusplus") machen.

Von Python rate ich generell ab. Da bringt einfach schon der Sprachkern einen ziemlichen Overhead mit. Mag auf einem Raspi noch gehen, auf kleineren Kisten definitiv ein no-go.


TeeTier  17.04.2018, 12:48
Ich habe hier beispielsweise ein Newsblog-System laufen, was in C++ als Monolith implementiert ist und wo das Binary (inklusive HTTP-Server, also komplett von vorn bis DB alles in einem Prozess) gerade mal gut 2 MB groß ist. Läuft wunderbar auf einem Raspberry Pi, könnte man auf einer Hardware sogar ein Dutzend Instanzen von betreiben.

Ha, du bist auch so ein Spinner! Genau wie ich! ;)

Mein HTTP-Server (inkl. DB usw.) ist in Assembler geschrieben und läuft auch aufm RasPI. Das Binary ist ca. 30 KB groß, wobei der meiste Platz von Strings eingenommen wird. (z. B. alle möglichen Response-Header, usw.)

Das Binary ist eine statische ELF, ohne jegliche Abhängigkeiten (nicht mal libc o. ä., "ldd" liefert keine Ausgabe!) und die gespawnten Prozesse laufen in einem ptrace() Kontext, wobei sämtliche Syscalls soz. "von außen" auf Plausibilität geprüft werden, was das System extrem sicher macht.

Ein RasPi ist dafür allerdings total überdimensioniert und ein kleiner µC dürfte theoretisch auch ausreichen, sofern ein Ethernet-Interface vorhanden ist. Hatte dafür aber noch keine Zeit ...

Aber schön, dass es hier noch andere Spinner gibt! ;)

1
dan030  17.04.2018, 14:07
@TeeTier

Ich mach' den Quatsch beruflich seit mehr als 20 Jahren. Manchmal findet man sogar Kunden, die für sowas Wertschätzung zeigen.

Highlight war um die Jahrtausendwende mal ein Freemail/Webmail/Free-Homepage-Dienst, dessen Ablaufumgebung komplett auf eine 3.5"-Diskette passte. Zwei Stück Pentium 2/350 MHz (zzgl. Failover-Systeme) haben damals über 80 Tsd. Nutzer versorgt...

Von diesen Ultraminimaldingern (also komplett Assembler o. ä.) bin ich weg, weil in meinem Feld die Datenstrukturen einfach zu komplex geworden sind. Deswegen setze ich heute auf ein über die Jahre entwickeltes C++-basiertes Framework, welches einen Haufen Basisfunktionalität für komfortables Handling strukturierter Daten bereitstellt. Da schleppt man sich zwar über den "Unterbau" dreistellige Kilobytes ein. Aber den Speicher hat man typischerweise ja heute, selbst in recht schlanken Controllern.

Ansonsten liegt der Fokus hier aber weniger auf Einplatinenkram, sondern eher darauf, mit einzelnen Linux-Servern wirklich hohe Requestzahlen abfrühstücken zu können. Datenprozessoren, die per HTTP-Push zweistellige Millionen an Datensätzen täglich reingedrückt bekommen usw. Oder Echtzeit-Beurteilung von größeren Datenmengen z. B. im Bereich automatisierter Personaldisposition in Unternehmen, wo der Rechner auf Basis einer sechsstelligen Datenmenge ad hoc entscheiden muss, wo welcher Mitarbeiter am besten einzusetzen ist (und wo sich die Bewertungslage mit jedem bereits disponierten Einsatz verändert, also quasi ständig neu durchgerechnet werden muss). Wenn solche Operationen dann im kleinen einstelligen ms-Bereich durchrasseln, dann bin ich ja schon zufrieden... :-)

1
dan030  17.04.2018, 14:24
@TeeTier

Nachtrag zu gespawnten Prozessen usw.: Da scheinen wir nach unterschiedlichen Paradigmen zu arbeiten. Ich vermeide "forkende" Architekturen und arbeite lieber pseudoparallel, bzw. eventgetrieben aus einer select()/epoll()-Loop heraus. Und dann ggf. mehrere statisch instanzierte Prozesse, die über IPC-Mechanismen miteinander kommunizieren (auch im Framework enthalten).

Hat im Kontext z. B. von einer HTTP-Server-Library den großen Vorteil, dass man den gesamten Betriebsstatus sehr gut von einer Stelle aus zu fassen bekommt und Dinge wie Lastmanagement, Traffic Shaping usw. zentral abfrühstücken kann. Auch so Dinge wie "wie viele Connections bleiben per keep-alive offen" sind da dann sehr schön steuerbar, genauso wie der Speicherbedarf (adaptives Buffer Management). Ein ganz zentraler Punkt bei Anwendungen hier ist, dass sie auch bei Lastpeaks nicht zusammenkrachen dürfen. Bei irgendwelchen Serverprozessen, die wild Tochterprozesse in die Welt setzen, ist da meines Erachtens die Kontrolle wesentlich schlechter möglich.

1
TeeTier  17.04.2018, 16:35
@dan030

Bei den gespawnten Prozessen habe ich mich schlecht ausgedrückt; die liegen natürlich vorher im Pool und werden über IPC synchronisiert.

Ich hatte das hier früher schon mehrmals unter anderen Fragen erwähnt, aber hier passt es nochmal:

Scheduler, Speichermanager, Netzwerkstack usw. sind zu großen Teilen selbstentwickelt (Kernelmodule) und aufeinander abgestimmt, sodass ich einige Millionen parallele Anfragen parallel abarbeiten kann. (Aufm PC, nicht aufm RasPi ... für den RasPi müsste ich das mal testen, aber gefühlt würde ich sagen, dass ich auch hier auf eine hohe Zahl an Requests pro Sekunde komme. Leider hat der RasPi eine vorsintflutlichen Netzwerk-Hardware, die hier garantiert zum Flaschenhals werden wird. Ein Rockchip wäre hier DEUTLICH leistungsfähiger.)

Siehe dazu: https://www.loverpi.com/collections/featured-products/products/libre-computer-board-roc-rk3328-cc

Dazu passt auch das C10M-Problem (nicht C10K!) mit dem man Millionen von parallelen Requests bedienen kann (ein ähnlicher Ansatz wie deiner, mit der Pseudo-Parallelität):

http://c10m.robertgraham.com/p/manifesto.html

Die großen Loadbalancer wie Akamai machen das übrigens auch so.

Assembler ist zwar teilweise ein Krampf, vor allem bei komplexen Stukturen, aber bislang bin ich noch nicht an die Grenze gekommen, ab der ich mich zu C gezwungen sah.

Trotzdem mag ich solche Spielereien, und deine Geschichte mit den Disketten klingt auch wahnsinnig interessant. :)

1
dan030  17.04.2018, 16:54
@TeeTier

Übelster Flaschenhals beim Raspi ist ohnehin, dass da alles(!) über einen(!) USB2.0 läuft. Und wenn da z. B. ein größerer write auf die Storage läuft (welche ja normalerweise Flash-Keks ist), dann steht die Hütte erstmal. Grauenhaft.

C10K bekomme ich mit meinem Kram auf einem besseren PC hin - inklusive Anwendungslogik dahinter. Zumindest in vielen Szenarien mit "leicht" zu beantwortenden Anfragen (inkl. Website-Rendering basierend auf Templates). Allerdings ist das eigentlich auch schon jenseits dessen, was die meisten Kunden brauchen. Hier liegt der Fokus nicht so sehr auf extrem hohen Requestzahlen, sondern eher auf nur "höheren" Requestzahlen bei gleichzeitig etwas mehr Logik dahinter.

Beispiel, was ich hier heute gerade auf dem Tisch habe: intelligente Suche in einem ziemlich unordentlichen Buchdatenbestand, wo z. B. Titelsuche mit unscharfen/falsch gesechriebenen Eingaben, Suche nach ähnlichen Titeln usw. laufen muss. Problem: es handelt sich um eine Plattform mit dreistelliger Händlerzahl und etlichen Millionen Titeln, gern Unikate. Das Zeug ist nicht vernünftig katalogisiert, man kann sich also nicht ans Systematik-Daten orientieren, sondern muss wirklich die Nutzdatenfelder heranziehen, also Klartext-Daten aus Stringfeldern. Und die haben deutlich unterschiedliche Qualität, je nach Händler.

Wenn ich in so einem kranken Szenario qualifizierte Ergebnisse in maximal kleinen zweistelligen ms aus dem ganzen Rotz rausbekomme, dann reicht das für den Kunden. Da weiß ich, dass ich mit 1 Core dann 30-40 solcher Suchanfragen pro Sekunde wegschaffen kann, also in einer besseren Multicore-Server-CPU kleine dreistellige Zahl an Queries/sec. Das ist schon 'ne Menge Holz, wenn es "nur" um einen mittelständischen Plattform-Anbieter geht.

BTW läuft sowas hier komplett ohne "künstliche Blödheit", sondern stur mit deterministischer Algorithmik. Letztlich spanne ich brutal große Indizes im Hauptspeicher auf (Blech ist ja eher billig), um mich auf diese Weise da schnell durchfressen zu können.

Indexupdates kommen dann aus einem Primärdatenbestand einfach als SQL-Dumpfiles. D. h. der Stammbestand wird in einer "echten" DB generiert, und ich lese einfach asynchron zum laufenden Betrieb die Dumpfiles ein und aktualisiere gleitend die Indizes. Man kann schon lustige Dinge bauen, wenn die Kunden einen machen lassen...

0

Microcontroller eher C, C++ kann da schnell zu fallen führen und man muss bei der C++ Entwicklung für Embedded Systems schon genau wissen, was die Librarys intern so machen.

Bei C sollte man btw auch nicht jede Library nehmen, kein malloc, calloc oder realloc etc.

Für Crossplatform am PC ist Python natürlich gut geeignet und es gibt auch jede Menge Librarys. Ich selbst bin ein Fan von C# ist aber bis auf Mono und .NET Core nicht wirklich Crossplatform. Aufgrund der Syntaktischen nähe zu C und unsigned Datentypen aber mein Favorit wenn es darum geht ein Interface zwischen µC und PC zu schreiben.


Lamanini  16.04.2018, 17:57

Nicht zu vergessen Java. Der Boss bei Cross-Platform :)

0
PeterKremsner  16.04.2018, 20:04
@Lamanini

Von der Plattformunabhängigkeit erste Klasse, aber mir gefällt das Design der Sprache nicht wirklich.

Irgendwie kommt mir zumindest in Java alles komplizierter vor als in C# und ein großer Nachteil für mich ist es, dass es keine unsigned Datentypen gibt. Das macht das Porting von C auf Java schwieriger und auch einigen Sachen funktionieren eben mal nicht so wie gedacht wenn man oft mit solchen Datentypen arbeitet.

1
TeeTier  17.04.2018, 12:38
@Lamanini

Genau genommen ist Java überhaupt nicht Crossplatform, obwohl damit immer geworben wird.

Vergleiche einfach mal die Plattformen, für die es ein JRE gibt mit denen, für die es einen C-Compiler gibt.

Genau genommen dürfte deshalb das gute alte ANSI-C bzw. inzwischen C99 der "Boss" bei der Plattformunabhängigkeit sein. Verglichen damit, ist Java absolut starr an eine Hand voll Mainstream-Systeme gekoppelt. :)

1
PeterKremsner  17.04.2018, 12:46
@TeeTier

Sofern man das Programm selbst und nicht das Kompilat betrachtet stimmts ;)

1
TeeTier  17.04.2018, 12:53
@PeterKremsner

Naja komm, alle Java-Projekte ab mittlerer Größe haben Weichen im Code, um Betriebssystemabhängige Eigenheiten zu umschiffen. Das fängt beim Pfadseparator an, geht über Dinge wie Registry oder die Locale, und hört bei JNI auf.

"Hello World" in Java mag tatsächlich Plattformunabhängig sein, aber alles darüber hinaus stößt irgendwann an die grenzen der "völligen Unabhängigkeit". :)

Also sooooo viel nimmt sich das nicht mit C-Programmen. :)

1
PeterKremsner  17.04.2018, 12:59
@TeeTier

Das stimmt aber trotz dieser weichen muss der Code nicht erneut auf der jeweiligen Platform kompiliert werden, das meinte ich.

1

Ist das deine Frage? Ja, C++ und Python sind für das, was du vorhast, gut geeignet.