Differ from earlier post, I work with all cdef function here. If I work with function pointer of fused_type input, it will raise "Invalid use of fused types, type cannot be specialized". On the contrary, the function pointer with built-in type works well. Why?
cimport cython
# raise error
ctypedef fused fused_type:
float
int
ctypedef fused_type (* _func_pointer) (fused_type[:])
cdef fused_type base_func(fused_type[:] arg1):
return arg1[0]
cdef fused_type c_entry(fused_type[:] arg1, _func_pointer func):
return func(arg1)
cdef fused_type base_wrapper(fused_type[:] arg1):
return c_entry(arg1, base_func)
""" ------- """
# works
cdef int base_func(int[:] arg1):
return arg1[0]
cdef int c_entry(int[:] arg1, _func_pointer func):
return func(arg1)
cdef int base_wrapper(int[:] arg1):
return c_entry(arg1, base_func)
You need to change it to
cdef fused_type base_wrapper(fused_type[:] arg1):
return c_entry(arg1, base_func[fused_type])
When base_wrapper
is specialized, that selects the specialization of base_func
for whatever fused_type
currently is in base_wrapper
.
The rough explanation of why:
ctypedef fused_type (* _func_pointer) (fused_type[:])
This doesn't define a function pointer type that takes and returns fused_type
. Instead it defines a fused type with containing two types:
float (*)(float[:])
int (*)(int[:])
When you do base_func
on its own it isn't a "real" function - you get one of the specializations either by calling it, or my manually selecting it (e.g. base_func[int]
).
Therefore in base_wrapper
the line return c_entry(arg1, base_func)
doesn't know which specialization of base_func
it should be using, and therefore can't pick which of the two types of _func_pointer
it should match.
The Cython fused type system is fairly dump and doesn't make too much of an effort to resolve confusion - it's either an unambiguous exact match or no match at all.