In Python, come accedere a un uint16 [3] array avvolto da SWIG (cioè unwrap un PySwigObject)?
Domanda
Questa è Python domanda. Ho una variabile A
>>> A
<Swig Object of type 'uint16_t *' at 0x8c66fa0>
>>> help(A)
class PySwigObject(object)
Swig object carries a C/C++ instance pointer
L'esempio di cui con A è una matrice [3] uint16 contigua ed il problema è quello di ottenere l'accesso a tale matrice da Python.
In Python, come posso creare una variabile B di lunghezza 3, che mi dà l'accesso in lettura / scrittura alla stessa memoria puntato dal puntatore avvolto in un?
Credo che il problema ha due parti:
- Come ottenere il puntatore di A. (penso punti 0x8c66fa0 a un oggetto Swig, non l'oggetto avvolto).
- Come inizializzare una sorta di matrice Python utilizzando un puntatore di memoria e di un noto tipo di dati. (Numpy ha un metodo frombuffer, ma quello che sembra essere necessario è un metodo frommemory). Forse sarà necessario un po 'di casting.
Questo dovrebbe essere facile credo, ma ho letto e hacking per più di un giorno!
Per risolvere la seconda parte, penso che un esempio potrebbe cominciare in questo modo:
>>> import numpy
>>> C = numpy.ascontiguousarray([5,6,7],"uint16")
>>> C
array([5, 6, 7], dtype=uint16)
>>> C.data
<read-write buffer for 0x8cd9340, size 6, offset 0 at 0x8902f00>
Quindi provare a costruire B (di qualsiasi tipo vettoriale) utilizzando "0x8902f00" e "uint16" e verificare se la modifica B [2] provoca cambiamenti nel C [2].
Molte grazie per i tuoi suggerimenti o un chiaro esempio.
Saluti,
Owen
Soluzione
Dopo più la lettura e la roba provare, le risposte sono le seguenti:
1. The wrapped pointer in PySwigObject A is available as A.__long__() . 2. A raw pointer can be cast into an indexable type using ctypes as follows import ctypes pA = ctypes.cast( A.__long__(), ctypes.POINTER( ctypes.c_uint16 ) )
Poi gli elementi possono essere affrontati come pA [0], pA [1] ecc
pA punti alla stessa memoria come l'oggetto originale, quindi fare attenzione a non usare pA dopo che l'oggetto originale viene eliminato.
Ecco un esempio per la seconda parte del problema (utilizzando un puntatore non elaborato di tipo noto in Python),
C = numpy.ascontiguousarray([5,6,7],"uint16") # make an array
C
rawPointer = C.ctypes.data
pC = ctypes.cast( rawPointer, ctypes.POINTER( ctypes.c_uint16 ))
pC[0:3]
pC[1]=100
pC[0:3]
C
L'esecuzione l'esempio in Python mostrerà che sia C [1] e PC [1] sono stati cambiati a 100.
risolto. :)