ossrv_pub/boost_apis/boost/python/opaque_pointer_converter.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright Gottfried Ganßauge 2003..2006
       
     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/converter/registrations.hpp>
       
    15 # include <boost/python/detail/dealloc.hpp>
       
    16 # include <boost/python/detail/none.hpp>
       
    17 # include <boost/python/type_id.hpp>
       
    18 # include <boost/python/errors.hpp>
       
    19 
       
    20 # include <boost/type_traits/remove_pointer.hpp>
       
    21 # include <boost/type_traits/is_pointer.hpp>
       
    22 # include <boost/type_traits/is_void.hpp>
       
    23 
       
    24 # include <boost/implicit_cast.hpp>
       
    25 
       
    26 # include <boost/mpl/eval_if.hpp>
       
    27 # include <boost/mpl/identity.hpp>
       
    28 # include <boost/mpl/assert.hpp>
       
    29 
       
    30 // opaque --
       
    31 //
       
    32 // registers to- and from- python conversions for a type Pointee.
       
    33 //
       
    34 // Note:
       
    35 // In addition you need to define specializations for type_id
       
    36 // on the type pointed to by Pointer using
       
    37 // BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
       
    38 //
       
    39 // For an example see libs/python/test/opaque.cpp
       
    40 //
       
    41 namespace boost { namespace python {
       
    42 
       
    43 template <class Pointee>
       
    44 struct opaque
       
    45 {
       
    46     opaque()
       
    47     {
       
    48         if (type_object.tp_name == 0)
       
    49         {
       
    50             type_object.tp_name = const_cast<char*>(type_id<Pointee*>().name());
       
    51             if (PyType_Ready (&type_object) < 0)
       
    52             {
       
    53                 throw error_already_set();
       
    54             }
       
    55 
       
    56             this->register_self();
       
    57         }
       
    58     }
       
    59     
       
    60     static opaque instance;
       
    61 private:
       
    62     
       
    63     static void* extract(PyObject* op)
       
    64     {
       
    65         return PyObject_TypeCheck(op, &type_object)
       
    66             ? static_cast<python_instance*>(implicit_cast<void*>(op))->x
       
    67             : 0
       
    68             ;
       
    69     }
       
    70 
       
    71     static PyObject* wrap(void const* px)
       
    72     {
       
    73         Pointee* x = *static_cast<Pointee*const*>(px);
       
    74         
       
    75         if (x == 0)
       
    76             return detail::none();
       
    77 
       
    78         if ( python_instance *o = PyObject_New(python_instance, &type_object) )
       
    79         {
       
    80             o->x = x;
       
    81             return static_cast<PyObject*>(implicit_cast<void*>(o));
       
    82         }
       
    83         else
       
    84         {
       
    85             throw error_already_set();
       
    86         }
       
    87     }
       
    88 
       
    89     void register_self()
       
    90     {
       
    91         converter::registration const *existing =
       
    92             converter::registry::query (type_id<Pointee*>());
       
    93 
       
    94         if ((existing == 0) || (existing->m_to_python == 0))
       
    95         {
       
    96             converter::registry::insert(&extract, type_id<Pointee>());
       
    97             converter::registry::insert(&wrap, type_id<Pointee*>());
       
    98         }
       
    99     }
       
   100 
       
   101     struct python_instance
       
   102     {
       
   103         PyObject_HEAD
       
   104         Pointee* x;
       
   105     };
       
   106     
       
   107     static PyTypeObject type_object;
       
   108 };
       
   109 
       
   110 template <class Pointee>
       
   111 opaque<Pointee> opaque<Pointee>::instance;
       
   112 
       
   113 template <class Pointee>
       
   114 PyTypeObject opaque<Pointee>::type_object =
       
   115 {
       
   116     PyObject_HEAD_INIT(0)
       
   117     0,
       
   118     0,
       
   119     sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ),
       
   120     0,
       
   121     ::boost::python::detail::dealloc,
       
   122     0,          /* tp_print */
       
   123     0,          /* tp_getattr */
       
   124     0,          /* tp_setattr */
       
   125     0,          /* tp_compare */
       
   126     0,          /* tp_repr */
       
   127     0,          /* tp_as_number */
       
   128     0,          /* tp_as_sequence */
       
   129     0,          /* tp_as_mapping */
       
   130     0,          /* tp_hash */
       
   131     0,          /* tp_call */
       
   132     0,          /* tp_str */
       
   133     0,          /* tp_getattro */
       
   134     0,          /* tp_setattro */
       
   135     0,          /* tp_as_buffer */
       
   136     0,          /* tp_flags */
       
   137     0,          /* tp_doc */
       
   138     0,          /* tp_traverse */
       
   139     0,          /* tp_clear */
       
   140     0,          /* tp_richcompare */
       
   141     0,          /* tp_weaklistoffset */
       
   142     0,          /* tp_iter */
       
   143     0,          /* tp_iternext */
       
   144     0,          /* tp_methods */
       
   145     0,          /* tp_members */
       
   146     0,          /* tp_getset */
       
   147     0,          /* tp_base */
       
   148     0,          /* tp_dict */
       
   149     0,          /* tp_descr_get */
       
   150     0,          /* tp_descr_set */
       
   151     0,          /* tp_dictoffset */
       
   152     0,          /* tp_init */
       
   153     0,          /* tp_alloc */
       
   154     0,          /* tp_new */
       
   155     0,          /* tp_free */
       
   156     0,          /* tp_is_gc */
       
   157     0,          /* tp_bases */
       
   158     0,          /* tp_mro */
       
   159     0,          /* tp_cache */
       
   160     0,          /* tp_subclasses */
       
   161     0,          /* tp_weaklist */
       
   162 #if PYTHON_API_VERSION >= 1012
       
   163     0           /* tp_del */
       
   164 #endif
       
   165 };
       
   166 }} // namespace boost::python
       
   167 
       
   168 #  if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
       
   169 
       
   170 #  define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
       
   171 
       
   172 #  else
       
   173 
       
   174 // If you change the below, don't forget to alter the end of type_id.hpp
       
   175 #   define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)                     \
       
   176     namespace boost { namespace python {                                        \
       
   177     template<>                                                                  \
       
   178     inline type_info type_id<Pointee>(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee))    \
       
   179     {                                                                           \
       
   180         return type_info (typeid (Pointee *));                                  \
       
   181     }                                                                           \
       
   182     template<>                                                                  \
       
   183     inline type_info type_id<const volatile Pointee&>(                          \
       
   184         BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&))                  \
       
   185     {                                                                           \
       
   186         return type_info (typeid (Pointee *));                                  \
       
   187     }                                                                           \
       
   188     }}
       
   189 
       
   190 #  endif
       
   191 
       
   192 # endif    // OPAQUE_POINTER_CONVERTER_HPP_