0

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.

gny-001f2
  • 29
  • 5
  • Does this answer your question? [Exporting C global variables to a python extension](https://stackoverflow.com/questions/17793353/exporting-c-global-variables-to-a-python-extension) – mkrieger1 Jul 27 '20 at 10:35
  • The suggested question seems to deal with constants, which I am already familiar with. However module_state can change during program runtime and I want to make each change available. – gny-001f2 Jul 27 '20 at 10:42
  • This is relevant (although pure Python) https://stackoverflow.com/questions/880530/can-modules-have-properties-the-same-way-that-objects-can. – DavidW Jul 27 '20 at 11:39
  • @DavidW yes I could use properties to work around it, but that adds two layers - an internal C ```_module``` and a user facing python ```module```. – gny-001f2 Jul 27 '20 at 11:45
  • Or a `__getattr__` function (if you're using a suitable version of Python?). I dunno if there's a better way of doing it – DavidW Jul 27 '20 at 13:02
  • I believe that has the same problem as using properties. Since __getattr__ has to be declared in your python code while my module is written entirely in C. – gny-001f2 Jul 27 '20 at 14:36
  • I haven't tried it, but I don't see why you couldn't define a C function called `__getattr__`. I'll give it a go... – DavidW Jul 27 '20 at 16:15

1 Answers1

0

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.

DavidW
  • 29,336
  • 6
  • 55
  • 86