6

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?

cubuspl42
  • 7,833
  • 4
  • 41
  • 65
xpadvent
  • 95
  • 5
  • thanks for your reply , actually my requests is import a python module into C++ and get all function names and filled them to a combobox that i can select which function to be executed , and i am not familiar with python CAPI , so i don't know how to extract function names , i found PyModule_GetDict function but don't know how to iterate over it – xpadvent Sep 25 '19 at 11:16

1 Answers1

6

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:

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.

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • thanks very much , i learn much from your code , that's helpful , really appreciated – xpadvent Sep 25 '19 at 11:19
  • 1
    Even aside from error checking, this is highly non-idiomatic. What happened to `PyImport_ImportModule` and `PyDict_Next`? – Davis Herring Sep 25 '19 at 13:07
  • 1
    @DavisHerring May be, I didn't dig hard enough. I made and checked a revised sample according to your hints. Thanks for the comment. – Scheff's Cat Sep 25 '19 at 13:29