错误消息“无法将< type_name> *转换为Python对象”。在Cython [英] Error message "Cannot convert <type_name>* to Python object" in Cython

查看:109
本文介绍了错误消息“无法将< type_name> *转换为Python对象”。在Cython的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我对以下Cython模块进行cython处理时

  %% cython 
cdef double * ptr = [1, 2,3]
print(ptr)

我收到以下错误消息:


无法将'double *'转换为Python对象


但是,下面的Cython模块是



  %% cython 
cdef double val = 0.0
打印(val)

被成功地进行了cythonized。



对于任何其他指针类型(例如 int * float * 等),也会发生此问题。

解决方案

print 是纯Python函数,为了能够要调用它,参数必须是Python对象。



显然,第一个Cython模块中的 ptr 都不第二个 val 是python对象。但是存在区别:Cython可以自动将 double 类型的 cdef 变量转换为Python-Float。 PyFloat_FromDouble c $ c> -这正是幕后情况:Cython从 val 创建一个临时的Python-Float,并将其传递给 print 并将其销毁。



还有其他类型可以自动转换为Python对象: double float int &类似,但 std: :vector 和其他c ++容器



但是,对于原始C指针( char * Py_UNICODE * 和它们的不同转世是一个例外-参见后面的示例)-因为不可能首先要做的是,因为Cython不知道指针指向的数组长度(根本就是数组吗?)。



在这种情况下的解决方案:必须手动将内存的内容转换为python列表(或与之对应的任何python类型),这里以函数 convert_to_python 为例:

  %% cython 
cdef convert_to_python(double * ptr,int n):
cdef int i
lst = []
对于范围(n)中的i:
lst.append(ptr [i])
返回ls t

cdef double * ptr = [1,2,3]
print(convert_to_python(ptr,3))

最值得注意的是, convert_to_python 将元素数量作为参数-信息Cython丢失。



Btw:Cython会自动将已知长度的C数组转换为Python对象,例如:

  %% cython 
cdef double arr [3]#Cython
arr [:] = [1,2,3]
打印的长度(= 3) arr)

编译没有问题。






字符* 签名字符* unsigned char * Py_UNICODE * 及其 const -变体是特殊的,因为他们可以自动转换个字节对象( char * )或 un icode -object( Py_UNICODE * ),假定它是一个以空字符结尾的C字符串(即字符 \0 标记结束)。因此,可以编写类似于

  cdef char a [3] 
a = [90,0, 90]#ord('Z')= 90
print(a)#char [3]衰减为char *
#b Z

如所见,结果不是b Z\x00Z,因为字符串在第一个 \0处被自动截断。为了确保将整个字符串转换为字节对象,必须指定长度:

  print(a [:3])
#b Z\x00Z

但是,如果没有<$ char $数组中的c $ c> \0 ,可能导致段错误(超出范围)。


When I cythonize the following Cython-module

%%cython
cdef double *ptr=[1,2,3]
print(ptr)

I get the following error message:

Cannot convert 'double *' to Python object

However, the following Cython module:

%%cython
cdef double val=0.0
print(val)

is cythonized without problems.

This problem occurs also for any other pointer type (i.e. int *, float * and so on).

解决方案

print is a pure Python function and in order to be able to call it, the arguments must be Python objects.

Obviously, neither ptr in the first Cython-module nor val in the second are python objects. There is however a difference: a cdef variable of type double can be converted to a Python-Float automaticly by Cython via PyFloat_FromDouble - and this is exactly what happens under the hood: Cython creates a temporary Python-Float from val, passes it to print and destroys it afterwards.

There are other types which can be automatically converted to Python objects: double, float, int & similar, but also std::vector and other c++-containers.

However, there is no such automatic conversion for raw-C-pointers (char *, Py_UNICODE* and their different reincarnations being an exception - see the example later on) - because it is not possible to do in the first place, as Cython doesn't know the length of the array (is it an array at all?) to which the pointer points.

The only solution in this case: one has to manually convert the content of the memory to a python list (or to whatever python-type it corresponds), here as example the function 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))

The most noteworthy thing is, that convert_to_python gets the number of elements as parameter - the information Cython is missing.

Btw: Cython would automatically convert C-arrays with known length to Python objects, for example:

%%cython 
cdef double arr[3] # length (=3) known to Cython 
arr[:]=[1,2,3]
print(arr)

compiles without problems.


char *, signed char *, unsigned char *, Py_UNICODE * and their const-variants are "special", because they can be automatically converted to either a bytes-object (char *) or unicode-object (Py_UNICODE *), assuming it is a null-terminated C-string (i.e. character \0 marks the end). Thus, it is possible to write code similar to

cdef char a[3] 
a = [90,0,90]   # ord('Z') = 90
print(a)        # char[3] decays to char *
# b"Z"

As one can see, the result is not b"Z\x00Z", because the string get automatically truncated at first `\0'. To ensure that the whole string converted to bytes object one has to specify length:

print(a[:3]) 
# b"Z\x00Z"

However, problem can arise if there is no \0 in the char-array, which could lead to segfaults (reads out of bounds).

这篇关于错误消息“无法将&lt; type_name&gt; *转换为Python对象”。在Cython的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