HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
plugin_python_shell.cpp
Go to the documentation of this file.
2 
3 #include "hal_core/defines.h"
6 
7 #include <Python.h>
8 #include <cstring>
9 #include <fstream>
10 
11 namespace hal
12 {
13  extern std::unique_ptr<BasePluginInterface> create_plugin_instance()
14  {
15  return std::make_unique<PluginPythonShell>();
16  }
17 
19  {
20  ProgramOptions description;
21 
22  description.add("--python", "start python shell");
23  description.add("--python-script", "run a python script in HAL. to pass args use --python-args", {ProgramOptions::A_REQUIRED_PARAMETER});
24  description.add(
25  {"--python-args", "--py-args"}, "supply arguments to the python invocation. to provide multiple arguments use '\"' and separate them with spaces", {ProgramOptions::A_REQUIRED_PARAMETER});
26 
27  return description;
28  }
29 
30  std::string PluginPythonShell::get_name() const
31  {
32  return std::string("HAL Python");
33  }
34 
35  std::string PluginPythonShell::get_version() const
36  {
37  return std::string("0.1");
38  }
39 
41  {
42  int argc = 0;
43  wchar_t** argv = nullptr;
44 
45  // python needs arguments as argc/argv, so we convert them here
46  if (args.is_option_set("--python-args"))
47  {
48  std::vector<std::string> py_args;
49  auto py_arg_str = args.get_parameter("--python-args");
50 
51  if (py_arg_str.find(' ') != std::string::npos)
52  {
53  py_args = utils::split(py_arg_str, ' ');
54  }
55  else
56  {
57  py_args.push_back(py_arg_str);
58  }
59 
60  /* copy command line interface options */
61  argc = py_args.size();
62  argv = new wchar_t*[argc];
63 
64  /* pass all parameters to python shell */
65  for (int i = 0; i < argc; i++)
66  {
67  argv[i] = Py_DecodeLocale(py_args[i].c_str(), nullptr);
68  if (argv[i] == nullptr)
69  {
70  log_error(get_name(), "unable to convert argument '{}' for Python", py_args[i]);
71  return false;
72  }
73  }
74  }
75 
76  // initiliaze python shell
77  Py_Initialize();
78 
79  PySys_SetArgv(argc, argv);
80 
81  PyRun_SimpleString("import sys");
82  PyRun_SimpleString(std::string("sys.path.append(\"" + utils::get_library_directory().string() + "\")").c_str());
83  PyRun_SimpleString("from hal_py import *");
84  PyRun_SimpleString("import hal_py");
85 
86  // changing cwd not required
87  // PyRun_SimpleString("import os");
88  // PyRun_SimpleString(("os.chdir(\""+ std::filesystem::current_path().string() +"\")").c_str());
89 
90  if (args.is_option_set("--python-script"))
91  {
92  auto file_path = args.get_parameter("--python-script");
93  if (!std::filesystem::exists(file_path) || std::filesystem::is_directory(file_path) || !utils::ends_with(file_path, std::string(".py")))
94  {
95  log_error(get_name(), "'{}' is not a python script file", file_path);
96  return false;
97  }
98 
99  std::ifstream stream(file_path);
100  std::string str;
101  stream.seekg(0, std::ios::end);
102  str.reserve(stream.tellg());
103  stream.seekg(0, std::ios::beg);
104  str.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
105 
106  PyRun_SimpleString(str.c_str());
107  }
108  else
109  {
110  Py_Main(argc, argv);
111  }
112 
113  Py_Finalize();
114 
115  /* cleanup of copied command line interface options */
116  for (int i = 0; i < argc; ++i)
117  {
118  PyMem_RawFree(argv[i]);
119  }
120  delete[] argv;
121  return 0;
122  }
123 } // namespace hal
ProgramOptions get_cli_options() const override
std::string get_name() const override
bool exec(ProgramArguments &args) override
std::string get_version() const override
std::string get_parameter(const std::string &flag) const
bool is_option_set(const std::string &flag) const
bool add(const std::string &flag, const std::string &description, const std::initializer_list< std::string > &parameters={})
static const std::string A_REQUIRED_PARAMETER
constant to specify that a parameter is required and does not have a default value.
#define log_error(channel,...)
Definition: log.h:78
std::filesystem::path get_library_directory()
Definition: utils.cpp:129
bool ends_with(const T &s, const T &end)
Definition: utils.h:149
std::vector< T > split(const T &s, const char delim, bool obey_brackets=false)
Definition: utils.h:239
Definition: defines.h:45
std::unique_ptr< BasePluginInterface > create_plugin_instance()