-
I have a C++ struct with multiple boolean options: struct Options {
bool one = false;
bool two = false;
bool three = false;
// ...
}; With straightforward Python bindings I can use it like this: options = ext.Options()
options.one = True
options.two = True
func(options) but I thought I'd rather do the same as: func(ext.Options(one=True, two=True)) So I added kwargs to the constructor: .def("__init__", [](Options* opt, const nb::kwargs& kwargs) {
new(opt) Options;
nb::object py_opt = nb::cast(opt);
for (auto [key, value] : kwargs)
py_opt.attr(key) = nb::cast<bool>(value);
}) The equivalent of this works in pybind11. In nanobind I get "attempted to access an uninitialized instance". nb::inst_set_state(py_opt, true, false); but I feel it's a misuse of this function. Is there a neater way to set a property from constructor? If I could get a pointer to the property's fset function (which is created in |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The Python instance isn't marked as properly initialized until the constructor finishes. That's important -- for example, what if one of the keyword arguments doesn't exist? Then the constructor will raise an exception, and the object should be invalid. But you just marked it as properly constructed. The following is safer and doesn't depend on implementation details (untested, may contain syntax errors). .def(nb::init<Options>())
.def("__init__", [](Options* opt, nb::kwargs kwargs) {
nb::object other = nb::type<Options>()();
for (auto [key, value] : kwargs)
other.attr(key) = nb::cast<bool>(value);
new (opt) Options(nb::cast<const Options &>(other));
}) |
Beta Was this translation helpful? Give feedback.
The Python instance isn't marked as properly initialized until the constructor finishes. That's important -- for example, what if one of the keyword arguments doesn't exist? Then the constructor will raise an exception, and the object should be invalid. But you just marked it as properly constructed. The following is safer and doesn't depend on implementation details (untested, may contain syntax errors).