【发布时间】:2017-05-07 20:31:28
【问题描述】:
免责声明:我从 Python Cookbook (O'Reilly) 中获取了以下示例。
假设我有以下简单的struct:
typedef struct {
double x,y;
} Point;
使用计算两个Points 之间的欧几里得距离的函数:
extern double distance(Point* p1, Point* p2);
所有这些都是名为 points 的共享库的一部分:
-
points.h- 头文件 -
points.c- 源文件 -
libpoints.so- 库文件(Cython 扩展链接到它)
我已经创建了我的包装 Python 脚本(称为 pypoints.py):
#include "Python.h"
#include "points.h"
// Destructor for a Point instance
static void del_Point(PyObject* obj) {
// ...
}
// Constructor for a Point instance
static void py_Point(PyObject* obj) {
// ...
}
// Wrapper for the distance function
static PyObject* py_distance(PyObject* self, PyObject* arg) {
// ...
}
// Method table
static PyMethodDef PointsMethods[] = {
{"Point", py_Point, METH_VARARGS, "Constructor for a Point"},
{"distance", py_distance, METH_VARARGS, "Calculate Euclidean distance between two Points"}
}
// Module description
static struct PyModuleDef pointsmodule = {
PyModuleDef_HEAD_INIT,
"points", // Name of the module; use "import points" to use
"A module for working with points", // Doc string for the module
-1,
PointsMethods // Methods provided by the module
}
请注意,这只是一个示例。对于struct 和上面的函数,我可以轻松使用ctypes 或cffi,但我想学习如何编写 Cython 扩展。 setup.py 此处不需要,因此无需发布。
现在你可以看到上面的构造函数允许我们这样做
import points
p1 = points.Point(1, 2) # Calls py_Point(...)
p2 = points.Point(-3, 7) # Calls py_Point(...)
dist = points.distance(p1, p2)
效果很好。但是,如果我想实际访问Point 结构的内部结构怎么办?例如我会怎么做
print("p1(x: " + str(p1.x) + ", y: " + str(p1.y))
如您所知,可以直接访问 struct 内部(如果我们使用 C++ 术语,我们可以说所有 struct 成员都是 public)所以在 C 代码中我们可以轻松地做到这一点
Point p1 = {.x = 1., .y = 2.};
printf("p1(x: %f, y: %f)", p1.x, p1.y)
在 Python 中,类成员(self.x、self.y)也可以在没有任何 getter 和 setter 的情况下访问。
我可以编写充当中间步骤的函数:
double x(Point* p);
double y(Point* p);
但是我不确定如何包装这些以及如何在方法表中描述它们的调用。
我该怎么做?我想要一个简单的p1.x 来在Python 中获取我的Point 结构的x。
【问题讨论】:
-
double x(Point* p);是一个名为x的函数的函数声明,它接受一个指向Point的指针作为参数并返回一个double— 所以你应该能够包装 (以及写)它。y函数也是如此。 -
要使用
p1.x和p1.y表示法Python,给定一个类似Point的类,您可以为一个名为x的属性创建属性(带有关联的getter 和可能的setter)和另一个一个为y。不确定是否可以为 Cython 实现属性。
标签: python c struct wrapper cython