source: NonGTP/Boost/boost/python/opaque_pointer_converter.hpp @ 857

Revision 857, 4.3 KB checked in by igarcia, 18 years ago (diff)
Line 
1// Copyright Gottfried Ganßauge 2003.
2// Distributed under the Boost Software License, Version 1.0. (See
3// accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5/*
6 * Generic Conversion of opaque C++-pointers to a Python-Wrapper.
7 */
8# ifndef OPAQUE_POINTER_CONVERTER_HPP_
9# define OPAQUE_POINTER_CONVERTER_HPP_
10
11# include <boost/python/detail/prefix.hpp>
12# include <boost/python/lvalue_from_pytype.hpp>
13# include <boost/python/to_python_converter.hpp>
14# include <boost/python/detail/dealloc.hpp>
15# include <boost/python/detail/none.hpp>
16# include <boost/type_traits/remove_pointer.hpp>
17# include <boost/type_traits/is_pointer.hpp>
18
19// opaque_pointer_converter --
20//
21// usage: opaque_pointer_converter<Pointer>("name")
22//
23// registers to- and from- python conversions for a type Pointer,
24// and a corresponding Python type called "name".
25//
26// Note:
27// In addition you need to define specializations for type_id
28// on the type pointed to by Pointer using
29// BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
30//
31// For an example see libs/python/test/opaque.cpp
32//
33namespace boost { namespace python {
34    namespace detail {
35        template <class R>
36        struct opaque_pointer_converter_requires_a_pointer_type
37# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
38        {}
39# endif
40        ;
41    }
42
43template <class Pointer>
44struct opaque_pointer_converter
45    : to_python_converter<
46          Pointer, opaque_pointer_converter<Pointer> >
47{
48    BOOST_STATIC_CONSTANT(
49        bool, ok = is_pointer<Pointer>::value);
50       
51    typedef typename mpl::if_c<
52        ok
53        , Pointer
54        , detail::opaque_pointer_converter_requires_a_pointer_type<Pointer>
55    >::type ptr_type;
56
57private:
58    struct instance;
59
60public:
61    explicit opaque_pointer_converter(char const* name)
62    {
63        type_object.tp_name = const_cast<char *> (name);
64
65        lvalue_from_pytype<
66            opaque_pointer_converter<ptr_type>,
67            &opaque_pointer_converter<ptr_type>::type_object
68        >();
69    }
70
71    static PyObject* convert(ptr_type x)
72    {
73        PyObject *result = 0;
74       
75        if (x != 0) {
76            instance *o = PyObject_New (instance, &type_object);
77
78            o->x   = x;
79            result = &o->base_;
80        } else {
81            result = detail::none();
82        }
83       
84        return (result);
85    }
86
87    static typename ::boost::remove_pointer<ptr_type>::type&
88    execute(instance &p_)
89    {
90        return *p_.x;
91    }
92
93private:
94    static PyTypeObject type_object;
95
96    // This is a POD so we can use PyObject_Del on it, for example.
97    struct instance
98    {
99        PyObject base_;
100        ptr_type x;
101    };
102};
103
104template <class Pointer>
105PyTypeObject opaque_pointer_converter<Pointer>::type_object =
106{
107    PyObject_HEAD_INIT(NULL)
108    0,
109    0,
110    sizeof(typename opaque_pointer_converter<Pointer>::instance),
111    0,
112    ::boost::python::detail::dealloc
113};
114}} // namespace boost::python
115#  ifdef BOOST_MSVC
116// MSC works without this workaround, but needs another one ...
117#  define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)      \
118     BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee)
119#  else
120#   define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)                     \
121    namespace boost { namespace python {                                        \
122    template<>                                                                  \
123    inline type_info type_id<Pointee>(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee))    \
124    {                                                                           \
125        return type_info (typeid (Pointee *));                                  \
126    }                                                                           \
127    template<>                                                                  \
128    inline type_info type_id<const volatile Pointee&>(                          \
129        BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&))                  \
130    {                                                                           \
131        return type_info (typeid (Pointee *));                                  \
132    }                                                                           \
133}}
134#  endif
135# endif    // OPAQUE_POINTER_CONVERTER_HPP_
Note: See TracBrowser for help on using the repository browser.