What about enumerations?
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.