Adding and attribute to an instance

J

J

Hi,


I am trying to add new data attributes to my extension classes from
within a script. I am under the impression that python allows
that implicity


This is the definition of my class

PyTypeObject CmdPlace::pyType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Place", /*tp_name*/
sizeof(CmdPlace::pyStruct), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*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*/
PyObject_GenericGetAttr, /*tp_getattro*/
PyObject_GenericSetAttr, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"CmdPlace", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
CmdPlace::sPyMethods, /* tp_methods */
CmdPlace::sPyMembers, /* tp_members */
CmdPlace::sPyGetSeters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};

I call

PyType_Ready(&PyType);
Py_INCREF(&PyType);

to initialize the type, and

PyObject_INIT((PyObject*)&mPyObject, &CmdPlace::pyType);

to initialize an object. Objects of this type are only ever
instantiated from C++. When I evaluate a sript I just add the object as
"MyObject" to the dicitonary passed to Py_Eval... All the
members and methods work fine, but when I do

MyObject.aNewAttribue = 12

I get at an error saying

object has no attribute "aNewAttribue".

I have looked at some of the source code in PyObject_GenericGetAttr and
it turns out that the object has no dictionary. It seens that the
address of the dictionary is computed somehow via tp_dictoffset in the
type object.

Basically my question is, how can I make this work.


Cheers
Jochen
 
J

Jeremy Moles

Hmmm--I would also be interested in knowing the answer to this. I get
the exact same behavior as the OP (probably because it's the intended
behavior?)
 
G

Gregory Bond

J said:
I have looked at some of the source code in PyObject_GenericGetAttr and
it turns out that the object has no dictionary. It seens that the
address of the dictionary is computed somehow via tp_dictoffset in the
type object.

I asked this a few months ago......

Basically, you need a PyObject * in your object record:

struct PyStruct {
PY_OBJECT_HEAD
// ...
PyObject *dict;
// ....
}


then add the offset to the tp_dictoffset member in the type struct:

PyTypeObject PyType {
// ....
offsetof(PyStruct, dict), /* tp_dictoffset */
// ...

Make sure you init this member to 0 (tp_init), and make sure you
PyXDECREF() it when the object is deleted (tp_dealloc).

Optionally: add a __dict__ entry to the PyMemberDefs so that
obj.__dict__ works (tho this is not necessary):

{"__dict__", T_OBJECT, offsetof(PyStruct, dict), READONLY },

The ROOOOOOLY cool bit: You don't need to add the dictionary with
PyDict_New() etc, because the python runtime will create this dict the
first time a new attrribute is added. So the cost of this feature for
object instances that don't have extra attributes is just 4 unused bytes
in the instance record! This is just sooooooo cool.


Greg.
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

Gregory said:
Make sure you init this member to 0 (tp_init), and make sure you
PyXDECREF() it when the object is deleted (tp_dealloc).

As this may cause your objects to appear in cycles, you may also
have to add support for cyclic GC (unless you already did this
before, and unless you can somehow rule out that your objects
are in cycles).

Regards,
Martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,787
Messages
2,569,631
Members
45,338
Latest member
41Pearline46

Latest Threads

Top