C-API, tp_dictoffset vs tp_members
Ulrich Eckhardt
doomster at knuut.de
Sun Jul 26 05:45:37 EDT 2009
"Martin v. Löwis" wrote:
>> I have a predefined set of members, some of which are optional.
>
> Having optional fields is also a good reason.
What is the use of T_OBJECT_EX vs T_OBJECT in PyMemberDef then? I would
have though that the former describes an optional field, because the
behaviour of accessing it when it is NULL is the same as accessing a
nonexistent field. However, I see that it still appears in the dir()
output even if it is NULL, so it seems I'm misunderstanding this.
>> The problem
>> I had with an embedded dictionary was that I can't see its elements using
>> "dir()".
>
> How so? That should work fine.
>>> import example
>>> x = example.Example()
>>> dir(x)
['__class__', '__delattr__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__str__']
>>> x.example_attribute
'example value'
The 'example_attribute' can be accessed, but it is not visible in the
dir() output. The code for this is below.
>> Now I just converted to using tp_members, and it still seems to
>> work correctly for the cases I tested.
>
> So how do you do optional fields now? In particular, how would you do
> optional integers?
See above, I would expect T_OBJECT_EX to do that.
Thanks!
Uli
/* example.c
gcc -Wall example.c -shared -I /usr/include/python2.5 -o example.so
*/
#include <Python.h>
#include <structmember.h>
typedef struct {
PyObject_HEAD
PyObject* dict;
} Example;
static void
Example_dealloc(PyObject* self)
{
Example* ex = (Example*)self;
Py_XDECREF(ex->dict);
self->ob_type->tp_free(self);
}
static PyObject *
Example_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
Example* self;
PyObject* attr;
self = (Example*)type->tp_alloc(type, 0);
if(self==NULL)
return NULL;
self->dict = PyDict_New();
if(self->dict==NULL) {
Py_DECREF(self);
return NULL;
}
attr = PyString_FromString("example value");
if(PyObject_SetAttrString((PyObject*)self, "example_attribute", attr)<0) {
Py_DECREF(self);
return NULL;
}
return (PyObject*)self;
}
static PyTypeObject ExampleType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"example.Example", /*tp_name*/
sizeof(Example), /*tp_basicsize*/
0, /*tp_itemsize*/
Example_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(Example, dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
Example_new, /* tp_new */
};
void
initexample(void)
{
PyObject* m;
if (PyType_Ready(&ExampleType) < 0)
return;
m = Py_InitModule3("example", 0,
"Example module that creates an extension type.");
if (m == NULL)
return;
Py_INCREF(&ExampleType);
PyModule_AddObject(m, "Example", (PyObject*)&ExampleType);
}
More information about the Python-list
mailing list