Forum: PC-Programmierung Programmschnittstellen, how to?


von Leo B. (luigi)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich sitze vor einem kleinen großen Problem. Ich habe für die Uni im 
Rahmen meiner Abschlussarbeit ein Gerät gebaut, welches mit dem PC 
verbunden ist. Am PC läuft dazu eine von mir in C++ geschriebene 
Steuerungssoftware mit GUI um das Gerät zu bedienen. (Betriebssystem ist 
Windows 7)

Nun nähert sich mein Projekt dem Ende und ein anderer Student möchte 
darauf aufbauend seine Arbeit beginnen. Ursprünglich war der Gedanke, 
dass spätere Studenten auf meinen Code in C++ aufbauen. Leider kann der 
aktuelle Nachfolger kein C++ und möchte seinen Teil in Python oder 
Matlab programmieren. Mein Betreuer hat ihm das nun auch zugesagt und 
irgendwie ist es nun meine Aufgabe geworden mein Programm aus diesen 
Sprachen ansprechbar zu machen.
Mein Betreuer der Ansicht, dass man JEDES Programm aus der Kommandozeile 
mit Parametern bedienen kann (bitte keine Diskussion hierzu) und so muss 
auch meines bedienbar sein, sofern ich keine andere Möglichkeit biete.
Leider ist mein Programm aber eben kein 
"Spaghetti-Code-einmal-duchlaufen-und fertig"-Programm, sondern leistet 
eine rege Interaktion mit der Hardware. Es ist notwendig, dass auf 
Inputs von der Hardware ebenso wie auf Inputs vom Benutzer/anderer 
Software reagiert wird.
Um die Struktur noch einmal zu verdeutlichen habe ich das Bild in den 
Anhang gehängt.

Meine Frage ist nun:
 Wie Programmiert man eine vernünftige Schnittstelle für andere Software 
und Skripte?

Ich hatte schon daran gedacht, irgendwie einen weg zu suchen, das 
Hauptprogramm normal auszuführen und per Kommandozeile aufrufbare 
miniprogramme zu schrieben, welche das drücken von Buttons auf der GUI 
simulieren, oder gar die Ausführung eigener Funktionen im Hauptprogramm 
veranlassen.
Events von der Hardware würden dann ein externes Programm (oder Skript) 
aufrufen, dessen Pfad und Parameter in einer Konfigurationsdatei 
hinterlegt sein könnten.

Aber wie löst man sowas eigentlich? Also wenn man saubere Arbeit 
abliefern will?
Wie ihr an meiner hoffentlich nicht all zu wirren und halbwegs 
verständlichen Fragestellung vielleicht schon erkennt, habe ich einfach 
gar keine Erfahrung wie das ohne GUI-Automatisierung funktionieren soll.

Vielen Dank für alle Tips, Hinweise, Ideen und sonstigen hilfreichen 
Gedanken.
Viele Grüße,
Leo

von John (Gast)


Lesenswert?

Kommt drauf an was Dein C++ Code so alles macht. GUIs und COM Ports sind 
in Matlab wirklich überhaupt kein Problem. Und wenn die Funktionalität 
der PC Software (im Sinne der eigentlichen Algorithmik) eh schon steht, 
ist der Kram vielleicht relativ zügig nach Matlab portiert.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn da ein Protokoll zwischen dem steuernden Programm (ganz links) 
und dem gesteuerten Programm (mitte) erforderlich ist, ist eine 
Kommandozeilensteuerung offensichtlich nicht das gelbe vom Ei.

Unter Windows ist eine verbreitete Variante in solch einem Fall die 
Verwendung von (D)COM als Automationsschnittstelle. Das kann man aus 
jeder Programmiersprache heraus nutzen, die Automation beherrscht, 
angefangen beim VBScript (das jedes Windows von sich aus beherrscht).

Das in Klammern gesetzte "D" steht für distributed, diese 
Programmierschnittstelle ist prinzipiell auch für den Netzwerkbetrieb 
geeignet (spätestens dann aber ein Krampf im Arsch, wenn es um das 
Debuggen oder sonstige Fehlersuche geht).

