I have 2 classes, A and B. B inherits from 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;
};
Now I would like to interface those two classes using Cython and have the possibility to call the getA() method from a B instance:
a = PyA()
b = PyB()
assert a.getA() == b.getA()
Currently my pyx file looks like this:
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()
While I hope this code is not doing anything too dangerous, I also hope there is a better way to handle it.
Also using the module generates the following output:
>>> 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
And I don't really like allocating an A instance just to free it immediately after.
Any advice about how to do it correctly ?
I make some experiments, and have quite ready answer but now i see where is the problem:
If your extension type has a base type, the
__cinit__
method of the base type is automatically called before your__cinit__
method is called; you cannot explicitly call the inherited__cinit__
method.
So the real problem is that Cython types still do not have constructors, only pre initializer hook __cinit__
which behave more like default constructors. You cannot call virtual method from constructor and you cannot call it from __cinit__
either (if you make a call, it behave like non virtual).
Somehow inside __cinit__
the type(self)
return correct type object, but it is useless. Cython do not have static fields, methods and type object can be only instance of type
(no metaclasses). Python @staticmethod
is easy overridable, so it is useless.
So there is no other way like to put allocation inside def __init__(self):
, and check for initialized thisptr
wherever you use it.
You may consider creating a global dummy C++ object, and assign it to thisptr
to avoid checking and crashing. There are no post initializer hook, so you will be unable to check if correct initialization already have taken place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With