Skip to content

Commit

Permalink
Introduce std::shared_ptr as default type holder for python bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
SamFlt committed May 5, 2024
1 parent 73361d0 commit c1825dd
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 53 deletions.
2 changes: 1 addition & 1 deletion modules/python/bindings/include/blob.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

namespace py = pybind11;

void bindings_vpDot2(py::class_<vpDot2, vpTracker> &pyDot2)
void bindings_vpDot2(py::class_<vpDot2, std::shared_ptr<vpDot2>, vpTracker> &pyDot2)
{
pyDot2.def_static("defineDots", [](std::vector<vpDot2> &dots,
const std::string &dotFile,
Expand Down
28 changes: 14 additions & 14 deletions modules/python/bindings/include/core/arrays.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ const char *numpy_fn_doc_nonwritable = R"doc(
)doc";

template<typename T>
void bindings_vpArray2D(py::class_<vpArray2D<T>> &pyArray2D)
void bindings_vpArray2D(py::class_<vpArray2D<T>, std::shared_ptr<vpArray2D<T>>> &pyArray2D)
{
pyArray2D.def_buffer(&get_buffer_info<T, vpArray2D>);

Expand All @@ -239,10 +239,10 @@ Construct a 2D ViSP array by **copying** a 2D numpy array.
)doc", py::arg("np_array"));

define_get_item_2d_array<py::class_<vpArray2D<T>>, vpArray2D<T>, T>(pyArray2D);
define_get_item_2d_array<py::class_<vpArray2D<T>, std::shared_ptr<vpArray2D<T>>>, vpArray2D<T>, T>(pyArray2D);
}

void bindings_vpMatrix(py::class_<vpMatrix, vpArray2D<double>> &pyMatrix)
void bindings_vpMatrix(py::class_<vpMatrix, std::shared_ptr<vpMatrix>, vpArray2D<double>> &pyMatrix)
{
pyMatrix.def_buffer(&get_buffer_info<vpMatrix>);

Expand All @@ -268,11 +268,11 @@ Construct a matrix by **copying** a 2D numpy array.
add_print_helper(pyMatrix, &vpMatrix::matlabPrint, "strMatlab", matlab_str_help);
add_cpp_print_helper(pyMatrix, &vpMatrix::cppPrint);

define_get_item_2d_array<py::class_<vpMatrix, vpArray2D<double>>, vpMatrix, double>(pyMatrix);
define_get_item_2d_array<py::class_<vpMatrix, std::shared_ptr<vpMatrix>, vpArray2D<double>>, vpMatrix, double>(pyMatrix);
}


void bindings_vpRotationMatrix(py::class_<vpRotationMatrix, vpArray2D<double>> &pyRotationMatrix)
void bindings_vpRotationMatrix(py::class_<vpRotationMatrix, std::shared_ptr<vpRotationMatrix>, vpArray2D<double>> &pyRotationMatrix)
{

pyRotationMatrix.def_buffer(&get_buffer_info<vpRotationMatrix>);
Expand All @@ -296,10 +296,10 @@ If it is not a rotation matrix, an exception will be raised.
:param np_array: The numpy 1D array to copy.
)doc", py::arg("np_array"));
define_get_item_2d_array<py::class_<vpRotationMatrix, vpArray2D<double>>, vpRotationMatrix, double>(pyRotationMatrix);
define_get_item_2d_array<py::class_<vpRotationMatrix, std::shared_ptr<vpRotationMatrix>, vpArray2D<double>>, vpRotationMatrix, double>(pyRotationMatrix);
}

