В Python, как получить доступ к массиву uint16[3], обернутому SWIG (т.е.развернуть PySwigObject)?
Вопрос
Это вопрос Python.У меня есть переменная A
>>> A
<Swig Object of type 'uint16_t *' at 0x8c66fa0>
>>> help(A)
class PySwigObject(object)
Swig object carries a C/C++ instance pointer
Экземпляр, на который ссылается A, представляет собой непрерывный массив uint16[3], и проблема заключается в том, чтобы получить доступ к этому массиву из Python.
В Python, как я могу создать переменную B длиной 3, которая дает мне доступ на чтение / запись к той же памяти, на которую указывает указатель, заключенный в A?
Я думаю, что проблема состоит из двух частей:
- Как вывести указатель из A.(Я думаю, что 0x8c66fa0 указывает на Swig-объект, а не на обернутый объект).
- Как инициализировать какой-то массив Python, используя указатель на память и известный тип данных.(В Numpy есть метод frombuffer, но, похоже, необходим метод frommemory.) Возможно, потребуется некоторое приведение.
Я думаю, это должно быть легко, но я читал и взламывал больше дня!
Чтобы решить вторую часть, я думаю, пример мог бы начинаться так:
>>> 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>
Затем попробуйте построить B (любого векторного типа), используя "0x8902f00" и "uint16", и проверьте, вызывает ли изменение B[2] изменения в C[2].
Большое спасибо за ваши предложения или наглядный пример.
С уважением,
Оуэн
Решение
После дополнительного прочтения и опробования материала ответы будут следующими:
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 ) )
Тогда элементы могут быть адресованы как pA[0], pA[1] и т.Д
pA указывает на ту же память, что и исходный объект, поэтому будьте осторожны и не используйте pA после удаления исходного объекта.
Вот пример только для второй части проблемы (при использовании необработанного указателя известного типа в 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
Запуск примера на Python покажет, что и C [1], и pC [1] были изменены на 100.
Решаемая.:)