Reputation: 171
I am trying to create a wrapper for a c++ method that returns a c++ class(vtkPolyData) which comes from an external c++ library (vtk). The same library has python binding available which is already installed in my python environment. How do you tell pybind that the c++ class (vtkPolydata) and its python variant are the same?
I tried to use this custom type caster macro. but I get TypeError: Unable to convert function return value to a Python type! The signature was : (self: Versa3dLib.skeletonizer, offset distance: float) -> vtkPolyData
which is confusing since it looks like the conversion maps to the correct type but python is unable to interpret it. So I am not sure what's wrong since I don't see anything wrong with the macro either. I noticed that in python vtkPolyData has type vtkCommonDataModelPython.vtkPolyData
. is that why the conversion is not done correctly?
#include "skeletonizer.h"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "PybindVTKTypeCaster.h"
#include <vtkSmartPointer.h>
namespace py = pybind11;
PYBIND11_VTK_TYPECASTER(vtkPolyData)
PYBIND11_DECLARE_HOLDER_TYPE(T, vtkSmartPointer<T>);
namespace pybind11 { namespace detail {
template <typename T>
struct holder_helper<vtkSmartPointer<T>> { // <-- specialization
static const T *get(const vtkSmartPointer<T> &p) { return p.GetPointer(); }
};
}}
PYBIND11_MODULE(Versa3dLib, m)
{
py::class_<skeletonizer>(m, "skeletonizer")
.def(py::init<vtkPolyData *>())
.def("get_offset", &skeletonizer::get_offset,
"return vtkPolyData offset",
py::arg("offset distance"));
}
Skeletonizer
#ifndef SKELETONIZER_H
#define SKELETONIZER_H
#include <vtkPolyData.h>
#include <vector>
#include <vtkSmartPointer.h>
using namespace std;
class skeletonizer
{
public:
skeletonizer(vtkPolyData* data);
vtkSmartPointer<vtkPolyData> get_offset(double dist);
};
#endif
skeletonizer cpp
#include "skeletonizer.h"
skeletonizer::skeletonizer(vtkPolyData* data)
{
};
vtkSmartPointer<vtkPolyData> skeletonizer::get_offset(double dist)
{
vtkSmartPointer<vtkPolyData> offsets = vtkSmartPointer<vtkPolyData>::New();
return offsets;
};
Upvotes: 4
Views: 4461
Reputation: 2004
I think this should be a more general solution (hopefully easier to use?):
I believe this should be an improvement on the VTK code by:
vtkSmartPointer
and vtkNew
(assuming the types inside these are VTK types).Made the code kind-of follow Drake's C++ + Python binding conventions.
For the above solution you had, I think it was close leveraging the SMTK code, but the holder type instantation was incorrect - you'd need type_caster
specializations for the smart pointers (which the vtk_pybind
code I posted would provide).
I'll see if I can post an issue on SMTK to see if they want to improve / simplify their binding code (esp. if people refer to it!).
EDIT: Posted issue here: https://gitlab.kitware.com/cmb/smtk/issues/228
Upvotes: 1