我已经将一个算法从C语言重写为Cython,这样我就可以利用融合类型并且更容易从Python调用。该算法可以使用多个数组以及一些其他参数。这些数组被接受为指向指针的指针(例如)。我想通过提供多个数组作为numpy数组的元组,从Python中调用cython代码,但是由于融合类型的原因,这样做会变得有些混乱。以下是我现在的工作方式的简单示例:
import numpy
cimport numpy
ctypedef fused test_dtype:
numpy.float32_t
numpy.float64_t
cdef int do_stuff(test_dtype **some_arrays):
if test_dtype is numpy.float32_t:
return 1
elif test_dtype is numpy.float64_t:
return 2
else:
return -1
def call_do_stuff(tuple some_arrays):
cdef unsigned int num_items = len(some_arrays)
cdef void **the_pointer = <void **>malloc(num_items * sizeof(void *))
if not the_pointer:
raise MemoryError("Could not allocate memory")
cdef unsigned int i
cdef numpy.ndarray[numpy.float32_t, ndim=2] tmp_arr32
cdef numpy.ndarray[numpy.float64_t, ndim=2] tmp_arr64
if some_arrays[0].dtype == numpy.float32:
for i in range(num_items):
tmp_arr32 = some_arrays[i]
the_pointer[i] = &tmp_arr32[0, 0]
return do_stuff(<numpy.float32_t **>the_pointer)
elif some_arrays[0].dtype == numpy.float64:
for i in range(num_items):
tmp_arr64 = some_arrays[i]
the_pointer[i] = &tmp_arr64[0, 0]
return do_stuff(<numpy.float64_t **>cols_pointer)
else:
raise ValueError("Array data type is unknown")
我知道我可以在元组中指定类型,但是如果我理解正确的话,不能指定比"object"更复杂的内容。有没有人知道更简洁的实现方式?欢迎分享其它Cython技巧。
还有其他参数需要传递,包括与数组相同类型的 "fill_value" 参数。如果可以通过数组或填充参数在调用时确定 "test_dtype",那么代码会更简单,但我找不到一个好的方法来保证 C 以正确的类型接收值。例如,传递 numpy.nan 或 numpy.float64(numpy.nan) 并不能保证数据类型。