当前位置: 首页 > 面试题库 >

Cython:“无法转换Python对象”错误

夏博
2023-03-14
问题内容

我正在尝试从Python调用带有数组参数的C函数的测试项目:

test.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数据结构传递给需要指针的c代码int *, double *,...。但是,指针不是python对象,因此我们无法将它们从python代码传递到python代码。

用Cython可以自动处理转换到intdoublefloat等等,甚至char *(它是一个空终止的c-字符串)和一些STL-
容器
,而不是指针(char *作为一个例外)。

有两种最常见的情况:

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

1.通过内存视图传递:

在python中,我们无法以某种方式获取指针,因此必须在cython中完成。将array.arrayor或numpy.array(或任何其他支持buffer-
protocol的
python对象ctypes.Array,例如,参见此SO-
question
)传递给cython函数的首选是内存视图:

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对象(类型化的内存视图),因此可以将其传递给python函数(defcpdef)。
  2. &arr[0]用于获取内存视图的缓冲区的地址。其结果是类型int *
  3. 该函数的调用是“类型安全的”,您不能例如array.array('I', [0]*2)将其传递给它,因为它不是int-memory-view,而是unsigned int-memory-view。

2.传递非连续内存(例如列表):

list与Co.合作的还有更多工作:信息没有存储在普通的c数组中,因此我们需要先将其复制到连续内存中,将此temp变量传递给我们的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.array或者numpy.array如果需要使用c代码进行数据交换。



 类似资料:
  • 问题内容: 我正在尝试测试某个数字的十进制表示形式是否至少包含两次数字9,所以我决定执行以下操作: 但是Python始终会以“ TypeError:无法将’int’对象隐式转换为str”进行响应。 我在这里做错了什么?实际上,是否存在一种更聪明的方法来检测整数的十进制表示形式中包含某个数字的频率? 问题答案: 您的问题在这里: 您需要使字符串文字,而不是整数: 为了更好地计算字符串中出现的次数,请

  • 问题内容: 假设我们有一个类型的对象。我们定义了第二个。什么是最好的做法是“转换”的对象,以和保存所有数据? 问题答案: 这会进行“类转换”,但会带来附带损害。创建另一个对象并替换为BrainCore发布的对象会更安全- 但是此代码可以执行您要求的操作,而不会创建新对象。

  • 问题内容: 我正在尝试编写文本游戏,但在定义的函数中遇到了错误,该错误使你基本上无法在制作角色后花费技能点。最初,错误表明我正在尝试从代码的这一部分的整数中减去一个字符串。显然这是错误的,所以我用… 修复了它,但是现在我遇到了一个以前从未见过的错误(新程序员),并且我对确切要告诉我的内容以及如何解决它感到困惑。 这是我的部分功能不起作用的代码: 这是我在shell中获得这部分代码时遇到的错误: 有

  • 问题内容: 以下代码应在rpy2中创建一个热图 但是,它导致以下错误 从文档中,我了解到r.heatmap期望使用“数字矩阵”。如何将np.array转换为所需的数据类型? 问题答案: 您需要添加 请参阅rpy2文档的numpy部分(此处为旧版2.x版本)中的更多内容 在2.2.x之前,仅导入即可。 仅此导入就足以将numpy对象自动转换为rpy2对象。 为什么将其作为可选导入,而它却可以包含在函

  • 我为jsf创建了一个自定义转换器。getAsObject()工作正常,但getAsString()返回异常。我不确定问题出在哪里,我尝试过用不同的方式将对象转换为字符串,但它不断返回异常。 这是我的代码: 这是Product类(为简单起见排除了getter/Setters/equals()/hash()): 这是stack我得到的: 这是我使用转换器的jsf:

  • 问题内容: 我有JSON文件,看起来像 因此,键是字符串“ SUBS_ID”,值是一个名为FeatureDetails的模型,其中包含属性“ featureSetName,featureName,…”。所以我像这样使用google.json lib从JSON文件中读取内容, 然后我试图遍历此HashMap以获取值并将其转换为我的FeatureDetails模型, 这是我的FeatureDetail