Как мне вернуть boost::python::tuple, содержащий PyObject*?

В настоящее время у меня есть класс boost.python, который я использую для получения изображений с камеры Basler, преобразую их в изображения opencv и возвращаю их в виде массивов для сценария python.

Первоначально у меня был следующий код, который работал:

    PyObject *capture()
    {
        PyObject * ret;
        CGrabResultPtr ptrGrabResult;
        CPylonImage pylonImage;
        Mat image;
        //timer t;
        try
        {
            // Set timer to 0
            //t.reset();

            // get a pointer to pylon image
            camera->RetrieveResult( 50000, ptrGrabResult, TimeoutHandling_ThrowException);

            // Get dimensions of image
            int imageWidthPixels = ptrGrabResult->GetWidth();
            int imageHeightPixels = ptrGrabResult->GetHeight();

             if (ptrGrabResult->GrabSucceeded())
             {
                // Convert Grab result from YUV422 to BGR8
                formatConverter->Convert(pylonImage, ptrGrabResult);

                // Convert pylon image to opencv image
                image = Mat(imageHeightPixels, imageWidthPixels, CV_8UC3, (std::uint8_t *) pylonImage.GetBuffer());
                // Convert opencv image to PyObject
                ret = pbcvt::fromMatToNDArray(image);
                return ret;
            }
            else
            {

                //cout << "Error: " << ptrGrabResult->GetErrorCode() << " " << ptrGrabResult->GetErrorDescription() << endl;
            }


         }
        catch (const GenericException &e)
        {
            // Error handling.
            cerr << "An exception occurred." << endl
            << e.GetDescription() << endl;
        }

        // Return empty image if acquisition failed
        return pbcvt::fromMatToNDArray(Mat());
    }

Однако я хотел бы эмулировать функционирование VideoCapture opencv и вернуть кортеж. Таким образом, я наивно изменил код таким образом:

    boost::python::tuple capture()
    {
        PyObject * ret;
        CGrabResultPtr ptrGrabResult;
        CPylonImage pylonImage;
        Mat image;
        //timer t;
        try
        {
            // Set timer to 0
            //t.reset();

            // get a pointer to pylon image
            camera->RetrieveResult( 50000, ptrGrabResult, TimeoutHandling_ThrowException);

            // Get dimensions of image
            int imageWidthPixels = ptrGrabResult->GetWidth();
            int imageHeightPixels = ptrGrabResult->GetHeight();

             if (ptrGrabResult->GrabSucceeded())
             {
                // Convert Grab result from YUV422 to BGR8
                formatConverter->Convert(pylonImage, ptrGrabResult);

                // Convert pylon image to opencv image
                image = Mat(imageHeightPixels, imageWidthPixels, CV_8UC3, (std::uint8_t *) pylonImage.GetBuffer());
                // Convert opencv image to PyObject
                ret = pbcvt::fromMatToNDArray(image);
                return boost::python::make_tuple(true, ret);
            }
            else
            {

                //cout << "Error: " << ptrGrabResult->GetErrorCode() << " " << ptrGrabResult->GetErrorDescription() << endl;
            }


         }
        catch (const GenericException &e)
        {
            // Error handling.
            cerr << "An exception occurred." << endl
            << e.GetDescription() << endl;
        }

        // Return opencv image
        return boost::python::make_tuple(false, pbcvt::fromMatToNDArray(Mat()));
    }

Но когда я пытаюсь скомпилировать, я получаю следующую ошибку:

In file included from /usr/include/boost/python/call.hpp:15:0,
                 from /usr/include/boost/python/object_core.hpp:14,
                 from /usr/include/boost/python/args.hpp:25,
                 from /usr/include/boost/python.hpp:11,
                 from /home/anand/docker/pybasler/src/pyBasler.cpp:3:
