Getting pointer to the C extension module

I have a C extension which defines a class with various methods. In one of the class method, I need to get the __file__ attribute of the module. I know that I can use PyModule_GetFilenameObject() but I can’t figure out how to get a pointer to the module object. All I have is the pointer to the self instance object.

I’ve tried using PyType_GetModule(Py_TYPE(self)) or PyType_GetModuleByDef(Py_TYPE(self), &ModuleDef) but both return NULL.

How can I get a pointer to the module object without using a global variable?

I don’t have exact experience with this post or the cpython api, but if you are defining a class method, shouldn’t self already be of the type, and calling Py_TYPE gives you type, i.e. the builtin root object?

Or are you defining an instance method and that was me misinterpreting your wording?

Didn’t you call PyModule_Create or similar in the extension’s initialisation function? That returned a pointer to the module object.

Yes, that was my understanding, which is why I used Py_TYPE(self) to get the type. However, that did not work.

I am. However, there are two things about that:

  1. As far as I know, the __file__ attribute is only set after PyInit_*() returns so you can’t get the attribute value within PyInit_*().
  2. Even if I could get the value, I would have to use a global variable to store the path, which I am trying to avoid. Otherwise, I could just use a global variable to store the pointer to the module.

If you use multi-phase initialization then it’s available in the exec_module phase (which is usually the main one).

To use PyType_GetModule they need to be heap types (i.e. created by PyType_FromModuleAndSpec or similar).

Isolating Extension Modules — Python 3.12.4 documentation is a useful link (the "module state access from regular methods"section)

Your documentation link was very helpful. Thank you.

However, it seems that when attempting to access the module from a regular method through the defining class, the type still needs to be heap-allocated. In essence, it seems that, no matter what, multi-phase initializsation has to be used.

Switching to multi-phase initialization allowed me to successfully get the module pointer and the module path.

I still have to use a global variable since there is no way that I can store what I want in the class instance (I either have a pointer to the module or a pointer to the class but not both).