【问题标题】:Expose an underlying struct as a member of a custom type within a Python extension在 Python 扩展中将底层结构公开为自定义类型的成员
【发布时间】:2011-10-25 23:38:31
【问题描述】:

这个问题是对上一个问题的轻微改动:Accessing the underlying struct of a PyObject

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

我到处寻找我能想到的地方,阅读了许多 Python 扩展示例,阅读了许多教程、文档等,但一直无法找到一种干净的方法来做到这一点。

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

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

#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);

    ...
}

【问题讨论】:

    标签: python c struct


    【解决方案1】:

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

    阅读本文后,似乎可以通过为 Point 结构中的特定成员定义一组 setter/getter 来做到这一点。像这样简单的事情似乎有点矫枉过正,但它似乎工作得很好。

    下面是一个关于如何对 Point 的“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;
    }
    

    最后,将 point_getset 结构添加到之前定义的 PyTypeObject 结构中的 tp_getset 字段。需要注意的是,对于简单的情况,您仍然可以在传统的 PyMemberDef 结构中定义成员。

    【讨论】:

      猜你喜欢
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多