"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); }
-- http://mail.python.org/mailman/listinfo/python-list