猿问

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

我正在尝试运行一个 cython 示例,该示例比许多教程(例如本指南)中的示例要复杂一些。


这是一个最小的示例(请不要介意它没有太多功能)和重现我的问题的步骤:


有 c++ 类Rectangle和Group2(我把所有东西都放在 .h 文件中以使其更短):


// Rectangle.h

namespace shapes { 

    class Rectangle {

        public:

            Rectangle() {}

    };


    class Group2 {

    public:

        Group2(Rectangle rect0, Rectangle rect1) {}

    };

}

然后创建一个grp2.pyx文件(在相同的文件夹在上述报头),与包装器Rectangle和Group2:


# RECTANGLE

cdef 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()


# GROUP2

cdef 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, Extension

from Cython.Build import cythonize


setup(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 文件中有一些错误,但我不知道是什么。


富国沪深
浏览 163回答 1
1回答

梦里花落0921

您应该PyRectangle在def-functions的签名中以及PyRectangle.c_rect在将矩形传递给 C++-functions 时使用。这意味着您的代码应该是:cdef class PyGroup2:&nbsp; &nbsp; ...&nbsp; &nbsp; def __cinit__(self, PyRectangle rect0, PyRectangle rect1):&nbsp; &nbsp; &nbsp; &nbsp; self.c_group2 = Group2(rect0.c_rect, rect1.c_rect)请继续阅读以获取更详细的解释。传递给def-functions 的所有参数都是 Python 对象(即objectCython 说法中的类型),毕竟这些函数将从纯 Python 中调用,而纯 Python 只知道 Python 对象。但是,您可以添加一些语法糖并在def- 函数的签名中使用“后期绑定” ,例如,而不是def do_something(n):&nbsp; ...用def do_something(int n):&nbsp; ...在幕后,Cython 会将此代码转换为类似以下内容:def do_something(n_):&nbsp; &nbsp;cdef int n = n_ # conversion to C-int&nbsp; &nbsp;...这种自动转换对于像int或这样的内置类型是可能的double,因为 Python-C-API 中有这些转换的功能(即PyLong_AsLong, PyFloat_AsDouble)。Cython 还处理错误检查,因此您不应手动进行这些转换。但是,对于像您的Rectangle-class 这样的用户定义类型/类,这种自动转换是不可能的 - Cython 只能自动转换为cdef-classes/extensions,即PyRectangle,因此PyRectangle应该在签名中使用:cdef class PyGroup2:&nbsp; &nbsp; ...&nbsp; &nbsp; def __cinit__(self, PyRectangle rect0, PyRectangle rect1):&nbsp; &nbsp; &nbsp; &nbsp; ...在 Cython 完成从objectto的转换之后,必须使用- 指针手动执行从toPyRectangle的最后一步:PyRectangleRectanglec_rect...def __cinit__(self, PyRectangle rect0, PyRectangle rect1):&nbsp; &nbsp; self.c_group2 = Group2(rect0.c_rect, rect1.c_rect)cpdef-function的规则类似,因为它们可以从纯 Python 中调用。在“早期绑定”仅适用于该用Cython可以自动从/ coverted到Python对象类型。不出所料,唯一可以在其签名中包含 C++ 类的cdef函数是-functions。
随时随地看视频慕课网APP
我要回答