You want to use Cython memory views. They are designed for passing array slices between functions that are a part of the same Cython module. You may need to inline the function within your Cython module to get the full performance benefit, but that isn't always necessary. You can take a look at the documentation. I recently wrote a rather lengthy answer to another question that looks in to when memory views should be used. If you want a more detailed examination of why slicing works well with memory views, have a look at this blog post.
If you don't use memory views, the slicing involving NumPy arrays still involves a Python call and is not performed in C.
For your specific case, here are a few thoughts: If you are passing array slices between functions in your Cython module you should be able to use a memory view to pass the slices. This approach does depend on compile-time optimizations, so if you need to pass an array between two functions that are compiled at separate times, you will have to use a pointer to pass data between functions. This will mean doing some careful pointer arithmetic, but it should still work. If you need to do slicing and use NumPy functions, you may just end up having to use NumPy arrays, but it could be worth trying to use NumPy arrays and memory views that view the same data. That way you will be able to pass slices as memory views, while only having to create NumPy arrays when you really need them.
Also, I would recommend making the function func
a C-function so that you don't have to go through the overhead of calling a Python function when you call it.
You can do that by using the cdef
or cpdef
keyword to declare it.
Use cdef
if you don't need to call it from outside the module.
Use cpdef
if you want a C function and a corresponding Python wrapper that is accessible to Python.