将底层结构公开为Python扩展中自定义类型的成员

2024-04-26 09:30:14 发布

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

这个问题是前一个问题的一个小小的旋转:Accessing the underlying struct of a PyObject

除了在我的版本中,我想知道如何将Point结构的字段公开为新类型的成员。在

我找遍了所有我能想到的地方,读了很多Python扩展的例子,也读了很多教程、文档等等,但还没有找到一个干净的方法来实现这一点。在

下面是我想做的一个例子。我有一些内部结构,我想通过Python扩展公开,但是我不想在代码中重新定义这个结构。问题的主要区域似乎是PyMemeberDef定义…从PointObject结构的上下文来看,Point结构内部x或y的偏移量是多少?在

非常感谢任何帮助,谢谢。在

#include <Python.h>
#include <structmember.h>

// This is actually defined elsewhere in someone else's code.
struct Point {
 int x;
 int y;
};

struct PointObject {
 PyObject_HEAD
 struct Point* my_point;
 int z;
};

static PyMemberDef point_members[] = {
    {"z", T_INT, offsetof(struct PointObject, z), 0, "z field"},
    {"x", T_INT, offsetof(???), 0, "point x field"},
    {"y", T_INT, offsetof(???), 0, "point y field"},
    {NULL}
};

static PyTypeObject PointType = {
    PyObject_HEAD_INIT(NULL)
    .tp_name = "Point",
    .tp_basicsize = sizeof(PointObject),
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_doc = "Point objects",
    .tp_members = point_members,
    .tp_init = (initproc)point_init,
};

...

PyMODINIT_FUNC
initMainModule(void)
{
    PyObject *m = Py_InitModule(MODULE, NULL);

    // Register PointType
    PointType.tp_new = PyType_GenericNew;
    if (PyType_Ready(&PointType) < 0)
            return;
    Py_INCREF(&PointType);
    PyModule_AddObject(m, "Point", (PyObject *)&PointType);

    ...
}

Tags: pyfield结构nullstructintpointpyobject
1条回答
网友
1楼 · 发布于 2024-04-26 09:30:14

我强烈建议您阅读http://docs.python.org/release/2.6/_sources/extending/newtypes.txt,特别是“对数据属性提供更精细的控制”一节。在

在阅读本文之后,似乎可以通过为Point结构中的特定成员定义setter/getter集合来做到这一点。对于这么简单的事情来说,这确实有点过分了,但它似乎工作得很好。在

下面是一个关于如何对点的“x”字段执行此操作的示例,该示例基于在前面的示例中添加以下代码:

static PyGetSetDef point_getset[] = {
  {"x", (getter)point_get_x, (setter)point_set_x, "", NULL},
  {NULL}
};

static PyObject*
point_get_x(struct PointObject *self, void *closure)
{
     return Py_BuildValue("i", self->my_point->x);
}

static int
point_set_x(struct PointObject *self, PyObject *value, void *closure)
{
  PyErr_SetString(PyExc_TypeError, "Attribute is read-only!");
  return -1;
}

最后,在前面定义的PyTypeObject结构中,将point-getset结构添加到tp-getset字段中。应该注意的是,对于简单的情况,您仍然可以在传统的PyMemberDef结构中定义成员。在

相关问题 更多 >