在cython中伪造模板

Faking templates in cython

本文关键字:伪造 cython      更新时间:2023-10-16

这个问题与这个问题有关,从某种意义上说,它应该是一个解决方案,但不工作,我想知道为什么。其思想是将模板的不同实例化为某些抽象类的派生类,这些类的函数然后只调用派生类对象上的方法。然而,它完全不起作用:

<标题> foo.pyx h1>
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'

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

在派生类中,iVector类中的v属性为"…"直接存储在对象的C结构体中。"。它不能在Python中使用,只能在C中使用,从而导致您看到的错误。

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

你要做的是实现一个"虚拟"属性。这在c++中也行不通:当你试图访问一个不存在的属性时,你会得到一个编译器错误,即使存在一个具有该属性的派生类。

一般来说,您可以通过将属性访问转换为调用cdef方法来解决这个问题,该方法是"虚拟的",但具体如何做取决于您要解决的实际问题。