Seite 1 von 1

ctypes problem: von void* zu ndarray im callback

Verfasst: Freitag 13. Februar 2009, 15:15
von hst
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

Verfasst: Freitag 13. Februar 2009, 16:58
von Darii
Guck dir mal die Doku zu numpy.ctypeslib an, das könnte was für dich sein.

Verfasst: Freitag 13. Februar 2009, 18:34
von hst
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

Verfasst: Freitag 13. Februar 2009, 18:50
von Darii
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.

Verfasst: Freitag 13. Februar 2009, 20:23
von hst
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...

Verfasst: Freitag 13. Februar 2009, 21:30
von Darii
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 ^^