Ein alternativer Ansatz wäre die Verwendung eines über Sockets 
transportierten Protokolls, je nach Komplexität der transportierten 
Daten auch als reine Textvariante (dann kann die Funktionalität mit 
einem simplen Telnet-Client getestet werden). Beispiele für diese Art 
von Kommunikation sind Email-Clients.

Das verbreitete http-Protokoll ist hier ungünstig, da es für jeden 
Kommunikationsvorgang eine neue Verbindung herstellt, und nicht 
innerhalb einer Verbindung einen dauerhaften Dialog nutzt.

Die Verwendung dieser Art von Socket-Schnittstelle böte automatisch die 
Netzwerkfähigkeit und im Gegensatz zum Automationsansatz auch die 
Plattformunabhängigkeit -- so einem Socket ist es herzlich wurscht, ob 
die einlaufenden Daten von einem Linux- oder Windows-System kommen.

Andere Schnittstellen (DLLs, die wiederum irgendwelche 
Interprozesskommunikationsmechanismen kapseln) schränken die Auswahl der 
verwendbaren Programmiersprachen ein.

Ein wichtiger Aspekt aber ist die Betrachtung der zu übertragenden 
Daten, welcher Art sind diese und in welchen Mengen treten sie auf, und 
in welchem Zeitrahmen sind sie zu übertragen?

von Hans (Gast)


Lesenswert?

Falls es nicht schon der Fall ist, würde ich die GUI und die Logik zum 
Steuern der Hardware in eine EXE für die GUI und eine DLL für die 
Hardwareansteuerung aufteilen.

Die DLL exportiert ein C++-Interface, das die GUI-EXE benutzt. Jemand 
mit C++-Kenntnissen sollte nur die DLL (und das Header-File) benötigen, 
um die Hardware ansteuern zu können.

Zusätzlich zum C++-Interface exportierst Du noch ein ggf. vereinfachtes 
C-Interface. In den meisten Scriptsprachen ist es möglich, C-Funktionen 
aus DLLs aufzurufen. Wie das genau mit der Wunschsprache Deines 
Nachfolgers funktioniert, sollte er aus meiner Sicht selber rausfinden.

Falls das nicht reicht, musst Du ihm halt ensprechende Bindings für 
Matlab oder Python anbieten. Dazu gibts jede Menge Anleitungen, einfach 
mal "Call C funtion from Matlab/Python/whatever" googlen.

von Georg (Gast)


Lesenswert?

Leo B. schrieb:
> eine rege Interaktion mit der Hardware.

Frage: was soll der Kollege denn entwickeln? Als Minimum braucht er die 
kommunikation mit der Hardware, also was über die serielle Schnittstelle 
läuft, dann kann er sich aus jeder belibigen Sprache heraus mit deiner 
Hardware unterhalten. Und die Beschreibung des seriellen Protokolls 
solltest du eigentlich schon für dich selbst angefertigt haben.

Leo B. schrieb:
> Mein Betreuer der Ansicht, dass man JEDES Programm aus der Kommandozeile
> mit Parametern bedienen kann

Ja, aber halt nur einmal, nämlich beim Start (man kann auch tricksen und 
das Programm mehrfach aufrufen und so weitere Befehle übergeben, aber 
das greift dann schon tiefer in die Windows-Programmierung ein).

Leo B. schrieb:
> Ich hatte schon daran gedacht, irgendwie einen weg zu suchen, das
> Hauptprogramm normal auszuführen und per Kommandozeile aufrufbare
> miniprogramme zu schrieben

Naja, wenn das so sein muss. Dazu muss man aber nicht verschiedene 
Programme schreiben, das geht auch in ein und demselben Programm, wenn 
das nicht ein zweitesmal startet, sondern sich mit seiner ersten Instanz 
in Verbindung setzt. Ob im selben Programm oder einem anderen, Windows 
bietet verschiedene Möglichkeiten der Inter-Prozess-Kommunikation, z.B. 
Pipes, dazu muss man sich halt einlesen. Egal wie, das bisherige 
Programm muss natürlich so gestaltet sein, dass es die Kommandos annimmt 
und beantwortet, aber da du sowieso ein Event-gesteuertes Programm hast, 
musst du bloss den Event "Remote Command" hinzufügen, und natürlich 
spezifizieren, was auf welches Kommando was passieren soll. Ein eigener 
Thread wäre für sowas nicht schlecht. Das lohnt sich natürlich nur, wenn 
dein Programm was sinnvolles treibt - wenn der Kollege was ganz anderes 
will, soll er sich doch gleich mit der Hardware direkt unterhalten.

