我想在cython中使用类似structurarray的东西,并且我希望这个structurarray在python中和在cython中一样容易访问。 基于一时兴起,我使用了一个重排,使用了一个看起来像我想要使用的结构的数据类型。奇怪的是,对于python来说,可以使用一个strucy数组。在
这是我的例子
# This is a "structarray in cython with numpy recarrays" testfile
import numpy as np
cimport numpy as np
# My structarray has nodes with fields x and y
# This also works without packed, but I have seen packed used in other places where people asked similar questions
# I assume that for two doubles that is equivalent but is necessary for in8s in between
cdef packed struct node:
double x
double y
# I suppose that would be the equivalent numpy dtype?
# Note: During compilation it warns me about double to float downcasts, but I do not see where
nodetype = [('x' , np.float64),('y', np.float64)]
def fun():
# Make 10 element recarray
# (Just looked it up. A point where 1-based indexing would save a look in the docs)
mynode1 = np.recarray(10,dtype=nodetype)
# Recarray with cdef struct
mynode1 = np.recarray(10,dtype=nodetype)
# Fill it with non-garbage somewhere
mynode1[2].x=1.0
mynode1[2].y=2.0
# Brave: give recarray element to a c function assuming its equivalent to the struct
ny = cfuny(mynode1[2])
assert ny==2.0 # works!
# Test memoryview, assuming type node
cdef node [:] nview = mynode1
ny = cfunyv(nview,2)
assert ny==2.0 # works!
# This sets the numpy recarray value with a c function the gts a memoryview
cfunyv_set(nview,5,9.0)
assert mynode1[5].y==9.0 # alsow works!
return 0
# return node element y from c struct node
cdef double cfuny(node n):
return n.y
# give element i from memoryview of recarray to c function expecting a c struct
cdef double cfunyv(node [:] n, int i):
return cfuny(n[i])
# write into recarray with a function expecting a memoryview with type node
cdef int cfunyv_set(node [:] n,int i,double val):
n[i].y = val
return 0
当然我不是第一个尝试这个的人。在
例如,Here也做了同样的事情,它甚至声明这种用法是手册here的一部分,但是我在页面上找不到这个。我怀疑它在某个地方。还有一些讨论涉及到在这种自定义类型中使用字符串(例如here),从答案中我发现,对cstruct进行重新排列的可能性是预期行为,在讨论中,我们讨论了如何结合一个关于给定示例的回归测试,并在某个点上修复了字符串错误。在
我的问题
我找不到任何文件表明,除了论坛答案,这应该是有效的。有人能告诉我文件记录在哪里吗?在
而且,为了一些额外的好奇心
回答最后一个问题:
Numpy的行为是在运行时而不是在编译时决定的。它将计算一个结构可以需要的最小空间量并分配这些空间块。它不会被任何编译器设置更改,所以应该是可靠的。在
因此,总是需要
cdef packed struct
来匹配numpy。但是,它不会生成符合标准的C代码。相反,它使用GCC、MSVC(以及其他)的扩展。因此,它在当前存在的主要C编译器上工作良好,但原则上可能在将来的编译器上失败。看起来应该可以使用C11标准alignas
以符合标准的方式实现相同的功能,因此如果需要的话,可以对Cython进行修改。在这似乎没有直接记录在案。我能给你的最好参考资料是这里的打字记忆视图docs。在
这似乎是支持PEP 3118缓冲区协议的结果,而不是对numpy结构化数据类型的特定cython支持。numpy为它的数组公开了一个
Py_buffer
结构,cython知道如何将它们转换成结构。在包装是必要的。我的understandingis x86是在itemsize字节边界上对齐的,而作为numpy结构的数据类型则压缩到尽可能小的空间中。最清楚的例子是:
相关问题 更多 >
编程相关推荐