diff --git a/Python/Bindings/CMakeLists.txt b/Python/Bindings/CMakeLists.txt index c64a4e2..b985f16 100644 --- a/Python/Bindings/CMakeLists.txt +++ b/Python/Bindings/CMakeLists.txt @@ -10,12 +10,16 @@ include_directories( BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Data ${CMAKE_CURRENT_SOURCE_DIR}/Processor + ${CMAKE_CURRENT_SOURCE_DIR}/Control ) # Python binding headers set( PYBINDING_HEADERFILES Data/DataPybind.hh Processor/ProcessorPybind.hh + Control/ControllerPybind.hh + Processor/SignalPybind.hh + Processor/SlotPybind.hh Processor/ProcessorRegistrar.hh Processor/ProcessorToolboxPybind.hh Processor/PyProcCreatorPybind.hh diff --git a/Python/Bindings/Control/ControllerPybind.hh b/Python/Bindings/Control/ControllerPybind.hh new file mode 100644 index 0000000..b309950 --- /dev/null +++ b/Python/Bindings/Control/ControllerPybind.hh @@ -0,0 +1,143 @@ +/* + * ControllerPybind.hh + * + * Created on: June 15, 2022 + * Author: P. T. Surukuchi + */ + +#ifndef PYTHON_BINDINGS_PROCESSOR_CONTROLLERPYBIND_HH_ +#define PYTHON_BINDINGS_PROCESSOR_CONTROLLERPYBIND_HH_ + +#include +#include + +#include "Controller.hh" +#include "factory.hh" + +namespace py = pybind11; + +namespace NymphPybind +{ + //trampoline class, see https://pybind11.readthedocs.io/en/stable/advanced/classes.html + class PyController : public Nymph::Controller { + public: + /* Inherit the constructors */ + using Nymph::Controller::Controller; + + /* Trampoline (need one for each virtual function) */ + bool WaitToContinue() override { + PYBIND11_OVERRIDE_NAME( /* Using PYBIND11_OVERRIDE since this is for a function with default (non-pure) implementation*/ + bool, /* Return type */ + Controller, /* Parent class */ + "wait_to_continue", // Name of method in Python (name) + WaitToContinue /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + bool WaitForBreakOrCanceled() override { + PYBIND11_OVERRIDE_NAME( + bool, /* Return type */ + Controller, /* Parent class */ + "wait_for_break_or_canceled", // Name of method in Python (name) + WaitForBreakOrCanceled /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + void WaitForEndOfRun() override { + PYBIND11_OVERRIDE_NAME( + void, /* Return type */ + Controller, /* Parent class */ + "wait_for_end_of_run", // Name of method in Python (name) + WaitForEndOfRun /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + void Continue() override { + PYBIND11_OVERRIDE_NAME( + void, /* Return type */ + Controller, /* Parent class */ + "continue", // Name of method in Python (name) + Continue /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + void Cancel( int code = 0 ) override { + PYBIND11_OVERRIDE_PURE_NAME( + void, /* Return type */ + Controller, /* Parent class */ + "cancel", // Name of method in Python (name) + Cancel /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + bool IsCanceled() const override { + PYBIND11_OVERRIDE_NAME( + bool, /* Return type */ + Controller, /* Parent class */ + "is_canceled", // Name of method in Python (name) + IsCanceled /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + void Break() override { + PYBIND11_OVERRIDE_NAME( + void, /* Return type */ + Controller, /* Parent class */ + "break", // Name of method in Python (name) + Break /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + bool IsAtBreak() const override { + PYBIND11_OVERRIDE_NAME( + bool, /* Return type */ + Controller, /* Parent class */ + "is_at_break", // Name of method in Python (name) + IsAtBreak /* Name of function in C++ (must match Python name) */ + ); + } + + /* Trampoline */ + void ChainIsQuitting( const std::string& name, std::exception_ptr ePtr = std::exception_ptr() ) override { + PYBIND11_OVERRIDE_NAME( + void, /* Return type */ + Controller, /* Parent class */ + "chain_is_quitting", // Name of method in Python (name) + ChainIsQuitting, /* Name of function in C++ (must match Python name) */ + name, + ePtr + ); + } + }; + + // std::shared_ptr< Nymph::Controller > get_controller(const std::string& type, const std::string& name) + // { + // scarab::factory< Nymph::Controller, const std::string& >* factory = scarab::factory< Nymph::Controller, const std::string& >::get_instance(); + // return std::shared_ptr< Nymph::Controller >(factory->create(type, name)); + // } + + void ExportController( py::module_& nymphController) + { + py::class_< Nymph::Controller, PyController, std::shared_ptr >(nymphController, "_Controller") + .def(py::init< >()) + .def("wait_to_continue", &Nymph::Controller::WaitToContinue) + .def("wait_for_break_or_canceled", &Nymph::Controller::WaitForBreakOrCanceled) + .def("wait_for_end_of_run", &Nymph::Controller::WaitForEndOfRun) + .def("continue", &Nymph::Controller::Continue) + .def("cancel", &Nymph::Controller::Cancel, py::arg("code") = 0 ) + .def("is_canceled", &Nymph::Controller::IsCanceled) + .def("break", &Nymph::Controller::Break) + .def("is_at_break", &Nymph::Controller::IsAtBreak) + .def("chain_is_quitting", &Nymph::Controller::ChainIsQuitting, py::arg("name"), py::arg("ePtr") = std::exception_ptr() ); + } + +} + +#endif /* PYTHON_BINDINGS_PROCESSOR_PROCESSORPYBIND_HH_ */ diff --git a/Python/Bindings/NymphPybind.cc b/Python/Bindings/NymphPybind.cc index 2a1e721..d0efe60 100644 --- a/Python/Bindings/NymphPybind.cc +++ b/Python/Bindings/NymphPybind.cc @@ -13,6 +13,8 @@ #include "Processor/ProcessorToolboxPybind.hh" #include "Processor/PyProcCreatorPybind.hh" #include "Processor/SignalPybind.hh" +#include "Data/DataPybind.hh" +#include "Control/ControllerPybind.hh" #include "Processor/SlotPybind.hh" #include "DataFrame.hh" @@ -26,7 +28,7 @@ PYBIND11_MODULE(_nymph, nymphPackage) nymphPackage.doc() = "Nymph package"; auto nymphControl = nymphPackage.def_submodule("control", "Control module"); - + NymphPybind::ExportController(nymphControl); auto nymphData = nymphPackage.def_submodule("data", "Data module"); NymphPybind::ExportData(nymphData); diff --git a/Testing/Python/testcontroller.py b/Testing/Python/testcontroller.py new file mode 100644 index 0000000..824bab0 --- /dev/null +++ b/Testing/Python/testcontroller.py @@ -0,0 +1,36 @@ + +""" + testcontroller.py + + Created on: Jun 15, 2022 + Author: P. T. Surukuchi +""" +import unittest + +import _nymph + +class TestController(_nymph.control._Controller): + + def __init__(self, test_var1=5): + super().__init__() + self.test_var1 = test_var1 + + def set_break_flag(flag): + self.fBreakFlag=flag + + def set_canceled(flag): + f_canceled.store(flag) + + def do_cancellation(flag): + _Controller.do_cancellation(code) + +class TestControllerMethod(unittest.TestCase): + controller=TestController() + def test_idata_assignment(self): + self.controller.SetCycleTimeMS( 100 ) + self.assertEqual(controller.GetCycleTimeMS(),0) + +if __name__ == '__main__': + unittest.main() + +