Search code examples
pythonscipynumbandimage

numba ctype matching with ndfilter


I am trying to use Numba cfunc as scipy.LowLevelCallable inside ndi.generic_filter however I am facing signature matching issue. If I set return type to int16 it recognize as short if I set to int32 or intc it says long. Both signatures cannot be matched. The matching problem is in return type

import numpy as np
import scipy
from numba import cfunc, carray, types
import scipy.ndimage as ndi

@cfunc("intc (CPointer(float64),intp, CPointer(float64), voidptr)") #problematic
def myfunc(values_ptr, len_values, result, data):
    #some work here
    return 1

footprint = np.array([[0, 1, 0],[1, 1, 1],[0, 1, 0]], dtype=bool)
from scipy import ndimage as ndi

a=np.random.random((100,100))
ndi.generic_filter(a, scipy.LowLevelCallable(myfunc.ctypes), footprint=footprint)

This is the Error:

ValueError: Invalid scipy.LowLevelCallable signature "long (double *, long, double *, void *)". Expected one of: ['int (double *, intptr_t, double *, void *)', 'int (double *, npy_intp, double *, void *)', 'int (double *, int, double *, void *)', 'int (double *, long, double *, void *)']

System specs (if related): Python 2.7.10 (32-bit), Numba 0.39.0


Solution

  • It seems that you ran into this known issue. Specifically, there appears to be no way to produce the signature expected by LowLevelCallable with Numba on platforms where int and long are the same size (such as 64 bit flavors of Windows).

    I suggest you support a fix on GitHub. In the meantime, your best bet is to pass the Numba functon directly into generic_filter and accept some function call overhead, or to wrap the function in a supported way, e.g. via Cython.