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

2

8

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!

Liborio answered 27/7, 2016 at 18:1 Comment(0)
G
19

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
Genous answered 1/8, 2016 at 14:59 Comment(6)
shouldn't you be calling Py_Finalize(); at the end?Outwash
@TrevorHickey, no. As noted in the Boost.Python embedding documentation, Py_Finalize() should not be called to stop the interpreter.Genous
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?Freytag
@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.Decare
Here is my example of Boost.Python: github.com/koponomarenko/embed_python_in_cxxDecare
Instead of setenv("PYTHONPATH",...) you could consider something like auto sys_mod = boost::python::import("sys"); sys_mod.attr("path").attr("append")(".");Unrefined
H
-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()
Heintz answered 27/7, 2016 at 18:32 Comment(2)
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 pythonVariance
Boost python doesn't help you there. boost is a c++ module. try this docs.python.org/3/extending/embedding.htmlHeintz

© 2022 - 2024 — McMap. All rights reserved.