[ctypes] - libnodave

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Servus,
ich versuche heute krampfhaft mit Hilfe von ctypes libnodave anzusprechen (der code ist auch online einsehbar, allerdings in einer älteren Version). Meine Vorkenntnisse im Umgang mit ctypes waren bis Gestern gleich null, und ich brauche mal ein paar Tipps.
Das ganze mache ich im Moment unter Ubuntu und Python 2.6
zuerst mal was ich bisher gemacht habe:

Code: Alles auswählen

import ctypes
import os

DLL_LOC = os.path.join('libnodave', 'libnodave.so')

class _daveOSserialType(ctypes.Structure):
    _fields_ = [("rfd", ctypes.c_int),
                ("wfd", ctypes.c_int)]

def main():
    dave = ctypes.cdll.LoadLibrary(DLL_LOC)
    fds = _daveOSserialType()
    fds.rfd = dave.setPort(ctypes.c_char_p('/dev/ttyUSB0'),
                           ctypes.c_char_p('9600'),
                           ctypes.c_char('e'))
    
    di = dave.daveNewInterface(fds, ctypes.c_char_p('IF1'), 0, 20, 0)
    
    
if __name__ == '__main__':
    main()
Ich habe versucht mich nach der Anleitung aus der Doku gettingStarted - Programming a basic application zu richten. Hier sitzte ich im Moment fest. Die Funktion ``daveNewInterface`` gibt mir einen Zeiger zurück auf ein Struct vom Typ ``_daveInterface`` zurück. Auf das struct selber will ich für den späteren Gebrauch gar nicht zugreifen können. Ich muss den Zeiger aber noch an andere Funktionen übergeben. Wie mache ich das? Reicht es den Integer, den ich bekomme weiterzugeben? Oder muss ich mir einen ``ctypes.POINTER()`` erstellen und den übergeben?
lunar

Der Rückgabewert von "daveNewInterface" ist doch bereits ein Zeiger, worin läge der Sinn, diesen nochmals in einen Zeiger zu verpacken?! Das wäre im Gegenteil vollkommen falsch.

Bei größeren Anbindungen mit ctypes ist es im Übrigen sinnvoll, die verwendeten Funktionen mit Signaturen und mit Rückgabetypen zu dekorieren, damit Python vor der Übergabe von Parametern deren Typen prüfen kann, so dass Du im Falle von Typfehlern aussagekräftige Fehlermeldungen erhältst anstatt einfach falsche Werte oder Speicherzugriffsverletzungen.
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Ich stehe da momentan ein wenig auf dem Schlauch. Python bekommt als Rückgabewert ja nur einen Integer. Wenn meine C-Kenntnisse mich hier nicht im Stich lassen ist das ein Zeiger auf den Speicher wo mein Struct beginnt. Ich hätte jetzt gedacht das ich beim Übergeben des Zeigers an die nächste Funktion irgendwie auch den Passenden Typ weitergeben müsste.
Also kann ich einfach weitermachen indem ich den Rückgabewert von ``dave.daveNewInterface()`` an die nächste Funktion übergebe, korrekt? Ich probier das direkt mal aus:

Code: Alles auswählen

def main():
    dave = ctypes.cdll.LoadLibrary(DLL_LOC)
    fds = _daveOSserialType()
    fds.rfd = dave.setPort(ctypes.c_char_p('/dev/ttyUSB0'),
                           ctypes.c_char_p('9600'),
                           ctypes.c_char('e'))
    

    di = dave.daveNewInterface(fds, ctypes.c_char_p('IF1'), 0, 20, 0)
    res = dave.daveInitAdapter(di)
    dc = dave.daveNewConnection(di, 2, 0, 0)
    res = dave.daveConnectPLC(dc)
momentan bekomme ich mit dieser Variante noch Fehlermeldungen - ich werde mal schauen ob ich alle Parameter richtig habe. Und mit dekorieren der Funktionen meinst du wohl den argtype angeben wie im Tutorial erklärt? Das werde ich dann wohl nachholen.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

In der Doku steht dazu:
By default functions are assumed to return the C int type. Other return types can be specified by setting the restype attribute of the function object.
Ohne, daß ich es jemals probiert hätte oder 100%ig weiß ob es richtig ist, würde ich noch das restype attribute wie in der Doku beschrieben explizit setzen. Eventuell einfach auf c_void_p. Aber bitte nagel mich nicht darauf fest.
lunar

Es gibt in der Bibliothek keine Typen mehr. Ein solches Konzept existiert nur im C-Quelltext. In der Bibliothek gibt es nur noch Funktionen, die entsprechend der Aufrufkonventionen ungetypte Werte über den Stack oder bestimmte Register zurückgeben. Die Interpretation dieser Werte ist dem Aufrufer überlassen.

