mirror of https://gitlab.com/cppit/jucipp
15 changed files with 218 additions and 25 deletions
@ -0,0 +1,55 @@
|
||||
#pragma once |
||||
|
||||
#include "config.h" |
||||
#include "menu.h" |
||||
#include "python_interpreter.h" |
||||
#include "python_module.h" |
||||
#include <pybind11/embed.h> |
||||
#include <pybind11/functional.h> |
||||
|
||||
class __attribute__((visibility("default"))) |
||||
Plugins { |
||||
public: |
||||
Plugins() : jucipp_module("Jucipp", Module::init_jucipp_module) { |
||||
auto &config = Config::get(); |
||||
config.load(); |
||||
auto sys = py::module::import("sys"); |
||||
sys.attr("path").cast<py::list>().append(config.plugins.path); |
||||
// sys.attr("excepthook") = py::cpp_function([](py::object type, py::object value, py::object traceback) {
|
||||
// Terminal::get().print("const std::string &message\n");
|
||||
// });
|
||||
} |
||||
void load() { |
||||
boost::filesystem::directory_iterator end_it; |
||||
for(boost::filesystem::directory_iterator it(Config::get().plugins.path); it != end_it; it++) { |
||||
auto module_name = it->path().stem().string(); |
||||
if(module_name.empty()) |
||||
continue; |
||||
const auto is_directory = boost::filesystem::is_directory(it->path()); |
||||
const auto has_py_extension = it->path().extension() == ".py"; |
||||
const auto is_pycache = module_name == "__pycache__"; |
||||
if((is_directory && !is_pycache) || has_py_extension) { |
||||
try { |
||||
auto module = interpreter.add_module(module_name); |
||||
if (module) { |
||||
Terminal::get().print("Reloading plugin ´" + module_name + "´\n"); |
||||
interpreter.reload_module(module); |
||||
} else { |
||||
Terminal::get().print("Loading plugin ´" + module_name + "´\n"); |
||||
py::module::import(module_name.c_str());
|
||||
} |
||||
|
||||
} |
||||
catch(py::error_already_set &error) { |
||||
Terminal::get().print("Error loading plugin `" + module_name + "`:\n" + error.what() + "\n"); |
||||
} |
||||
} |
||||
if(interpreter.error()) |
||||
std::cerr << py::error_already_set().what() << std::endl; |
||||
} |
||||
} |
||||
|
||||
private: |
||||
py::detail::embedded_module jucipp_module; |
||||
Python::Interpreter interpreter; |
||||
}; |
||||
@ -0,0 +1,3 @@
|
||||
#pragma once |
||||
#include <pybind11/pybind11.h> |
||||
namespace py = pybind11; |
||||
@ -0,0 +1,31 @@
|
||||
#include "python_interpreter.h" |
||||
|
||||
pybind11::module Python::Interpreter::add_module(const std::string &module_name) { |
||||
return pybind11::reinterpret_borrow<pybind11::module>(PyImport_AddModule(module_name.c_str())); |
||||
} |
||||
|
||||
pybind11::object Python::Interpreter::error() { |
||||
return pybind11::reinterpret_borrow<pybind11::object>(PyErr_Occurred()); |
||||
} |
||||
|
||||
pybind11::module Python::Interpreter::reload_module(pybind11::module &module) { |
||||
auto reload = pybind11::reinterpret_steal<pybind11::module>(PyImport_ReloadModule(module.ptr())); |
||||
if(!reload) { |
||||
throw pybind11::error_already_set(); |
||||
} |
||||
return reload; |
||||
} |
||||
|
||||
#include <pybind11/embed.h> |
||||
#include <iostream> |
||||
|
||||
Python::Interpreter::~Interpreter() { |
||||
if (error()){ |
||||
std::cout << py::error_already_set().what() << std::endl; |
||||
} |
||||
py::finalize_interpreter(); |
||||
} |
||||
|
||||
Python::Interpreter::Interpreter() { |
||||
py::initialize_interpreter(); |
||||
} |
||||
@ -0,0 +1,13 @@
|
||||
#pragma once |
||||
#include "python_bind.h" |
||||
|
||||
namespace Python { |
||||
class Interpreter { |
||||
public: |
||||
pybind11::module static add_module(const std::string &module_name); |
||||
pybind11::module static reload_module(pybind11::module &module); |
||||
pybind11::object static error(); |
||||
~Interpreter(); |
||||
Interpreter(); |
||||
}; |
||||
}; // namespace Python
|
||||
@ -0,0 +1,62 @@
|
||||
#pragma once |
||||
#include "python_bind.h" |
||||
#include "terminal.h" |
||||
#include <boost/filesystem.hpp> |
||||
#include <pybind11/stl.h> |
||||
|
||||
namespace pybind11 { |
||||
namespace detail { |
||||
template <> |
||||
struct type_caster<boost::filesystem::path> { |
||||
public: |
||||
PYBIND11_TYPE_CASTER(boost::filesystem::path, _("str")); |
||||
bool load(handle src, bool) { |
||||
const std::string path = pybind11::str(src); |
||||
value = path; |
||||
return !PyErr_Occurred(); |
||||
} |
||||
|
||||
static handle cast(boost::filesystem::path src, return_value_policy, handle) { |
||||
return pybind11::str(src.string()); |
||||
} |
||||
}; |
||||
} |
||||
} |
||||
|
||||
class Module { |
||||
static void init_terminal_module(pybind11::module &api) { |
||||
py::class_<Terminal, std::unique_ptr<Terminal, py::nodelete>>(api, "Terminal") |
||||
.def(py::init([]() { return &(Terminal::get()); })) |
||||
.def("process", (int (Terminal::*)(const std::string &, const boost::filesystem::path &, bool)) & Terminal::process, |
||||
py::arg("command"), |
||||
py::arg("path") = "", |
||||
py::arg("use_pipes") = false) |
||||
.def("async_process", (void (Terminal::*)(const std::string &, const boost::filesystem::path &, const std::function<void(int)> &, bool)) & Terminal::async_process, |
||||
py::arg("command"), |
||||
py::arg("path") = "", |
||||
py::arg("callback") = nullptr, |
||||
py::arg("quiet") = false) |
||||
.def("kill_last_async_process", &Terminal::kill_last_async_process, |
||||
py::arg("force") = false) |
||||
.def("kill_async_processes", &Terminal::kill_async_processes, |
||||
py::arg("force") = false) |
||||
.def("print", &Terminal::print, |
||||
py::arg("message"), |
||||
py::arg("bold") = false) |
||||
.def("async_print", (void (Terminal::*)(const std::string &, bool)) & Terminal::async_print, |
||||
py::arg("message"), |
||||
py::arg("bold") = false) |
||||
.def("async_print", (void (Terminal::*)(size_t, const std::string &)) & Terminal::async_print, |
||||
py::arg("line_nr"), |
||||
py::arg("message")) |
||||
.def("configure", &Terminal::configure) |
||||
.def("clear", &Terminal::clear); |
||||
}; |
||||
|
||||
public: |
||||
static auto init_jucipp_module() { |
||||
auto api = py::module("Jucipp", "API"); |
||||
Module::init_terminal_module(api); |
||||
return api.ptr(); |
||||
}; |
||||
}; |
||||
Loading…
Reference in new issue