[{"id":38917,"web_url":"https://patchwork.libcamera.org/comment/38917/","msgid":"<8a19677a-1858-4c5f-8b15-7f73da845188@ideasonboard.com>","date":"2026-05-19T08:41:50","subject":"Re: [RFC PATCH v1] py: Use smart holder for `Camera` if available","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 05. 19. 9:21 keltezéssel, Barnabás Pőcze írta:\n> The `Camera` class has a private destructor, so `std::shared_ptr<>` cannot\n> be used as a holder type. In recent versions of pybind11, the custom holder\n> type that was used no longer works:\n> \n>    RuntimeError: Unable to convert std::shared_ptr<T> to Python when the bound\n>    type does not use std::shared_ptr or py::smart_holder as its holder type\n> \n> This appears to be intentional and the fact that it worked is accidental.\n> \n> Fix that by using a \"smart holder\" since pybind11 3.x, and falling back to\n> the custom one in previous versions.\n> \n> Link: https://github.com/pybind/pybind11/issues/6064\n> Closes: https://gitlab.freedesktop.org/camera/libcamera/-/work_items/334\n> ---\n\nMore context:\n\n   * https://github.com/pybind/pybind11/issues/6064\n   * https://github.com/pybind/pybind11/pull/6065\n   * https://github.com/pybind/pybind11/pull/6066\n   * https://github.com/pybind/pybind11/pull/6068\n   * https://github.com/pybind/pybind11/pull/6069\n\nand I have only tested this with pybind11 3.0.4.\n\n>   src/py/libcamera/py_main.cpp | 12 ++++++++++--\n>   1 file changed, 10 insertions(+), 2 deletions(-)\n> \n> diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp\n> index d0ef6915b..3b101f996 100644\n> --- a/src/py/libcamera/py_main.cpp\n> +++ b/src/py/libcamera/py_main.cpp\n> @@ -34,6 +34,7 @@ LOG_DEFINE_CATEGORY(Python)\n>   \n>   }\n>   \n> +#if PYBIND11_VERSION_MAJOR < 3\n>   /*\n>    * This is a holder class used only for the Camera class, for the sole purpose\n>    * of avoiding the compilation issue with Camera's private destructor.\n> @@ -79,6 +80,13 @@ private:\n>   \n>   PYBIND11_DECLARE_HOLDER_TYPE(T, PyCameraSmartPtr<T>)\n>   \n> +using PyCameraHolder = PyCameraSmartPtr<Camera>;\n> +using PyCameraArg = PyCameraSmartPtr<Camera>;\n> +#else\n> +using PyCameraHolder = py::smart_holder;\n> +using PyCameraArg = std::shared_ptr<Camera>;\n> +#endif\n> +\n>   /*\n>    * Note: global C++ destructors can be ran on this before the py module is\n>    * destructed.\n> @@ -103,7 +111,7 @@ PYBIND11_MODULE(_libcamera, m)\n>   \t */\n>   \n>   \tauto pyCameraManager = py::class_<PyCameraManager, std::shared_ptr<PyCameraManager>>(m, \"CameraManager\");\n> -\tauto pyCamera = py::class_<Camera, PyCameraSmartPtr<Camera>>(m, \"Camera\");\n> +\tauto pyCamera = py::class_<Camera, PyCameraHolder>(m, \"Camera\");\n>   \tauto pySensorConfiguration = py::class_<SensorConfiguration>(m, \"SensorConfiguration\");\n>   \tauto pyCameraConfiguration = py::class_<CameraConfiguration>(m, \"CameraConfiguration\");\n>   \tauto pyCameraConfigurationStatus = py::enum_<CameraConfiguration::Status>(pyCameraConfiguration, \"Status\");\n> @@ -347,7 +355,7 @@ PYBIND11_MODULE(_libcamera, m)\n>   \t\t.def(\"range\", &StreamFormats::range);\n>   \n>   \tpyFrameBufferAllocator\n> -\t\t.def(py::init<PyCameraSmartPtr<Camera>>(), py::keep_alive<1, 2>())\n> +\t\t.def(py::init<PyCameraArg>(), py::keep_alive<1, 2>())\n>   \t\t.def(\"allocate\", [](FrameBufferAllocator &self, Stream *stream) {\n>   \t\t\tint ret = self.allocate(stream);\n>   \t\t\tif (ret < 0)","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id A00AABDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 19 May 2026 08:41:56 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6501162E6A;\n\tTue, 19 May 2026 10:41:55 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0A17362E6A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 May 2026 10:41:53 +0200 (CEST)","from [IPV6:2a01:cb1d:8f2:800:9eb6:570e:4fb2:add3] (unknown\n\t[IPv6:2a01:cb1d:8f2:800:9eb6:570e:4fb2:add3])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 263787CA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 May 2026 10:41:40 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"ofxZMkES\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1779180100;\n\tbh=Tm65XuUe3s5UUdTlolw4xP7ZLJ2BNNZYm1+8BIiXLUA=;\n\th=Date:Subject:From:To:References:In-Reply-To:From;\n\tb=ofxZMkESrE8pfmceKvTSA04iI5IRH9QjM/Lh1eDdpF334djC9u/Fn/lMQS1JPTTca\n\tHecKKltiKtktc5LrEKnWInhBNOqQ4RhUkfRqZYSjWXBFu+PwV5LNzns0S6UIwlYbLP\n\tR9/icwWjiCGYHWhEze66tWqGd4J1eJGiGcr1IVlg=","Message-ID":"<8a19677a-1858-4c5f-8b15-7f73da845188@ideasonboard.com>","Date":"Tue, 19 May 2026 10:41:50 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [RFC PATCH v1] py: Use smart holder for `Camera` if available","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","References":"<20260519072152.346204-1-barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260519072152.346204-1-barnabas.pocze@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38918,"web_url":"https://patchwork.libcamera.org/comment/38918/","msgid":"<bc845b23-b404-44e8-a5c4-830ff042e203@ideasonboard.com>","date":"2026-05-19T08:55:44","subject":"Re: [RFC PATCH v1] py: Use smart holder for `Camera` if available","submitter":{"id":109,"url":"https://patchwork.libcamera.org/api/people/109/","name":"Tomi Valkeinen","email":"tomi.valkeinen@ideasonboard.com"},"content":"Hi,\n\nOn 5/19/26 09:21, Barnabás Pőcze wrote:\n> The `Camera` class has a private destructor, so `std::shared_ptr<>` cannot\n> be used as a holder type. In recent versions of pybind11, the custom holder\n> type that was used no longer works:\n> \n>    RuntimeError: Unable to convert std::shared_ptr<T> to Python when the bound\n>    type does not use std::shared_ptr or py::smart_holder as its holder type\n> \n> This appears to be intentional and the fact that it worked is accidental.\n> \n> Fix that by using a \"smart holder\" since pybind11 3.x, and falling back to\n> the custom one in previous versions.\n> \n> Link:https://github.com/pybind/pybind11/issues/6064\n> Closes:https://gitlab.freedesktop.org/camera/libcamera/-/work_items/334\n> ---\n>   src/py/libcamera/py_main.cpp | 12 ++++++++++--\n>   1 file changed, 10 insertions(+), 2 deletions(-)\n\nLooks sensible to me. I tested on pybind11 2.11.1-2. At some point we \ncan perhaps require pybind11 3.x, but probably not yet. Or switch to \nnanobind. Or if we get the C API, then the py side will be much simpler.\n\nReviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n\n  Tomi","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 8BC24BDCBC\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 19 May 2026 08:55:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 33C8063021;\n\tTue, 19 May 2026 10:55:49 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7CCC962FE1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 May 2026 10:55:47 +0200 (CEST)","from [IPV6:2a01:cb1d:8f2:800:1f3a:ce7e:2f55:583a] (unknown\n\t[IPv6:2a01:cb1d:8f2:800:1f3a:ce7e:2f55:583a])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9EB89ABF;\n\tTue, 19 May 2026 10:55:34 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"mMAhdT8t\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1779180934;\n\tbh=yKDmVRgQOPO/d8yKyQS31yTjFztpOfpl0AcMFn9c5o8=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=mMAhdT8tov2Vhqi2OW4SiMJfEMoD5XzF4Ub4wwsIo06Trj9GgRxsIN/erqhmFVu7n\n\tzRGK5E2utYkExACnWj7x4J7O1nreCXvNl7d3onsSIJ9rNW3XmwjhKlL+xKEAgWtmfG\n\teNhoI9mne4Z950cfCstbB0+iw12KwyadFKOlsu4o=","Message-ID":"<bc845b23-b404-44e8-a5c4-830ff042e203@ideasonboard.com>","Date":"Tue, 19 May 2026 10:55:44 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [RFC PATCH v1] py: Use smart holder for `Camera` if available","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260519072152.346204-1-barnabas.pocze@ideasonboard.com>","Content-Language":"en-US","From":"Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>","In-Reply-To":"<20260519072152.346204-1-barnabas.pocze@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38940,"web_url":"https://patchwork.libcamera.org/comment/38940/","msgid":"<20260520230248.GA96381@killaraus.ideasonboard.com>","date":"2026-05-20T23:02:48","subject":"Re: [RFC PATCH v1] py: Use smart holder for `Camera` if available","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Barnabás,\n\nThank you for the patch.\n\nOn Tue, May 19, 2026 at 09:21:52AM +0200, Barnabás Pőcze wrote:\n> The `Camera` class has a private destructor, so `std::shared_ptr<>` cannot\n> be used as a holder type. In recent versions of pybind11, the custom holder\n> type that was used no longer works:\n> \n>   RuntimeError: Unable to convert std::shared_ptr<T> to Python when the bound\n>   type does not use std::shared_ptr or py::smart_holder as its holder type\n> \n> This appears to be intentional and the fact that it worked is accidental.\n> \n> Fix that by using a \"smart holder\" since pybind11 3.x, and falling back to\n> the custom one in previous versions.\n> \n> Link: https://github.com/pybind/pybind11/issues/6064\n> Closes: https://gitlab.freedesktop.org/camera/libcamera/-/work_items/334\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  src/py/libcamera/py_main.cpp | 12 ++++++++++--\n>  1 file changed, 10 insertions(+), 2 deletions(-)\n> \n> diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp\n> index d0ef6915b..3b101f996 100644\n> --- a/src/py/libcamera/py_main.cpp\n> +++ b/src/py/libcamera/py_main.cpp\n> @@ -34,6 +34,7 @@ LOG_DEFINE_CATEGORY(Python)\n>  \n>  }\n>  \n> +#if PYBIND11_VERSION_MAJOR < 3\n>  /*\n>   * This is a holder class used only for the Camera class, for the sole purpose\n>   * of avoiding the compilation issue with Camera's private destructor.\n> @@ -79,6 +80,13 @@ private:\n>  \n>  PYBIND11_DECLARE_HOLDER_TYPE(T, PyCameraSmartPtr<T>)\n>  \n> +using PyCameraHolder = PyCameraSmartPtr<Camera>;\n> +using PyCameraArg = PyCameraSmartPtr<Camera>;\n> +#else\n> +using PyCameraHolder = py::smart_holder;\n> +using PyCameraArg = std::shared_ptr<Camera>;\n> +#endif\n> +\n>  /*\n>   * Note: global C++ destructors can be ran on this before the py module is\n>   * destructed.\n> @@ -103,7 +111,7 @@ PYBIND11_MODULE(_libcamera, m)\n>  \t */\n>  \n>  \tauto pyCameraManager = py::class_<PyCameraManager, std::shared_ptr<PyCameraManager>>(m, \"CameraManager\");\n> -\tauto pyCamera = py::class_<Camera, PyCameraSmartPtr<Camera>>(m, \"Camera\");\n> +\tauto pyCamera = py::class_<Camera, PyCameraHolder>(m, \"Camera\");\n>  \tauto pySensorConfiguration = py::class_<SensorConfiguration>(m, \"SensorConfiguration\");\n>  \tauto pyCameraConfiguration = py::class_<CameraConfiguration>(m, \"CameraConfiguration\");\n>  \tauto pyCameraConfigurationStatus = py::enum_<CameraConfiguration::Status>(pyCameraConfiguration, \"Status\");\n> @@ -347,7 +355,7 @@ PYBIND11_MODULE(_libcamera, m)\n>  \t\t.def(\"range\", &StreamFormats::range);\n>  \n>  \tpyFrameBufferAllocator\n> -\t\t.def(py::init<PyCameraSmartPtr<Camera>>(), py::keep_alive<1, 2>())\n> +\t\t.def(py::init<PyCameraArg>(), py::keep_alive<1, 2>())\n>  \t\t.def(\"allocate\", [](FrameBufferAllocator &self, Stream *stream) {\n>  \t\t\tint ret = self.allocate(stream);\n>  \t\t\tif (ret < 0)","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 9621CBDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 20 May 2026 23:02:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 863C463024;\n\tThu, 21 May 2026 01:02:51 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 03E4A62E9D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 21 May 2026 01:02:49 +0200 (CEST)","from killaraus.ideasonboard.com (unknown\n\t[IPv6:2a01:cb1d:8f2:800:42d6:38fa:3bdf:70df])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C469B268;\n\tThu, 21 May 2026 01:02:35 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NQKfjW1O\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1779318155;\n\tbh=NdwIgzoTiNEG6Q9wA4v37QvEAy1HAMixvVu222PAe/s=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=NQKfjW1OC3hLrY+JIp/OIavhXud5fw8YP5knYVlvDxy/lfm3R6hfVM0wvW9lIEjwm\n\tYDbpRizSeJn7KyAXGXFFE1RrwvQNGXnsBUMd/BjDSEsOpRFcgxJkCIXFJ5Y+3IxCgK\n\tqcCw9239R0cIfPIlnET7dUbDfJMkM4I3tTSPQW60=","Date":"Thu, 21 May 2026 01:02:48 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [RFC PATCH v1] py: Use smart holder for `Camera` if available","Message-ID":"<20260520230248.GA96381@killaraus.ideasonboard.com>","References":"<20260519072152.346204-1-barnabas.pocze@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20260519072152.346204-1-barnabas.pocze@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]