Я новичок в интерфейсе Cython / C ++ и в настоящее время изучаю примеры в документации. Я пытаюсь найти способ обернуть структуру C ++ (вместо собственных типов C / C ++), которая используется в качестве спецификатора типа аргумента конструктора класса C ++. Затем я могу создать экземпляр класса C ++ на стороне Python.
Во-первых, файл rectangle.cpp
, который является упрощенной версией примера только с конструкторами. Здесь я представлю структуру, которая будет использоваться в качестве типа аргумента для конструктора. (Я объединил заголовочный файл .h
с .cpp
только для того, чтобы сделать сообщение короче. Хотя это обычно компилируется.)
прямоугольник. cpp
#include <iostream>
namespace shapes {
struct Point {
int x0;
int y0;
int x1;
int y1;
};
class Rectangle {
public:
int x0, y0, x1, y1;
Rectangle();
Rectangle(Point point);
~Rectangle();
};
// Default constructor
Rectangle::Rectangle () {}
Rectangle::Rectangle (Point point) {
this->x0 = point.x0;
this->y0 = point.y0;
this->x1 = point.x1;
this->y1 = point.y1;
}
// Destructor
Rectangle::~Rectangle () {}
}
Во-вторых, файл rectangle.pxd
, который в основном является копией из примера, за исключением того, что я включил cdef struct Point
для объявления структуры. ( Не уверен, что это правильный подход. )
rectangle.pxd
# Declare the class with cdef
cdef extern from "rectangle.cpp" namespace "shapes":
cdef struct Point:
int x0
int y0
int x1
int y1
cdef cppclass Rectangle:
Rectangle() except +
Rectangle(Point) except + # Not sure if this is correct
int x0, y0, x1, y1
В-третьих, rect.pyx
файл
rect.pyx
# distutils: language = c++
from rectangle cimport Rectangle, Point
# Create a Cython extension type which holds a C++ instance
# as an attribute and create a bunch of forwarding methods
# Python extension type.
cdef class PyRectangle:
cdef Point point # Not sure if this is correct
cdef Rectangle c_rect # Hold a C++ instance which we're wrapping
def __cinit__(self, Point point):
self.c_rect = Rectangle(point)
Наконец, setup.py
, что идентично примеру.
setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("rect.pyx"))
Если я скомпилирую стандартную команду python3 setup.py build_ext --inplace
, появится следующая ошибка. (Исходный пример можно без проблем скомпилировать и запустить.)
[1/1] Cythonizing rect.pyx
Error compiling Cython file:
------------------------------------------------------------
...
PyTypeObject *Py_TYPE(obj)
bint PyMapping_Check(obj)
object PyErr_Format(exc, const char *format, ...)
@cname("__pyx_convert__from_py_shapes::Point")
cdef Point __pyx_convert__from_py_shapes::Point(obj) except *:
^
------------------------------------------------------------
FromPyStructUtility:11:41: Expected an identifier or literal
Traceback (most recent call last):
File "setup.py", line 5, in <module>
setup(ext_modules=cythonize("rect.pyx"))
File "/usr/lib/python3/dist-packages/Cython/Build/Dependencies.py", line 877, in cythonize
cythonize_one(*args)
File "/usr/lib/python3/dist-packages/Cython/Build/Dependencies.py", line 997, in cythonize_one
raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: rect.pyx
Я уверен, что при переносе структуры есть ошибки, так как ошибка вызывается FromPyStructUtility
. Но я не нашел прямого ответа / решения для этого конкретного сценария. Если я хочу сохранить код C ++ как есть, то есть настаивать на передаче структуры конструктору, как мне реализовать это на стороне Cython? Ваши комментарии / предложения / учебники будут высоко оценены.