[libcamera-devel] [RFC v1 3/7] py: Move ControlValue helpers to py_helpers.cpp

Kieran Bingham kieran.bingham at ideasonboard.com
Fri Jun 24 10:22:17 CEST 2022


Quoting Tomi Valkeinen (2022-06-23 15:47:32)
> Clean up the py_main.cpp a bit by moving the ControlValue helpers to a
> separate file.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>
> ---
>  src/py/libcamera/meson.build    |  1 +
>  src/py/libcamera/py_helpers.cpp | 98 +++++++++++++++++++++++++++++++++
>  src/py/libcamera/py_helpers.h   | 13 +++++
>  src/py/libcamera/py_main.cpp    | 83 +---------------------------
>  4 files changed, 114 insertions(+), 81 deletions(-)
>  create mode 100644 src/py/libcamera/py_helpers.cpp
>  create mode 100644 src/py/libcamera/py_helpers.h
> 
> diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build
> index eb884538..04578bac 100644
> --- a/src/py/libcamera/meson.build
> +++ b/src/py/libcamera/meson.build
> @@ -15,6 +15,7 @@ pybind11_dep = pybind11_proj.get_variable('pybind11_dep')
>  pycamera_sources = files([
>      'py_enums.cpp',
>      'py_geometry.cpp',
> +    'py_helpers.cpp',

Should this be called py_controls? Or do you expect other support code
to go in here too. Or maybe it's more about types, 'py_types' ..


>      'py_main.cpp',
>  ])
>  
> diff --git a/src/py/libcamera/py_helpers.cpp b/src/py/libcamera/py_helpers.cpp
> new file mode 100644
> index 00000000..d0a8b5c4
> --- /dev/null
> +++ b/src/py/libcamera/py_helpers.cpp
> @@ -0,0 +1,98 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>
> + */
> +
> +#include "py_helpers.h"
> +
> +#include <libcamera/libcamera.h>
> +
> +#include <pybind11/functional.h>
> +#include <pybind11/smart_holder.h>

You have this in the py_helpers header too, so I don't think it needs to
be duplicated here.

What's it used for? I thought it was just for the Camera destructor or
something, I don't see Camera used here ?

Anyway, the code move to it's own component file makes sense to me.


Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

