sibennet
sibennet

Reputation: 53

Cython overloading "no suitable method found"

I am having trouble accessing overloaded constructors in a C++ class through Cython. I am trying to wrap a C++ class as described here. The class has multiple constructors with the same number of arguments, differing only by type, such as the class mentioned here. However, Cython has trouble deciding which constructor to call, giving the error "no suitable method found".

For instance, given foo.h as follows

class Foo 
{
    public:
        int which_constructor;

        Foo(int){ which_constructor = 1; }
        Foo(bool){ which_constructor = 2; };

        ~Foo();
};

and pyfoo.pyx as follows

from libcpp cimport bool as bool_t

cdef extern from "foo.h":
    cdef cppclass Foo:
        Foo(int)
        Foo(bool_t)
        int which_constructor

cdef class PyFoo:
    cdef Foo *thisptr      # hold a C++ instance which we're wrapping

    def __cinit__( self, *args, **kwargs):
        # get list of arg types to distinquish overloading
        args_types = []
        for arg in args:
            args_types.append(type(arg))

        if (args_types == [int]):
            self.thisptr = new Foo(args[0])
        elif (args_types == [bool]):
            self.thisptr = new Foo(args[0])
        else:
            pass

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

and a setup file setup_pyfoo.py as follows

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

setup(
    ext_modules = cythonize(
        Extension("pyfoo", ["pyfoo.pyx"],
            language="c++",
        )
    )
)

when I attempt to compile, I get the following error

C:\Users\bennett.OCM\Documents\Python\Cython>python setup_pyfoo.py build_ext --i
nplace
Compiling pyfoo.pyx because it changed.
Cythonizing pyfoo.pyx

Error compiling Cython file:
------------------------------------------------------------
...
        for arg in args:
            args_types.append(type(arg))

        # four differnent constructors.
        if (args_types == [int]):
            self.thisptr = new Foo(args[0])
                                 ^
------------------------------------------------------------

pyfoo.pyx:20:34: no suitable method found

Error compiling Cython file:
------------------------------------------------------------
...

        # four differnent constructors.
        if (args_types == [int]):
            self.thisptr = new Foo(args[0])
        elif (args_types == [bool]):
            self.thisptr = new Foo(args[0])
                                 ^
------------------------------------------------------------

pyfoo.pyx:22:34: no suitable method found

If I remove one or other of the constructor definitions in pyfoo.pyx, things work correctly, even though the multiple constructors still exist in foo.h. I suspect that Cython needs to be coerced into calling a particular constructor. I just don't know how to help it. Can anyone help me?

Upvotes: 5

Views: 1850

Answers (1)

You can cast your arguments explicitly:

if (args_types == [int]):
    self.thisptr = new Foo(<int> args[0])
elif (args_types == [bool]):
    self.thisptr = new Foo(<bool_t> args[0])
else:
    pass

Be sure to cast to <bool_t> and not <bool>, otherwise it will give you an ambiguous overloading error.

Upvotes: 3

Related Questions