Auf dieser Ebene sind Ganzzzahlen und Zeiger daher dasselbe. Insofern ist es korrekt, die Rückgabe einer Funktion einfach direkt an eine andere weiterzugeben, wenn beide Funktionen in C denselben Typen an dieser Stelle haben. Wenn Du dabei Fehlermeldungen erhältst, dann liegt der Fehler an anderer Stelle.

Und ja, ich meine den "argtype" (und im Übrigen auch den "returntype"). In der Tat solltest Du das nachholen, und sei es nur, um ein Verständnis für die Typen der Funktionen zu entwickeln. Zudem ist das zwingend erforderlich, sobald Du mit Typen arbeitest, die abweichende Darstellungen oder Aufrufkonventionen haben (e.g. kürzere Ganzzahlen oder v.a. Fließkommazahlen).
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Hi noch einmal,
ein großes Danke an euch beiden. Dank euch hab ich es dann doch irgendwann hin bekommen die Lib zu verwenden. Nachdem ich erst einmal den Durchblick hatte was alles zu erledigen ist hatte mein Prototyp schnell ausgedient und ich hab mich an die Arbeit gemacht einen für meine Bedürfnisse (meinen ersten) Wrapper zu erstellen der mir einen einfachen Zugriff auf die C-API erlaubt.
Seit heute unterhält sich meine Simatic S5 schon recht ordentlich mit meinem Rechner

Sebastian
pierrelepoint
User
Beiträge: 1
Registriert: Mittwoch 2. März 2011, 15:05

Lonestar hat geschrieben:Hi noch einmal,
ein großes Danke an euch beiden. Dank euch hab ich es dann doch irgendwann hin bekommen die Lib zu verwenden. Nachdem ich erst einmal den Durchblick hatte was alles zu erledigen ist hatte mein Prototyp schnell ausgedient und ich hab mich an die Arbeit gemacht einen für meine Bedürfnisse (meinen ersten) Wrapper zu erstellen der mir einen einfachen Zugriff auf die C-API erlaubt.
Seit heute unterhält sich meine Simatic S5 schon recht ordentlich mit meinem Rechner

Sebastian


Hallo Sebastian,

mein Deutsch ist sehr schlecht, aber ich versuche trotzdem...
Ich habe die selbe Probleme mit ctypes, und ich muss irgendwie mit hilfe Python, DB's von eine Siemens s7 CPU erreichen. Die Kommunikation würde durch MPI (serielle Schnittstelle) erfolgen. Bitte wenn du kannst, mich weiterhelfen, oder falls machbar ist, die *.py Quellencode durch zu senden. Meine addresse: pierrelepoint1544@gmail.com

Danke, Péter.
marlob
User
Beiträge: 51
Registriert: Mittwoch 23. August 2006, 20:13

Würde mich auch interessieren. Vielleicht kannst du es ja hier hochladen :D
gruss
marlob
-------------------------------------
Linux Mint 17 + Python 2.7.6
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

hmmm hier hochladen :roll: das Problem ist danach muss ich es erst mal verbessern bis die das Forum nicht mehr ganz so viel zu meckern hat :oops:. Eigentlich habe ich das Projekt Anfang Dezember an die Seite gelegt da ich die Ganze Anbindung an die SPS doch nicht mehr gebraucht habe. Da ganze ist so weit das ich auf meine S5 lesend und schreibend zugreifen kann. Um viel mehr habe ich mich aber nicht gekümmert. Das sollte man an den Vielen TODOs schon erkennen.

Falls es dem einen Oder anderen helfen kann will ich aber gerne weiterhelfen soweit ich das kann. Nur bitte ich um Verständnis das meine Reaktionen auf Verbesserungen/Anfragen etwas dauern können. Ich hab meinen Momentanen Stand mal hier ins Pastebin hoch geladen.

Zu beachten wäre wohl das im gleichen Ordner in der auch die Datei ``libnodave.py`` liegt ein Unterordner Existieren sollte der da heißt ``libnodave``. Das ist einfach der Ordner in dem der Inhalt des Archivs das man unter http://sourceforge.net/projects/libnodave/ herunterladen kann liegt. Wer die Pfade anpassen möchte sollte sich dann wohl die Methode ``libnodave.get_dll_loc(self)`` anschauen.
marlob
User
Beiträge: 51
Registriert: Mittwoch 23. August 2006, 20:13

Erstmal Danke :D

Ich werde es mir mal ansehen.
gruss
marlob
-------------------------------------
Linux Mint 17 + Python 2.7.6
emilio20
User
Beiträge: 22
Registriert: Donnerstag 17. Oktober 2013, 21:08

Hallo
ich bin erst neu in Python. komme aus der S7 welt.
Möchte gerne auf meinem Linux Sat Reciver ein paar Variablen aus eine S7 315PN auslesen.
Hierzu müsste ich über ethernet auf die SPS zugreigen.
Was muss ich im Progrmm anpassen damit ich eine verbindung über ethernet erhalte ?
Zuletzt geändert von emilio20 am Samstag 26. Oktober 2013, 17:49, insgesamt 1-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Es ist denn Ehernet?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten