2

I wonder how can I define a static class variable from C++ for Python? The equivalent Python code would be like:

class foo:
    bar = int

I tried to use tp_getset field when defining the type, but it turns out it doesn't work and returns a getset_descriptor in Python, and it doesn't work when called on instances (AttributeError). Furthermore, Python doc says directly manipulating tp_dict with C API is unsafe. But it doesn't tell what to use instead. (see here)

I deliberately chose int in the example since I'm referencing some other class in it, if that matters.

4
  • 1
    Maybe here you can find the answer stackoverflow.com/questions/68645/… Commented Sep 9, 2017 at 17:01
  • @magicleon, Yes, that's what I want. But I meant from C++, in a library/module using C-API. Commented Sep 9, 2017 at 17:03
  • See issue #12719 on why accessing tp_dict is unsafe. Commented Sep 9, 2017 at 17:12
  • @myaut: setting class attributes during module initialisation is common practice however. Commented Sep 9, 2017 at 17:20

1 Answer 1

2

The tp_getset defines descriptors for a type; descriptors are bound to instances when accessed via the __getattribute__ hook, so are not suitable to define class attributes.

You can add attributes to a class by setting them on the PyTypeObject.tp_dict object for the type; do so in the module's initialization function (PyInit_<modulename>), for example, after finalising the type with PyType_Ready() (which makes sure the tp_dict object exists):

PyObject *d;
PyObject *bar;

d = PyFoo_Type.tp_dict;

bar = PyLong_FromLong(42);
if (bar == NULL || PyDict_SetItemString(d, "bar", bar) < 0)
    return NULL;
Py_DECREF(bar);

This is untested C code; I'm not familiar enough with C++ to confidently provide you with a C++ version instead.

If you want to see a real-life example, see the datetime module, where the datetime.min, datetime.max, etc. class attributes are set.

Sign up to request clarification or add additional context in comments.

3 Comments

Can I say that it's safe to modify tp_dict directly before I call PyModule_AddObject?
@YiFei: I believe so; there is an interaction with PyObject_SetAttrString() that's not supported, but modifying tp_dict in module initialisers is used in multiple places in the Python codebase.
@YiFei: for example, the sys module deletes entries from tp_dict objects for specific types (removing __new__ methods to prevent new instances).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.