2017-02-10 75 views
4

我试着在这个URL的例子。 http://cython.readthedocs.io/en/latest/src/userguide/buffer.htmlCython缓冲区协议示例错误

为了测试它,我做了以下工作。

import pyximport 
pyximport.install(build_dir = 'build') 
import ctest 

m = ctest.Matrix(10) 
m.add_row() 
print(m) 

这给了我一个错误,当我打电话被定义为

from cpython cimport Py_buffer 
from libcpp.vector cimport vector 

cdef class Matrix: 
    cdef Py_ssize_t ncols 
    cdef Py_ssize_t shape[2] 
    cdef Py_ssize_t strides[2] 
    cdef vector[float] v 

    def __cinit__(self, Py_ssize_t ncols): 
     self.ncols = ncols 

    def add_row(self): 
     """Adds a row, initially zero-filled.""" 
     self.v.extend(self.ncols) 
    ... 

此错误m.add_row()函数说 TypeError: 'int' object is not iterable

在类add_row使得完全有道理的,我假设在cython中调用一个向量的扩展与python列表中的扩展完全一样。您不会将它传递给一个数字,而是一个附加到列表中的可迭代对象。

我可以这样解决它......

def add_row(self): 
    """Adds a row, initially zero-filled.""" 
    self.v.extend([0] * self.ncols) 

我只是或不知道是否有在本例中一个错字如果我失去了一些东西。此外,扩展函数来自矢量的位置在哪里?在使用cython发布的vector.pxd文件中,它永远不会导入扩展函数,并且它甚至不存在于C++标准库中。 cython是否对矢量类型做了特别的事情?

https://github.com/cython/cython/blob/master/Cython/Includes/libcpp/vector.pxd

回答

2

CPP的vector可以被自动转换为一个python列表。通过检查行self.v.extend([0] * self.ncols)的c代码,创建了一个新的python列表:__pyx_t_2 = PyList_New(1 * ((__pyx_v_self->ncols<0) ? 0:__pyx_v_self->ncols))。因此extend实际上是python list的extend方法。

这种自动转换还可以通过以下代码验证(在jupyter笔记本):

%%cython -+ 
from libcpp.vector cimport vector 

def test_cpp_vector_to_pylist(): 
    cdef vector[int] cv 
    for i in range(10): 
     cv.push_back(i) 
    return cv 

a = test_cpp_vector_to_pylist() 
print a  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
print type(a) # <type 'list'> 

然而,cv被转换为临时Python列表在这样的情况下,原始的cpp vertor将保持未修饰的,如以下代码表示:

%%cython -+ 
from libcpp.vector cimport vector 

def test_cpp_vector_to_pylist_1(): 
    cdef vector[int] cv 
    for i in range(10): 
     cv.append(i) # Note: the append method of python list 
    return cv 

a = test_cpp_vector_to_pylist_1() 
print a  # [] 
print type(a) # <type 'list'> 

此外,交流阵列还可以被转换为自动Python列表:

%%cython 

def test_c_array_to_pylist(): 
    cdef int i 
    cdef int[10] ca 
    for i in range(10): 
     ca[i] = i 
    return ca 

a = test_c_array_to_pylist() 
print a  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
print type(a) # <type 'list'> 
+0

可能值得添加的是,列表不会被转换回向量,所以向量不会被延长。 – DavidW

+0

这是正确的,添加另一个代码片段来显示。 – oz1