Nektar++
NekPyConfig.hpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: NekPyConfig.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: NekPy configuration to include boost headers and define
32// commonly-used macros.
33//
34///////////////////////////////////////////////////////////////////////////////
35
36#ifndef NEKTAR_LIBRARY_LIBUTILITIES_PYTHON_NEKPYCONFIG_HPP
37#define NEKTAR_LIBRARY_LIBUTILITIES_PYTHON_NEKPYCONFIG_HPP
38
39#include <boost/version.hpp>
40#include <memory>
41
42// Boost 1.62 and earlier don't have native support for std::shared_ptr. This
43// includes various patches that are pulled from the git changeset 97e4b34a15
44// from the main boost.python github repository, which is where fixes were
45// added to include std::shared_ptr support.
46#if BOOST_VERSION < 106300
47#include "ShPtrFixes.hpp"
48#endif
49
50#include "FunctorSignature.hpp"
51
52#ifdef BOOST_HAS_NUMPY
53
54#include <boost/python.hpp>
55#include <boost/python/numpy.hpp>
56
57namespace py = boost::python;
58namespace np = boost::python::numpy;
59
60#else
61
62#include <boost/numpy.hpp>
63#include <boost/python.hpp>
64
65namespace py = boost::python;
66namespace np = boost::numpy;
67
68#endif
69
70#define SIZENAME(s) SIZE_##s
71#define NEKPY_WRAP_ENUM(ENUMNAME, MAPNAME) \
72 { \
73 py::enum_<ENUMNAME> tmp(#ENUMNAME); \
74 for (int a = 0; a < (int)SIZENAME(ENUMNAME); ++a) \
75 { \
76 tmp.value(MAPNAME[a], (ENUMNAME)a); \
77 } \
78 tmp.export_values(); \
79 }
80#define NEKPY_WRAP_ENUM_STRING(ENUMNAME, MAPNAME) \
81 { \
82 py::enum_<ENUMNAME> tmp(#ENUMNAME); \
83 for (int a = 0; a < (int)SIZENAME(ENUMNAME); ++a) \
84 { \
85 tmp.value(MAPNAME[a].c_str(), (ENUMNAME)a); \
86 } \
87 tmp.export_values(); \
88 }
89#if PY_MAJOR_VERSION == 2
90#define NEKPY_WRAP_ENUM_STRING_DOCS(ENUMNAME, MAPNAME, DOCSTRING) \
91 { \
92 py::enum_<ENUMNAME> tmp(#ENUMNAME); \
93 for (int a = 0; a < (int)SIZENAME(ENUMNAME); ++a) \
94 { \
95 tmp.value(MAPNAME[a].c_str(), (ENUMNAME)a); \
96 } \
97 tmp.export_values(); \
98 PyTypeObject *pto = reinterpret_cast<PyTypeObject *>(tmp.ptr()); \
99 PyDict_SetItemString(pto->tp_dict, "__doc__", \
100 PyString_FromString(DOCSTRING)); \
101 }
102#else
103#define NEKPY_WRAP_ENUM_STRING_DOCS(ENUMNAME, MAPNAME, DOCSTRING) \
104 { \
105 py::enum_<ENUMNAME> tmp(#ENUMNAME); \
106 for (int a = 0; a < (int)SIZENAME(ENUMNAME); ++a) \
107 { \
108 tmp.value(MAPNAME[a].c_str(), (ENUMNAME)a); \
109 } \
110 tmp.export_values(); \
111 PyTypeObject *pto = reinterpret_cast<PyTypeObject *>(tmp.ptr()); \
112 PyDict_SetItemString(pto->tp_dict, "__doc__", \
113 PyUnicode_FromString(DOCSTRING)); \
114 }
115#endif
116
117#if BOOST_VERSION >= 106300
118
120{
121
122/** @brief shared_ptr_from_python specialization for std:shared_ptr
123 *
124 * @details
125 * The standard boost::python::shared_ptr_from_python have some special trick
126 * trying to preserve the python id(obj) for some simple use-patterns.
127 *
128 * This is done using a shared_ptr<void> with customer deleter with reference to
129 * the python object, allowing the same python object to be revealed to the
130 * python user.
131 *
132 * Unfortunately, that implementation breaks the weak-pointer mechanism of
133 * shared-ptr, invalidating any reasonable use inside the the c++ library.
134 *
135 * Thus, we choose to undo this approach, using standard robust c++ mechanisms,
136 * and sacrifice the 'id(obj)' requirement.
137 *
138 * Notice that the implementation is a copy of the original, with the exception
139 * of the construct method.
140 */
141template <class T> struct shared_ptr_from_python<T, std::shared_ptr>
142{
143
145 {
146 converter::registry::insert(
147 &convertible, &construct, type_id<std::shared_ptr<T>>()
148#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
149 ,
150 &converter::expected_from_python_type_direct<T>::get_pytype
151#endif
152 );
153 }
154
155private:
156 static void *convertible(PyObject *p)
157 {
158 if (p == Py_None)
159 {
160 return p;
161 }
162 return converter::get_lvalue_from_python(p, registered<T>::converters);
163 }
164
165 static void construct(PyObject *source,
166 rvalue_from_python_stage1_data *data)
167 {
168 void *const storage =
169 ((converter::rvalue_from_python_storage<std::shared_ptr<T>> *)data)
170 ->storage.bytes;
171 if (data->convertible == source)
172 {
173 new (storage) std::shared_ptr<T>();
174 }
175 else
176 {
177 reference_arg_from_python<std::shared_ptr<T> &> sp(source);
178 if (sp.convertible())
179 {
180 new (storage) std::shared_ptr<T>(sp());
181 }
182 else
183 {
184 std::shared_ptr<void> hold_convertible_ref_count(
185 (void *)nullptr,
186 shared_ptr_deleter(handle<>(borrowed(source))));
187 new (storage)
188 std::shared_ptr<T>(hold_convertible_ref_count,
189 static_cast<T *>(data->convertible));
190 }
191 }
192 data->convertible = storage;
193 }
194};
195
196} // namespace boost::python::converter
197
198#endif
199
200/**
201 * @brief Helper structure to construct C++ command line `argc` and `argv`
202 * variables from a Python list.
203 */
205{
206 /**
207 * @brief Constructor.
208 *
209 * @param py_argv List of command line arguments from Python.
210 */
211 CppCommandLine(py::list &py_argv) : m_argc(py::len(py_argv))
212 {
213 int i = 0;
214 size_t bufSize = 0;
215 char *p;
216
217 m_argv = new char *[m_argc + 1];
218
219 // Create argc, argv to give to the session reader. Note that this needs
220 // to be a contiguous block in memory, otherwise MPI (specifically
221 // OpenMPI) will likely segfault.
222 for (i = 0; i < m_argc; ++i)
223 {
224 std::string tmp = py::extract<std::string>(py_argv[i]);
225 bufSize += tmp.size() + 1;
226 }
227
228 m_buf.resize(bufSize);
229 for (i = 0, p = &m_buf[0]; i < m_argc; ++i)
230 {
231 std::string tmp = py::extract<std::string>(py_argv[i]);
232 std::copy(tmp.begin(), tmp.end(), p);
233 p[tmp.size()] = '\0';
234 m_argv[i] = p;
235 p += tmp.size() + 1;
236 }
237
238 m_argv[m_argc] = nullptr;
239 }
240
241 /**
242 * @brief Destructor.
243 */
245 {
246 if (m_argv == nullptr)
247 {
248 return;
249 }
250
251 delete m_argv;
252 }
253
254 /**
255 * @brief Returns the constructed `argv`.
256 */
257 char **GetArgv()
258 {
259 return m_argv;
260 }
261
262 /**
263 * @brief Returns the constructed `argc`.
264 */
266 {
267 return m_argc;
268 }
269
270private:
271 /// Pointers for strings `argv`.
272 char **m_argv = nullptr;
273 /// Number of arguments `argc`.
274 int m_argc = 0;
275 /// Buffer for storage of the argument strings.
276 std::vector<char> m_buf;
277};
278
279/**
280 * @brief A helper class that for factory-based classes allows
281 * std::shared_ptr<T> as something that boost::python recognises, otherwise
282 * modules constructed from the factory will not work from Python.
283 */
284template <typename T> struct WrapConverter
285{
287 {
288 py::objects::class_value_wrapper<
289 std::shared_ptr<T>,
290 py::objects::make_ptr_instance<
291 T, py::objects::pointer_holder<std::shared_ptr<T>, T>>>();
292 }
293};
294
295#endif
def copy(self)
Definition: pycml.py:2663
STL namespace.
Helper structure to construct C++ command line argc and argv variables from a Python list.
int GetArgc()
Returns the constructed argc.
int m_argc
Number of arguments argc.
std::vector< char > m_buf
Buffer for storage of the argument strings.
char ** m_argv
Pointers for strings argv.
~CppCommandLine()
Destructor.
CppCommandLine(py::list &py_argv)
Constructor.
char ** GetArgv()
Returns the constructed argv.
A helper class that for factory-based classes allows std::shared_ptr<T> as something that boost::pyth...