void bindings_vpHomogeneousMatrix(py::class_<vpHomogeneousMatrix, vpArray2D<double>> &pyHomogeneousMatrix)
void bindings_vpHomogeneousMatrix(py::class_<vpHomogeneousMatrix, std::shared_ptr<vpHomogeneousMatrix>, vpArray2D<double>> &pyHomogeneousMatrix)
{
pyHomogeneousMatrix.def_buffer(get_buffer_info<vpHomogeneousMatrix>);
pyHomogeneousMatrix.def("numpy", [](vpHomogeneousMatrix &self) -> np_array_cf<double> {
Expand All @@ -323,12 +323,12 @@ If it is not a homogeneous matrix, an exception will be raised.
:param np_array: The numpy 1D array to copy.
)doc", py::arg("np_array"));
define_get_item_2d_array<py::class_<vpHomogeneousMatrix, vpArray2D<double>>, vpHomogeneousMatrix, double>(pyHomogeneousMatrix);
define_get_item_2d_array<py::class_<vpHomogeneousMatrix, std::shared_ptr<vpHomogeneousMatrix>, vpArray2D<double>>, vpHomogeneousMatrix, double>(pyHomogeneousMatrix);
}



void bindings_vpTranslationVector(py::class_<vpTranslationVector, vpArray2D<double>> &pyTranslationVector)
void bindings_vpTranslationVector(py::class_<vpTranslationVector, std::shared_ptr<vpTranslationVector>, vpArray2D<double>> &pyTranslationVector)
{
pyTranslationVector.def_buffer(&get_buffer_info<vpTranslationVector>);

Expand All @@ -349,11 +349,11 @@ Construct a Translation vector by **copying** a 1D numpy array of size 3.
:param np_array: The numpy 1D array to copy.
)doc", py::arg("np_array"));
define_get_item_1d_array<py::class_<vpTranslationVector, vpArray2D<double>>, vpTranslationVector, double>(pyTranslationVector);
define_get_item_1d_array<py::class_<vpTranslationVector, std::shared_ptr<vpTranslationVector>, vpArray2D<double>>, vpTranslationVector, double>(pyTranslationVector);
}


void bindings_vpColVector(py::class_<vpColVector, vpArray2D<double>> &pyColVector)
void bindings_vpColVector(py::class_<vpColVector, std::shared_ptr<vpColVector>, vpArray2D<double>> &pyColVector)
{
pyColVector.def_buffer(&get_buffer_info<vpColVector>);

Expand All @@ -373,7 +373,7 @@ Construct a column vector by **copying** a 1D numpy array.
:param np_array: The numpy 1D array to copy.
)doc", py::arg("np_array"));
define_get_item_1d_array<py::class_<vpColVector, vpArray2D<double>>, vpColVector, double>(pyColVector);
define_get_item_1d_array<py::class_<vpColVector, std::shared_ptr<vpColVector>, vpArray2D<double>>, vpColVector, double>(pyColVector);

add_print_helper(pyColVector, &vpColVector::csvPrint, "strCsv", csv_str_help);
add_print_helper(pyColVector, &vpColVector::maplePrint, "strMaple", maple_str_help);
Expand All @@ -382,7 +382,7 @@ Construct a column vector by **copying** a 1D numpy array.

}

