Wahl des richtigen Programmiervorgehens

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

Hallo zusammen,

ich habe vor ein Programm zu schreiben, das die Daten eines Spektrometers (von OceanOptics) ausliest und nach meinen Wünschen verarbeitet.
Es gibt unteranderem für C/Cpp eine offizielle Bibliothek die dazu verwendet werden kann, die Daten aus dem Spektrometer auszulesen. (Die Bibliothek verwendet aber auch Bibliotheken von Java JDK)

Meine ersten Überlegungen gingen nun dahin die Daten mit C aus dem Spektrometer zu lesen und die Verarbeitung und insbesondere die GUI mit Python zu programmieren. Für die Schnittstelle zwischen C und Python hab ich mir jetzt cytpes und Cython angekuckt, aber ich bin mir noch sehr unsicher, wie ich das Programm jetzt tatsächlich programmieren soll.
  • - Wenn ich ctypes verwende hätte ich den Vorteil, dass ich die .dlls in Visual Studio programmieren kann und die Zusätzlichen Java-Bibliotheken über die Projekteigenschaften einfach eingebunden werden können. Hier habe ich aber das Problem, das für das Auslesen des Spektrometers in C ein Wrapper-Objekt erzeugt wird und ich durch mein Programm nicht weitere Wrapper-Objekt erstellen darf. Ich hab aber die ctypes Dokumentation jetzt so verstanden das bei jedere Übergabe ein neues identisches Objekt übergeben wird.
    (Note that ctypes does not have OOR (original object return), it constructs a new, equivalent object each time you retrieve an attribute)
    Damit dürfte ich dann in Probleme laufen.
    - Wenn ich aber Cython verwende, kann ich Visual Studio nicht mehr verwenden und ich bekomme den #include der Bibliotheken nicht hin. (Dem C-Compiler (MinGW) zu sagen, wo es die Bibliotheken findet. <- Nach Tage langem googlen)
    - Die dritte Möglichkeit wäre ganz auf C/CPP umzusteigen. Das würde ich am liebsten vermeiden, weil ich mich in C nicht so gut auskenne wie in Python und ich in die ganze GUI programmierung einarbeten müsst, aber ich würde wohl sicher zu meinem Ziel kommen.
Habt Ihr irgendwelche Tipps für mich und könnt mir eine Möglickeit empfehlen?

Freundlichst,
Modibo
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Modibo: Warum darfst Du keine weiteren Wrapper erzeugen? Und was ist überhaupt ein Wrapper bei Dir? So wie ich das lese, gibt es fertige Bibliotheken für Java, .NET oder als "binäre" Bibliothek. Ersteres kann man mit Jython, zweites mit IronPython und letztes entweder direkt mit ctypes oder über einen selbst programmierten Wrapper ansprechen. Ich entscheide mich immer für ctypes, wenn es geht, weil da kann ich schon die fertige DLL einbinden und muß mich nicht mit irgendwelchen Abhängigkeiten und Compiler-Konfigurationen herumschlagen, vor allem dann, wenn die Abhängigkeiten auch noch Java beinhalten. Auf was beziehst Du Dich mit Deinem Zitat? Wo glaubst Du, dass das für Dich relevant ist?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Modibo hat geschrieben:Hier habe ich aber das Problem, das für das Auslesen des Spektrometers in C ein Wrapper-Objekt erzeugt wird und ich durch mein Programm nicht weitere Wrapper-Objekt erstellen darf.
Das ist aber der übliche Weg, wenn man ``ctypes`` verwendet. Steht wirklich fest, dass diese Vorgabe nicht verletzt werden darf? Denn ``ctypes`` würde dir vieles erleichtern, wie du selbst und Sirius3 ja bereits angesprochen haben.
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

