Как мне вернуть 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));
разрешит ошибку.