Cosmo
Cosmo

Reputation: 940

Python C API: How to get something from a module

In Python C API, I already know how to import a module via PyImport_ImportModule, as described in Python Documentation: Importing Modules. I also know that there is a lot of ways to create or allocate or initialize a module and some functions for operating a module, as described in Python Documentation: Module Objects.

But how can I get a function from a module (and call it), or, get a type/class from a module (and instantiate it), or, get an object from a module (and operate on it), or get anything from a module and do anything I want to do?

I think this can be a fool question but I really cannot find any tutorial or documentation. The only way I think that I can achieve this is use PyModule_GetDict to get the __dict__ property of the module and fetch what I want, as described in the latter documentation I mentioned. But the documentation also recommend that one should not use this function to operate the module.

So any "official way" or best practice for getting something from a module?

Upvotes: 2

Views: 2299

Answers (2)

Pavel Shishpor
Pavel Shishpor

Reputation: 997

To illustrate previous answer - link - with code:

  • a recommended way that uses a generic PyObject_GetAttrString function:
    const char *module_name = "...", *func = "...";

    PyObject *pyfunc = NULL;
    PyObject *pymodule = PyImport_ImportModule(module_name);
    if (!pymodule) {
        /* error handling here */
    }

    pyfunc = PyObject_GetAttrString(pymodule, func);
    Py_DECREF(pymodule);

    if (!pyfunc) {
        /* error handling here */
    }

    /* Call 'pyfunc' here or do whatever is needed */
    
    Py_DECREF(pyfunc);  /* decref once 'pyfunc' is not needed */
  • a working but not recommended way that directly manipulates a module's __dict__:
    const char *module_name = "...", *func = "...";

    PyObject *pyfunc = NULL;
    PyObject *pymodule = PyImport_ImportModule(module_name);
    if (!pymodule) {
        /* error handling here */
    }

    PyObject *pymoduledict = PyModule_GetDict(pymodule);
    PyObject *pyfunc = PyDict_GetItemString(pymoduledict, func);
    Py_DECREF(pymodule);

    if (!pyfunc) {
        /* error handling here */
    }

    /* Call 'pyfunc' here or do whatever is needed */
    
    Py_DECREF(pyfunc);  /* decref once 'pyfunc' is not needed */

Upvotes: 0

DavidW
DavidW

Reputation: 30935

According to the documentation for PyModule_GetDict:

It is recommended extensions use other PyModule_*() and PyObject_*() functions rather than directly manipulate a module’s __dict__.

The functions you need are generic object functions (PyObject_*) rather than module functions (PyModule_*), and I suspect this is where you were looking in the wrong place.

You want to use PyObject_GetAttr or PyObject_GetAttrString.

Upvotes: 4

Related Questions