ctypes - pointer to pointer to buffer - aber wie?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
FelixW
User
Beiträge: 7
Registriert: Dienstag 25. August 2009, 14:47

Hallo zusammen!

Ich versuche aktuell eine .dll einer Digitalkamera mit Python anzusprechen und verwende dazu natürlich ctypes.
Obwohl ich ein totaler Neuling bin was Python angeht, komme ich sehr gut zurecht - bis auf an einer Stelle; und zwar verlangt die .dll Funktion als Parameter einen Pointer auf einen Pointer auf einen Buffer…
Die Funktion erlaubt das aufnehmen und transferieren der Daten einzelner Bilder in den Speicher über diesen Buffer.

Syntax:

Code: Alles auswählen

 HVSTATUS __stdcall HVSnapShot(HHV hhv, BYTE **ppBuffer, int nSum) 
Parameter:
HHV hhv; --> Handle to Camera (funktioniert)
BYTE **ppBuffer; --> pointer to pointer to buffer (funktioniert anscheinend nicht)
Int nSum; --> Number of buffers [number of images that have been snapped in memory] (funktioniert)

Beispiel aus der .dll Dokumentation:

Code: Alles auswählen

// Snap two images into buffers, buffer size is decided by image resolution
// here assuming a image is 800 * 600
BYTE Buffer1 [800*600]; //Buffer for one image
BYTE Buffer2 [800*600]; //Buffer for another image
Byte *ppBuffer[2]; //This Array keeps the pointer to each buffer
ppBuffer[0] = Buffer1;
ppBuffer[1] = Buffer2;

HVSnapShot(hhv, ppBuffer, 2);
Dass der Fehler beim Buffer liegt, habe ich darüber festgestellt, dass andere Kamerafunktionen, die keinen benötigen funktionieren. Meine bisherige Lösung ist offenbar unzureichend und lautet im Moment (für ein Bild, man will sich ja noch steigern können):

Code: Alles auswählen

 ## bestimme benötigte Größe pro Bild
buffer_size = 800 * 600 * ctypes.sizeof(ctypes.c_byte)
## belege etwas Platz…
ImageBuffer = ctypes.create_string_buffer(buffer_size)
## rufe die Funktion auf
ctypes.windll.LoadLibrary("HVDAILT").HVSnapShot(hhv, ctypes.byref(ImageBuffer),1)
Mein Python verabschiedet sich dann mit einer Fehlermeldung (Windows); wenn ich diese ignoriere kann ich noch weiter Befehle an die Kamera senden, sie ist jedoch (nach eigener Aussage) beschäftigt.
Ich vermute, dass das Problem ist, dass ich eigentlich einen Array mit Pointern zu den einzelnen ImageBuffers brauche, den ich via ctypes dann übergeben kann?

Daher drei Fragen:
- Vermute ich richtig?
- Wie mache ich es richtig?
- Gibt es eine Möglichkeit nicht jeden Buffer einzeln an den Array zu übergeben (sagen wir mal, ich wollte einen Film aufnehmen…)


Ich freue mich auf eure Antworten!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich kenne mich mit ctypes nicht genau aus, ich würde aber folgendes vermuten:

Code: Alles auswählen

buf = ctypes.c_byte*800*600

library = ctypes.windll.LoadLibrary("HVDAILT")

library.HVSnapShot(hhv,ctypes. pointer(buf),1)

#oder
library.HVSnapShot(hhv, ctypes.point(ctypes.pointer(buf)),1)
Das Leben ist wie ein Tennisball.
FelixW
User
Beiträge: 7
Registriert: Dienstag 25. August 2009, 14:47

Hallo EyDu,

pointer() bzw. byref() können nur Instanzen von ctypes übergeben.

Code: Alles auswählen

buf=ctypes.c_byte*800*600
gibt als Ergebnis dies:
class '__main__.c_byte_Array_800_Array_600'

und kann nicht übergeben werden. als Workaround zu der (glaube ich) vorgesehenen Funktion create_string_buffer() wäre:

Code: Alles auswählen

ImageBuffer = (ctypes.c_byte * 320 * 256) ()
dies erzeugt ein:
__main__.c_byte_Array_320_Array_256 object at 0x01122620
und kann aus mir unerfindlichen Gründen übergeben werden (aber hauptsache ist ja, dass es funktioniert :D )

Code: Alles auswählen

a = ctypes.byref(ImageBuffer)
b = ctypes.pointer(ImageBuffer)
a ist: cparam 'P' (01175468)
b ist: ctypes.LP_c_byte_Array_320_Array_256 object at 0x011226C0

Leider bin ich nicht geübt genug um diese filigranen Unterschiede zu würdigen (und stelle daher einfach nur fest, dass ich auf "a" nicht wiederholt in byref() oder pointer() verwenden kann, auf "b" jedoch schon).



Positiv ist, dass mit deinem Aufruf gemäß:

Code: Alles auswählen

library.HVSnapShot(hhv, ctypes.pointer(ctypes.pointer(ImageBuffer)),1)
Python nicht mehr abstürzt, aber die Kamera den Befehl nicht akzeptiert. Ein erster Schritt in die richtige Richtung, aber vermutlich nicht die komplette Lösung.
Antworten