Search code examples
pythonc++boost-python

How to import a function from python file by Boost.Python


I am totally new to boost.python. I reviewed a lot of recommending of using boost.python to apply with python, however still not easy to understand and find a solution for me.

What I want is to import a function or class that directly from a python "SourceFile"

Example File: Main.cpp MyPythonClass.py

Let's says if there is a "Dog" class in "MyPythonClass.py" with "bark()" function, how do I get callback and send argument in cpp?

I have no idea what I should do! Please help me!


Solution

  • When one needs to call Python from C++, and C++ owns the main function, then one must embed the Python interrupter within the C++ program. The Boost.Python API is not a complete wrapper around the Python/C API, so one may find the need to directly invoke parts of the Python/C API. Nevertheless, Boost.Python's API can make interoperability easier. Consider reading the official Boost.Python embedding tutorial for more information.


    Here is a basic skeleton for a C++ program that embeds Python:

    int main()
    {
      // Initialize Python.
      Py_Initialize();
    
      namespace python = boost::python;
      try
      {
        ... Boost.Python calls ...
      }
      catch (const python::error_already_set&)
      {
        PyErr_Print();
        return 1;
      }
    
      // Do not call Py_Finalize() with Boost.Python.
    }
    

    When embedding Python, it may be necessary to augment the module search path via PYTHONPATH so that modules can be imported from custom locations.

    // Allow Python to load modules from the current directory.
    setenv("PYTHONPATH", ".", 1);
    // Initialize Python.
    Py_Initialize();
    

    Often times, the Boost.Python API provides a way to write C++ code in a Python-ish manner. The following example demonstrates embedding a Python interpreter in C++, and having C++ import a MyPythonClass Python module from disk, instantiate an instance of MyPythonClass.Dog, and then invoking bark() on the Dog instance:

    #include <boost/python.hpp>
    #include <cstdlib> // setenv
    
    int main()
    {
      // Allow Python to load modules from the current directory.
      setenv("PYTHONPATH", ".", 1);
      // Initialize Python.
      Py_Initialize();
    
      namespace python = boost::python;
      try
      {
        // >>> import MyPythonClass
        python::object my_python_class_module = python::import("MyPythonClass");
    
        // >>> dog = MyPythonClass.Dog()
        python::object dog = my_python_class_module.attr("Dog")();
    
        // >>> dog.bark("woof");
        dog.attr("bark")("woof");
      }
      catch (const python::error_already_set&)
      {
        PyErr_Print();
        return 1;
      }
    
      // Do not call Py_Finalize() with Boost.Python.
    }
    

    Given a MyPythonClass module that contains:

    class Dog():
        def bark(self, message):
            print "The dog barks: {}".format(message)
    

    The above program outputs:

    The dog barks: woof