diff --git a/src/py-opentimelineio/bindings-common/casters.h b/src/py-opentimelineio/bindings-common/casters.h new file mode 100644 index 0000000000..5e6cf8f8bc --- /dev/null +++ b/src/py-opentimelineio/bindings-common/casters.h @@ -0,0 +1,18 @@ +#include +#include +#include "nonstd/optional.hpp" + +using nonstd::optional; +using nonstd::nullopt_t; + +namespace pybind11 { namespace detail { + // Caster for converting to/from nonstd::optional. + // Pybind11 supports optional types when C++17 is used. + // So for now we have to create the casters manually. + // See https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html#c-17-library-containers + template struct type_caster> + : public optional_caster> {}; + + template<> struct type_caster + : public void_caster {}; +}} diff --git a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp index 6c5c523fa4..776467c1ae 100644 --- a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp +++ b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp @@ -6,6 +6,8 @@ #include "opentime/rationalTime.h" #include "opentimelineio/stringUtils.h" +#include "opentimelineio/optional.h" +#include "py-opentimelineio/bindings-common/casters.h" namespace py = pybind11; using namespace pybind11::literals; @@ -28,11 +30,10 @@ struct ErrorStatusConverter { ErrorStatus error_status; }; - -IsDropFrameRate df_enum_converter(py::object& df) { - if (df.is(py::none())) { +IsDropFrameRate df_enum_converter(optional& df) { + if (!df.has_value()) { return IsDropFrameRate::InferFromRate; - } else if (py::cast(py::bool_(df))) { + } else if (df.value()) { return IsDropFrameRate::ForceYes; } else { return IsDropFrameRate::ForceNo; @@ -107,7 +108,7 @@ For example, the duration of a clip from frame 10 to frame 15 is 6 frames. Resul .def("to_frames", (int (RationalTime::*)() const) &RationalTime::to_frames, "Returns the frame number based on the current rate.") .def("to_frames", (int (RationalTime::*)(double) const) &RationalTime::to_frames, "rate"_a, "Returns the frame number based on the given rate.") .def("to_seconds", &RationalTime::to_seconds) - .def("to_timecode", [](RationalTime rt, double rate, py::object drop_frame) { + .def("to_timecode", [](RationalTime rt, double rate, optional drop_frame) { return rt.to_timecode( rate, df_enum_converter(drop_frame), diff --git a/src/py-opentimelineio/opentimelineio-bindings/otio_utils.h b/src/py-opentimelineio/opentimelineio-bindings/otio_utils.h index da70920356..82b2856351 100644 --- a/src/py-opentimelineio/opentimelineio-bindings/otio_utils.h +++ b/src/py-opentimelineio/opentimelineio-bindings/otio_utils.h @@ -6,8 +6,8 @@ #include #include #include +#include "py-opentimelineio/bindings-common/casters.h" #include "opentimelineio/any.h" -#include "opentimelineio/optional.h" #include "opentimelineio/stringUtils.h" #include "opentimelineio/serializableObject.h" #include "opentimelineio/vectorIndexing.h" @@ -17,13 +17,6 @@ using namespace opentimelineio::OPENTIMELINEIO_VERSION; void install_external_keepalive_monitor(SerializableObject* so, bool apply_now); -namespace pybind11 { namespace detail { - template struct type_caster> - : public optional_caster> {}; - - template<> struct type_caster - : public void_caster {}; -}} template struct managing_ptr {