簡體   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