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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.