Hört sich so an wie eine Software die ich zur Überwachung, Speicherung 
und Auswertung von mehrtägigen Messreihen auf eigener Hardware 
geschrieben habe.

Georg

von Bernd K. (prof7bit)


Lesenswert?

Leo B. schrieb:
> Ich hatte schon daran gedacht, irgendwie einen weg zu suchen, das
> Hauptprogramm normal auszuführen und per Kommandozeile aufrufbare
> miniprogramme zu schrieben,

Ja, das ist ein gängiger Weg.

Implementiere eine Client-Server Architektur. Das lang laufende 
Hauptprogramm ist der Server, ein kleines Kommandozeilentool (ein 
einziges reicht) ist der Client, es wertet beim Aufruf seine 
Kommnandozeilenparameter aus, kontaktiert dann den Server, sendet einen 
Befehl (evtl mit zusätzlichen Daten), wartet auf Antwort (evtl auch mit 
Daten), gibt dann das Ergebnis in einem einfach zu parsenden Format an 
stdout aus und beendet sich bei Erfolg mit exit code 0.

Fehlermeldungen oder menschenlesbare Debuginformationen oder 
Fortschrittsbalken oder dergleichen  sollen an stderr ausgegeben werden 
so daß der Parser des aufrufende Prozesses das einfach auseinander 
halten kann.

Wenn Du es ganz geschickt anstellt kannst Du sogar später noch das 
Client-Server Protokoll erweitern ohne den Kommandozeilenclient anpassen 
zu müssen wenn Du es so gestaltest daß er beliebige Befehle absetzen und 
beliebige Antworten empfangen und an stdout wieder ausgeben kann.

Als Protokoll zwischen Client und Server kannst Du alles nehmen was zur 
Interprozesskommunikation taugt, ich würde aber auf jeden Fall was 
plattformübergreifendes nehmen und etwas das auch über das Netzwerk 
funktioniert, am besten ein einfaches textbasiertes menschenles- (und 
schreib-) bares Protokoll über *TCP/IP*, so lässt sich das bereits 
während der Entwicklung mit Telnet ausprobieren und debuggen, noch bevor 
der Client überhaupt komplett fertig gestellt ist. Dieses Protokoll 
solltest Du genau dokumentieren und an Deinen Nachfolger weitergeben, 
dann kann seine Anwendung später auch selbst einen Client implementieren 
wenn sie weiter fortgeschritten ist und braucht nicht mehr das 
Kommandozeilentool.

: Bearbeitet durch User
von asdasdasd (Gast)


Lesenswert?

https://wiki.python.org/moin/boost.python/SimpleExample

Eventuell hilft dir das, wenn du deine Logik vom Gui gut getrennt hast.

von asdasdasd (Gast)


Lesenswert?


von Leo B. (luigi)


Lesenswert?

Vielen Dank für die vielen Hilfreichen Informationen.
Ich muss zugeben ich bin damit gerade etwas überfordert.

Zunächst zur Frage, was da kommuniziert werden muss. Das sind Kommandos 
wie Deckel auf, Deckel zu, Teller drehen. In die andere Richtung müssen 
Informationen weiter gereicht werden, wie SensorN aktiviert/deaktiviert. 
Von der Häufigkeit her nichts, was man als mensch nicht bewältigen kann, 
nur hat eben keiner Lust 24/7 vorm PC zu sitzen und Knöpfe zu drücken.