@Sirius:
  • Wrapper ist ein Objekt, der in den Bibliotheken definiert ist und über den Kommunikation mit dem Spektrometer läuft.
    Also man kann dann später folgendes verwenden:

    Code: Alles auswählen

    pixelArray = wrapper.getSpectrum(spectrometerIndex)
    Die Bibliotheken liegen als .h vor. Ich glaub sie rufen dann aber auch .lib und .dll auf, weil ich entsprechende Einträge in meinen Projekteigenschaften von Visual Studio habe.
    Wenn ich ctypes verwende hab ich mir das jetzt so vorgestellt, dass ich zunächst eine .dll habe die mir das Wrapper Objekt erzeugt und es zurück an mei Python-Skript schickt. Dann würde ich bei jedem aktualisieren des Spektrums eine andere .dll aufrufen, der ich den Wrapper übergeben und die mir im Gegenzug die neue Daten zurück gibt. Ich hab das jetzt so verstanden, dass bei jeder "Übergabe" ein neues (identisches) Objekt erzeuge, also genau das was ich eigentlich nicht will.
@snafu
Das mit dem nur einen Wrapper-Objekt hab ich aus dem Programming Manual der Bibliothek:
Your application must create only ONE instance of the wrapper object. This
wrapper object is then shared by all spectrometers under the control of your
application. Any and all threads created by your application must then share a
reference to the same instance of the wrapper object. Furthermore, there may only
be ONE application (EXE) running on your computer that creates a wrapper object
and controls spectrometers. All interaction with all Ocean Optics spectrometers
attached to your computer must be performed within this one single
executable/application.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Modibo: Du darfst den Wrapper aus deiner Bibliothek nicht mit "Wrapper" im Kontext von ``ctypes`` verwechseln. Bei ``ctypes`` handelt es sich um Wrapper-Objekte, die auf den Namen der zu nutzenden C-Bibliothek verweisen. Denen weist man Informationen über die Typen für die einzelnen Parameter zu, die für den Funktionsaufruf benötigt werden (also die Typen aus der Signatur der C-Funktion). Ebenso weist man den Rückgabetyp der Funktion zu, damit ``ctypes`` die Rückgabe des Funktionsaufrufs auf Python-Ebene in ein passendes Python-Objekt konvertieren kann. Das hat rein gar nichts mit dem Wrapper aus deiner spezifischen C-Bibliothek zu tun. Bitte lies dir das ``ctypes``-Tutorial durch, falls sich in deinem Gesicht gerade ein großes Fragezeichen auftut. Ein bißchen Vorwissen deinerseits wäre schon ganz gut, bevor man über solche eigentlich grundlegenden Dinge spricht.

Oder habe ich dich in diesem Punkt missverstanden? Ich habe jedenfalls an das oben beschriebene gedacht, als ich im vorherigen Beitrag auf den Wrapper eingegangen bin.

EDIT: Achso, und wenn du sicherstellen möchtest, dass ein Objekt auf C-Ebene nur einmal verwendet wird (ich beziehe mich jetzt auf den Wrapper in deiner C-Bibliothek), dann ist das ein prima Anwendungsfall für das Singleton-Pattern.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Modibo: Wrapper gibt es eben für alles mögliche. ctypes verwendet Wrapper um c-Datentypen in Python zugänglich zu machen und da kann eben die selbe Variable (Pointer auf Dein Ocean-Wrapper-Objekt) über unterschiedliche Python-Objekte angesprochen werden. Das wird dann wohl eher so aussehen:

Code: Alles auswählen

pixel_array = ocean_dll.getSpectrum(wrapper, spectrometer_index)
Das könnte man dann natürlich noch für eine bessere API in einer schönen Pythonklasse kapseln (wieder eine andere Art Wrapper).
Die Bibliotheken liegen als .h vor. Ich glaub sie rufen dann aber auch .lib und .dll auf.
Wenn dieses Verständnis von Bibliotheken Deinem aktueller Stand entspricht, solltest Du Dich auch noch dringen in Bibliotheksprogrammierung einarbeiten. Für ctypes braucht man eigentlich nur die DLL. Aus den h-Dateien kann man aber auch, wenn die Dokumentation zu schlecht ist, alles nötige für den Aufruf der Funktionen finden.
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

Gut.Das heißt ja, dass es mit ctypes klappen sollte.

Mit Wrapper hab ich übrigends immer die Objekte gemeint, die von der Bibliothek definiert werden (ab jetzt Spektrometer-Objekte). Wusste gar nicht, das diese Typfestlegung in c/ctypes auch so genannt werden.

