casacore
PycBasicData.h
Go to the documentation of this file.
1//# PycBasicData.h: Convert casa data types to/from python
2//# Copyright (C) 2006
3//# Associated Universities, Inc. Washington DC, USA.
4//#
5//# This library is free software; you can redistribute it and/or modify it
6//# under the terms of the GNU Library General Public License as published by
7//# the Free Software Foundation; either version 2 of the License, or (at your
8//# option) any later version.
9//#
10//# This library is distributed in the hope that it will be useful, but WITHOUT
11//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13//# License for more details.
14//#
15//# You should have received a copy of the GNU Library General Public License
16//# along with this library; if not, write to the Free Software Foundation,
17//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18//#
19//# Correspondence concerning AIPS++ should be addressed as follows:
20//# Internet email: aips2-request@nrao.edu.
21//# Postal address: AIPS++ Project Office
22//# National Radio Astronomy Observatory
23//# 520 Edgemont Road
24//# Charlottesville, VA 22903-2475 USA
25//#
26//# $Id: PycBasicData.h,v 1.5 2006/10/25 01:42:13 gvandiep Exp $
27
28#ifndef PYRAP_PYCBASICDATA_H
29#define PYRAP_PYCBASICDATA_H
30
31// include python first to avoid _POSIX_C_SOURCE redefined warnings
32#include <boost/python.hpp>
33#include <boost/python/object.hpp>
34#include <casacore/python/Converters/PycArray.h>
35#include <casacore/casa/BasicSL/String.h>
36#include <casacore/casa/Arrays/IPosition.h>
37#include <casacore/casa/Arrays/Vector.h>
38#include <casacore/casa/Utilities/Assert.h>
39#include <casacore/casa/Exceptions/Error.h>
40#include <vector>
41#include <map>
42
43#if PY_MAJOR_VERSION >= 3
44#define IS_PY3K
45#endif
46
47// Define classes and functions to convert the basic data types and
48// containers to and from Python.
49
50namespace casacore { namespace python {
51
52 // Prevent a converter from being registered multiple times.
54 {
55 public:
56 static bool get (const std::string& name);
57 static void set (const std::string& name);
58 private:
59 static std::map<std::string,bool> _registry;
60 };
61
62 // Check if the given object is a sequence object.
63 // If so, return true.
64 // py_obj gets changed if the given object was a scalar numpy/numarray.
65 // In that case it is flattened.
66 bool getSeqObject (boost::python::object& py_obj);
67
68 // Convert a String object to python.
70 {
71 static boost::python::object makeobject(String const& s)
72 { return boost::python::object((const std::string&)s); }
73 static PyObject* convert(String const& s)
74 { return boost::python::incref(makeobject(s).ptr()); }
75 };
76
77 // Convert a String object from python.
79 {
81 {
82 boost::python::converter::registry::push_back(
84 &construct,
85 boost::python::type_id<String>());
86 }
87
88 static void* convertible(PyObject* obj_ptr)
89 {
90#ifdef IS_PY3K
91 if (!PyUnicode_Check(obj_ptr)) return 0;
92#else
93 if (!PyString_Check(obj_ptr) && !PyUnicode_Check(obj_ptr)) return 0;
94#endif
95 return obj_ptr;
96 }
97
98 static void construct(
99 PyObject* obj_ptr,
100 boost::python::converter::rvalue_from_python_stage1_data* data)
101 {
102 char* value = NULL;
103 boost::python::object temp_bytes_obj;
104 if (PyUnicode_Check(obj_ptr)) {
105 PyObject * temp_bytes = PyUnicode_AsEncodedString(obj_ptr, "UTF-8", "strict"); // Owned reference
106
107 if (temp_bytes != NULL) {
108 // Take over lifetime management of temp_bytes
109 temp_bytes_obj = boost::python::object(boost::python::handle<>(temp_bytes));
110 value = PyBytes_AS_STRING(temp_bytes);
111 } else {
112 boost::python::throw_error_already_set();
113 }
114#ifndef IS_PY3K
115 } else if (PyString_Check(obj_ptr)) {
116 value = PyString_AsString(obj_ptr);
117#endif
118 } else {
119 boost::python::throw_error_already_set();
120 }
121 if (value == 0) boost::python::throw_error_already_set();
122 void* storage = (
123 (boost::python::converter::rvalue_from_python_storage<String>*)
124 data)->storage.bytes;
125 new (storage) String(value);
126 data->convertible = storage;
127 }
128 };
129
130
131 // Default operations on all containers for conversion from Python
132 // container to C++ one.
133
134 // Copied from
135 // scitbx/include/scitbx/boost_python/container_conversions.h that is
136 // described in the <a
137 // href="http://www.boost.org/libs/python/doc/v2/faq.html">
138 // Boost.Python FAQ. </a>
139
140 // @author Ralf W. Grosse-Kunstleve <rwgk@yahoo.com> of
141 // <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
143 {
144 static bool check_convertibility_per_element() { return true; }
145
146 template <typename ContainerType>
147 static bool check_size(boost::type<ContainerType>, std::size_t)
148 {
149 return true;
150 }
151
152 template <typename ContainerType>
153 static void assert_size(boost::type<ContainerType>, std::size_t)
154 {}
155
156 template <typename ContainerType>
157 static void reserve(ContainerType&, std::size_t)
158 {}
159 };
160
161 // Operations on containers that have variable capacity for
162 // conversion from Python container to C++ one.
163
164 // Copied from
165 // scitbx/include/scitbx/boost_python/container_conversions.h that is
166 // described in the <a
167 // href="http://www.boost.org/libs/python/doc/v2/faq.html">
168 // Boost.Python FAQ. </a>
169
170 // @author Ralf W. Grosse-Kunstleve <rwgk@yahoo.com> of
171 // <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
173 {
174 template <typename ContainerType>
175 static void reserve(ContainerType& a, std::size_t sz)
176 {
177 a.reserve(sz);
178 }
179
180 template <typename ContainerType, typename ValueType>
181 static void set_value(ContainerType& a, std::size_t i, ValueType const& v)
182 {
183 AlwaysAssert(a.size() == i, AipsError);
184 a.push_back(v);
185 }
186 };
187
189 {
190 template <typename ContainerType>
191 static void reserve(ContainerType& a, std::size_t sz)
192 {
193 a.resize(sz);
194 }
195
196 template <typename ContainerType, typename ValueType>
197 static void set_value(ContainerType& a, std::size_t i, ValueType const& v)
198 {
199 assert(a.size() > i);
200 a[i] = v;
201 }
202 };
203
205 {
206 template <typename ContainerType>
207 static void reserve(ContainerType& a, std::size_t sz)
208 {
209 a.resize(sz);
210 }
211
212 template <typename ContainerType, typename ValueType>
213 static void set_value(ContainerType& a, std::size_t i, ValueType const& v)
214 {
215 assert(a.size() > i);
216 a[a.size() - i - 1] = v;
217 }
218 };
219
220
221 // A wrapper of a conversion function to convert a STL vector to a
222 // Python list. This class satisfies the requirements of the
223 // boost::python::to_python_converter conversion template argument.
224
225 // Copied from
226 // scitbx/include/scitbx/boost_python/container_conversions.h that is
227 // described in the <a
228 // href="http://www.boost.org/libs/python/doc/v2/faq.html">
229 // Boost.Python FAQ. </a>
230
231 // @author Ralf W. Grosse-Kunstleve <rwgk@yahoo.com> of
232 // <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
233 template < typename ContainerType >
234 struct to_list
235 {
236 // Creates and returns a Python list from the elements copied
237 // from a STL container. The ContainerType must be a container
238 // with STL iterators defined on it.
239 // It may contain any type of object supported by the
240 // boost::python::object constructor.
241 static boost::python::object makeobject (ContainerType const& c)
242 {
243 boost::python::list result;
244 typename ContainerType::const_iterator i = c.begin();
245 typename ContainerType::const_iterator iEnd = c.end();
246 for( ; i != iEnd; ++i) {
247 result.append(*i);
248 }
249 return result;
250 }
251 static PyObject* convert (ContainerType const& c)
252 {
253 return boost::python::incref(makeobject(c).ptr());
254 }
255 };
256 //# Make specialisations for various types.
257 template <>
259 {
261 static boost::python::list makeobject (ContainerType const& c)
262 {
263 // Reverse IPosition values.
264 boost::python::list result;
265 for (int i=c.size()-1; i>=0; --i) {
266 result.append(c[i]);
267 }
268 return result;
269 }
270 static PyObject* convert (ContainerType const& c)
271 {
272 return boost::python::incref(makeobject(c).ptr());
273 }
274 };
275 //# This specialisation is needed because on OS-X 10.9 clang-3.5 with
276 //# Boost-Python 1.57 gives a compile error
277 //# /opt/casa/01/include/boost/python/converter/arg_to_python.hpp:209:9:
278 //# error: no matching constructor for initialization of
279 //# 'boost::python::converter::detail::arg_to_python_base'
280 //# : arg_to_python_base(&x, registered<T>::converters)
281 template <>
282 struct to_list <std::vector <bool> >
283 {
284 typedef std::vector <bool> ContainerType;
285 static boost::python::list makeobject (ContainerType const& c)
286 {
287 boost::python::list result;
288 ContainerType::const_iterator i = c.begin();
289 ContainerType::const_iterator iEnd = c.end();
290 for( ; i != iEnd; ++i) {
291 bool b = *i;
292 result.append(b);
293 }
294 return result;
295 }
296 static PyObject* convert (ContainerType const& c)
297 {
298 return boost::python::incref(makeobject(c).ptr());
299 }
300 };
301 template <>
302 struct to_list <std::vector <casacore::String> >
303 {
304 typedef std::vector <casacore::String> ContainerType;
305 static boost::python::list makeobject (ContainerType const& c)
306 {
307 boost::python::list result;
308 ContainerType::const_iterator i = c.begin();
309 ContainerType::const_iterator iEnd = c.end();
310 for( ; i != iEnd; ++i) {
311 result.append((std::string const&)(*i));
312 }
313 return result;
314 }
315 static PyObject* convert (ContainerType const& c)
316 {
317 return boost::python::incref(makeobject(c).ptr());
318 }
319 };
320 template <>
321 struct to_list <casacore::Array <casacore::String> >
322 {
324 static boost::python::object makeobject (ContainerType const& c)
325 {
326 boost::python::list result;
328 ContainerType::const_iterator iEnd = c.end();
329 for( ; i != iEnd; ++i) {
330 result.append((std::string const&)(*i));
331 }
332 return result;
333 }
334 static PyObject* convert (ContainerType const& c)
335 {
336 return boost::python::incref(makeobject(c).ptr());
337 }
338 };
339 template <>
340 struct to_list <casacore::Vector <casacore::String> >
341 {
343 static boost::python::object makeobject (ContainerType const& c)
344 {
345 boost::python::list result;
347 ContainerType::const_iterator iEnd = c.end();
348 for( ; i != iEnd; ++i) {
349 result.append((std::string const&)(*i));
350 }
351 return result;
352 }
353 static PyObject* convert (ContainerType const& c)
354 {
355 return boost::python::incref(makeobject(c).ptr());
356 }
357 };
358
359 // Converts an STL vector or casa Array of T objects to Python list.
360 // Copied from
361 // scitbx/include/scitbx/boost_python/container_conversions.h that is
362 // described in the <a
363 // href="http://www.boost.org/libs/python/doc/v2/faq.html">
364 // Boost.Python FAQ. </a>
365 // @author Ralf W. Grosse-Kunstleve <rwgk@yahoo.com> of
366 // <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
367 template < typename T >
369 {
371 {
372 boost::python::to_python_converter < std::vector < T >,
374 }
375 };
376 template < typename T >
378 {
380 {
381 boost::python::to_python_converter < casacore::Array < T >,
383 }
384 };
385 template < typename T >
387 {
389 {
390 boost::python::to_python_converter < casacore::Vector < T >,
392 }
393 };
395 {
397 {
398 boost::python::to_python_converter < casacore::IPosition,
400 }
401 };
402
403
404 // Conversion of Python sequence to C++ container.
405
406 // Copied from
407 // scitbx/include/scitbx/boost_python/container_conversions.h that is
408 // described in the <a
409 // href="http://www.boost.org/libs/python/doc/v2/faq.html">
410 // Boost.Python FAQ. </a>
411 // @author Ralf W. Grosse-Kunstleve <rwgk@yahoo.com> of
412 // <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
413 template <typename ContainerType, typename ConversionPolicy>
415 {
416 typedef typename ContainerType::value_type container_element_type;
417
419 {
420 boost::python::converter::registry::push_back(
422 &construct,
423 boost::python::type_id<ContainerType>());
424 }
425
426 // Appears to return @a obj_ptr if it is type of Python sequence
427 // that can be convertible to C++ container.
428 static void* convertible(PyObject* obj_ptr)
429 {
430 using namespace boost::python;
431 handle<> py_hdl(obj_ptr);
432 if (PyErr_Occurred()) {
433 PyErr_Clear();
434 return 0;
435 }
436 object py_obj(py_hdl);
437 incref(obj_ptr); // incr refcount, because ~object decrements it
438 // Accept single values.
439 if (PyBool_Check(obj_ptr)
440 || PyLong_Check(obj_ptr)
441 || PyFloat_Check(obj_ptr)
442 || PyComplex_Check(obj_ptr)
443#ifndef IS_PY3K
444 || PyInt_Check(obj_ptr)
445 || PyString_Check(obj_ptr)
446#endif
447 || PyUnicode_Check(obj_ptr)) {
448 extract<container_element_type> elem_proxy(py_obj);
449 if (!elem_proxy.check()) return 0;
450 return obj_ptr;
451 }
452 // An array scalar is accepted.
453 if (PycArrayScalarCheck(obj_ptr)) {
454 return obj_ptr;
455 }
456 // Get the sequence object.
457 // It can be a numarray/numpy scalar in which case
458 // it fills py_obj with a flattened array.
459 if (! getSeqObject (py_obj)) {
460 return 0;
461 }
462 // Check the sequence.
463 // It must be convertible to an iterator.
464 handle<> obj_iter(allow_null(PyObject_GetIter(py_obj.ptr())));
465 if (!obj_iter.get()) {
466 PyErr_Clear();
467 return 0;
468 }
469 if (!check_convertibility (py_obj.ptr())) {
470 return 0;
471 }
472 return obj_ptr;
473 }
474
475 // Constructs a C++ container from a Python sequence.
476 static void construct(
477 PyObject* obj_ptr,
478 boost::python::converter::rvalue_from_python_stage1_data* data)
479 {
480 using namespace boost::python;
481 using boost::python::converter::rvalue_from_python_storage;
482 void* storage = (
483 (rvalue_from_python_storage<ContainerType>*)
484 data)->storage.bytes;
485 new (storage) ContainerType();
486 data->convertible = storage;
487 ContainerType& result = *((ContainerType*)storage);
488 if (PyBool_Check(obj_ptr)
489 || PyLong_Check(obj_ptr)
490 || PyFloat_Check(obj_ptr)
491 || PyComplex_Check(obj_ptr)
492 || PyUnicode_Check(obj_ptr)
493#ifndef IS_PY3K
494 || PyString_Check(obj_ptr)
495 || PyInt_Check(obj_ptr)
496#endif
497 || PycArrayScalarCheck(obj_ptr)) {
498 extract<container_element_type> elem_proxy(obj_ptr);
499 ConversionPolicy::reserve(result, 1);
500 ConversionPolicy::set_value(result, 0, elem_proxy());
501 return;
502 }
503 handle<> py_hdl(obj_ptr);
504 object py_obj = object(py_hdl);
505 incref(obj_ptr); // incr refcount, because ~object decrements it
506 assert (getSeqObject (py_obj));
507 fill_container (result, py_obj.ptr());
508 // ConversionPolicy::reserve(result, 1);
509 // ConversionPolicy::set_value(result, 0,
510 // extract<container_element_type>(py_flat.attr("__getitem__")(0)));
511 }
512
513 // Constructs a C++ container from a Python sequence.
514 static ContainerType make_container(PyObject* obj_ptr)
515 {
516 ContainerType result;
517 fill_container (result, obj_ptr);
518 return result;
519 }
520
521 private:
522 static void fill_container (ContainerType& result, PyObject* obj_ptr)
523 {
524 using namespace boost::python;
525 int obj_size = PyObject_Length(obj_ptr);
526 handle<> obj_iter(PyObject_GetIter(obj_ptr));
527 ConversionPolicy::reserve(result, obj_size);
528 std::size_t i=0;
529 for(;;i++) {
530 handle<> py_elem_hdl(allow_null(PyIter_Next(obj_iter.get())));
531 if (PyErr_Occurred()) throw_error_already_set();
532 if (!py_elem_hdl.get()) break; // end of iteration
533 object py_elem_obj(py_elem_hdl);
534 extract<container_element_type> elem_proxy(py_elem_obj);
535 ConversionPolicy::set_value(result, i, elem_proxy());
536 }
537 ConversionPolicy::assert_size(boost::type<ContainerType>(), i);
538 }
539
540 static bool check_convertibility(PyObject* obj_ptr)
541 {
542 using namespace boost::python;
543 handle<> obj_iter(allow_null(PyObject_GetIter(obj_ptr)));
544 if (!obj_iter.get()) { // must be convertible to an iterator
545 PyErr_Clear();
546 return false;
547 }
548 int obj_size = PyObject_Length(obj_ptr);
549 if (obj_size < 0) { // must be a measurable sequence
550 PyErr_Clear();
551 return false;
552 }
553 if (ConversionPolicy::check_convertibility_per_element()) {
554 if (!ConversionPolicy::check_size(
555 boost::type<ContainerType>(), obj_size)) return false;
556 // All elements in a range and array have the same type, so
557 // need to check the first element only.
558 bool is_same = PyRange_Check(obj_ptr) ||
559 (PySequence_Check(obj_ptr)
560 && !PyTuple_Check(obj_ptr) && !PyList_Check(obj_ptr));
561 int i = 0;
562 for (;;i++) {
563 handle<> py_elem_hdl(allow_null(PyIter_Next(obj_iter.get())));
564 if (PyErr_Occurred()) {
565 PyErr_Clear();
566 return false;
567 }
568 if (!py_elem_hdl.get()) break; // end of iteration
569 object py_elem_obj(py_elem_hdl);
570 extract<container_element_type> elem_proxy(py_elem_obj);
571 if (!elem_proxy.check()) return false;
572 if (is_same) break; // all elements are of the same type
573 }
574 if (!is_same) assert(i == obj_size );
575 }
576 return true;
577 }
578 };
579
580 // Register the String conversion.
582 {
583 static void reg();
584 };
587
588 // Register the IPosition conversion.
590 {
591 static void reg();
592 };
595
596 // Register the std::vector conversions.
597 template < typename T >
599 {
600 static void reg()
601 {
602 std::string tname(typeid(std::vector<T>).name());
603 if (! pyregistry::get (tname)) {
604 pyregistry::set (tname);
608 }
609 }
610 };
611 template < typename T >
614
615 // Register the casacore::Vector conversions.
616 template < typename T >
618 {
619 static void reg()
620 {
621 std::string tname(typeid(casacore::Vector<T>).name());
622 if (! pyregistry::get (tname)) {
623 pyregistry::set (tname);
628 }
629 }
630 };
631 template < typename T >
634
635
636 // Register all standard basic conversions.
637 // These are String, IPosition, Vector<String>, Vector<Int>,
638 // Vector<Double>, Vector<DComplex>.
640}}
641
642#endif
#define AlwaysAssert(expr, exception)
These marcos are provided for use instead of simply using the constructors of assert_ to allow additi...
Definition: Assert.h:157
ConstIteratorSTL const_iterator
Definition: Array.h:853
String: the storage and methods of handling collections of characters.
Definition: String.h:225
Prevent a converter from being registered multiple times.
Definition: PycBasicData.h:54
static bool get(const std::string &name)
static std::map< std::string, bool > _registry
Definition: PycBasicData.h:59
static void set(const std::string &name)
const Double c
Fundamental physical constants (SI units):
void register_convert_casa_string()
Definition: PycBasicData.h:585
void register_convert_basicdata()
Register all standard basic conversions.
Bool PycArrayScalarCheck(PyObject *obj_ptr)
Check if the PyObject is an array scalar object.
void register_convert_casa_iposition()
Definition: PycBasicData.h:593
void register_convert_casa_vector()
Definition: PycBasicData.h:632
bool getSeqObject(boost::python::object &py_obj)
Check if the given object is a sequence object.
void register_convert_std_vector()
Definition: PycBasicData.h:612
this file contains all the compiler specific defines
Definition: mainpage.dox:28
LatticeExprNode value(const LatticeExprNode &expr)
This function returns the value of the expression without a mask.
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition: Complex.h:352
static void set_value(ContainerType &a, std::size_t i, ValueType const &v)
Definition: PycBasicData.h:213
static void reserve(ContainerType &a, std::size_t sz)
Definition: PycBasicData.h:207
Convert a String object from python.
Definition: PycBasicData.h:79
static void * convertible(PyObject *obj_ptr)
Definition: PycBasicData.h:88
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data)
Definition: PycBasicData.h:98
Convert a String object to python.
Definition: PycBasicData.h:70
static PyObject * convert(String const &s)
Definition: PycBasicData.h:73
static boost::python::object makeobject(String const &s)
Definition: PycBasicData.h:71
static void reserve(ContainerType &a, std::size_t sz)
Definition: PycBasicData.h:191
static void set_value(ContainerType &a, std::size_t i, ValueType const &v)
Definition: PycBasicData.h:197
Register the IPosition conversion.
Definition: PycBasicData.h:590
Register the String conversion.
Definition: PycBasicData.h:582
Register the casacore::Vector conversions.
Definition: PycBasicData.h:618
Register the std::vector conversions.
Definition: PycBasicData.h:599
Default operations on all containers for conversion from Python container to C++ one.
Definition: PycBasicData.h:143
static void assert_size(boost::type< ContainerType >, std::size_t)
Definition: PycBasicData.h:153
static bool check_size(boost::type< ContainerType >, std::size_t)
Definition: PycBasicData.h:147
static bool check_convertibility_per_element()
Definition: PycBasicData.h:144
static void reserve(ContainerType &, std::size_t)
Definition: PycBasicData.h:157
Conversion of Python sequence to C++ container.
Definition: PycBasicData.h:415
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data)
Constructs a C++ container from a Python sequence.
Definition: PycBasicData.h:476
static ContainerType make_container(PyObject *obj_ptr)
Constructs a C++ container from a Python sequence.
Definition: PycBasicData.h:514
static void fill_container(ContainerType &result, PyObject *obj_ptr)
Definition: PycBasicData.h:522
static void * convertible(PyObject *obj_ptr)
Appears to return obj_ptr if it is type of Python sequence that can be convertible to C++ container.
Definition: PycBasicData.h:428
static bool check_convertibility(PyObject *obj_ptr)
Definition: PycBasicData.h:540
ContainerType::value_type container_element_type
Definition: PycBasicData.h:416
Converts an STL vector or casa Array of T objects to Python list.
Definition: PycBasicData.h:369
Operations on containers that have variable capacity for conversion from Python container to C++ one.
Definition: PycBasicData.h:173
static void reserve(ContainerType &a, std::size_t sz)
Definition: PycBasicData.h:175
static void set_value(ContainerType &a, std::size_t i, ValueType const &v)
Definition: PycBasicData.h:181
static boost::python::object makeobject(ContainerType const &c)
Definition: PycBasicData.h:324
static PyObject * convert(ContainerType const &c)
Definition: PycBasicData.h:334
static PyObject * convert(ContainerType const &c)
Definition: PycBasicData.h:270
static boost::python::list makeobject(ContainerType const &c)
Definition: PycBasicData.h:261
static boost::python::object makeobject(ContainerType const &c)
Definition: PycBasicData.h:343
static PyObject * convert(ContainerType const &c)
Definition: PycBasicData.h:296
static boost::python::list makeobject(ContainerType const &c)
Definition: PycBasicData.h:285
static boost::python::list makeobject(ContainerType const &c)
Definition: PycBasicData.h:305
static PyObject * convert(ContainerType const &c)
Definition: PycBasicData.h:315
A wrapper of a conversion function to convert a STL vector to a Python list.
Definition: PycBasicData.h:235
static PyObject * convert(ContainerType const &c)
Definition: PycBasicData.h:251
static boost::python::object makeobject(ContainerType const &c)
Creates and returns a Python list from the elements copied from a STL container.
Definition: PycBasicData.h:241