summaryrefslogtreecommitdiff
path: root/src/pyutils.h
blob: 84a0db7ebebfc4225c2888b574c2f667e57c1f31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#ifndef _PY_UTILS_H
#define _PY_UTILS_H

template <typename T, typename TfromPy>
struct object_from_python
{
  object_from_python() {
    boost::python::converter::registry::push_back
      (&TfromPy::convertible, &TfromPy::construct,
       boost::python::type_id<T>());
  }
};

template <typename T, typename TtoPy, typename TfromPy>
struct register_python_conversion
{
  register_python_conversion() {
    boost::python::to_python_converter<T, TtoPy>();
    object_from_python<T, TfromPy>();
  }
};

template <typename T>
struct python_optional : public boost::noncopyable
{
  struct optional_to_python
  {
    static PyObject * convert(const boost::optional<T>& value)
    {
      return (value ? boost::python::to_python_value<T>()(*value) :
	              boost::python::detail::none());
    }
  };
   
  struct optional_from_python
  {
    static void * convertible(PyObject * source)
    {
      using namespace boost::python::converter;

      if (source == Py_None)
	return source;

      const registration& converters(registered<T>::converters);

      if (implicit_rvalue_convertible_from_python(source, converters)) {
	rvalue_from_python_stage1_data data =
	  rvalue_from_python_stage1(source, converters);
	return rvalue_from_python_stage2(source, data, converters);
      }
      return NULL;
    }

    static void construct(PyObject * source,
			  boost::python::converter::rvalue_from_python_stage1_data * data)
    {
      using namespace boost::python::converter;

      void * const storage = ((rvalue_from_python_storage<T> *) data)->storage.bytes;

      if (data->convertible == source)	    // == None
	new (storage) boost::optional<T>(); // A Boost uninitialized value
      else
	new (storage) boost::optional<T>(*static_cast<T *>(data->convertible));

      data->convertible = storage;
    }
  };

  explicit python_optional() {
    register_python_conversion<boost::optional<T>,
      optional_to_python, optional_from_python>();
  }
};

//boost::python::register_ptr_to_python< boost::shared_ptr<Base> >();

#endif // _PY_UTILS_H