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
ctypes problem: von void* zu ndarray im callback
Und du willst? Hab dann dein Problem nicht verstandenhst hat geschrieben:Da drin finde ich Unterstützung für den umgekehrten Weg, also die Übergabe eines nparray an eine aufzurufende C-Funktion.
Meine Kenntnisse in dem Bereich sind beschränkt.Hast Du detailliertere Tips?
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:
Ich habe noch crashes, aber das ist wohl was anderes...
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)
Dafür ist doch die numpy.ctypeslib da(oder ich hab dich falsch verstanden).
Edit: Jaaaaa, 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.]]