在cython中伪造模板

时间:2015-08-25 17:45:19

标签: c++ templates cython

这个问题与this one有关,因为它应该是一个解决方案,但不起作用,我想知道为什么。我们的想法是让模板的不同实例化成为某个abstract-y类的派生类,其函数只需调用派生类的方法即可。宾语。但是,它完全无法工作:

foo.pyx

from libcpp.vector cimport vector
cdef class Vector:
    def show(self):
        print(self.v)

cdef class iVector(Vector):
    cdef vector[int] v
    def __init__(self, v):
        for e in v:
            self.v.push_back(e)

cdef class lVector(Vector):
    cdef vector[long] v
    def __init__(self, v):
        for e in v:
            self.v.push_back(e)

setup.py

from distutils.core import setup, Extension
from Cython.Build import cythonize

e = Extension("foo", sources=["foo.pyx"], language="c++")
setup(ext_modules = cythonize([e]))
在ipython中

In [1]: import foo

In [2]: v = foo.iVector(range(5))

In [3]: v.show()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-ea66b5f25fed> in <module>()
----> 1 v.show()

/home/kartikv/Programs/foo.pyx in foo.Vector.show (foo.cpp:768)()
      2 cdef class Vector:
      3     def show(self):
----> 4         print(self.v)
      5 
      6 cdef class iVector(Vector):

AttributeError: 'foo.iVector' object has no attribute 'v'

但它完全是......

1 个答案:

答案 0 :(得分:2)

当Cython编译print(self.v)时,它必须决定是否发出代码以访问Python级或C级属性。由于没有为Vector类声明名为v的cdef属性,因此它会发出Python级访问的代码。

在派生类中,v类中的iVector属性为“... stored directly in the object’s C struct.” 。它不能从Python获得,只能从C中获得,导致您看到的错误。

您可以将v声明为publicreadonly,这将使其对Python可见,但这不适用于更复杂的类型(正如您在评论中提到的那样)。

您要做的是实现“虚拟”属性。这在C ++中甚至不起作用:在尝试访问不存在的属性时会出现编译器错误,即使存在具有它的派生类也是如此。

通常,您可以通过将属性访问转换为调用cdef方法which is “virtual”来解决此问题,但具体如何操作取决于您尝试解决的实际问题。