7

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!

陽品駒
  • 107
  • 1
  • 8

2 Answers2

17

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
Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169
  • shouldn't you be calling `Py_Finalize();` at the end? – Trevor Hickey Oct 07 '17 at 07:55
  • @TrevorHickey, no. As noted in the [Boost.Python embedding documentation](http://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/tutorial/tutorial/embedding.html), `Py_Finalize()` should not be called to stop the interpreter. – Tanner Sansbury Oct 08 '17 at 19:59
  • How can I hide python scripts file contents? Is there anyway to encrypt python files but still decrypt and call python module in c++ runtime? – pat Jan 23 '18 at 09:23
  • 1
    @TannerSansbury, this is an excellent answer. Please suggest the whole info in your comment to be added to the official Boost.python docs. The official docs are missing this kind of information. Thanks, it really helped me a lot. – Kostiantyn Ponomarenko Jun 07 '20 at 07:59
  • Here is my example of `Boost.Python`: https://github.com/koponomarenko/embed_python_in_cxx – Kostiantyn Ponomarenko Jun 07 '20 at 08:48
-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()
kbang
  • 694
  • 9
  • 25
  • Sorry, I think maybe there is some misunderstanding.I have to work in C++ environment, so I want my C++ program directly use Dog.bark() from python.... not in python – 陽品駒 Jul 28 '16 at 02:18
  • Boost python doesn't help you there. boost is a c++ module. try this https://docs.python.org/3/extending/embedding.html – kbang Jul 28 '16 at 03:20