IO-WARRIOR Bibliothek "iowkit.dll" mit python benutzen.

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
zianou
User
Beiträge: 6
Registriert: Freitag 19. Oktober 2012, 19:46

Hallo,

ich versuche gerade IO-WARRIOR40 mit Python über die Bibliothek "iowkit.dll" zu steuern. Dabei benutze ich das Python-Modul ctypes. Einige Methoden konnte ich aufrufen, aber mit anderen Methoden habe ich leider Schwierigkeiten, deswegen möchte ich wissen, ob im Forum vielleicht jemand Erfahrung mit IO-WARRIOR und Python hat und mir dabei helfen kann.
folgende Methoden konnte ich bis jetzt aufrufen:

Code: Alles auswählen

import ctypes

IO_BIB = ctypes.CDLL("IOWKIT")
HANDLE = IO_BIB.IowKitOpenDevice()
NUM_DEV = IO_BIB.IowKitGetNumDevs()
Die C-Methoden, mit den ich momentan Probleme habe, werden wie folgendes deklariert:

Code: Alles auswählen

ULONG IOWKIT_API IowKitRead(IOWKIT_HANDLE devHandle, ULONG numPipe,
PCHAR buffer, ULONG length);
function IowKitRead(devHandle: IOWKIT_HANDLE; numPipe: ULONG;
buffer: PChar; length: ULONG): ULONG; stdcall;

Code: Alles auswählen

ULONG IOWKIT_API IowKitReadNonBlocking(IOWKIT_HANDLE devHandle, ULONG numPipe,
PCHAR buffer, ULONG length);
function IowKitReadNonBlocking(devHandle: IOWKIT_HANDLE; numPipe: ULONG;
buffer: PChar; length: ULONG): ULONG; stdcall;
für Hilfe oder Tipps wäre ich sehr dankbar.
Zuletzt geändert von zianou am Samstag 20. Oktober 2012, 15:25, insgesamt 1-mal geändert.
BlackJack

@zianou: Wo liegt denn das Problem? Wie versuchst Du es und was passiert dann?

Ich würde die Funktionen aus der Bibliothek an Namen auf Modulebene binden und wie in der `ctypes`-Dokumentation die Argument- und Rückgabetypen definieren. Bei bei ``void *`` oder ``unsigned long`` als Rückgabetyp bin ich mir nicht so ganz sicher ob das abhängig von der Plattform in der Bitanzahl nicht von ``int`` abweichen kann, was `ctypes` annimmt, wenn man keinen Rückgabetyp festlegt.

Wenn das alles ordentlich „deklariert” ist, musst Du noch einen Puffer, zum Beispiel mit `ctypes.create_string_buffer()` erstellen, und dann die Funktionen aufrufen.
zianou
User
Beiträge: 6
Registriert: Freitag 19. Oktober 2012, 19:46

@BlackJack: mein Problem ist jetzt bei der Deklarierung der Parametern, denn ich muss zugeben, ich habe bis jetzt nicht die große Erfahrung mit ctypes gesammelt und mit C habe ich leider auch noch nie programmiert.

Die Methode "IowKitWrite" wird von Code Mercenaries wie folgt definiert:

Code: Alles auswählen

IowKitWrite

Declaration:
ULONG IOWKIT_API IowKitWrite(IOWKIT_HANDLE devHandle, ULONG numPipe,
PCHAR buffer, ULONG length);
function IowKitWrite(devHandle: IOWKIT_HANDLE; numPipe: ULONG;
buffer: PChar; length: ULONG): ULONG; stdcall;

Write length bytes of data to pipe numPipe of IO-Warrior. The return value is the number of bytes
written. Writing something else than a single report of the correct size and a valid report ID for the pipe
fails for Windows. The function allows writing to the I/O pins through pipe 0 and Special Mode functions
through pipe 1. To be completely compatible with the Windows version libiowkit.so expects a ReportID 0
for pipe 0 (I/O pins) even if Linux does not have a ReportID on pipe 0. The ReportID is stripped from the
data sent to the device.
Sample write to pipe 0 of an IO-Warrior 40:
DWORD value consists of 32 bits, which correspond to the 32 IO-Warrior 40 I/O pins. Each bit has the
following meaning:
When a 1 is written to a pin the output driver of that pin is off and the pin is pulled high by an internal
resistor. The pin can now be used as an input or an output with high state.
When a 0 is written to a pin the output driver is switched on pulling the pin to ground. The pin is now a
output driving low.
For example, writing 0 (all 32 bits are zero) to IO-Warrior sets all pins as outputs driving low (so if you
have LEDs connected to them they will be on).
Reading the status of the pins does always return the logic level on the pins, not the value written to the
pin drivers.
Writing 0xFFFFFFFF (value in hex, all 32 bits set) sets all pins as inputs.
Note that if you want to use a pin as an input, you must first set it up as input, in other words, you must
write 1 to it. For connected LEDs this means they go off.
Und wenn ich dich gut verstanden habe, dann muss ich die Parameter "buffer" und "length" so definieren:

Buff = ctypes.create_string_buffer(4)
LEN = ctypes.c_ulong(8)

oder lege ich hier total falsch?
BlackJack

@zianou: C-Kenntnisse sind im Grunde eine Voraussetzung um `ctypes` Anwenden zu können. Denn damit muss man ja die Datentypen und API-Aufrufe von C nachbauen.

Einen Puffer kann man so erstellen allerdings stimmt die Länge nicht — weder die des Puffers, noch die von Deinem `LEN`. Beide müssen der Länge der C-Struktur entsprechen in der man das am Ende gerne haben möchte, beziehungsweise in der die zu schreibenden Daten stehen. Welche Struktur genau genommen werden muss, und damit auch deren Länge in Bytes, hängt vom angesprochenen Gerätetyp und der Pipe ab.

Wenn man `create_string_buffer()` verwendet, bekommt man auf Python-Seite eine Zeichenkette wo man eigentlich lieber Zahlen hätte.

Die API ist an der Stelle auch unschön, denn in den Beispielen in der Dokumentation wird eine Variable von einem ``struct``-Typ angelegt und darauf dann ein Zeiger übergeben wo laut Funktionssignatur der Typ ``char *`` erwartet wird. Bei den Beispielquelltexten sollte also eigentlich jeder vernünftige C-Compiler meckern.
Antworten