在Python中如何访问被SWIG封装的uint16[3]数组?

7 投票
1 回答
3382 浏览
提问于 2025-04-15 18:56

这是一个关于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中,我怎么才能创建一个长度为3的变量B,让我可以读写A指向的同一块内存呢?

我觉得这个问题可以分成两部分:

  1. 如何从A中获取指针。(我觉得0x8c66fa0指向的是一个Swig对象,而不是被包装的对象。)
  2. 如何使用内存指针和已知的数据类型来初始化某种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>

然后尝试使用“0x8902f00”和“uint16”来构建B(无论是什么向量类型),并测试如果改变B[2]是否会导致C[2]的变化。

非常感谢你的建议或清晰的例子。

祝好,

Owen

1 个回答

8

经过更多的阅读和尝试,答案如下:

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。

解决了。 :)

撰写回答