/usr/include/boost/python/converter/arg_to_python.hpp: In instantiation of ‘static void boost::python::converter::detail::reject_raw_object_helper<T, Convertibility>::error(Convertibility) [with T = _object; Convertibility = char*]’:
/usr/include/boost/python/converter/arg_to_python.hpp:189:57:   required from ‘void boost::python::converter::detail::reject_raw_object_ptr(T*) [with T = _object]’
/usr/include/boost/python/converter/arg_to_python.hpp:217:36:   required from ‘boost::python::converter::detail::pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr) [with Ptr = _object*]’
/usr/include/boost/python/converter/arg_to_python.hpp:256:13:   required from ‘boost::python::converter::arg_to_python<T>::arg_to_python(const T&) [with T = _object*]’
/usr/include/boost/python/object_core.hpp:292:44:   required from ‘static PyObject* boost::python::api::object_initializer_impl<is_proxy, is_object_manager>::get(const T&, mpl_::false_) [with T = _object*; bool is_proxy = false; bool is_object_manager = false; PyObject = _object; mpl_::false_ = mpl_::bool_<false>]’
/usr/include/boost/python/object_core.hpp:235:13:   required from ‘PyObject* boost::python::api::object_base_initializer(const T&) [with T = _object*; PyObject = _object]’
/usr/include/boost/python/object_core.hpp:250:46:   required from ‘boost::python::api::object::object(const T&) [with T = _object*]’
/usr/include/boost/python/detail/make_tuple.hpp:25:9:   required from ‘boost::python::tuple boost::python::make_tuple(const A0&, const A1&) [with A0 = bool; A1 = _object*]’
/home/anand/docker/pybasler/src/pyBasler.cpp:130:63:   required from here
/usr/include/boost/python/converter/arg_to_python.hpp:181:72: error: incomplete type ‘boost::python::converter::detail::cannot_convert_raw_PyObject<_object*>’ used in nested name specifier
           cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead();
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
/usr/include/boost/python/converter/arg_to_python.hpp: In instantiation of ‘static void boost::python::converter::detail::reject_raw_object_helper<T, Convertibility>::error(Convertibility) [with T = _object; Convertibility = int*]’:
/usr/include/boost/python/converter/arg_to_python.hpp:194:56:   required from ‘void boost::python::converter::detail::reject_raw_object_ptr(T*) [with T = _object]’
/usr/include/boost/python/converter/arg_to_python.hpp:217:36:   required from ‘boost::python::converter::detail::pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr) [with Ptr = _object*]’
/usr/include/boost/python/converter/arg_to_python.hpp:256:13:   required from ‘boost::python::converter::arg_to_python<T>::arg_to_python(const T&) [with T = _object*]’
/usr/include/boost/python/object_core.hpp:292:44:   required from ‘static PyObject* boost::python::api::object_initializer_impl<is_proxy, is_object_manager>::get(const T&, mpl_::false_) [with T = _object*; bool is_proxy = false; bool is_object_manager = false; PyObject = _object; mpl_::false_ = mpl_::bool_<false>]’
/usr/include/boost/python/object_core.hpp:235:13:   required from ‘PyObject* boost::python::api::object_base_initializer(const T&) [with T = _object*; PyObject = _object]’
/usr/include/boost/python/object_core.hpp:250:46:   required from ‘boost::python::api::object::object(const T&) [with T = _object*]’
/usr/include/boost/python/detail/make_tuple.hpp:25:9:   required from ‘boost::python::tuple boost::python::make_tuple(const A0&, const A1&) [with A0 = bool; A1 = _object*]’
/home/anand/docker/pybasler/src/pyBasler.cpp:130:63:   required from here
/usr/include/boost/python/converter/arg_to_python.hpp:181:72: error: incomplete type ‘boost::python::converter::detail::cannot_convert_raw_PyObject<_object*>’ used in nested name specifier
CMakeFiles/pbcvt.dir/build.make:62 : la recette pour la cible « CMakeFiles/pbcvt.dir/src/pyBasler.cpp.o » a échouée
make[2]: *** [CMakeFiles/pbcvt.dir/src/pyBasler.cpp.o] Erreur 1
CMakeFiles/Makefile2:67 : la recette pour la cible « CMakeFiles/pbcvt.dir/all » a échouée
make[1]: *** [CMakeFiles/pbcvt.dir/all] Erreur 2
Makefile:129 : la recette pour la cible « all » a échouée
make: *** [all] Erreur 2

Что я делаю неправильно? И как я мог получить желаемый результат?

1 ответ

Решение

Ключевым индикатором проблемы является эта строка в ошибке компиляции:

/usr/include/boost/python/converter/arg_to_python.hpp:181:72: error: incomplete type ‘boost::python::converter::detail::cannot_convert_raw_PyObject<_object*>’ used in nested name specifier
       cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead();

Это говорит о том, что вы не можете напрямую преобразовать PyObject* для object, Вы должны сказать ему, как обращаться с правом собственности на PyObject*, Это сделано с boost::python::handle тип.

Таким образом, изменив эту строку:

return boost::python::make_tuple(true, ret);

чтобы:

boost::python::make_tuple(true, boost::python::handle<>(ret));

разрешит ошибку.

Другие вопросы по тегам