Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to list all function names of a Python module in C++?

I have a C++ program, I want to import a Python module and list all function names in this module. How can I do it?

I used the following code to get the dict from a module:

PyDictObject* pDict = (PyDictObject*)PyModule_GetDict(pModule);

But how to list the functions names?

like image 847
xpadvent Avatar asked Sep 24 '19 07:09

xpadvent


Video Answer


1 Answers

Out of curiosity, I tried to puzzle this out.

First, a minimal Python module testModule.py:

def main():
  print("in test.main()")

def funcTest():
  print("in test.funcTest()")

Second, a minimal C++ sample testPyModule.cc to load and evaluate the testModule:

// standard C++ header:
#include <iostream>

// Python header:
#include <Python.h>

int main()
{
  // initialize Python interpreter
  Py_Initialize();
  // run script
  const char *const script =
    "# tweak sys path to make Python module of cwd locatable\n"
    "import sys\n"
    "sys.path.insert(0, \".\")\n";
  PyRun_SimpleString(script);
  // get module testModule
  PyObject *pModuleTest = PyImport_ImportModule("testModule"); // new reference
  // evaluate dictionary of testModule
  PyObject *const pDict = PyModule_GetDict(pModuleTest); // borrowed
  // find functions
  std::cout << "Functions of testModule:\n";
  PyObject *pKey = nullptr, *pValue = nullptr;
  for (Py_ssize_t i = 0; PyDict_Next(pDict, &i, &pKey, &pValue);) {
    const char *key = PyUnicode_AsUTF8(pKey);
    if (PyFunction_Check(pValue)) {
      std::cout << "function '" << key << "'\n";
    }
  }
  Py_DECREF(pModuleTest);
  // finalize Python interpreter
  Py_Finalize();
}

Output:

Functions of testModule:
function 'main'
function 'funcTest'

Notes:

To puzzle this out, I had to dig through the doc. pages. These are the links for the pages I used:

  • Importing Modules: PyImport_ImportModule
  • Module Objects: PyModule_GetDict()
  • Function Objects: PyFunction_Check()
  • Dictionary Objects: PyDict_Next()
  • Unicode Objects and Codecs: PyUnicode_AsUTF8().

It's obvious that I didn't check any pointer for NULL (or nullptr) to keep the sample short and compact. Production code should do this, of course.

like image 200
Scheff's Cat Avatar answered Sep 26 '22 16:09

Scheff's Cat