I have a C++ class with a virtual method:
//C++
class A
{
public:
A() {};
virtual int override_me(int a) {return 2*a;};
int calculate(int a) { return this->override_me(a) ;}
};
What I would like to do is to expose this class to Python with Cython, inherit from this class in Python and have the correct overridden called:
#python:
class B(PyA):
def override_me(self, a):
return 5*a
b = B()
b.calculate(1) # should return 5 instead of 2
Is there a way to do this ?
Now I’m thinking, it could also be great if we could override the virtual method in Cython as well (in a pyx file), but allowing users to do this in pure python is more important.
Edit: If this helps, a solution could be to use the pseudocode given here: http://docs.cython.org/src/userguide/pyrex_differences.html#cpdef-functions
But there are two problems then :
- I don’t know how to write this pseudocode in Cython
- maybe there is a better approach
Excellent !
Not complete but sufficient.
I’ve been able to do the trick for my own purpose. Combining this post with the sources linked above.
It’s not been easy, since I’m a beginner at Cython, but I confirm that it is the only way I could find over the www.
Thanks a lot to you guys.
I am sorry that I don’t have so much time go into textual details, but here are my files (might help to get an additional point of view on how to put all of this together)
setup.py :
TestClass :
ITestClass.h :
ITestClass.cpp :
EDIT2 : A note about PURE virtual methods (it appears to be a quite recurrent concern). As shown in the above code, in that particular fashion, “TestClass::override_me()” CANNOT be pure since it has to be callable in case the method is not overridden in the Python’s extended class (aka : one doesn’t fall in the “error”/”override not found” part of the “ITestClass::override_me()” body).
Extension : elps.pyx :
Finally, the python calls :
This should make the previous linked work hopefully more straight to the point we’re discussing here…
EDIT : On the other hand the above code could be optimized by using ‘hasattr’ instead of try/catch block :
The above code, of course, makes a difference only in the case where we don’t override the ‘override_me’ method.