0

The Python C API has the function PyImport_ImportModule that returns a new reference to the module. As a new reference, it must be disposed of at some point.

Most objects created during module initialization are added to the module with PyModule_AddObject, which steals the reference (when successful). However, I'd like to store the module reference from PyImport_ImportModule in a global variable for quick access. Something like this:

#include <Python.h>

static PyObject *imported_module;

static PyModuleDef myextension_module = {
    PyModuleDef_HEAD_INIT,
    .m_name = "myextension",
    .m_doc = "My extension module that uses an imported module",
    .m_size = -1,
};

PyMODINIT_FUNC PyInit_myextension(void)
{
    // ...

    PyObject *m;
    m = PyModule_Create(&md4c_module);
    if (m == NULL) {
        return NULL;
    }

    // ...

    imported_module = PyImport_ImportModule("extratypes");
    if (imported_module == NULL) {
        Py_DECREF(m);
        return NULL;
    }
    // Presumably, imported_module needs to be Py_DECREF'd at some point

    return m;
}

Is creating traverse/clear/free functions the proper way to clean up (similar to how it is described here, but using these instead), or is it better to just go ahead and PyModule_AddObject the imported module to the current module (in which case, is it still safe to use the reference that was stolen)? Or are both/neither the correct way to handle it?

Dominick Pastore
  • 4,177
  • 2
  • 17
  • 29
  • It's not quite clear what you mean, or what kind of cleanup you think you need. If you own a reference to the module, you just need to Py_DECREF that reference whenever you're about to get rid of the reference, just like any other reference to any other object. – user2357112 Apr 27 '20 at 05:38
  • tp_traverse/tp_clear/tp_dealloc functions are things you write when you're writing your own type, which you don't seem to be doing here. – user2357112 Apr 27 '20 at 05:39
  • @user2357112supportsMonica Right, but the hope is to keep a reference to the module for the duration of the extension module's life, by storing it in a global variable. (It has objects that the extension's functions will need to instantiate as return values.) But if I do that, at some point, I assume the reference must still be Py_DECREF'd, during some sort of cleanup action for the extension module. How that would work is what I'm unclear on. – Dominick Pastore Apr 27 '20 at 05:53
  • @user2357112supportsMonica Regarding tp_traverse/tp_clear/tp_dealloc: that thought came from [here](https://docs.python.org/3/c-api/module.html#c.PyModuleDef.m_traverse) (though they aren't named exactly the same). But I wasn't sure if this sort of thing was their intended use. – Dominick Pastore Apr 27 '20 at 05:58
  • I don't think Python actually has support for cleaning up extension modules. Your global variable will just hang around until the whole process dies, with no point at which you're actually supposed to decref the reference you're asking about. – user2357112 Apr 27 '20 at 06:08
  • @user2357112supportsMonica I see. That said, looking more at the API docs for imports, I suspect there are better ways to do this. I think I have some more reading to do. – Dominick Pastore Apr 27 '20 at 06:35

0 Answers0