Reputation: 12587
Cython documentation shows how to declare existing C++ classes with overloaded methods.
However, if I define my own cppclass
with an overloaded method ...
cdef cppclass point:
float x, y
point():
this.x = 0
this.y = 0
float sum():
return this.x + this.y
float sum(int z): # COMPILE ERROR
return this.x + this.y + z
... I get
Function signature does not match previous declaration
Overloading the constructor gives the same error there:
cdef cppclass point:
float x, y
point():
this.x = 0
this.y = 0
point(float X, float Y): # COMPILE ERROR
this.x = X
this.y = Y
float sum():
return this.x + this.y
Am I doing this incorrectly, or is this feature missing?
Update: Default arguments seem to be unusable too:
cdef cppclass point:
float x, y
point(float X=0, float Y=0):
this.x = X
this.y = Y
float sum():
return this.x + this.y
cdef float use_point():
cdef point p
p = point(1, 2)
return p.sum()
... passes Cython, but gets tripped up by the C++ compiler ("wrong number of arguments")
Upvotes: 10
Views: 2683
Reputation: 30917
As I said in a comment: this clearly is a bug/unsupported feature, and so it's probably much more useful to report it on the Cython issues list on github than post it here.
However, if you're interested in a hacky short-term workround then the following works:
float sum(...):
return this.x + this.y
float sum2 "sum"(int z):
return this.x + this.y + z
# A test function to prove it
def test():
cdef point pt
a = pt.sum()
b = pt.sum(3)
return a,b # returns (0.0, 3.0)
This uses 2 tricks
Cython lets you specify an "actual" name for the function by putting it in quotes. Thus float sum2 "sum"(int z):
ends up calling the function sum
, but it tricks Cython so that it doesn't register than you've reused the same name. The automatic C++ type deduction will work correctly though.
...
(i.e. C varargs) will match anything but it given the lowest priority by the C++ type deduction mechanism. Therefore sum(3)
picks sum(int)
ahead of sum(...)
. This also stops Cython thinking too hard about the types and leaves it up to C++ (as desired). The downside is that it won't tell you if you pass a huge nonsensical list of arguments but will just silently call the (...)
version.
This hack doesn't work for constructors, and doesn't look easy to make work for constructors.
Upvotes: 9
Reputation: 20675
The page you reference in its first part shows examples of exposing interfaces to existing C++ classes. In such case overloaded methods are allowed. I do not think overloading is allowed when implementing classes in Cython. The second part of the page shows how to implement wrappers - Cython classes that wrap C++ classes. Take a look at the example:
cdef class PyRectangle:
cdef Rectangle c_rect # hold a C++ instance which we're wrapping
def __cinit__(self, int x0, int y0, int x1, int y1):
self.c_rect = Rectangle(x0, y0, x1, y1)
def get_area(self):
return self.c_rect.getArea()
def get_size(self):
cdef int width, height
self.c_rect.getSize(&width, &height)
return width, height
def move(self, dx, dy):
self.c_rect.move(dx, dy)
Constructor is named __cinit__
. It works similary as in Python. Cython syntax is like in Python. I don't think you can name your constructor same as class name. You didn't provide __init__
nor __cinit__
, thus the default constructor expects no arguments.
Upvotes: 1