> +#include <pybind11/stl.h>
> +#include <pybind11/stl_bind.h>
> +
> +namespace py = pybind11;
> +
> +using namespace libcamera;
> +
> +template<typename T>
> +static py::object valueOrTuple(const ControlValue &cv)
> +{
> +       if (cv.isArray()) {
> +               const T *v = reinterpret_cast<const T *>(cv.data().data());
> +               auto t = py::tuple(cv.numElements());
> +
> +               for (size_t i = 0; i < cv.numElements(); ++i)
> +                       t[i] = v[i];
> +
> +               return std::move(t);
> +       }
> +
> +       return py::cast(cv.get<T>());
> +}
> +
> +py::object controlValueToPy(const ControlValue &cv)
> +{
> +       switch (cv.type()) {
> +       case ControlTypeBool:
> +               return valueOrTuple<bool>(cv);
> +       case ControlTypeByte:
> +               return valueOrTuple<uint8_t>(cv);
> +       case ControlTypeInteger32:
> +               return valueOrTuple<int32_t>(cv);
> +       case ControlTypeInteger64:
> +               return valueOrTuple<int64_t>(cv);
> +       case ControlTypeFloat:
> +               return valueOrTuple<float>(cv);
> +       case ControlTypeString:
> +               return py::cast(cv.get<std::string>());
> +       case ControlTypeRectangle: {
> +               const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data());
> +               return py::cast(v);
> +       }
> +       case ControlTypeSize: {
> +               const Size *v = reinterpret_cast<const Size *>(cv.data().data());
> +               return py::cast(v);
> +       }
> +       case ControlTypeNone:
> +       default:
> +               throw std::runtime_error("Unsupported ControlValue type");
> +       }
> +}
> +
> +template<typename T>
> +static ControlValue controlValueMaybeArray(const py::object &ob)
> +{
> +       if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) {
> +               std::vector<T> vec = ob.cast<std::vector<T>>();
> +               return ControlValue(Span<const T>(vec));
> +       }
> +
> +       return ControlValue(ob.cast<T>());
> +}
> +
> +ControlValue pyToControlValue(const py::object &ob, ControlType type)
> +{
> +       switch (type) {
> +       case ControlTypeBool:
> +               return ControlValue(ob.cast<bool>());
> +       case ControlTypeByte:
> +               return controlValueMaybeArray<uint8_t>(ob);
> +       case ControlTypeInteger32:
> +               return controlValueMaybeArray<int32_t>(ob);
> +       case ControlTypeInteger64:
> +               return controlValueMaybeArray<int64_t>(ob);
> +       case ControlTypeFloat:
> +               return controlValueMaybeArray<float>(ob);
> +       case ControlTypeString:
> +               return ControlValue(ob.cast<std::string>());
> +       case ControlTypeRectangle:
> +               return ControlValue(ob.cast<Rectangle>());
> +       case ControlTypeSize:
> +               return ControlValue(ob.cast<Size>());
> +       case ControlTypeNone:
> +       default:
> +               throw std::runtime_error("Control type not implemented");
> +       }
> +}
> diff --git a/src/py/libcamera/py_helpers.h b/src/py/libcamera/py_helpers.h
> new file mode 100644
> index 00000000..cd31e2cc
> --- /dev/null
> +++ b/src/py/libcamera/py_helpers.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>
> + */
> +
> +#pragma once
> +
> +#include <libcamera/libcamera.h>
> +
> +#include <pybind11/smart_holder.h>
> +
> +pybind11::object controlValueToPy(const libcamera::ControlValue &cv);
> +libcamera::ControlValue pyToControlValue(const pybind11::object &ob, libcamera::ControlType type);
> diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp
> index 17b17f60..5a423ece 100644
> --- a/src/py/libcamera/py_main.cpp
> +++ b/src/py/libcamera/py_main.cpp
> @@ -21,93 +21,14 @@
>  #include <pybind11/stl.h>
>  #include <pybind11/stl_bind.h>
>  
> +#include "py_helpers.h"
> +
>  namespace py = pybind11;
>  
>  using namespace libcamera;
>  
>  LOG_DEFINE_CATEGORY(Python)
>  
> -template<typename T>
> -static py::object valueOrTuple(const ControlValue &cv)
> -{
> -       if (cv.isArray()) {
> -               const T *v = reinterpret_cast<const T *>(cv.data().data());
> -               auto t = py::tuple(cv.numElements());
> -
> -               for (size_t i = 0; i < cv.numElements(); ++i)
> -                       t[i] = v[i];
> -
> -               return std::move(t);
> -       }
> -
> -       return py::cast(cv.get<T>());
> -}
> -
> -static py::object controlValueToPy(const ControlValue &cv)
> -{
> -       switch (cv.type()) {
> -       case ControlTypeBool:
> -               return valueOrTuple<bool>(cv);
> -       case ControlTypeByte:
> -               return valueOrTuple<uint8_t>(cv);
> -       case ControlTypeInteger32:
> -               return valueOrTuple<int32_t>(cv);
> -       case ControlTypeInteger64:
> -               return valueOrTuple<int64_t>(cv);
> -       case ControlTypeFloat:
> -               return valueOrTuple<float>(cv);
> -       case ControlTypeString:
> -               return py::cast(cv.get<std::string>());
> -       case ControlTypeRectangle: {
> -               const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data());
> -               return py::cast(v);
> -       }
> -       case ControlTypeSize: {
> -               const Size *v = reinterpret_cast<const Size *>(cv.data().data());
> -               return py::cast(v);
> -       }
> -       case ControlTypeNone:
> -       default:
> -               throw std::runtime_error("Unsupported ControlValue type");
> -       }
> -}
> -
> -template<typename T>
> -static ControlValue controlValueMaybeArray(const py::object &ob)
> -{
> -       if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) {
> -               std::vector<T> vec = ob.cast<std::vector<T>>();
> -               return ControlValue(Span<const T>(vec));
> -       }
> -
> -       return ControlValue(ob.cast<T>());
> -}
> -
> -static ControlValue pyToControlValue(const py::object &ob, ControlType type)
> -{
> -       switch (type) {
> -       case ControlTypeBool:
> -               return ControlValue(ob.cast<bool>());
> -       case ControlTypeByte:
> -               return controlValueMaybeArray<uint8_t>(ob);
> -       case ControlTypeInteger32:
> -               return controlValueMaybeArray<int32_t>(ob);
> -       case ControlTypeInteger64:
> -               return controlValueMaybeArray<int64_t>(ob);
> -       case ControlTypeFloat:
> -               return controlValueMaybeArray<float>(ob);
> -       case ControlTypeString:
> -               return ControlValue(ob.cast<std::string>());
> -       case ControlTypeRectangle:
> -               return ControlValue(ob.cast<Rectangle>());
> -       case ControlTypeSize:
> -               return ControlValue(ob.cast<Size>());
> -       case ControlTypeNone:
> -       default:
> -               throw std::runtime_error("Control type not implemented");
> -       }
> -}
> -
>  static std::weak_ptr<CameraManager> gCameraManager;
>  static int gEventfd;
>  static std::mutex gReqlistMutex;
> -- 
> 2.34.1
>


More information about the libcamera-devel mailing list