我正在使用Python(via ctypes)包装的C库来运行一系列计算.在运行的不同阶段,我想将数据导入Python,特别是numpy数组.
我正在使用的包装为数组数据做了两种不同类型的返回(我特别感兴趣):
ctypes数组:当我这样做时type(x)(其中x是ctypes数组,我得到了一个<class 'module_name.wrapper_class_name.c_double_Array_12000'>回报.我知道这些数据是文档中内部数据的副本,我可以numpy轻松地将它变成一个数组:
>>> np.ctypeslib.as_array(x)
Run Code Online (Sandbox Code Playgroud)这将返回numpy数据的一维数组.
ctype指向数据的指针:在这种情况下,从库的文档中,我知道我得到一个指向存储的数据并直接用于库.乳清我做type(y)(y是指针)我得到了<class 'module_name.wrapper_class_name.LP_c_double'>.在这种情况下,我仍然可以索引数据y[0][2],但我只能通过一个超级尴尬的方式将它变成numpy:
>>> np.frombuffer(np.core.multiarray.int_asbuffer(
ctypes.addressof(y.contents), array_length*np.dtype(float).itemsize))
Run Code Online (Sandbox Code Playgroud)我在Travis Oliphant的旧numpy邮件列表帖子中找到了这个,但在numpy文档中没有.如果不是这种方法,我尝试如上,我得到以下内容:
>>> np.ctypeslib.as_array(y)
...
... BUNCH OF STACK INFORMATION
...
AttributeError: 'LP_c_double' object has no attribute '__array_interface__'
Run Code Online (Sandbox Code Playgroud)
这种np.frombuffer方法是最佳还是唯一的方法?我对其他建议numpy持开放态度,但我仍然希望使用,因为我有很多其他后处理代码,它依赖于numpy我想要对这些数据使用的功能.
在接下来的回答"我可以强迫一个numpy ndarray获取其记忆的所有权吗?" 我尝试PyArray_ENABLEFLAGS通过Cython的NumPy包装器使用Python C API函数,发现它没有暴露.
以下尝试手动公开它(这只是重现故障的最小示例)
from libc.stdlib cimport malloc
import numpy as np
cimport numpy as np
np.import_array()
ctypedef np.int32_t DTYPE_t
cdef extern from "numpy/ndarraytypes.h":
void PyArray_ENABLEFLAGS(np.PyArrayObject *arr, int flags)
def test():
cdef int N = 1000
cdef DTYPE_t *data = <DTYPE_t *>malloc(N * sizeof(DTYPE_t))
cdef np.ndarray[DTYPE_t, ndim=1] arr = np.PyArray_SimpleNewFromData(1, &N, np.NPY_INT32, data)
PyArray_ENABLEFLAGS(arr, np.NPY_ARRAY_OWNDATA)
Run Code Online (Sandbox Code Playgroud)
失败并出现编译错误:
Error compiling Cython file:
------------------------------------------------------------
...
def test():
cdef int N = 1000
cdef DTYPE_t *data = <DTYPE_t *>malloc(N …Run Code Online (Sandbox Code Playgroud) 在我之前的问题中,我学会了调整子类的大小ndarray.整齐.不幸的是,当我尝试调整大小的数组是计算的结果时,它不再有效:
import numpy as np
class Foo(np.ndarray):
def __new__(cls,shape,dtype=np.float32,buffer=None,offset=0,
strides=None,order=None):
return np.ndarray.__new__(cls,shape,dtype,buffer,offset,strides,order)
def __array_prepare__(self,output,context):
print output.flags['OWNDATA'],"PREPARE",type(output)
return np.ndarray.__array_prepare__(self,output,context)
def __array_wrap__(self,output,context=None):
print output.flags['OWNDATA'],"WRAP",type(output)
return np.ndarray.__array_wrap__(self,output,context)
a = Foo((32,))
#resizing a is no problem
a.resize((24,),refcheck=False)
b = Foo((32,))
c = Foo((32,))
d = b+c
#Cannot resize `d`
d.resize((24,),refcheck=False)
Run Code Online (Sandbox Code Playgroud)
确切的输出(包括追溯)是:
True PREPARE <type 'numpy.ndarray'>
False WRAP <class '__main__.Foo'>
Traceback (most recent call last):
File "test.py", line 26, in <module>
d.resize((24,),refcheck=False)
ValueError: cannot resize this array: it does not own …Run Code Online (Sandbox Code Playgroud) 我读过关于numpy.frombuffer的内容,但找不到任何从指针创建数组的方法.