Cython:维度不是“tagPyArrayObject”的成员

Ora*_*cle 4 cython

我以面向对象的风格实现了纯Python代码。在某些方法中存在时间密集型循环,我希望通过对代码进行 cythonizing 来加快速度。

我使用了大量 numpy 数组,并且很难将类转换为 Cython 扩展类型。

这里我声明两个 numpy 数组“verteces”和“norms”作为属性:

将 numpy 导入为 np c将 numpy 导入为 np

cdef class Geometry(object):

    cdef:
        np.ndarray verteces
        np.ndarray norms

    def __init__(self, config):
        """ Initialization"""
        self.config         = config

        self.verteces       = np.empty([1,3,3],dtype=np.float32)
        self.norms          = np.empty(3,dtype=np.float32)
Run Code Online (Sandbox Code Playgroud)

在运行时,将定义数组的实际大小。调用Geometry.load()同一个类的方法时会发生这种情况。该方法打开一个 STL 文件并循环遍历三角形条目。

最后我想确定三角形和射线的交点。在相应的方法中,我使用以下声明。

cdef void hit(self, object photon):
    """ Ray-triangle intersection according to Moeller and Trumbore algorithm """

    cdef:
        np.ndarray[DTYPE_t, ndim=3] verteces    = self.verteces         # nx3x3
        np.ndarray[DTYPE_t, ndim=2] norms       = self.norms
        np.ndarray[DTYPE_t, ndim=1] ph_dir      = photon.direction
        np.ndarray[DTYPE_t, ndim=1] ph_origin   = photon.origin

        np.ndarray[DTYPE_t, ndim=1] v0, v1, v2, vec1, vec2, trsc, norm, v, p_inter

        float a, b, par, q, q0, q1, s0, s1

        int i_tri
Run Code Online (Sandbox Code Playgroud)

当我尝试编译此代码时,我收到以下错误消息:

'dimensions' is not a member of 'tagPyArrayObject'
Run Code Online (Sandbox Code Playgroud)

错误

我不是很熟悉 cython 编程,但也许错误是因为我必须在 C 扩展类型中初始化固定大小的数组?然而,在读取 STL 文件之前,数组的大小是未知的。

小智 7

不确定这是否与您的问题有关,但在我的 setup.py 文件中指定“NPY_1_7_API_VERSION”宏时,我收到了相同的错误消息。

extension_module = Extension(
    'yourfilename',
    sources=["yourfilename.pyx],
    include_dirs=[numpy.get_include()],
    define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
)
Run Code Online (Sandbox Code Playgroud)

使用这个宏,一个简单的npmatrix.shape[0]numpy 函数被编译为:

/* "yourfilename.pyx":35
 * 
 *     cpdef int vcount(self):
 *         return self.npmatrix.shape[0]
 * 
 */
  __pyx_r = (__pyx_v_self->npmatrix->dimensions[0]);
Run Code Online (Sandbox Code Playgroud)

这会导致错误。只需删除宏就解决了我的这个错误。