Does Cython support dynamic_cast?

657 views
Skip to first unread message

Jasmine Sandhu

unread,
Jan 10, 2013, 6:10:53 PM1/10/13
to cython...@googlegroups.com
Say I have the following C++ class:
namespace shapes {
// Simply a base class with virtual destructor
class DLL Polygon {
public:
Polygon();
virtual ~Polygon();
virtual string Type();
string _type;
virtual double getArea()=0;
};

class DLL Rectangle : public virtual Polygon {      // virtual inheritance
    public:
        double area;
Rectangle(double x0, double y0, double x1, double y1);
~Rectangle();
double getLength(); // Add method that does not exist in Base class

string Type();    // override base function
double getArea();   // implement virtual method
    };


Since Rectangle inherits virtual Polygon, in C++, I would need to do a dynamic cast
to access the methods for the Rectangle class. See example below:
        Polygon * polygon = new Rectangle(1,2,3,4);
Rectangle * rect;

rect = dynamic_cast<Rectangle *>(polygon);        // dynamic cast

cout << polygon->Type() << endl;
cout << "area: "<< polygon->getArea() << endl;
cout << rect->getLength() << endl;


I know cython supports the following for casting:

    cdef Polygon * polygon  
    cdef Rectangle * rect
    polygon = new Rectangle(x0,y0,x1,y1)
    rect = <Rectangle *>polygon                   // static cast

However, since Rectangle does virtual inheritance of Polygon, I get a compiler error:
Rectangle/cy_rectangle.cpp:1557: error: cannot convert from base ‘shapes::Polygon’ to derived type ‘shapes::Rectangle’ via virtual base ‘shapes::Polygon’

Can I do a dynamic_cast in Cython?

Thanks,
Jasmine

Bradley Froehle

unread,
Jan 10, 2013, 7:48:44 PM1/10/13
to cython...@googlegroups.com
You can think of the dynamic_cast as a function with a template parameter which Cython doesn't yet support.  But you can implement it as:

cdef extern from "*"
    Rectangle* dynamic_cast_rectangle_ptr "dynamic_cast<Rectangle*>" (Polygon*) except NULL

cdef Polygon *polygon
cdef Rectangle *rect
polygon = new Rectangle(x0, y0, x1, y1)
rect = dynamic_cast_rectangle_ptr(polygon)

Jasmine Sandhu

unread,
Jan 11, 2013, 8:36:20 PM1/11/13
to cython...@googlegroups.com
On Thursday, January 10, 2013 4:48:44 PM UTC-8, Bradley Froehle wrote:
You can think of the dynamic_cast as a function with a template parameter which Cython doesn't yet support.  But you can implement it as:

cdef extern from "*"
    Rectangle* dynamic_cast_rectangle_ptr "dynamic_cast<Rectangle*>" (Polygon*) except NULL

Thanks Brad - this is indeed very useful. 
I got it to work by playing around with it, but could you please explain the syntax:

What does cdef extern from * mean? Doesn't it have to be externed from some header file?

It looks like the following defines the function and give its implementation all in one line:

Rectangle* dynamic_cast_rectangle_ptr "dynamic_cast<Rectangle*>" (Polygon*) except NULL

Thanks,
Jasmine

Bradley Froehle

unread,
Jan 11, 2013, 9:20:20 PM1/11/13
to cython...@googlegroups.com
Sorry, I meant cdef extern from *, which is short for "no include is necessary" (http://docs.cython.org/src/userguide/external_C_code.html).  

Jasmine Sandhu

unread,
Jan 14, 2013, 6:17:26 PM1/14/13
to cython...@googlegroups.com
On Friday, January 11, 2013 6:20:20 PM UTC-8, Bradley Froehle wrote:
Sorry, I meant cdef extern from *, which is short for "no include is necessary" (http://docs.cython.org/src/userguide/external_C_code.html).  

Great, thank you for the link and explanation. 
This solved my problem.

Jasmine
Reply all
Reply to author
Forward
0 new messages