ctypes problem: von void* zu ndarray im callback

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
hst
User
Beiträge: 3
Registriert: Freitag 13. Februar 2009, 14:51

Hallo Experten,

ich blicke auch nach einiger Sucherei und Probiererei noch nicht durch. Ich versuch eine existierende C-Bibliothek zu wrappen und wollte dazu ctypes verwenden, da es zu den Standardbibliotheken gehört und rein auf der Python-Seite arbeitet. So weit sind meine Erfahrungen damit auch gut, bloß jetzt bin ich auf ein Problem gestoßen bei dem ich festhänge.

Die Library ruft eine Callback-Funktion auf die ich gern in Python implementieren würde. Die Signatur der Callback-Funktion ist etwas komplizierter, aber der Demonstration halber reicht es, folgende Signatur als Beispiel zu nehmen:

int callback(void *buffer);

buffer ist dabei ein Zeiger auf einen Speicherbereich, der in Wirklichkeit ein zweidimensionales Array aus 32-bit float beinhaltet. Die Array-Größe ist dem Programm bekannt, aber variabel. Auf der Python-Seite hätte ich gern Zugriff auf das Array als ndarray (Numpy). Der Python-Code soll auf dem Array rumrechnen können und die geänderten Daten am Ende des Callbacks auch wieder dem aufrufenden C-Code zur Verfügung stehen. Dabei möchte ich möglicht wenige Datenkopien haben, denn es kann um größere Arrays gehen.

Wie muß die Typdefinition für den Callback in ctypes aussehen, und wie bekomme ich das in ein ndarray konvertiert, so daß auch der Rückweg funktioniert?

Gruß und Danke!
Stefan
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Guck dir mal die Doku zu numpy.ctypeslib an, das könnte was für dich sein.
hst
User
Beiträge: 3
Registriert: Freitag 13. Februar 2009, 14:51

Danke!

Da drin finde ich Unterstützung für den umgekehrten Weg, also die Übergabe eines nparray an eine aufzurufende C-Funktion. Wie es in meinem Fall helfen könnte sehe ich noch nicht.

Hast Du detailliertere Tips?

Stefan
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

hst hat geschrieben:Da drin finde ich Unterstützung für den umgekehrten Weg, also die Übergabe eines nparray an eine aufzurufende C-Funktion.
Und du willst? Hab dann dein Problem nicht verstanden
Hast Du detailliertere Tips?
Meine Kenntnisse in dem Bereich sind beschränkt.
hst
User
Beiträge: 3
Registriert: Freitag 13. Februar 2009, 14:51

Ich will aus einem void* ein nparray erzeugen. Der C-Code erzeugt und verwaltet den Speicher und der Python-Code soll nur den Inhalt lesen und modifizieren können.

Ich habe allerdings inzwischen so etwas ähnliches wie Erfolg gehabt mit diesem Code:

Code: Alles auswählen

p = cast(buf, POINTER(c_byte * buffersize))
b = buffer(p.contents, 0, buffersize)
a = pylab.frombuffer(b, pylab.float32)
arr = a.reshape(x,y)
Ich habe noch crashes, aber das ist wohl was anderes...
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Dafür ist doch die numpy.ctypeslib da(oder ich hab dich falsch verstanden).

Code: Alles auswählen

const int cols = 2;
const int rows = 4;

void makearray(void *array) {
  int i,j;
  for(i=0; i<cols; i++)
      for(j=0; j<rows; j++)
        ((float*)array)[j*cols+i] = j*cols+i;
}

Code: Alles auswählen

In [1]: import numpy 

In [2]: import numpy.ctypeslib as ct 

In [3]: lib = ct.load_library("test.dylib",".") 

In [4]: lib.makearray.argtypes = [ct.ndpointer(dtype=numpy.float32, shape=(4,2),flags='C_CONTIGUOUS')] 

In [5]: ar = numpy.array([0]*8, dtype=numpy.float32).reshape((4,2))

In [6]: lib.makearray(ar)

Out[6]: 2

In [7]: print ar
[[ 0.  1.]
 [ 2.  3.]
 [ 4.  5.]
 [ 6.  7.]]
Edit: Jaaaaa, ich hab dich falsch verstanden ^^
Antworten