Cython和C++继承

asc*_*bol 13 c++ python inheritance cython

我有2个班,A和B. B继承自A.

//C++    
class A
{
    public:
        int getA() {return this->a;};
        A() {this->a = 42;}
    private:
        int a;

};

class B: public A
{
    public:
       B() {this->b = 111;};
       int getB() {return this->b;};
    private:
        int b;

};
Run Code Online (Sandbox Code Playgroud)

现在我想使用Cython连接这两个类,并且可以从B实例调用getA()方法:

a = PyA()
b = PyB()
assert a.getA() == b.getA()
Run Code Online (Sandbox Code Playgroud)

目前我的pyx文件如下所示:

cdef extern from "Inherit.h" :
    cdef cppclass A:
       int getA()

    cdef cppclass B(A):
       int getB()


cdef class PyA:
    cdef A* thisptr

    def __cinit__(self):
       print "in A: allocating thisptr"
       self.thisptr = new A()
    def __dealloc__(self):
       if self.thisptr:
           print "in A: deallocating thisptr"
           del self.thisptr

    def getA(self):
       return self.thisptr.getA()

cdef class PyB(PyA):
    def __cinit__(self):
       if self.thisptr:
          print "in B: deallocating old A"
          del self.thisptr
       print "in B: creating new b"
       self.thisptr = new B()

    def __dealloc__(self):
       if self.thisptr:
           print "in B: deallocating thisptr"
           del self.thisptr
           self.thisptr = <A*>0

    def getB(self):
       return (<B*>self.thisptr).getB()
Run Code Online (Sandbox Code Playgroud)

虽然我希望这段代码没有做太危险的事情,但我也希望有更好的方法来处理它.

此外,使用该模块还会生成以下输出:

>>> from inherit import *
>>> b = PyB()
in A: allocating thisptr
in B: deallocating old A
in B: creating new b
>>> b.getA()
42
>>> b.getB()
111
>>> del b
in B: deallocating thisptr
Run Code Online (Sandbox Code Playgroud)

我真的不喜欢分配A实例只是为了立即释放它.

关于如何正确地做到这一点的任何建议?

Arp*_*ius 8

我做了一些实验,并且已经准备好了答案,但现在我知道问题在哪里:

如果扩展类型具有基类型,则在__cinit__调用__cinit__方法之前会自动调用基类型的方法; 你不能显式调用继承的__cinit__方法.

所以真正的问题是Cython类型仍然没有构造函数,只有pre initializer hook __cinit__,它的行为更像默认构造函数.你不能调用构造函数从虚方法,你不能把它从__cinit__任一(如果您拨打一个电话,它表现得像非虚拟).

不知怎的,里面__cinit__type(self)返回正确类型的对象,但它是无用的.Cython没有静态字段,方法和类型对象只能是实例type(没有元类).Python @staticmethod很容易覆盖,所以它没用.

因此,没有其他方法可以将分配放在内部def __init__(self):,并thisptr在您使用它的任何地方检查初始化.

您可以考虑创建一个全局虚拟C++对象,并将其分配thisptr给以避免检查和崩溃.没有post initializer hook,因此您将无法检查是否已经进行了正确的初始化.