What about enumerations?
barnou-psee opened this issue · 0 comments
Hi,
I must say I really like the idea of this utility to ease my parameters structures usage in Python. I encountered an issue with bound enumerations. I use enumerations quite a lot in C++ mainly in factories. I can easily have a nlohmann converters for them, I can easily bind them, but I'm lost when trying to have the two functionalities working together.
It's quite logic since the nlohmann json bindings expect classic types and I guess enumerations fall into a special structures. I tried to get how I could handle those errors but I struggle finding how I could do that.
module.cpp
#include
#include "nlohmann/json.hpp"
// This is where I copied pybind11_json.hpp
#include "converters/json.h"#define MODULE_NAME footest
namespace testing_pybind11_json {
enum class Foo : uint32_t { ZERO, ONE, TWO, THREE };
NLOHMANN_JSON_SERIALIZE_ENUM(Foo,
{{Foo::ZERO, "ZERO"},
{Foo::ONE, "ONE"},
{Foo::TWO, "TWO"},
{Foo::THREE, "THREE"}})void print_json(const nlohmann::json &j) {
std::cout << std::endl << std::setw(4) << j.dump() << std::endl;
}void print_dict(const py::dict &d) {
nlohmann::json j;
j = d;
std::cout << std::endl << std::setw(4) << j.dump() << std::endl;
}} // namespace testing_pybind11_json
PYBIND11_MODULE(MODULE_NAME, m) {
Py_Initialize();
PyEval_InitThreads();py::enum_<testing_pybind11_json::Foo>(m, "Foo") .value("ZERO", testing_pybind11_json::Foo::ZERO) .value("ONE", testing_pybind11_json::Foo::ONE) .value("TWO", testing_pybind11_json::Foo::TWO) .value("THREE", testing_pybind11_json::Foo::THREE); m.def("print_json", &testing_pybind11_json::print_json); m.def("print_dict", &testing_pybind11_json::print_dict);
}
footest_pytest.cpp
import footest import pytest
@pytest.mark.module("binding.utils")
def pytestcase_testing_pybind11_print_json():
footest.print_json({'a': 1, 'b': 2})
footest.print_json({'a': 1, 'b': 2, 'c': footest.Foo.ONE})
@pytest.mark.module("binding.utils")
def pytestcase_testing_pybind11_print_dict():
footest.print_dict({'a': 1, 'b': 2})
footest.print_dict({'a': 1, 'b': 2, 'c': footest.Foo.ONE})
It returns me different type of error depending on the function I'm using.
With print_json
: it tries to use directly type_caster
but seems to fall in a strange case.
@pytest.mark.module("binding.utils")
def pytestcase_testing_pybind11_print_json():
mci.print_json({'a': 1, 'b': 2})
> mci.print_json({'a': 1, 'b': 2, 'c': mci.Foo.ONE})
E TypeError: print_json(): incompatible function arguments. The following argument types are supported:
E 1. (arg0: json) -> None
E
E Invoked with: {'a': 1, 'b': 2, 'c': <Foo.ONE: 1>}
sdk/modules/computational_imaging/python/tests/bindings/calibration_pytest.py:148: TypeError
With print_dict
: I avoid using type_caster
but calls directly the to_json
function which goes well until the incompatible enum.
@pytest.mark.module("binding.utils")
def pytestcase_testing_pybind11_print_dict():
mci.print_dict({'a': 1, 'b': 2})
> mci.print_dict({'a': 1, 'b': 2, 'c': mci.Foo.ONE})
E RuntimeError: to_json not implemented for this type of object: <Foo.ONE: 1>
sdk/modules/computational_imaging/python/tests/bindings/calibration_pytest.py:154: RuntimeError
I don't know if it's even possible to catch the enumeration case and call the to_json
/ from_json
of the underlying enumeration.