How to import a function from python file by Boost

2019-04-09 19:59发布

问题:

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!

回答1:

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


回答2:

Boost python is used to call cplusplus functions from a python source. Pretty much like the Perl xs module.

If you have a function say bark() in main.cpp, you can use boost python to convert this main.cpp into a python callable module.

Then from python script(assuming link output file is main.so):

import main
main.bark()