为了账号安全,请及时绑定邮箱和手机立即绑定

“无法将 Python 对象参数转换为类型 '<typename>'”

“无法将 Python 对象参数转换为类型 '<typename>'”

PHP
富国沪深 2021-06-10 17:17:31
我正在尝试运行一个 cython 示例,该示例比许多教程(例如本指南)中的示例要复杂一些。这是一个最小的示例(请不要介意它没有太多功能)和重现我的问题的步骤:有 c++ 类Rectangle和Group2(我把所有东西都放在 .h 文件中以使其更短):// Rectangle.hnamespace shapes {     class Rectangle {        public:            Rectangle() {}    };    class Group2 {    public:        Group2(Rectangle rect0, Rectangle rect1) {}    };}然后创建一个grp2.pyx文件(在相同的文件夹在上述报头),与包装器Rectangle和Group2:# RECTANGLEcdef extern from "Rectangle.h" namespace "shapes":    cdef cppclass Rectangle:        Rectangle() except +cdef class PyRectangle:    cdef Rectangle c_rect    def __cinit__(self):        self.c_rect = Rectangle()# GROUP2cdef extern from "Rectangle.h" namespace "shapes":    cdef cppclass Group2:        Group2(Rectangle rect0, Rectangle rect1) except +    cdef class PyGroup2:    cdef Group2 c_group2    def __cinit__(self, Rectangle rect0, Rectangle rect1):        self.c_group2 = Group2(rect0, rect1)该扩展是通过setup.py我从命令行 ( python setup.py build_ext -i)调用的文件构建的:from distutils.core import setup, Extensionfrom Cython.Build import cythonizesetup(ext_modules = cythonize(Extension(           name="grp2",                                # the extension name           sources=["grp2.pyx"], # the Cython source            language="c++",                        # generate and compile C++ code      )))在这一点上我在错误_cinint_的PyGroup2:无法将 Python 对象参数转换为“矩形”类型我想我的 pyx 文件中有一些错误,但我不知道是什么。
查看完整描述

1 回答

?
梦里花落0921

TA贡献1772条经验 获得超6个赞

您应该PyRectangle在def-functions的签名中以及PyRectangle.c_rect在将矩形传递给 C++-functions 时使用。


这意味着您的代码应该是:


cdef class PyGroup2:

    ...

    def __cinit__(self, PyRectangle rect0, PyRectangle rect1):

        self.c_group2 = Group2(rect0.c_rect, rect1.c_rect)

请继续阅读以获取更详细的解释。


传递给def-functions 的所有参数都是 Python 对象(即objectCython 说法中的类型),毕竟这些函数将从纯 Python 中调用,而纯 Python 只知道 Python 对象。


但是,您可以添加一些语法糖并在def- 函数的签名中使用“后期绑定” ,例如,而不是


def do_something(n):

  ...


def do_something(int n):

  ...

在幕后,Cython 会将此代码转换为类似以下内容:


def do_something(n_):

   cdef int n = n_ # conversion to C-int

   ...

这种自动转换对于像int或这样的内置类型是可能的double,因为 Python-C-API 中有这些转换的功能(即PyLong_AsLong, PyFloat_AsDouble)。Cython 还处理错误检查,因此您不应手动进行这些转换。


但是,对于像您的Rectangle-class 这样的用户定义类型/类,这种自动转换是不可能的 - Cython 只能自动转换为cdef-classes/extensions,即PyRectangle,因此PyRectangle应该在签名中使用:


cdef class PyGroup2:

    ...

    def __cinit__(self, PyRectangle rect0, PyRectangle rect1):

        ...

在 Cython 完成从objectto的转换之后,必须使用- 指针手动执行从toPyRectangle的最后一步:PyRectangleRectanglec_rect


...

def __cinit__(self, PyRectangle rect0, PyRectangle rect1):

    self.c_group2 = Group2(rect0.c_rect, rect1.c_rect)

cpdef-function的规则类似,因为它们可以从纯 Python 中调用。在“早期绑定”仅适用于该用Cython可以自动从/ coverted到Python对象类型。


不出所料,唯一可以在其签名中包含 C++ 类的cdef函数是-functions。


查看完整回答
反对 回复 2021-06-15
  • 1 回答
  • 0 关注
  • 162 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信