From 6872857bb9ecc6abaadd2ed96ad6d699a61dfa39 Mon Sep 17 00:00:00 2001 From: Olivier BICHLER <olivier.bichler@cea.fr> Date: Tue, 3 Oct 2023 18:44:46 +0200 Subject: [PATCH] value cannot be moved in addAttr/setAttr (because needed in 2 places!) --- .../unit_tests/test_operator_binding.py | 23 +++++++++++++++++++ include/aidge/utils/DynamicAttributes.hpp | 16 ++++++------- python_binding/utils/pybind_Parameter.cpp | 16 +++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/aidge_core/unit_tests/test_operator_binding.py b/aidge_core/unit_tests/test_operator_binding.py index fcf4b0483..437c10ad8 100644 --- a/aidge_core/unit_tests/test_operator_binding.py +++ b/aidge_core/unit_tests/test_operator_binding.py @@ -67,6 +67,29 @@ class test_operator_binding(unittest.TestCase): self.generic_operator.add_attr("l_str", ["ok"]) self.assertEqual(self.generic_operator.get_attr("l_str"), ["ok"]) + def test_dynamicattribute_binding(self): + # Check original C++ attributes are binded + attrs = aidge_core.test_DynamicAttributes_binding() + self.assertEqual(attrs.has_attr("a"), True) + self.assertEqual(attrs.get_attr("a"), 42) + self.assertEqual(attrs.has_attr("b"), True) + self.assertEqual(attrs.get_attr("b"), "test") + self.assertEqual(attrs.has_attr("c"), True) + self.assertEqual(attrs.get_attr("c"), [True, False, True]) + self.assertEqual(attrs.get_attrs_name(), {"a", "b", "c"}) + self.assertEqual(attrs.has_attr("d"), False) + + # Add Python attributes + attrs.add_attr("d", 18.56) + self.assertEqual(attrs.get_attr("d"), 18.56) + self.assertEqual(attrs.has_attr("d"), True) + self.assertEqual(attrs.get_attrs_name(), {"a", "b", "c", "d"}) + self.assertEqual(attrs.has_attr("e"), False) + + # Check that added Python attribute is accessible in C++ + # Return the value of an attribute named "d" of type float64 (double in C++) + self.assertEqual(aidge_core.test_DynamicAttributes_binding_check(attrs), 18.56) + def test_compute_output_dims(self): in_dims=[25, 25] input = aidge_core.Producer(in_dims, name="In") diff --git a/include/aidge/utils/DynamicAttributes.hpp b/include/aidge/utils/DynamicAttributes.hpp index 0e91f0a53..24800428f 100644 --- a/include/aidge/utils/DynamicAttributes.hpp +++ b/include/aidge/utils/DynamicAttributes.hpp @@ -84,16 +84,16 @@ public: ///\tparam T expected Attribute type ///\param name Attribute name ///\param value Attribute value - template<class T> void addAttr(const std::string& name, T&& value) + template<class T> void addAttr(const std::string& name, const T& value) { - const auto& res = mAttrs.emplace(std::make_pair(name, libany::any(std::forward<T>(value)))); + const auto& res = mAttrs.emplace(std::make_pair(name, libany::any(value))); assert(res.second && "attribute already exists"); #ifdef PYBIND // We cannot handle Python object if the Python interpreter is not running if (Py_IsInitialized()) { // Keep a copy of the attribute in py::object that is updated everytime - mAttrsPy.emplace(std::make_pair(name, py::cast(std::forward<T>(value)))); + mAttrsPy.emplace(std::make_pair(name, py::cast(value))); } #endif } @@ -102,19 +102,19 @@ public: ///\tparam T expected Attribute type ///\param name Attribute name ///\param value Attribute value - template<class T> void setAttr(const std::string& name, T&& value) + template<class T> void setAttr(const std::string& name, const T& value) { - auto res = mAttrs.emplace(std::make_pair(name, libany::any(std::forward<T>(value)))); + auto res = mAttrs.emplace(std::make_pair(name, libany::any(value))); if (!res.second) - res.first->second = std::move(libany::any(std::forward<T>(value))); + res.first->second = libany::any(value); #ifdef PYBIND // We cannot handle Python object if the Python interpreter is not running if (Py_IsInitialized()) { // Keep a copy of the attribute in py::object that is updated everytime - auto resPy = mAttrsPy.emplace(std::make_pair(name, py::cast(std::forward<T>(value)))); + auto resPy = mAttrsPy.emplace(std::make_pair(name, py::cast(value))); if (!resPy.second) - resPy.first->second = std::move(py::cast(std::forward<T>(value))); + resPy.first->second = std::move(py::cast(value)); } #endif } diff --git a/python_binding/utils/pybind_Parameter.cpp b/python_binding/utils/pybind_Parameter.cpp index a15a7fc2f..2957876f3 100644 --- a/python_binding/utils/pybind_Parameter.cpp +++ b/python_binding/utils/pybind_Parameter.cpp @@ -4,6 +4,18 @@ namespace py = pybind11; namespace Aidge { +DynamicAttributes test_DynamicAttributes_binding() { + DynamicAttributes attrs; + attrs.addAttr<int>("a", 42); + attrs.addAttr<std::string>("b", "test"); + attrs.addAttr<std::vector<bool>>("c", {true, false, true}); + return attrs; +} + +double test_DynamicAttributes_binding_check(DynamicAttributes& attrs) { + return attrs.getAttr<double>("d"); +} + void init_Attributes(py::module& m){ py::class_<Attributes, std::shared_ptr<Attributes>>(m, "Attributes") .def("has_attr", &Attributes::hasAttr, py::arg("name")) @@ -15,6 +27,10 @@ void init_Attributes(py::module& m){ .def("add_attr", &DynamicAttributes::addAttrPy, py::arg("name"), py::arg("value")) .def("set_attr", &DynamicAttributes::setAttrPy, py::arg("name"), py::arg("value")) .def("del_attr", &DynamicAttributes::delAttr, py::arg("name")); + + m.def("test_DynamicAttributes_binding", &test_DynamicAttributes_binding); + m.def("test_DynamicAttributes_binding_check", &test_DynamicAttributes_binding_check, py::arg("attrs")); } + } -- GitLab