Search code examples
pythonc++boost

Possibility of using python method in C++ project


Python has a very useful optimization library called nevergrad, which I wanted to try using in a project written in C++. A simple test case on nevergrad:

import nevergrad as ng

# optimization function
def square(x): 
    return sum((x - 0.5) ** 2)

# solve method
def solve():
    optimizer = ng.optimizers.NGOpt(parametrization=2, budget=100)
    return optimizer.minimize(square).value 

The peculiarity of my task is that the minimization function that I want to use instead of square must call a method from the C++ project. Visually it looks like this: scheme of calls

If the call from C++ is done using Embedded Python, then the reverse call is done using boost.python. But the difficulty is that the C++ project has already been launched by the time it accesses python, and Class 2 has been initialized accordingly. However, in most boost.python usage examples, the C++ class initialization is done in python.

Is it possible to execute the sequence of calls shown in the picture C++ > Python > C++ and get the result in reverse order?


Solution

  • I did not try this out by myself, but reading the boost.Python docs, I guess the following approach should work (at least, in principle):

    • In your C++ code, instantiate your Class2 object as a wrapped object:

      object myClass2Object = (class_<Class2> ..., 
      
    • start the embedded Python interpreter and create the __main__ module

    • retrieve the main namespace and add your Class2 object to it:

      object main_module = import("__main__");
      object main_namespace = main_module.attr("__dict__");
      main_namespace["myClass2Object"]=myClass2Object;
      
    • import nevergrad into the interpreter as well as a Python solve function which expects a myClass2Object in the main namespace and uses it as for the target function

    • use exec or eval to call the solve function

      object result = eval("solve()", main_namespace); 
      

      and extract the results into native C++ variables from there.

    It would be nice if you can tell me how far this works, or if I am off-track with this answer.