gpt4 book ai didi

python - 如何创建一个可以接收 c++ 结构/实例或 python 对象作为参数的公共(public) cython 函数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:43:02 24 4
gpt4 key购买 nike

我的矩形.h

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

我的矩形.cpp

#include "Rectangle.h"
namespace shapes {
Rectangle::Rectangle() { }
Rectangle::Rectangle(int X0, int Y0, int X1, int Y1) {
x0 = X0;
y0 = Y0;
x1 = X1;
y1 = Y1;
}
Rectangle::~Rectangle() { }
int Rectangle::getArea() {
return (x1 - x0) * (y1 - y0);
}
}

我的 rect.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

我的 main.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

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

我试过 c struct 和 python object,两者都不适合我。如果我使用这段代码,编译器会给出一个错误

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

所以我在 PyRectangle 中添加了“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 公共(public)函数的正确方法?

最佳答案

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

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

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

#include "Rectangle.h" // this one is now first
#include "rect.h"

错误“shapes has not been declared”告诉你这个...


尊重你的第一次尝试,你是对的,你必须公开 PyRectangle。为此,您还需要指定一个“类型对象名称”,正如 Cython 告诉您的那样。你这样做如图 here (虽然说实话不是很清楚...):

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

这确保 PyRectangle 可用于 C/C++ 作为 struct c_PyRect(因此 cythonfunc 签名是 int cythonfunc(struct c_PyRect *);.)

此外,定义 PyRectangle 的 Python TypeObject 可用作 c_PyRect_t,但您不需要它。

关于python - 如何创建一个可以接收 c++ 结构/实例或 python 对象作为参数的公共(public) cython 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40572073/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com