Mit den Bibliotheken kenne ich mich wirklich kaum aus, einfach weil es jetzt das erste Mal ist, dass ich damit umgehen muss. Habe vorher immer mit reinem Python oder mit C für Microcontroller gearbeitet. Da kam das nicht so vor.
Aber das wird ja dann jetzt kommen...

Nochmal zu dem Programm:
Also was "Singleton-Pattern" ist, hab ich im Moment gar keine Ahnung aber das werde ich mir dann auch anschauen.
Ansonsten ist die Grundidee, dass ich mein Spektrometer-Objekt als Zeiger jeweils an Python bzw an meine von ctypes aufgerufenen .dll übergebe, oder?
Wie lange liegt den mein Spektrometerobjekt dann tatsächlich vor? Ich hätte jetzt eigentlich im ersten Gedanken gesagt: Nur solange wie meine .dll, die das Objekt erzeugt hat, auch läuft. Also dann nach Übergabe des Zeigers mit dem Durchlauf der dll "gelöscht" wird.
BlackJack

@Modibo: Wie lange so ein Objekt existiert hängt davon ab wie die API aussieht und was Du damit anstellst. DLLs laufen nicht durch, die laufen überhaupt nicht, das sind im Grunde einfach nur Funktionen die man aufrufen kann. Und die die nicht als `void` deklariert sind geben Daten zurück. Wie ein ”Objekt” dann konkret aussieht und wie man seinen Lebenszyklus steuert, hängt dann von der API ab, wie die ”Objekte” repräsentiert werden, und welche Funktionen zur Verwaltung zur Verfügung gestellt werden.

Wenn das eine C-API ist dann werden dort streng genommen gar keine Objekte definiert, denn so etwas kennt C nicht.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Modibo hat geschrieben:Wusste gar nicht, das diese Typfestlegung in c/ctypes auch so genannt werden.
Wrapper ist ein allgemeiner Begriff aus der Programmierung. "to wrap" heißt "umhüllen". Das wird meistens dann genutzt, wenn aus technischen Gründen oder aus Gründen des Komforts (d.h. leichtere Verwendbarkeit) eine dünne Schichte um etwas anderes gebildet wird. Dazu gehört z.B. die Übersetzung eines Funktionsaufrufs zwischen zwei verschiedenen Programmiersprachen oder manchmal auch die Übertragung von Aufrufparametern und Rückgabewerten zwischen Highlevel- und Lowlevel-Funktion. Weitere Infos dazu sollte dir die Suchmaschine deiner Wahl ausspucken...
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

Ok, dann weiß ich jetzt erstmal alles, um weiter arbeiten zu können.

Ich bedanke mich ausdrücklich bei Euch allen für Eure Hilfe.
Ihr habt mir bestimmt einen riesen Batzen Arbeit und Frust abgenommen.

Vielen Dank dafür!
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

Ich kann mit ctypes nur Bibliotheken aus C-Code verwenden und nicht aus C++-Code, oder?
Ich hab's jetzt mit C++ probiert und hänge an der Stelle, an der ich den Pointer zu meinem C++ Spektrometer-Objekt n Python speichern will.

Also meine C++ Teil sieht jetzt so aus:

Code: Alles auswählen

//OceanOpticsCommunicationDLL.cpp
#include "Wrapper.h"
#include "ArrayTypes.h"

#define DLLEXPORT extern "C" __declspec(dllexport)
DLLEXPORT Wrapper* open_spectrometer() {
	Wrapper wrapper;
	return &wrapper;
}
Und ich wollte das in Python so speichern:

Code: Alles auswählen

oceanOpticsCommunication = CDLL("OceanOpticsCommunicationDLL")
wrapperPointer = oceanOpticsCommunication.open_spectrometer()
BlackJack

@Modibo: Mal angenommen `Wrapper` wäre ein `struct` dann ist die Funktion kaputt weil die einen Zeiger auf Daten auf dem Stapel zurückgibt, die sofort nach dem Funktionsaufruf nicht mehr gültig sind.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Modibo: Willst Du jetzt nochmal einen eigenen C++-Wrapper für eine C-DLL schreiben um sie über ctypes in Python einzubinden? Das sieht für mich ein bißchen unnötig umständlich aus.
Antworten