pybind11: вернуть класс c ++ (с существующей привязкой python) к python - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь создать оболочку для метода c ++, который возвращает класс c ++ (vtkPolyData), который поступает из внешней библиотеки c ++ (vtk).В этой же библиотеке доступна привязка к python, которая уже установлена ​​в моей среде python.Как вы говорите pybind, что класс c ++ (vtkPolydata) и его вариант python совпадают?

Я пытался использовать этот макрос кастера нестандартного типа .но я получаю TypeError: Unable to convert function return value to a Python type! The signature was : (self: Versa3dLib.skeletonizer, offset distance: float) -> vtkPolyData

, что сбивает с толку, поскольку похоже, что преобразование соответствует правильному типу, но python не может его интерпретировать.Так что я не уверен, что не так, так как я не вижу ничего плохого и с макросом.Я заметил, что в python vtkPolyData имеет тип vtkCommonDataModelPython.vtkPolyData.Это почему преобразование не сделано правильно?

#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"));
}

Скелетонизатор

#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

Скелетонизатор cpp

#include "skeletonizer.h"


skeletonizer::skeletonizer(vtkPolyData* data)
{
};

vtkSmartPointer<vtkPolyData> skeletonizer::get_offset(double dist)
{
    vtkSmartPointer<vtkPolyData> offsets = vtkSmartPointer<vtkPolyData>::New();

    return offsets;
};

1 Ответ

0 голосов
/ 27 февраля 2019

Я думаю, что это должно быть более общее решение (надеюсь, проще в использовании?):

Я считаю, что это должно бытьулучшение кода VTK за счет:

  • Обобщение кастеров типов с использованием SFINAE (вместо того, чтобы требовать явных экземпляров ...).
  • Разрешить прямое приведение vtkSmartPointer и vtkNew (при условии, что типы внутри них являются типами VTK).

Сделан код, подобный следующему Соглашения о связывании Python C ++ + .

Для вышеупомянутогоРешение, которое у вас было, я думаю, что оно было близко к использованию кода SMTK, но инстанция типа держателя была неправильной - вам потребовалось бы type_caster специализаций для интеллектуальных указателей (которые предоставил бы код vtk_pybind, который я разместил).

Я посмотрю, смогу ли я опубликовать вопрос на SMTK, чтобы узнать, хотят ли они улучшить/ упростить их обязательный код (особенноесли люди обращаются к нему!).

РЕДАКТИРОВАТЬ: Опубликовано проблема здесь: https://gitlab.kitware.com/cmb/smtk/issues/228

...