2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-22 17:32:55 +00:00

This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.

[SVN r17843]
This commit is contained in:
nobody
2003-03-12 13:51:19 +00:00
parent b58503707f
commit d6dd4e48e2
3 changed files with 257 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
// Copyright Gottfried Ganßauge 2003. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
/*
* Generic Conversion of opaque C++-pointers to a Python-Wrapper.
*/
# ifndef OPAQUE_POINTER_CONVERTER_HPP_
# define OPAQUE_POINTER_CONVERTER_HPP_
# include <boost/python/lvalue_from_pytype.hpp>
# include <boost/python/to_python_converter.hpp>
# include <boost/python/detail/dealloc.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/type_traits/remove_pointer.hpp>
// opaque_pointer_converter --
//
// usage: opaque_pointer_converter<Pointer>("name")
//
// registers to- and from- python conversions for a type Pointer,
// and a corresponding Python type called "name".
//
// Note:
// In addition you need to define specializations for type_id
// on the type pointed to by Pointer using
// BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
//
// For an example see libs/python/test/opaque.cpp
//
namespace boost { namespace python {
namespace detail {
template <class R>
struct opaque_pointer_converter_requires_a_pointer_type
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
{}
# endif
;
}
template <class Pointer>
struct opaque_pointer_converter
: to_python_converter<
Pointer, opaque_pointer_converter<Pointer> >
{
BOOST_STATIC_CONSTANT(
bool, ok = is_pointer<Pointer>::value);
typedef typename mpl::if_c<
ok
, Pointer
, detail::opaque_pointer_converter_requires_a_pointer_type<Pointer>
>::type ptr_type;
struct instance;
explicit opaque_pointer_converter(char const* name)
{
type_object.tp_name = const_cast<char *> (name);
lvalue_from_pytype<
opaque_pointer_converter<ptr_type>,
&opaque_pointer_converter<ptr_type>::type_object
>();
}
static PyObject* convert(ptr_type x)
{
PyObject *result = 0;
if (x != 0) {
instance *o = PyObject_New (instance, &type_object);
o->x = x;
result = &o->base_;
} else {
result = detail::none();
}
return (result);
}
static typename ::boost::remove_pointer<ptr_type>::type&
execute(instance &p_)
{
return *p_.x;
}
private:
static PyTypeObject type_object;
// This is a POD so we can use PyObject_Del on it, for example.
struct instance
{
PyObject base_;
ptr_type x;
};
};
template <class Pointer>
PyTypeObject opaque_pointer_converter<Pointer>::type_object =
{
PyObject_HEAD_INIT(NULL)
0,
0,
sizeof(typename opaque_pointer_converter<Pointer>::instance),
0,
::boost::python::detail::dealloc
};
}} // namespace boost::python
# ifdef BOOST_MSVC
// MSC works without this workaround, but needs another one ...
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee)
# else
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
namespace boost { namespace python { \
template<> \
inline type_info type_id(boost::type<Pointee>*) { \
return type_info (typeid (Pointee *)); \
} \
template<> \
inline type_info type_id( \
boost::type<const volatile Pointee &>*) { \
return type_info (typeid (Pointee *)); \
} \
}}
# endif
# endif // OPAQUE_POINTER_CONVERTER_HPP_

View File

@@ -0,0 +1,51 @@
// Copyright Gottfried Ganßauge 2003. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
/*
* Generic Return value converter generator for opaque C++-pointers
*/
# ifndef RETURN_OPAQUE_POINTER_HPP_
# define RETURN_OPAQUE_POINTER_HPP_
# include <boost/python/opaque_pointer_converter.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/if.hpp>
namespace boost { namespace python {
namespace detail {
template <class Pointer>
struct opaque_conversion_holder {
inline PyObject *operator () (Pointer p) {
static opaque_pointer_converter<Pointer> converter (
typeid (Pointer).name());
return converter.convert(p);
}
};
template <class R>
struct return_opaque_pointer_requires_a_pointer_type
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
{}
# endif
;
}
struct return_opaque_pointer
{
template <class R>
struct apply
{
BOOST_STATIC_CONSTANT(
bool, ok = is_pointer<R>::value);
typedef typename mpl::if_c<
ok
, detail::opaque_conversion_holder<R>
, detail::return_opaque_pointer_requires_a_pointer_type<R>
>::type type;
};
};
}} // namespace boost::python
# endif // RETURN_OPAQUE_POINTER_HPP_

77
test/opaque.py Normal file
View File

@@ -0,0 +1,77 @@
# Copyright Gottfried Ganßauge 2003. Permission to copy, use,
# modify, sell and distribute this software is granted provided this
# copyright notice appears in all copies. This software is provided
# "as is" without express or implied warranty, and with no claim as
# to its suitability for any purpose.
"""
>>> from opaque_ext import *
>>> #
>>> # Check for correct conversion
>>> use(get())
# Check that None is converted to a NULL opaque pointer
>>> useany(get())
1
>>> useany(None)
0
# check that we don't lose type information by converting NULL opaque
# pointers to None
>>> assert getnull() is None
>>> useany(getnull())
0
>>> failuse(get())
Traceback (most recent call last):
...
RuntimeError: success
>>> #
>>> # Check that there is no conversion from integers ...
>>> use(0)
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
>>> #
>>> # ... and from strings to opaque objects
>>> use("")
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
>>> #
>>> # Now check the same for another opaque pointer type
>>> use2(get2())
>>> failuse2(get2())
Traceback (most recent call last):
...
RuntimeError: success
>>> use2(0)
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
>>> use2("")
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
>>> #
>>> # Check that opaque types are distinct
>>> use(get2())
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
>>> use2(get())
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
"""
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
sys.exit(run()[0])