print
- это чистая функция Python, и для возможности ее вызова аргументы должны быть объектами Python.
Очевидно, что ни ptr
в первом модуле Cython, ни val
во втором - объекты Python.Однако есть разница: переменная cdef
типа double
может быть автоматически преобразована в Python-Float с помощью Cython с помощью PyFloat_FromDouble
- и это именно то, что происходит под капотом: Cython создаетвременный Python-Float из val
, передает его в print
и впоследствии уничтожает.
Существуют другие типы, которые могут автоматически преобразовываться в объекты Python: double
, float
, int
и аналогичные, но также std::vector
и другие c ++ - контейнеры .
Однако такого автоматического преобразования для необработанных указателей C не существует, поскольку это невозможно сделать вВо-первых, поскольку Cython не знает длину массива (это вообще массив?), на который указывает указатель.
Единственное решение в этом случае: нужно вручную преобразовать содержимоепамять для списка Python (или для любого другого типа Python), например, функция convert_to_python
:
%%cython
cdef convert_to_python(double *ptr, int n):
cdef int i
lst=[]
for i in range(n):
lst.append(ptr[i])
return lst
cdef double *ptr=[1,2,3]
print(convert_to_python(ptr,3))
Самое замечательное, что convert_to_python
получает количество элементовкак параграфметра - информация о Cython отсутствует.
Кстати: Cython автоматически преобразует C-массивы с известной длиной в объекты Python, например:
%%cython
cdef double arr[3] # length (=3) known to Cython
arr[:]=[1,2,3]
print(arr)
компилируется без проблем.