如何创建一个公共的Cython函数,可以接收C++结构体/实例或Python对象作为参数?

2024-04-27 04:47:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我的矩形

namespace shapes {
    class Rectangle {
    public:
        int x0, y0, x1, y1;
        Rectangle();
        Rectangle(int x0, int y0, int x1, int y1);
        ~Rectangle();
        int getArea();
    };
}

我的矩形.cpp在

^{pr2}$

我的矩形pyx在

# distutils: language = c++
# distutils: sources = Rectangle.cpp

cdef extern from "Rectangle.h" namespace "shapes":
    cdef cppclass Rectangle:
        Rectangle() except +
        Rectangle(int, int, int, int) except +
        int x0, y0, x1, y1
        int getArea()

cdef class PyRectangle:
    cdef Rectangle c_rect
    def __cinit__(self, int x0, int y0, int x1, int y1):
        self.c_rect = Rectangle(x0, y0, x1, y1)
    def get_area(self):
        return self.c_rect.getArea()

cdef public int cythonfunc(PyRectangle py_rect):
    result = py_rect.get_area()
    return result

我的主.cpp在

#include <Python.h>

#include "rect.h"

#include "Rectangle.h"
#include <iostream>

int main (int argc, char *argv[])
{
  int result;
  Py_Initialize();

  PyInit_rect();
  shapes::Rectangle c_rect = shapes::Rectangle(0,0,2,1);
  result = cythonfunc(c_rect);
  std::cout<<result<<"\n";

  Py_Finalize();

  return 0;
}

我的生成文件

all:
        cython3 --cplus rect.pyx
        c++ -g -O2 -c rect.cpp -o rect.o `python3-config --includes`
        c++ -g -O2 -c Rectangle.cpp -o Rectangle.o `python3-config --includes`
        c++ -g -O2 -c main.cpp -o main.o `python3-config --includes`
        c++ -g -O2 -o rect Rectangle.o rect.o main.o `python3-config --libs`

clean:
        rm -f rect rect.cpp rect.h *.o

我的问题与“cythonfunc”有关矩形pyx. 这是一个公共函数,可以用矩形结构/对象作为参数从main调用,并将一个区域返回给主.cpp. 在

我试过c结构和python对象,都不适合我。如果我使用这些代码,编译器会给出一个错误

Error compiling Cython file:
------------------------------------------------------------
...
    def __cinit__(self, int x0, int y0, int x1, int y1):
        self.c_rect = Rectangle(x0, y0, x1, y1)
    def get_area(self):
        return self.c_rect.getArea()

cdef public int cythonfunc(PyRectangle py_rect):
                          ^
------------------------------------------------------------

rect.pyx:19:27: Function declared public or api may not have private types

所以我在pyregtangle中添加了“public”,但是得到了另一个错误:

Error compiling Cython file:
------------------------------------------------------------
...
        Rectangle() except +
        Rectangle(int, int, int, int) except +
        int x0, y0, x1, y1
        int getArea()

cdef public class PyRectangle:
    ^
------------------------------------------------------------

rect.pyx:12:5: Type object name specification required for 'public' C class

如果我将cythonfunc改为:

cdef public int cythonfunc(Rectangle c_rect):
    result = c_rect.getArea()
    return result

我的错误是:

In file included from main.cpp:3:0:
rect.h:21:42: warning: ‘cythonfunc’ initialized and declared ‘extern’
 __PYX_EXTERN_C DL_IMPORT(int) cythonfunc(shapes::Rectangle);
                                          ^
rect.h:21:42: error: ‘shapes’ has not been declared
main.cpp: In function ‘int main(int, char**)’:
main.cpp:17:29: error: ‘cythonfunc’ cannot be used as a function
   result = cythonfunc(c_rect);
                             ^

我只能成功地将单独的x0、y0、x1、y1作为参数传递给cythonfunc。有没有正确的方法将cpp结构/对象或python对象作为参数传递给cython公共函数?在


Tags: rectselfmainresultpubliccppintx1
1条回答
网友
1楼 · 发布于 2024-04-27 04:47:05

关于第二次尝试(这可能是从C++调用它的更明智的方法,尽管我将通过引用):

cdef public int cythonfunc(Rectangle c_rect):
    result = c_rect.getArea()
    return result

问题是它不知道Rectangle是什么,因为Cython生成的rect.h不包括{}。解决此问题的最简单方法是交换main.cpp中include的顺序:

^{pr2}$

错误“形状尚未声明”告诉您。。。在


关于你的第一次尝试,你是对的,你必须公开PyRectangle。为此,您还需要指定一个“typeobjectname”,正如Cython告诉您的那样。您可以按照here所示的方式进行操作(尽管说实话并不十分清楚……):

cdef public class PyRectangle [object c_PyRect, type c_PyRect_t]:
    # ... as before

这确保PyRectangle对C/C++的可用性为^ {< CD6>}(因此^ {< CD7>}签名为^ {< CD8>})

另外,定义TypeObject的PythonPyRectangle可用作c_PyRect_t,但您不需要它。在

相关问题 更多 >