Nektar++
VtkWrapper.hpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: VtkWrapper.hpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Helper routines from extracting VTK object pointers.
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#ifndef NEKTAR_FIELDUTILS_PYTHON_VTKWRAPPER_HPP
36#define NEKTAR_FIELDUTILS_PYTHON_VTKWRAPPER_HPP
37
38#include <vtkObjectBase.h>
39#include <vtkSmartPointer.h>
40#include <vtkVersion.h>
41
43
44/*
45 * Adapted from the code at:
46 * https://www.paraview.org/Wiki/Example_from_and_to_python_converters
47 *
48 * and: https://github.com/EricCousineau-TRI/repro/tree/master/python/vtk_pybind
49 */
50
51namespace pybind11::detail
52{
53
54template <typename T>
55struct type_caster<T, enable_if_t<std::is_base_of_v<vtkObjectBase, T>>>
56{
57private:
58 // Store value as a pointer
60
61public:
62 static constexpr auto name = _<T>();
63
64 bool load(handle src, bool)
65 {
66 std::string thisStr = "__this__";
67
68 PyObject *obj = src.ptr();
69
70 // first we need to get the __this__ attribute from the Python Object
71 if (!PyObject_HasAttrString(obj, thisStr.c_str()))
72 {
73 return false;
74 }
75
76 PyObject *thisAttr = PyObject_GetAttrString(obj, thisStr.c_str());
77 if (thisAttr == nullptr)
78 {
79 return false;
80 }
81
82 std::string str = PyUnicode_AsUTF8(thisAttr);
83
84 if (str.size() < 21)
85 {
86 return false;
87 }
88
89 auto iter = str.find("_p_vtk");
90 if (iter == std::string::npos)
91 {
92 return false;
93 }
94
95 auto className = str.substr(iter).find("vtk");
96 if (className == std::string::npos)
97 {
98 return false;
99 }
100
101 long address = stol(str.substr(1, 17));
102 vtkObjectBase *vtkObject = (vtkObjectBase *)((void *)address);
103
104 if (vtkObject->IsA(str.substr(className).c_str()))
105 {
106 value = vtkObject;
107 return true;
108 }
109
110 return false;
111 }
112
113 static handle cast(const T *src, return_value_policy policy, handle parent)
114 {
115 if (src == nullptr)
116 {
117 return none().release();
118 }
119
120 std::ostringstream oss;
121 oss << (vtkObjectBase *)src; // here don't get address
122 std::string address_str = oss.str();
123
124 try
125 {
126 py::object obj = py::module_::import("vtkmodules.vtkCommonCore")
127 .attr("vtkObjectBase")(address_str);
128 return obj.release();
129 }
130 catch (py::error_already_set &)
131 {
132 // Clear error to avoid potential failure to catch error in next
133 // try-catch block.
134 PyErr_Clear();
135 }
136
137 try
138 {
139 py::object obj =
140 py::module_::import("vtk").attr("vtkObjectBase")(address_str);
141 return obj.release();
142 }
143 catch (py::error_already_set &)
144 {
146 throw NekError("Unable to import VTK.");
147 }
148
149 // Should never get here!
150 return none().release();
151 }
152};
153
154/// VTK Pointer-like object - may be non-copyable.
155template <typename Ptr> struct vtk_ptr_cast_only
156{
157protected:
158 using Class = intrinsic_t<decltype(*std::declval<Ptr>())>;
159 using value_caster_type = type_caster<Class>;
160
161public:
162 static constexpr auto name = _<Class>();
163 static handle cast(const Ptr &ptr, return_value_policy policy,
164 handle parent)
165 {
166 return value_caster_type::cast(*ptr, policy, parent);
167 ;
168 }
169};
170
171/// VTK Pointer-like object - copyable / movable.
172template <typename Ptr>
174{
175private:
176 Ptr value;
177 // N.B. Can't easily access base versions...
178 using Class = intrinsic_t<decltype(*std::declval<Ptr>())>;
179 using value_caster_type = type_caster<Class>;
180
181public:
182 operator Ptr &()
183 {
184 return value;
185 }
186 // Does this even make sense in VTK?
187 operator Ptr &&() &&
188 {
189 return std::move(value);
190 }
191
192 template <typename T_>
193 using cast_op_type = pybind11::detail::movable_cast_op_type<T_>;
194
195 bool load(handle src, bool convert)
196 {
197 value_caster_type value_caster;
198 if (!value_caster.load(src, convert))
199 {
200 return false;
201 }
202 value = Ptr(value_caster.operator Class *());
203 return true;
204 }
205};
206
207template <typename Class>
208struct type_caster<vtkSmartPointer<Class>>
209 : public vtk_ptr_cast_and_load<vtkSmartPointer<Class>>
210{
211};
212
213template <typename Class>
214struct type_caster<vtkNew<Class>> : public vtk_ptr_cast_only<vtkNew<Class>>
215{
216};
217
218} // namespace pybind11::detail
219
220#endif
Nektar::ErrorUtil::NekError NekError
STL namespace.
static handle cast(const T *src, return_value_policy policy, handle parent)
Definition: VtkWrapper.hpp:113
VTK Pointer-like object - copyable / movable.
Definition: VtkWrapper.hpp:174
bool load(handle src, bool convert)
Definition: VtkWrapper.hpp:195
pybind11::detail::movable_cast_op_type< T_ > cast_op_type
Definition: VtkWrapper.hpp:193
VTK Pointer-like object - may be non-copyable.
Definition: VtkWrapper.hpp:156
static handle cast(const Ptr &ptr, return_value_policy policy, handle parent)
Definition: VtkWrapper.hpp:163
type_caster< Class > value_caster_type
Definition: VtkWrapper.hpp:159