[{"id":22902,"web_url":"https://patchwork.libcamera.org/comment/22902/","msgid":"<YnZtdHrVejOxoZ/o@pendragon.ideasonboard.com>","date":"2022-05-07T13:00:36","subject":"Re: [libcamera-devel] [PATCH v9 4/7] Add Python bindings","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Tomi,\n\nThank you for the patch.\n\nOn Sat, May 07, 2022 at 01:11:49PM +0300, Tomi Valkeinen wrote:\n> Add libcamera Python bindings. pybind11 is used to generate the C++ <->\n> Python layer.\n> \n> We use pybind11 'smart_holder' version to avoid issues with private\n> destructors and shared_ptr. There is also an alternative solution here:\n> \n> https://github.com/pybind/pybind11/pull/2067\n> \n> Only a subset of libcamera classes are exposed. Implementing and testing\n> the wrapper classes is challenging, and as such only classes that I have\n> needed have been added so far.\n> \n> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  meson.build                                   |   1 +\n>  meson_options.txt                             |   5 +\n>  src/meson.build                               |   1 +\n>  src/py/libcamera/__init__.py                  |  84 +++\n>  src/py/libcamera/meson.build                  |  51 ++\n>  src/py/libcamera/pyenums.cpp                  |  34 +\n>  src/py/libcamera/pymain.cpp                   | 642 ++++++++++++++++++\n>  src/py/meson.build                            |   1 +\n>  subprojects/.gitignore                        |   3 +-\n>  subprojects/packagefiles/pybind11/meson.build |   7 +\n>  subprojects/pybind11.wrap                     |   9 +\n>  11 files changed, 837 insertions(+), 1 deletion(-)\n>  create mode 100644 src/py/libcamera/__init__.py\n>  create mode 100644 src/py/libcamera/meson.build\n>  create mode 100644 src/py/libcamera/pyenums.cpp\n>  create mode 100644 src/py/libcamera/pymain.cpp\n>  create mode 100644 src/py/meson.build\n>  create mode 100644 subprojects/packagefiles/pybind11/meson.build\n>  create mode 100644 subprojects/pybind11.wrap\n\n[snip]\n\n> diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build\n> new file mode 100644\n> index 00000000..fce9fd5e\n> --- /dev/null\n> +++ b/src/py/libcamera/meson.build\n> @@ -0,0 +1,51 @@\n> +# SPDX-License-Identifier: CC0-1.0\n> +\n> +py3_dep = dependency('python3', required : get_option('pycamera'))\n> +\n> +if not py3_dep.found()\n> +    pycamera_enabled = false\n> +    subdir_done()\n> +endif\n> +\n> +pycamera_enabled = true\n> +\n> +pybind11_proj = subproject('pybind11')\n> +pybind11_dep = pybind11_proj.get_variable('pybind11_dep')\n> +\n> +pycamera_sources = files([\n> +    'pyenums.cpp',\n> +    'pymain.cpp',\n> +])\n> +\n> +pycamera_deps = [\n> +    libcamera_public,\n> +    py3_dep,\n> +    pybind11_dep,\n> +]\n> +\n> +pycamera_args = [\n> +    '-fvisibility=hidden',\n> +    '-Wno-shadow',\n> +    '-DPYBIND11_USE_SMART_HOLDER_AS_DEFAULT',\n> +]\n> +\n> +destdir = get_option('libdir') / ('python' + py3_dep.version()) / 'site-packages' / 'libcamera'\n> +\n> +pycamera = shared_module('_libcamera',\n> +                         pycamera_sources,\n> +                         install : true,\n> +                         install_dir : destdir,\n> +                         name_prefix : '',\n> +                         dependencies : pycamera_deps,\n> +                         cpp_args : pycamera_args)\n> +\n> +run_command('ln', '-fsT', '../../../../src/py/libcamera/__init__.py',\n> +            meson.current_build_dir() / '__init__.py',\n> +            check: true)\n> +\n> +install_data(['__init__.py'], install_dir : destdir)\n> +\n> +# \\todo Generate stubs when building. Depends on pybind11-stubgen. Sometimes\n> +# this works, sometimes doesn't... To generate pylibcamera stubs.\n> +# $ PYTHONPATH=build/src/py pybind11-stubgen --no-setup-py -o build/src/py libcamera\n> +# $ mv build/src/py/libcamera-stubs/* build/src/py/libcamera/\n\nCould you add the link you shared in the review of the previous version\nto explain what stubs are ?\n\n[snip]\n\n> diff --git a/src/py/libcamera/pymain.cpp b/src/py/libcamera/pymain.cpp\n> new file mode 100644\n> index 00000000..ee306186\n> --- /dev/null\n> +++ b/src/py/libcamera/pymain.cpp\n> @@ -0,0 +1,642 @@\n\n[snip]\n\n> +static std::weak_ptr<CameraManager> gCameraManager;\n> +static int gEventfd;\n> +static std::mutex gReqlistMutex;\n> +static std::vector<Request *> gReqList;\n> +\n> +static void handleRequestCompleted(Request *req)\n> +{\n> +\t{\n> +\t\tstd::lock_guard guard(gReqlistMutex);\n> +\t\tgReqList.push_back(req);\n> +\t}\n> +\n> +\tuint64_t v = 1;\n> +\tsize_t s = write(gEventfd, &v, 8);\n> +\tif (s != 8)\n> +\t\tthrow std::runtime_error(\"Unable to write to eventfd\");\n\nlibcamera doesn't handle exceptions thrown to it (exceptions thrown\ntowards Python are fine with me, assuming pybind11 handles them fine). A\nLOG(FATAL) would be better here.\n\n> +}\n\n[snip]","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 D1005C3256\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat,  7 May 2022 13:00:42 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F100865646;\n\tSat,  7 May 2022 15:00:41 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id EBD6665643\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  7 May 2022 15:00:40 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4488C6D5;\n\tSat,  7 May 2022 15:00:40 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1651928442;\n\tbh=QuCDkzW1qRJiyiU/gbJyKeWZItNLWkfaxMuN0qKtUdg=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=GLI6v/gPS3t/gsujkVx2UjW9Fv4Pd69NdDlXkFVzHg7iTSQyBg6EMj8Ib6I0FSCJt\n\tbo60Ix86RKhPpMKYazeagdHz30Q3SGXPst+u1NpOiVPHzR7cJNP79oa2SYovKAli/I\n\t2fporGN/HPwnQVyZrkJCJJePq8/Vz4LwgWKcRfnEbKquLiKr2P2IoyJ4dWHs1kfNqh\n\ttGZLzHkbSobO8gGYT89wS063AVx8eboO88ZtgbxGvtBa3pP5s+HlRuf3vgENoSNjgc\n\tmiq0lGmnJZHHrpsz/Ez2oyB0b62JUb9IQFiEjGA1xco2GaHOtS+Hw/UQXELg+5kg0T\n\tpURlIiy2JsEdQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1651928440;\n\tbh=QuCDkzW1qRJiyiU/gbJyKeWZItNLWkfaxMuN0qKtUdg=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=BD9Hs5XjF6vpT6ZQCwcu9Ln7+1JT4RrEQK6u9jCPpPE6X+AU43e6HbtZYKvm/Ot67\n\tKKpBiiFsOl+sexedu2BFgh/DtQY2BR211rpZE8ZIPw2R+rPuoo/20mGMxu6ngVnnMy\n\tOAzLn9pnhQktBS5o+/Zyg+8YLZ+VYAwQ+HcQQe54="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"BD9Hs5Xj\"; dkim-atps=neutral","Date":"Sat, 7 May 2022 16:00:36 +0300","To":"Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>","Message-ID":"<YnZtdHrVejOxoZ/o@pendragon.ideasonboard.com>","References":"<20220507101152.31412-1-tomi.valkeinen@ideasonboard.com>\n\t<20220507101152.31412-5-tomi.valkeinen@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220507101152.31412-5-tomi.valkeinen@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v9 4/7] Add Python bindings","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]