[英]Cython compilation error for free function (Cannot convert Python object argument to type 'FooBar *')
[英]"Cannot convert Python object argument to type '<typename>'" - error while wrapping c++-classes with Cython
我正在嘗試運行一個 cython 示例,該示例比許多教程(例如本指南)中的示例要復雜一些。
這是一個最小的示例(請不要介意它沒有太多功能)和重現我的問題的步驟:
有 c++-classes 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 文件中有一些錯誤,但我不知道是什么。
將矩形傳遞給 C++ 函數時,您應該在def
PyRectangle.c_rect
和PyRectangle.c_rect
的簽名中使用PyRectangle
。
這意味着您的代碼應該是:
cdef class PyGroup2:
...
def __cinit__(self, PyRectangle rect0, PyRectangle rect1):
self.c_group2 = Group2(rect0.c_rect, rect1.c_rect)
請繼續閱讀以獲取更詳細的解釋。
傳遞給所有的參數def
-functions是Python的對象(即類型的object
在用Cython-說法),畢竟這些功能將來自純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 處理了從object
到PyRectangle
的轉換PyRectangle
,從PyRectangle
到Rectangle
的最后一步必須通過使用c_rect
- 指針手動c_rect
:
...
def __cinit__(self, PyRectangle rect0, PyRectangle rect1):
self.c_group2 = Group2(rect0.c_rect, rect1.c_rect)
cpdef
的規則類似,因為它們可以從純 Python 中調用。 “早期綁定”僅適用於 Cython 可以自動從/向 Python 對象轉換的類型。
不出所料,唯一可以在其簽名中包含 C++ 類的函數是cdef
函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.