Program Listing for File pybind11_utils.hpp
↰ Return to documentation for file (include/yasmin/pybind11_utils.hpp)
// Copyright (C) 2025 Miguel Ángel González Santamarta
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef YASMIN_PYBIND11_UTILS_HPP
#define YASMIN_PYBIND11_UTILS_HPP
#include <memory>
#include <pybind11/pybind11.h>
#include "yasmin/blackboard.hpp"
#include "yasmin/blackboard_pywrapper.hpp"
namespace py = pybind11;
namespace yasmin {
namespace pybind11_utils {
inline std::shared_ptr<yasmin::Blackboard>
convert_blackboard_from_python(py::object blackboard_obj) {
std::shared_ptr<yasmin::Blackboard> blackboard;
// Case 1: None or not provided - create new Blackboard
if (blackboard_obj.is_none()) {
blackboard = std::make_shared<yasmin::Blackboard>();
}
// Case 2: Check if it's a BlackboardPyWrapper
else if (py::isinstance<yasmin::BlackboardPyWrapper>(blackboard_obj)) {
auto wrapper = blackboard_obj.cast<yasmin::BlackboardPyWrapper>();
// Get the shared pointer directly instead of copying
blackboard = wrapper.get_cpp_blackboard();
}
// Case 3: Check if it's a Blackboard
else if (py::isinstance<yasmin::Blackboard>(blackboard_obj)) {
blackboard = blackboard_obj.cast<std::shared_ptr<yasmin::Blackboard>>();
}
// Case 4: Unknown type - create a new blackboard
else {
blackboard = std::make_shared<yasmin::Blackboard>();
}
return blackboard;
}
template <typename Func> inline auto wrap_blackboard_callback(py::function cb) {
return [cb](std::shared_ptr<yasmin::Blackboard> blackboard, auto... args) {
py::gil_scoped_acquire acquire;
yasmin::BlackboardPyWrapper wrapper(blackboard);
cb(wrapper, args...);
};
}
template <typename ReturnType>
inline auto wrap_blackboard_callback_with_return(py::function cb) {
return [cb](std::shared_ptr<yasmin::Blackboard> blackboard) -> ReturnType {
py::gil_scoped_acquire acquire;
yasmin::BlackboardPyWrapper wrapper(blackboard);
return cb(wrapper).cast<ReturnType>();
};
}
template <typename ClassType, typename StateType>
inline void add_call_operator(ClassType &cls) {
cls.def(
"__call__",
[](StateType &self, py::object blackboard_obj = py::none()) {
auto blackboard = convert_blackboard_from_python(blackboard_obj);
// Release GIL to allow C++ threads (important for Concurrence) to run
py::gil_scoped_release release;
return self(blackboard);
},
"Execute the state and return the outcome",
py::arg("blackboard") = py::none());
}
} // namespace pybind11_utils
} // namespace yasmin
#endif // YASMIN_PYBIND11_UTILS_HPP