Nach allem was ich jetzt so gelesen und von euch erfahren habe, gefällt 
mir eine solche inter-Prozess-Kommunikation mit einem "Server" (mein 
existierendes Programm) mit einem "Client" (ein Kommandozeilen-Tool) am 
besten. Das entspricht vermutlich auch am Besten der Vorstellung meines 
Betreuers.
Allerdings muss ich mich in das Thema noch einarbeiten, weshalb ich für 
jedes Stichwort oder dergleichen noch dankbar bin. "Distributed" muss 
das nicht sein, vielleicht sogar besser wenn es nur lokal funktioniert, 
dann kann keiner (wenn auch evtl. nur versehentlich) Fehlfunktionen und 
Störungen verursachen.
Was es da für COM-Schnittstellen gibt ist mir allerdings noch nicht 
klar.
Ich könnte vielleicht eine lokale Netzwerkbasierte (UDP) 
Datenübertragung gestalten, aber ob das der "vorgesehene" weg ist? was 
gibt es da noch für Schnittstellen?

Ach ja vielleicht noch eine ganz wichtige Hintergrundinformation: bisher 
habe ich alles mit Qt programmiert und bin leider auch selbst gar nicht 
so bewandert in Sachen dll erzeugen oder einbinden. Oder auch boost, 
gehört habe ich schon viel davon, aber verwendet noch nie. Das Konzept 
ist mir relativ unbekannt.

von Noch einer (Gast)


Lesenswert?

> Kommandos wie Deckel auf
> inter-Prozess-Kommunikation mit einem "Server"

Würde erst mal schauen, ob ein einfacher TCP-Socket und einfache 
Textzeilen ausreichen.
Z.B. "set switch1 off\n" "get switch1\n"

Dein Nachfolger kann dann mit Kommandozeilentools wie netcat arbeiten. 
Oder er kann in einer beliebigen Programmiersprache selbst Textzeilen 
hin-und-her schicken.

von Schnittstellenbeschneider (Gast)


Lesenswert?

mir ist immernoch nicht klar wie wichtig dein bisheriges Programm auf 
dem PC für's betreiben der Peripherie ist.

Warum reicht nicht einfach die Beschreibung des Protokolls auf der ser. 
Schnittstelle?

(hab im Kopf das Modell Computer<->Wählmodem, das Protokoll hier 
"AT-commands" - trifft sowas nicht auch auf dein Fall zu?)

von Bernd K. (prof7bit)


Lesenswert?

Leo B. schrieb:
> bisher
> habe ich alles mit Qt programmiert

Da sollte es doch einfach sein mit den dort existierenden Komponenten 
(Qt ist ja fast wie LEGO® für Programmierer) mal eben eine TCP-Server zu 
instantiieren der seine Slots feuert wenn Ereignisse kommen. Der Vorteil 
von TCP und textbasiert wäre halt daß Du schon während der Entwicklung 
des Servers einfach mal ein telnet localhost machen kannst und dann 
machst Du in dieser Sitzung sowas:
1
Verbunden mit Messtisch-Steuerung v1.0
2
Schreibe hilfe um die Befehle aufzulisten
3
ok
4
> hilfe
5
Erlaubte Kommandos:
6
deckel [auf|zu] steuert den Deckel
7
tisch [links|rechts] steuert den Tisch
8
messung [foo|bar|baz] <anzahl> führt eine Messung aus
9
ende beendet die Sitzung
10
ok
11
> deckel auf
12
ok
13
> deckel zu
14
ok
15
> tisch links
16
ok
17
> messung foo 7
18
2.99, 3.01, 3.04, 2.98, 3.03, 3.01, 3.02
19
ok
20
>
21
ende
22
und tschüss...
23
24
connection reset by peer
und so weiter. Und wenn das geht dann schreibst Du nen Client. Ne 
TCP-Verbindung zu nem Server zu öffnen ist in jeder Programmiersprache 
genauso simpel (und programmatisch genauso zu bedienen) wie ne Datei zum 
Lesen/Schreiben zu öffnen.

von simon (Gast)


Lesenswert?

Am einfachsten wäre es, wenn die Logik von der GUI getrennt wäre und die 
Logik sich in einer DLL befinden würde. Das jetzt noch aufzuteilen 
müsste, wenn sauber programmiert, nicht viel Arbeit bedeuten. Dann aus 
Matlab die dll zu nutzen solle gehen und nicht mehr dein Problem sein.

Bei einer Client-Server Architektur würde ich etwas wie json-rpc oder 
xml-rpc empfehlen.

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
Noch kein Account? Hier anmelden.