[Cython] Fused Types

mark florisson markflorisson88 at gmail.com
Thu Apr 28 21:48:13 CEST 2011

On 26 April 2011 20:05, Robert Bradshaw <robertwb at math.washington.edu> wrote:
> On Tue, Apr 26, 2011 at 8:18 AM, mark florisson
> <markflorisson88 at gmail.com> wrote:
>> On 26 April 2011 16:43, Stefan Behnel <stefan_ml at behnel.de> wrote:
>>> mark florisson, 26.04.2011 16:23:
>>>> I've been working a bit on fused types
>>>> (http://wiki.cython.org/enhancements/fusedtypes), and I've got it to
>>>> generate code for every permutation of specific types. Currently it
>>>> only works for cdef functions. Now in SimpleCallNode I'm trying to use
>>>> PyrexTypes.best_match() to find the function with the best signature,
>>>> but it doesn't seem to take care of coercions, e.g. it calls
>>>> 'assignable_from' on the dst_type (e.g. char *), but for
>>>> BuiltinObjectType (a str) this returns false.
>>> Which is correct. "char*" cannot coerce from/to "str". It can coerce to
>>> "bytes", though.
>>> http://wiki.cython.org/enhancements/stringliterals
>> Right, I see, so the thing is that I was using string literals which
>> should be inferred as the bytes type when they are assigned to a char
>> *. The thing is that because the type is fused, the argument may be
>> anything, so I was hoping best_match would figure it out for me.
>> Apparently it doesn't, and indeed, this example doesn't work:
>> cdef extern from "Foo.h":
>>    cdef cppclass Foo:
>>        Foo(char *)
>>        Foo(int)
>> cdef char *foo = "foo"
>> cdef Foo* foo = new Foo("foo") # <- this doesn't work ("no suitable
>> method found")
>> cdef Foo* bar = new Foo(foo)   # <- this works
>> So that's pretty lame, I think I should fix that.
> Agreed.
>>>> Why is this the case,
>>>> don't calls to overloaded C++ methods need to dispatch properly here
>>>> also?
>>> If this doesn't work, I assume it just isn't implemented.
>>>> Other issues are public and api declarations. So should we support
>>>> that at all? We could define a macro that calls a function that does
>>>> the dispatch. So e.g. for this
>>>> ctypedef cython.fused_type(typeA, typeB) dtype
>>>> cdef func(dtype x):
>>>>     ...
>>>> we would get two generated functions, say, __pyx_typeA_func and
>>>> __pyx_typeB_func. So we could have a macro get_func(dtype) or
>>>> something that then substitutes __pyx_get_func(#dtype), where
>>>> __pyx_get_func returns the pointer to the right function based on the
>>>> type names. I'm not sure we should support it, right now I just put
>>>> the mangled names in the header. At least the cdef functions will be
>>>> sharable between Cython implementation files.
>>> I'm fine with explicitly forbidding this for now. It may eventually work for
>>> Python object types where we can properly dispatch, but it won't easily work
>>> for C types. It may work in C++, though.
>> Ok, will do.
> For the moment, putting mangled names in the header should be fine. A
> macro might make sense in the long term.
> Somewhat orthogonal, it could makes sense to do some dispatching on
> type for cpdef functions.
>>>> I also noticed that for cdef functions with optional argument it gets
>>>> a struct as argument, but this struct doesn't seem to end up in the
>>>> header file when the function is declared public. I believe that also
>>>> the typedefs for ctypedef-ed things in the .pyx file don't make it
>>>> there when used to type a cdef function's arguments. Should that be
>>>> fixed?
>>> No, I think this should also become a compiler error. These functions are
>>> not meant to be called from C code. It's a Cython convenience feature. As
>>> long as it's not correctly supported on both ends of the publicly exported
>>> C-API, it's best to keep users from using it at all.
>> Ok, I'll try to make Cython issue an error for these cases.
> +1
> - Robert
> _______________________________________________
> cython-devel mailing list
> cython-devel at python.org
> http://mail.python.org/mailman/listinfo/cython-devel

So I fixed all that, but I'm currently wondering about the proposed
cython.typeof(). I believe it currently returns a string with the type
name, and not the type itself. So I think it would be inconsistent to
suddenly start allowing comparison with 'is' and 'isinstance' and

I'm also wondering if it would be useful to allow actual type
retrieval, which could be used in declarations and casts. For instance
consider fusing two structs with the same attribute name but different
attribute types. Perhaps in your code you want to introduce a variable
compatible with such a type, e.g. consider this:

ctypdef struct A:
    int attrib

ctypedef struct B:
    char *attrib

ctypedef cython.fused_type(A, B) struct_t

cdef func(struct_t mystruct, int i):
    cdef cython.gettype(mystruct.attrib) var = mystruct.attrib + i

What do you think?

More information about the cython-devel mailing list