From 9660e910fe445c58e00d48a71ade9cd75931b092 Mon Sep 17 00:00:00 2001 From: Martin Peterlin Date: Fri, 23 Apr 2021 17:45:57 +0200 Subject: [PATCH 1/2] Allow addition of callbacks from Python code (cherry picked from commit 7a35e9c87d10d1c8e2256c82f8923ec38c143eb6) --- src/pybind11_common.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pybind11_common.hpp b/src/pybind11_common.hpp index a1d97ead8..10a07e7f2 100644 --- a/src/pybind11_common.hpp +++ b/src/pybind11_common.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include From d0af8ce6e238a6ed02c56bb2756869bc3667567b Mon Sep 17 00:00:00 2001 From: Martin Peterlin Date: Fri, 23 Apr 2021 17:49:18 +0200 Subject: [PATCH 2/2] Updated pybind11 and added 'addCallback' overload fix --- cmake/Hunter/config.cmake | 4 ++-- depthai-core | 2 +- src/DataQueueBindings.cpp | 34 ++++++++++++++++++++++---------- src/DeviceBootloaderBindings.cpp | 5 +---- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake index 5ace1a4e1..f74300ab0 100644 --- a/cmake/Hunter/config.cmake +++ b/cmake/Hunter/config.cmake @@ -2,6 +2,6 @@ hunter_config( pybind11 VERSION "2.6.3dev1" - URL "https://github.com/bstaletic/pybind11/archive/a4932c114a3a43c9d0157805a23c0c726e461b96.tar.gz" - SHA1 "e65484c0aa7dc3220123a7e48a50ae7a8cecdd1c" + URL "https://github.com/pybind/pybind11/archive/54430436fee2afc4f8443691075a6208f9ea8eba.tar.gz" + SHA1 "c8550f7d77e92045c996d17f1d214223d1e2e620" ) diff --git a/depthai-core b/depthai-core index c749bb65f..4721f1566 160000 --- a/depthai-core +++ b/depthai-core @@ -1 +1 @@ -Subproject commit c749bb65f055ccad80e8f0138e1df782ca4adc3c +Subproject commit 4721f1566665129853040cf97c06fddd8aeaf088 diff --git a/src/DataQueueBindings.cpp b/src/DataQueueBindings.cpp index 98bc8c0b5..d0761ee6a 100644 --- a/src/DataQueueBindings.cpp +++ b/src/DataQueueBindings.cpp @@ -11,16 +11,30 @@ void DataQueueBindings::bind(pybind11::module& m){ using namespace dai; using namespace std::chrono; - // To prevent blocking whole python interpreter, blocking functions like 'get' and 'send' + // To prevent blocking whole python interpreter, blocking functions like 'get' and 'send' // are pooled with a reasonable delay and check for python interrupt signal in between. // Bind DataOutputQueue + auto addCallbackLambda = [](DataOutputQueue& q, py::function cb) -> int { + pybind11::module inspect_module = pybind11::module::import("inspect"); + pybind11::object result = inspect_module.attr("signature")(cb).attr("parameters"); + auto numParams = pybind11::len(result); + if(numParams == 2){ + return q.addCallback(cb.cast)>>()); + } else if (numParams == 1){ + return q.addCallback(cb.cast)>>()); + } else if (numParams == 0){ + return q.addCallback(cb.cast>()); + } else { + throw py::value_error("Callback must take either zero, one or two arguments"); + } + }; py::class_>(m, "DataOutputQueue", DOC(dai, DataOutputQueue)) .def("getName", &DataOutputQueue::getName, DOC(dai, DataOutputQueue, getName)) - .def("addCallback", static_cast)>)>(&DataOutputQueue::addCallback), py::arg("callback"), DOC(dai, DataOutputQueue, addCallback)) - .def("addCallback", static_cast)>)>(&DataOutputQueue::addCallback), py::arg("callback"), DOC(dai, DataOutputQueue, addCallback, 2)) - .def("addCallback", static_cast)>(&DataOutputQueue::addCallback), py::arg("callback"), DOC(dai, DataOutputQueue, addCallback, 3)) + .def("addCallback", addCallbackLambda, py::arg("callback"), DOC(dai, DataOutputQueue, addCallback)) + .def("addCallback", addCallbackLambda, py::arg("callback"), DOC(dai, DataOutputQueue, addCallback, 2)) + .def("addCallback", addCallbackLambda, py::arg("callback"), DOC(dai, DataOutputQueue, addCallback, 3)) .def("removeCallback", &DataOutputQueue::removeCallback, py::arg("callbackId"), DOC(dai, DataOutputQueue, removeCallback)) .def("setBlocking", &DataOutputQueue::setBlocking, py::arg("blocking"), DOC(dai, DataOutputQueue, setBlocking)) @@ -28,11 +42,11 @@ void DataQueueBindings::bind(pybind11::module& m){ .def("setMaxSize", &DataOutputQueue::setMaxSize, py::arg("maxSize"), DOC(dai, DataOutputQueue, setMaxSize)) .def("getMaxSize", &DataOutputQueue::getMaxSize, DOC(dai, DataOutputQueue, getMaxSize)) .def("getAll", [](DataOutputQueue& obj){ - + std::vector> messages; bool timedout = true; do { - { + { // releases python GIL py::gil_scoped_release release; @@ -50,15 +64,15 @@ void DataQueueBindings::bind(pybind11::module& m){ return messages; }, DOC(dai, DataOutputQueue, getAll, 2)) .def("get", [](DataOutputQueue& obj){ - + std::shared_ptr d = nullptr; bool timedout = true; do { - { + { // releases python GIL py::gil_scoped_release release; - // block for 100ms + // block for 100ms d = obj.get(milliseconds(100), timedout); } @@ -84,7 +98,7 @@ void DataQueueBindings::bind(pybind11::module& m){ .def("setMaxSize", &DataInputQueue::setMaxSize, py::arg("maxSize"), DOC(dai, DataInputQueue, setMaxSize)) .def("getMaxSize", &DataInputQueue::getMaxSize, DOC(dai, DataInputQueue, getMaxSize)) .def("send", [](DataInputQueue& obj, std::shared_ptr d){ - + bool sent = false; do { diff --git a/src/DeviceBootloaderBindings.cpp b/src/DeviceBootloaderBindings.cpp index f39de7f91..e8fb23d87 100644 --- a/src/DeviceBootloaderBindings.cpp +++ b/src/DeviceBootloaderBindings.cpp @@ -3,9 +3,6 @@ // depthai #include "depthai/device/DeviceBootloader.hpp" -// pybind for functions -#include "pybind11/functional.h" - void DeviceBootloaderBindings::bind(pybind11::module& m){ using namespace dai; @@ -34,7 +31,7 @@ void DeviceBootloaderBindings::bind(pybind11::module& m){ .def_static("createDepthaiApplicationPackage", &DeviceBootloader::createDepthaiApplicationPackage, py::arg("pipeline"), py::arg("pathToCmd") = "", DOC(dai, DeviceBootloader, createDepthaiApplicationPackage)) .def_static("getEmbeddedBootloaderVersion", &DeviceBootloader::getEmbeddedBootloaderVersion, DOC(dai, DeviceBootloader, getEmbeddedBootloaderVersion)) .def_static("getEmbeddedBootloaderBinary", &DeviceBootloader::getEmbeddedBootloaderBinary, DOC(dai, DeviceBootloader, getEmbeddedBootloaderBinary)) - + .def(py::init(), py::arg("deviceDesc"), DOC(dai, DeviceBootloader, DeviceBootloader)) .def(py::init(), py::arg("deviceDesc"), py::arg("pathToCmd"), DOC(dai, DeviceBootloader, DeviceBootloader, 2)) .def("flash", &DeviceBootloader::flash, py::arg("progressCallback"), py::arg("pipeline"), DOC(dai, DeviceBootloader, flash))