1

I would like to translate this Python code into C++ code using Pybind11 or directly the Python C API:

import ast

code = "print('Hello World!')"

code_ast = ast.parse(code, mode="exec") # "code" being a string containing code
# ... perform some modifications on "code_ast"
exec(compile(code_ast, filename="<ast>", mode="exec"))

Here is what I have currently using Pybind11:

#include <iostream>
#include "pybind11/embed.h"

namespace py = pybind11;

std::string code = "print('Hello World!')";

py::module ast = py::module::import("ast");
py::module builtins = py::module::import("builtins");

py::object code_ast = ast.attr("parse")(code, "<unknown>", "exec");
// ... perform some modifications on "code_ast"
py::object compiled_code = builtins.attr("compile")(code_ast, "<ast>", "exec");
builtins.attr("exec")(compiled_code);

Unfortunately, the last line of C++ code raises a runtime error: SystemError: frame does not exist.

I'm not sure I understand this error, I tried to pass the globals and locals to exec, it didn't solve the issue.

EDIT: When passing globals, it says: SystemError: <built-in function globals> returned NULL without setting an error

Any idea on how to achieve this properly?

Martin Renou
  • 424
  • 2
  • 10
  • You should post a [MCVE], the frame object is missing for some reason, that has nothing to do with your posted code. Your posted code is fine. – llllllllll Nov 02 '18 at 10:02
  • I have no frame object in my code, it's an internal object of the Python interpreter. The code posted is not fine, the interpreter was complaining because I wasn't passing the global namespace to the `exec` function. – Martin Renou Nov 05 '18 at 12:58
  • The only thing missing is the `include` of the needed header files, I'll edit the question. – Martin Renou Nov 05 '18 at 12:59

1 Answers1

1

I found my answer, I wasn't using the globals function from Pybind11, but the built-in one from Python (builtins.attr("globals")()).

This is the working version:

py::module ast = py::module::import("ast");
py::module builtins = py::module::import("builtins");

py::object code_ast = ast.attr("parse")(code, "<unknown>", "exec");
// ... perform some modifications on "code_ast"
py::object compiled_code = builtins.attr("compile")(code_ast, "<ast>", "exec");
builtins.attr("exec")(compiled_code, py::globals());
Martin Renou
  • 424
  • 2
  • 10