gpt4 book ai didi

python - 赛通: "Cannot convert Python object"错误

转载 作者:行者123 更新时间:2023-11-28 21:03:04 25 4
gpt4 key购买 nike

我试图让一个测试项目工作,它从 Python 调用一个带有数组参数的 C 函数:

测试.cpp:

void testFn(int arr[]);

void testFn(int arr[])
{
arr[0] = 1;
arr[1] = 2;
}

caller.pyx:

import ctypes

cdef extern from "test.cpp":
void testFn(int arr[])

def myTest():
a = [0, 0]
arr = a.ctypes.data_as(ctypes.POINTER(ctypes.c_integer))
testFn(arr)
print(arr)

setup.caller.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

sourcefiles = ['caller.pyx']
ext_modules = [Extension("caller", sourcefiles)]

setup(
name = 'test app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)

但是当我尝试构建项目时出现错误:

$ python setup.caller.py build_ext --inplace
running build_ext
cythoning caller.pyx to caller.c

Error compiling Cython file:
------------------------------------------------------------
...
def myTest():
a = [0, 0]
arr = a.ctypes.data_as(ctypes.POINTER(ctypes.c_integer))
testFn(arr)
^
------------------------------------------------------------

caller.pyx:13:11: Cannot convert Python object to 'int *'

最佳答案

这个问题经常出现,但我没能找到一个好的重复目标,这超出了“只要这样做,它就会起作用”。

这是一种非常常见的情况:您尝试将一些 python 数据结构传递给需要指针 int *, double *,... 的 c 代码。但是指针不是 python 对象,所以我们不能将它们从/传递到 python 代码。

Cython 可以自动处理到intdoublefloat 等的转换,甚至是char * (它是一个以 null 结尾的 c 字符串)和一些 stl-containers , 但不是指向指针(char * 是一个异常(exception))。

最常见的情况有两种:

  1. python 数据的内部表示已经是一个 c 数组(array.array, numpy-arrays)。
  2. 内部表示不是连续数组(例如list)

<强>1。通过内存 View 传递:

在 python 中我们无法以某种方式获取指针,所以这必须在 cython 中完成。我的第一选择是传递 array.arraynumpy.array(或任何其他支持 buffer-protocol 的 python 对象,用于 ctypes.Array参见例如这个 SO-question )到一个 cython 函数将是一个内存 View :

def myTest(int[:] arr):
testFn(&arr[0])

现在从 python 调用它:

>>> import array
>>> a=array.array('i', [0]*2)
>>> import caller
>>> caller.myTest(a)
>>> a
array('i', [1, 2]) #it worked

下面很重要

  1. int[:] 是一个 python 对象(类型化内存 View ),因此它可以传递给 python 函数(defcpdef).
  2. &arr[0] 用于取内存 View 的缓冲区地址。它的结果是 int * 类型。
  3. 该函数的调用是“类型安全的”,您不能将例如 array.array('I', [0]*2) 传递给它,因为它不是 int-memory-view 但 unsigned int-memory-view。

<强>2。传递非连续内存(例如列表):

list 和 Co. 还有更多工作:信息不存储在普通 c 数组中,因此我们需要先将它们复制到连续内存中,将此临时变量传递给我们的 c-代码并将结果复制回列表,我们的 cython 函数可能如下所示

import array
def myTest2(lst):
tmp=array.array('i', lst)
myTest(tmp)
lst.clear()
lst.extend(tmp)

现在在重新加载 caller 模块之后:

>>> lst=[0,0]
>>> caller.myTest2(lst)
[1, 2]

因此,可以将列表的内容传递给 c 函数,但基本上您想要使用 array.arraynumpy.array 如果您需要与 C 代码进行数据交换。

关于python - 赛通: "Cannot convert Python object"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47005382/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com