void bindings_vpRowVector(py::class_<vpRowVector, vpArray2D<double>> &pyRowVector)
void bindings_vpRowVector(py::class_<vpRowVector, std::shared_ptr<vpRowVector>, vpArray2D<double>> &pyRowVector)
{
pyRowVector.def_buffer(&get_buffer_info<vpRowVector>);
pyRowVector.def("numpy", [](vpRowVector &self) -> np_array_cf<double> {
Expand All @@ -400,7 +400,7 @@ Construct a row vector by **copying** a 1D numpy array.
:param np_array: The numpy 1D array to copy.
)doc", py::arg("np_array"));
define_get_item_1d_array<py::class_<vpRowVector, vpArray2D<double>>, vpRowVector, double>(pyRowVector);
define_get_item_1d_array<py::class_<vpRowVector, std::shared_ptr<vpRowVector>, vpArray2D<double>>, vpRowVector, double>(pyRowVector);
add_print_helper(pyRowVector, &vpRowVector::csvPrint, "strCsv", csv_str_help);
add_print_helper(pyRowVector, &vpRowVector::maplePrint, "strMaple", maple_str_help);
add_print_helper(pyRowVector, &vpRowVector::matlabPrint, "strMatlab", matlab_str_help);
Expand Down
56 changes: 28 additions & 28 deletions modules/python/bindings/include/core/image_conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct SimpleConversionStruct
unsigned int srcBytesPerPixel;
unsigned int destBytesPerPixel;

void add_conversion_binding(py::class_<vpImageConvert> &pyImageConvert)
void add_conversion_binding(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert)
{
pyImageConvert.def_static(name.c_str(), [this](py::array_t<unsigned char, py::array::c_style> &src,
py::array_t<unsigned char, py::array::c_style> &dest) {
Expand Down Expand Up @@ -123,7 +123,7 @@ struct SimpleConversionStruct<ConversionFunction2DWithFlip>
unsigned int srcBytesPerPixel;
unsigned int destBytesPerPixel;

void add_conversion_binding(py::class_<vpImageConvert> &pyImageConvert)
void add_conversion_binding(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert)
{
pyImageConvert.def_static(name.c_str(), [this](py::array_t<unsigned char, py::array::c_style> &src,
py::array_t<unsigned char, py::array::c_style> &dest, bool flip) {
Expand Down Expand Up @@ -172,7 +172,7 @@ struct ConversionFromYUVLike

unsigned int destBytesPerPixel;

void add_conversion_binding(py::class_<vpImageConvert> &pyImageConvert)
void add_conversion_binding(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert)
{
pyImageConvert.def_static(name.c_str(), [this](py::array_t<unsigned char, py::array::c_style> &src,
py::array_t<unsigned char, py::array::c_style> &dest) {
Expand Down Expand Up @@ -228,26 +228,26 @@ unsigned size411(unsigned h, unsigned w)

void rgb_or_rgba_to_hsv_verification(const py::buffer_info &bufsrc, const py::buffer_info &bufdest, const unsigned destBytes, const unsigned height, const unsigned width)
{
if (bufsrc.ndim != 3 || bufdest.ndim != 3) {
throw std::runtime_error("Expected to have src and dest arrays with at least two dimensions.");
}
if (bufdest.shape[0] != 3) {
throw std::runtime_error("Source array should be a 3D array of shape (3, H, W) ");
}
if (bufsrc.shape[2] != destBytes) {
std::stringstream ss;
ss << "Target array should be a 3D array of shape (H, W, " << destBytes << ")";
throw std::runtime_error(ss.str());
}
if (bufsrc.shape[0] != height || bufsrc.shape[1] != width) {
std::stringstream ss;
ss << "src and dest must have the same number of pixels, but got HSV planes with dimensions (" << height << ", " << width << ")";
ss << "and RGB array with dimensions (" << bufdest.shape[0] << ", " << bufdest.shape[1] << ")";
throw std::runtime_error(ss.str());
}
if (bufsrc.ndim != 3 || bufdest.ndim != 3) {
throw std::runtime_error("Expected to have src and dest arrays with at least two dimensions.");
}
if (bufdest.shape[0] != 3) {
throw std::runtime_error("Source array should be a 3D array of shape (3, H, W) ");
}
if (bufsrc.shape[2] != destBytes) {
std::stringstream ss;
ss << "Target array should be a 3D array of shape (H, W, " << destBytes << ")";
throw std::runtime_error(ss.str());
}
if (bufsrc.shape[0] != height || bufsrc.shape[1] != width) {
std::stringstream ss;
ss << "src and dest must have the same number of pixels, but got HSV planes with dimensions (" << height << ", " << width << ")";
ss << "and RGB array with dimensions (" << bufdest.shape[0] << ", " << bufdest.shape[1] << ")";
throw std::runtime_error(ss.str());
}
}

void add_hsv_double_to_rgb_or_rgba_binding(py::class_<vpImageConvert> &pyImageConvert,
void add_hsv_double_to_rgb_or_rgba_binding(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert,
void (*fn)(const double *, const double *, const double *, unsigned char *, unsigned int), const char *name, const unsigned destBytes)
{
pyImageConvert.def_static(name, [fn, destBytes](py::array_t<double, py::array::c_style> &src,
Expand All @@ -266,7 +266,7 @@ void add_hsv_double_to_rgb_or_rgba_binding(py::class_<vpImageConvert> &pyImageCo
}, "Convert from HSV Planes (as a 3 x H x W array) to a an RGB/RGBA array (as an H x W x 3 or H x W x 4 array)", py::arg("hsv"), py::arg("rgb"));
}

void add_hsv_uchar_to_rgb_or_rgba_binding(py::class_<vpImageConvert> &pyImageConvert,
void add_hsv_uchar_to_rgb_or_rgba_binding(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert,
void (*fn)(const unsigned char *, const unsigned char *, const unsigned char *, unsigned char *, unsigned int, bool), const char *name, const unsigned destBytes)
{
pyImageConvert.def_static(name, [fn, destBytes](py::array_t<unsigned char, py::array::c_style> &src,
Expand All @@ -282,10 +282,10 @@ void add_hsv_uchar_to_rgb_or_rgba_binding(py::class_<vpImageConvert> &pyImageCon
unsigned char *dest_ptr = static_cast<unsigned char *>(bufdest.ptr);
fn(h, s, v, dest_ptr, height * width, h_full);

}, "Convert from HSV Planes (as a 3 x H x W array) to a an RGB/RGBA array (as an H x W x 3 or H x W x 4 array)", py::arg("hsv"), py::arg("rgb"), py::arg("h_full")=true);
}, "Convert from HSV Planes (as a 3 x H x W array) to a an RGB/RGBA array (as an H x W x 3 or H x W x 4 array)", py::arg("hsv"), py::arg("rgb"), py::arg("h_full") = true);
}

void add_rgb_or_rgba_uchar_to_hsv_binding(py::class_<vpImageConvert> &pyImageConvert,
void add_rgb_or_rgba_uchar_to_hsv_binding(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert,
void (*fn)(const unsigned char *, unsigned char *, unsigned char *, unsigned char *, unsigned int, bool), const char *name, const unsigned destBytes)
{
pyImageConvert.def_static(name, [fn, destBytes](py::array_t<unsigned char, py::array::c_style> &src,
Expand All @@ -302,10 +302,10 @@ void add_rgb_or_rgba_uchar_to_hsv_binding(py::class_<vpImageConvert> &pyImageCon
const unsigned char *rgb = static_cast<unsigned char *>(bufsrc.ptr);
fn(rgb, h, s, v, height * width, h_full);

}, "Convert from HSV Planes (as a 3 x H x W array) to a an RGB/RGBA array (as an H x W x 3 or H x W x 4 array)", py::arg("rgb"), py::arg("hsv"), py::arg("h_full")=true);
}, "Convert from HSV Planes (as a 3 x H x W array) to a an RGB/RGBA array (as an H x W x 3 or H x W x 4 array)", py::arg("rgb"), py::arg("hsv"), py::arg("h_full") = true);
}

void add_rgb_or_rgba_double_to_hsv_binding(py::class_<vpImageConvert> &pyImageConvert,
void add_rgb_or_rgba_double_to_hsv_binding(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert,
void (*fn)(const unsigned char *, double *, double *, double *, unsigned int), const char *name, const unsigned destBytes)
{
pyImageConvert.def_static(name, [fn, destBytes](py::array_t<unsigned char, py::array::c_style> &src,
Expand All @@ -326,7 +326,7 @@ void add_rgb_or_rgba_double_to_hsv_binding(py::class_<vpImageConvert> &pyImageCo

/* Demosaicing implem */
template <class DataType>
void add_demosaic_to_rgba_fn(py::class_<vpImageConvert> &pyImageConvert, void (*fn)(const DataType *, DataType *, unsigned int, unsigned int, unsigned int), const char *name)
void add_demosaic_to_rgba_fn(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert, void (*fn)(const DataType *, DataType *, unsigned int, unsigned int, unsigned int), const char *name)
{
pyImageConvert.def_static(name, [fn](py::array_t<DataType, py::array::c_style> &src,
py::array_t<DataType, py::array::c_style> &dest,
Expand Down Expand Up @@ -360,7 +360,7 @@ void add_demosaic_to_rgba_fn(py::class_<vpImageConvert> &pyImageConvert, void (*

}

void bindings_vpImageConvert(py::class_<vpImageConvert> &pyImageConvert)
void bindings_vpImageConvert(py::class_<vpImageConvert, std::shared_ptr<vpImageConvert>> &pyImageConvert)
{
// Simple conversions where the size input is a single argument
{
Expand Down
8 changes: 4 additions & 4 deletions modules/python/bindings/include/core/images.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const char *numpy_fn_doc_image = R"doc(
* Image 2D indexing
*/
template<typename T, typename NpRep>
void define_get_item_2d_image(py::class_<vpImage<T>> &pyClass)
void define_get_item_2d_image(py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>> &pyClass)
{
pyClass.def("__getitem__", [](const vpImage<T> &self, std::pair<int, int> pair) -> T {
int i = pair.first, j = pair.second;
Expand Down Expand Up @@ -98,7 +98,7 @@ void define_get_item_2d_image(py::class_<vpImage<T>> &pyClass)
*/
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value, void>::type
bindings_vpImage(py::class_<vpImage<T>> &pyImage)
bindings_vpImage(py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>> &pyImage)
{
pyImage.def_buffer([](vpImage<T> &image) -> py::buffer_info {
return make_array_buffer<T, 2>(image.bitmap, { image.getHeight(), image.getWidth() }, false);
Expand Down Expand Up @@ -138,7 +138,7 @@ Construct an image by **copying** a 2D numpy array.

template<typename T>
typename std::enable_if<std::is_same<vpRGBa, T>::value, void>::type
bindings_vpImage(py::class_<vpImage<T>> &pyImage)
bindings_vpImage(py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>> &pyImage)
{
using NpRep = unsigned char;
static_assert(sizeof(T) == 4 * sizeof(NpRep));
Expand Down Expand Up @@ -182,7 +182,7 @@ where the 4 denotes the red, green, blue and alpha components of the image.
}
template<typename T>
typename std::enable_if<std::is_same<vpRGBf, T>::value, void>::type
bindings_vpImage(py::class_<vpImage<T>> &pyImage)
bindings_vpImage(py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>> &pyImage)
{
using NpRep = float;
static_assert(sizeof(T) == 3 * sizeof(NpRep));
Expand Down
4 changes: 2 additions & 2 deletions modules/python/bindings/include/core/pixel_meter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

#include "core/utils.hpp"

void bindings_vpPixelMeterConversion(py::class_<vpPixelMeterConversion> &pyPM)
void bindings_vpPixelMeterConversion(py::class_<vpPixelMeterConversion, std::shared_ptr<vpPixelMeterConversion>> &pyPM)
{
pyPM.def_static("convertPoints", [](const vpCameraParameters &cam, const py::array_t<double> &us, const py::array_t<double> &vs) {
py::buffer_info bufu = us.request(), bufv = vs.request();
Expand Down Expand Up @@ -107,7 +107,7 @@ Example usage:
)doc", py::arg("cam"), py::arg("us"), py::arg("vs"));
}

void bindings_vpMeterPixelConversion(py::class_<vpMeterPixelConversion> &pyMP)
void bindings_vpMeterPixelConversion(py::class_<vpMeterPixelConversion, std::shared_ptr<vpMeterPixelConversion>> &pyMP)
{
pyMP.def_static("convertPoints", [](const vpCameraParameters &cam, const py::array_t<double> &xs, const py::array_t<double> &ys) {
py::buffer_info bufx = xs.request(), bufy = ys.request();
Expand Down
2 changes: 1 addition & 1 deletion modules/python/bindings/include/mbt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

namespace py = pybind11;

void bindings_vpMbGenericTracker(py::class_<vpMbGenericTracker, vpMbTracker> &pyMbGenericTracker)
void bindings_vpMbGenericTracker(py::class_<vpMbGenericTracker, std::shared_ptr<vpMbGenericTracker>, vpMbTracker> &pyMbGenericTracker)
{
pyMbGenericTracker.def("track", [](vpMbGenericTracker &self, std::map<std::string, const vpImage<unsigned char> *> &mapOfImages,
std::map<std::string, py::array_t<double, py::array::c_style>> &mapOfPointClouds) {
Expand Down
6 changes: 4 additions & 2 deletions modules/python/generator/visp_python_bindgen/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,14 @@ def add_method_doc_to_pyargs(method: types.Method, py_arg_strs: List[str]) -> Li
# Reference public base classes when creating pybind class binding
base_class_strs = list(map(lambda base_class: get_typename(base_class.typename, owner_specs, header_env.mapping),
filter(lambda b: b.access == 'public', cls.class_decl.bases)))
class_template_str = ', '.join([name_cpp] + base_class_strs)
# py::class template contains the class, its holder type, and its base clases.
# The default holder type is std::unique_ptr. when the cpp function argument is a shared_ptr, Pybind will raise an error when calling the method.
py_class_template_str = ', '.join([name_cpp, f'std::shared_ptr<{name_cpp}>'] + base_class_strs)
doc_param = [] if class_doc is None else [class_doc.documentation]
buffer_protocol_arg = ['py::buffer_protocol()'] if cls_config['use_buffer_protocol'] else []
cls_argument_strs = ['submodule', f'"{name_python}"'] + doc_param + buffer_protocol_arg

class_decl = f'\tpy::class_ {python_ident} = py::class_<{class_template_str}>({", ".join(cls_argument_strs)});'
class_decl = f'\tpy::class_ {python_ident} = py::class_<{py_class_template_str}>({", ".join(cls_argument_strs)});'

# Definitions
# Skip constructors for classes that have pure virtual methods since they cannot be instantiated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ def build_naive_mapping(self, data: Union[NamespaceScope, ClassScope], mapping,
for typedef in data.typedefs:
if not name_is_anonymous(typedef.type.typename):
current_mapping[typedef.name] = get_type(typedef.type, {}, current_mapping)
print(current_mapping[typedef.name])
else:
current_mapping[typedef.name] = scope + typedef.name
for enum in data.enums:
Expand Down

0 comments on commit c1825dd

Please sign in to comment.