繁体   English   中英

将 ctypes object 转换为 numpy 数组

[英]Convert ctypes object to numpy array

我正在尝试编写一个 ctypes 结构,以便可以轻松地将其转换为 numpy 数组并用于分配。 这是一个显示问题的简单示例:

from ctypes import Structure, c_double
import numpy as np

class Vec3d:
    x = 1
    y = 2
    z = 3
    def __array__(self, dtype):
        return np.array([self.x, self.y, self.z])

class Vec3dS(Structure):
    _fields_ = [("x", c_double), ("y", c_double), ("z", c_double)]
    def __array__(self, dtype):
        return np.array([self.x, self.y, self.z])

v = Vec3d()
vs = Vec3dS(1,2,3)
n = np.zeros((2,3))
n[0] = v
n[1] = vs

第一个赋值n[0]=v有效,但第二个赋值 n n[1]=vs无效。 Numpy 似乎能够将v转换为 numpy 数组,但赋值最终失败,因为数组的数据类型错误:

TypeError: Cannot cast array data from dtype([('x', '<f8'), ('y', '<f8'), ('z', '<f8')]) to dtype('float64').

它与我使用的 dtype 相同

np.array(vs)

为什么在使用ctypes.Structure时实施__array__ (我也试过__array_interface__ )不起作用? 我如何修改Vec3dS class 以提示 numpy 如何将其转换为具有正确数据类型和值的 numpy 数组?

编辑:我怀疑ctypes.Structure实现了优先于__array__的 PEP 3118。 是否可以从 python 端覆盖它?

使用numpy.frombuffer似乎效果很好。

v = Vec3d(1,2,3)
l = [1,2,3]
n = np.zeros((2,3))

n[0] = l
n[1] = np.frombuffer(v)

assert (n[0] == n[1]).all()

如果您使用np.zeros(2, dtype=Vec3dS)而不是np.zeros((2,3))那么您根本不需要在 ctypes 结构上使用__array__

from ctypes import Structure, c_double
import numpy as np

class Vec3d:
    x = 1
    y = 2
    z = 3
    def __array__(self, dtype):
        return np.array(
            (self.x, self.y, self.z),
            dtype=[('x', np.double), ('y', np.double), ('z', np.double)])

class Vec3dS(Structure):
    _fields_ = [("x", c_double), ("y", c_double), ("z", c_double)]

v = Vec3d()
vs = Vec3dS(1,2,3)
n = np.zeros(2, dtype=Vec3dS)
# note: since the array is 1d, we need `...` to prevent decay to scalars, which
# don't behave well with `__array__`
n[0, ...] = v
n[1, ...] = vs

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM