Ad

How Do I Expose A C Variable To Python As A Variable?

- 1 answer

Suppose in a custom python module written in C, I declare the variable:

static int module_state;

The functions in my module set the state of this variable. If I want to know the value of module_state, I can declare a getter function like this:

PyObject * get_module_state(PyObject *self)
{
   return PyLong_FromLong(module_state);
}

On python (3) I could simply do:

import module
...
state = module.get_module_state()

However, I want to expose it as a variable:

import module
state = module.module_state

I looked at PyMemberDef and PyGetterSetterDef in the API but I am confused about how to use them to expose the variable. Generally speaking I don't want the python user to be able to modify the variable.

The purpose of this variable is very similar to errno, and I want to make it available as transparently as possible.

Ad

Answer

The two main suggestions in Can modules have properties the same way that objects can? can actually be translated pretty "easily" to C.

  1. A module-level __getattr__. This needs Python 3.7. You just define a function called __getattr__ using the normal C API mechanism, PyMethodDef.

    This function would do something like:

    if (PyUnicode_CompareWithASCIIString(arg, "name") == 0) {
        return PyLong_FromLong(your_variable);
    }
    else {
        PyErr_SetObject(PyExc_AttributeError, arg);
        return NULL;
    }
    

    Note that the limitation (which I think you're OK with) is that variable would be read-only since there isn't an equivalent module __setattr__.

  2. Use a class instead of the module. This can be a class defined in C, with PyMemberDef exposing the C variable as a property.

    This probably works best for a submodule (e.g. main_mod.submod). That way the main module could add your class instance to sys.modules something like:

    PyObject *sys_modules = PySys_GetObject("modules");
    PyDict_SetItemString(sys_modules, "main_mod.submod", instance);
    

    I think this way's probably much more trouble than the first option, but it would work in C.

Ad
source: stackoverflow.com
Ad