From 0ce58986d4fed13a128a5e251c23d339a0d2642a Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Wed, 26 Dec 2018 23:25:27 +0100 Subject: [PATCH] initial support for pybind11: Python bindings of S4U are underway --- .travis.yml | 1 + CMakeLists.txt | 25 +++++++- src/bindings/python/simgrid_python.cpp | 89 ++++++++++++++++++++++++++ tools/docker/Dockerfile.build-deps | 2 +- 4 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 src/bindings/python/simgrid_python.cpp diff --git a/.travis.yml b/.travis.yml index 2c17bb8f7b..3c814f5892 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ addons: - libdw-dev - libevent-dev - libunwind8-dev + - pybind11-dev homebrew: packages: - python diff --git a/CMakeLists.txt b/CMakeLists.txt index 786e63d830..02a0859d10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,7 +139,7 @@ set(PythonInterp_FIND_VERSION_COUNT 1) set(PythonInterp_FIND_VERSION_MAJOR 3) include(FindPythonInterp) if(NOT PYTHONINTERP_FOUND) - message(FATAL_ERROR "Please install Python (version 3 or higher).") + message(FATAL_ERROR "Please install Python (version 3 or higher) to compile SimGrid.") endif() SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) @@ -847,6 +847,23 @@ if(enable_java) include(${CMAKE_HOME_DIRECTORY}/tools/cmake/Java.cmake) endif() +# Python binding, generated with pybind11 +set(PYBIND11_CPP_STANDARD -std=c++11) +find_package(pybind11) +option(enable_python "Whether the Python bindings are activated." ${pybind11_FOUND}) # ON by default if dependencies are met + +if(enable_python) + if(pybind11_FOUND) + pybind11_add_module(simgrid_python src/bindings/python/simgrid_python.cpp) + set_source_files_properties(src/bindings/python/simgrid_python.cpp PROPERTIES COMPILE_FLAGS -Wno-attributes) + set_source_files_properties(src/bindings/python/simgrid_python.cpp PROPERTIES COMPILE_FLAGS -std=gnu++14) + target_link_libraries(simgrid_python PUBLIC simgrid) + set_target_properties(simgrid_python PROPERTIES LIBRARY_OUTPUT_NAME simgrid) + else() + message(FATAL_ERROR "Please install pybind11-dev to build the Python bindings (or disable that option).") + endif() +endif() + ### Make tests if(enable_memcheck_xml) set(enable_memcheck true) @@ -938,6 +955,12 @@ if (${Java_FOUND}) else() message(" Compile Java ................: NO") endif() +if(pybind11_FOUND) + message(" Compile Python bindings .....: ${enable_python}") + message(" module ....................: ${PYTHON_MODULE_PREFIX}simgrid${PYTHON_MODULE_EXTENSION}") +else() + message(" Compile Python bindings .....: NO (disabled, or pybind11 not found)") +endif() message(" Compile Lua .................: ${SIMGRID_HAVE_LUA}") message(" Compile Smpi ................: ${HAVE_SMPI}") message(" Smpi fortran ..............: ${SMPI_FORTRAN}") diff --git a/src/bindings/python/simgrid_python.cpp b/src/bindings/python/simgrid_python.cpp new file mode 100644 index 0000000000..79791a4cb2 --- /dev/null +++ b/src/bindings/python/simgrid_python.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +namespace py = pybind11; +using simgrid::s4u::Actor; +using simgrid::s4u::ActorPtr; +using simgrid::s4u::Engine; +using simgrid::s4u::Host; + +XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_python, "S4U python"); + +PYBIND11_DECLARE_HOLDER_TYPE(T, boost::intrusive_ptr); + +namespace { + +static std::string get_simgrid_version() +{ + int major, minor, patch; + sg_version_get(&major, &minor, &patch); + return simgrid::xbt::string_printf("%i.%i.%i", major, minor, patch); +} + +static std::string simgrid_version = get_simgrid_version(); + +} // namespace + +PYBIND11_MODULE(simgrid, m) +{ + + m.doc() = "SimGrid userspace API"; + + m.attr("simgrid_version") = simgrid_version; + + m.def("info", [](char* s) { XBT_INFO("%s", s); }, "Display a logging message of default priority."); + + m.def("execute", py::overload_cast(&simgrid::s4u::this_actor::execute), + "Block the actor, computing the given amount of flops"); + m.def("yield_", &simgrid::s4u::this_actor::yield); + + py::class_(m, "Engine") + .def(py::init([](std::vector args) -> simgrid::s4u::Engine* { + static char noarg[] = {'\0'}; + int argc = args.size(); + std::unique_ptr argv(new char*[argc + 1]); + for (int i = 0; i != argc; ++i) + argv[i] = args[i].empty() ? noarg : &args[i].front(); + argv[argc] = nullptr; + // Currently this can be dangling, we should wrap this somehow. + return new simgrid::s4u::Engine(&argc, argv.get()); + })) + .def("load_platform", &Engine::load_platform) + .def("load_deployment", &Engine::load_deployment) + .def("run", &Engine::run) + .def("register_function", [](Engine*, const char* name, std::function)> f) { + simgrid::simix::register_function( + name, [f](std::vector args) -> simgrid::simix::ActorCode { return [args, f]() { f(args); }; }); + }); + + // Currently, Host lead to segfault: + py::class_>(m, "Host").def("by_name", &Host::by_name); + + simgrid::s4u::ActorPtr (*create_actor)(std::string, Host*, std::function) = &Actor::create; + + py::class_(m, "Actor"); + + m.def("create_actor", create_actor); + + m.def("create_actor", [](std::string name, Host* host) -> std::function)> { + return [name, host](std::function f) -> ActorPtr { + return simgrid::s4u::Actor::create(name.c_str(), host, std::move(f)); + }; + }); +} diff --git a/tools/docker/Dockerfile.build-deps b/tools/docker/Dockerfile.build-deps index 3a296f3311..4e76b830e1 100644 --- a/tools/docker/Dockerfile.build-deps +++ b/tools/docker/Dockerfile.build-deps @@ -4,7 +4,7 @@ FROM debian:testing # - Install SimGrid's dependencies RUN apt update && \ apt install -y \ - g++ gcc gfortran default-jdk \ + g++ gcc gfortran default-jdk pybind11-dev \ git \ valgrind \ libboost-dev libboost-all-dev \ -- 2.20.1