2
0
mirror of https://github.com/boostorg/python.git synced 2026-02-02 21:12:15 +00:00

auto_ptr support

[SVN r16228]
This commit is contained in:
Dave Abrahams
2002-11-14 01:40:16 +00:00
parent 6b4dc2901d
commit 0e76fcf706
13 changed files with 225 additions and 23 deletions

View File

@@ -103,7 +103,9 @@ template <class T>
struct arg_rvalue_from_python
{
typedef typename boost::add_reference<
typename boost::add_const<T>::type
T
// We can't add_const here, or it would be impossible to pass
// auto_ptr<U> args from Python to C++
>::type result_type;
arg_rvalue_from_python(PyObject*);

View File

@@ -5,7 +5,6 @@
// to its suitability for any purpose.
#ifndef ARG_TO_PYTHON_BASE_DWA200237_HPP
# define ARG_TO_PYTHON_BASE_DWA200237_HPP
# include <boost/python/converter/to_python_function_type.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/handle.hpp>

View File

@@ -11,9 +11,11 @@
# include <boost/python/converter/registered.hpp>
# include <boost/python/converter/registered_pointee.hpp>
# include <boost/python/detail/void_ptr.hpp>
# include <boost/call_traits.hpp>
# include <boost/python/detail/void_return.hpp>
# include <boost/python/errors.hpp>
# include <boost/type_traits/has_trivial_copy.hpp>
# include <boost/mpl/logical/and.hpp>
# include <boost/mpl/bool_c.hpp>
namespace boost { namespace python { namespace converter {
@@ -38,7 +40,14 @@ namespace detail
template <class T>
struct return_rvalue_from_python
{
typedef typename call_traits<T>::param_type result_type;
typedef typename mpl::if_<
mpl::logical_and<
has_trivial_copy<T>, mpl::bool_c<(sizeof(T) <= 2 * sizeof(double))>
>
, T
, T&
>::type result_type;
return_rvalue_from_python();
result_type operator()(PyObject*);
private:

View File

@@ -6,6 +6,7 @@
#ifndef TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
# define TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/static_assert.hpp>
namespace boost { namespace python { namespace converter {
@@ -19,9 +20,35 @@ typedef PyObject* (*to_python_function_t)(void const*);
template <class T, class ToPython>
struct as_to_python_function
{
// Assertion functions used to prevent wrapping of converters
// which take non-const reference parameters. The T* argument in
// the first overload ensures it isn't used in case T is a
// reference.
template <class U>
static int convert_function_must_take_value_or_const_reference(U(*)(T), int, T* = 0);
template <class U>
static int convert_function_must_take_value_or_const_reference(U(*)(T const&), long ...);
static PyObject* convert(void const* x)
{
return ToPython::convert(*(T const*)x);
BOOST_STATIC_ASSERT(
sizeof(
convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L))
== sizeof(int));
// Yes, the const_cast below opens a hole in const-correctness,
// but it's needed to convert auto_ptr<U> to python.
//
// How big a hole is it? It allows ToPython::convert() to be
// a function which modifies its argument. The upshot is that
// client converters applied to const objects may invoke
// undefined behavior. The damage, however, is limited by the
// use of the assertion function. Thus, the only way this can
// modify its argument is if T is an auto_ptr-like type. There
// is still a const-correctness hole w.r.t. auto_ptr<U> const,
// but c'est la vie.
return ToPython::convert(*const_cast<T*>(static_cast<T const*>(x)));
}
};

View File

@@ -6,9 +6,7 @@
#ifndef CLASS_CONVERTERS_DWA2002119_HPP
# define CLASS_CONVERTERS_DWA2002119_HPP
# include <boost/python/object/class_wrapper.hpp>
# include <boost/mpl/for_each.hpp>
# include <boost/python/handle.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/object/find_instance.hpp>
# include <boost/python/object/inheritance.hpp>

View File

@@ -13,14 +13,27 @@ namespace boost { namespace python { namespace objects {
// Used to convert objects of type Src to wrapped C++ classes by
// building a new instance object and installing a Holder constructed
// from the Src object.
// from a Src const&.
template <class Src, class Holder, class MakeInstance>
struct class_wrapper
: to_python_converter<Src,class_wrapper<Src,Holder,MakeInstance> >
{
static PyObject* convert(Src const& x)
{
return MakeInstance::execute(cref(x));
return MakeInstance::execute(boost::ref(x));
}
};
// Used to convert objects of type Src to wrapped C++ classes by
// building a new instance object and installing a Holder constructed
// from a Src value.
template <class Src, class Holder, class MakeInstance>
struct class_value_wrapper
: to_python_converter<Src,class_value_wrapper<Src,Holder,MakeInstance> >
{
static PyObject* convert(Src x)
{
return MakeInstance::execute(x);
}
};

View File

@@ -16,7 +16,6 @@
# include <boost/python/object/inheritance.hpp>
# include <boost/python/object/find_instance.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/python/object/class_wrapper.hpp>
# include <boost/python/pointee.hpp>
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/python/detail/preprocessor.hpp>

View File

@@ -11,6 +11,7 @@
# include <boost/python/pointee.hpp>
# include <boost/python/object/value_holder.hpp>
# include <boost/python/object/pointer_holder.hpp>
# include <boost/python/object/class_wrapper.hpp>
# include <boost/python/object/find_instance.hpp>
# include <boost/python/object/make_instance.hpp>
# include <boost/python/object/instance.hpp>
@@ -97,7 +98,7 @@ namespace detail
static inline void register_(mpl::bool_c<false>)
{
python::detail::force_instantiate(
objects::class_wrapper<
objects::class_value_wrapper<
Ptr
, type
, make_instance<T,type> >());

View File

@@ -55,15 +55,19 @@ rule bpl-test ( name ? : files * : requirements * )
boost-python-runtest $(name) : $(py) <pyd>$(modules) ;
}
bpl-test auto_ptr ;
bpl-test minimal ;
bpl-test args ;
bpl-test numpy ;
bpl-test enum ;
bpl-test docstring ;
bpl-test exception_translator ;
bpl-test pearu1 : test_cltree.py cltree.cpp ;
bpl-test try : newtest.py m1.cpp m2.cpp ;
bpl-test builtin_converters : test_builtin_converters.py test_builtin_converters.cpp ;
# Had to break this up into two files for MSVC6
extension builtin_converters : test_builtin_converters.cpp test_builtin_converters2.cpp <dll>../build/boost_python ;
boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters ;
bpl-test test_pointer_adoption ;
bpl-test operators ;
bpl-test callbacks ;
@@ -112,6 +116,8 @@ bpl-test pickle3 ;
bpl-test nested ;
bpl-test docstring ;
if $(TEST_BIENSTMAN_NON_BUGS)
{
bpl-test bienstman4 ;
@@ -161,11 +167,9 @@ run select_arg_to_python_test.cpp ../src/converter/type_id.cpp <lib>../../test/
: $(UNIT_TEST_PROPERTIES)
;
if $(TEST_EXPECTED_FAILURES)
{
compile-fail ./raw_pyobject_fail1.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./raw_pyobject_fail2.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./object_fail1.cpp : $(PYTHON_PROPERTIES) ;
}
compile-fail ./raw_pyobject_fail1.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./raw_pyobject_fail2.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./as_to_python_function.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./object_fail1.cpp : $(PYTHON_PROPERTIES) ;

70
test/auto_ptr.cpp Normal file
View File

@@ -0,0 +1,70 @@
// Copyright David Abrahams 2002. 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.
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/def.hpp>
#include "test_class.hpp"
#include <memory>
using namespace boost::python;
typedef test_class<> X;
int look(std::auto_ptr<X> const& x)
{
return (x.get()) ? x->value() : -1;
}
int steal(std::auto_ptr<X> x)
{
return x->value();
}
int maybe_steal(std::auto_ptr<X>& x, bool doit)
{
int n = x->value();
if (doit)
x.release();
return n;
}
std::auto_ptr<X> make()
{
return std::auto_ptr<X>(new X(77));
}
std::auto_ptr<X> callback(object f)
{
std::auto_ptr<X> x(new X(77));
// call<void>(f.ptr(),x);
// return std::auto_ptr<X>(new X(77));
return call<std::auto_ptr<X> >(f.ptr(), x);
}
std::auto_ptr<X> extract_(object o)
{
return extract<std::auto_ptr<X> >(o);
}
BOOST_PYTHON_MODULE(auto_ptr_ext)
{
class_<X, std::auto_ptr<X>, boost::noncopyable>("X", init<int>())
.def("value", &X::value)
;
def("look", look);
def("steal", steal);
def("maybe_steal", maybe_steal);
def("make", make);
def("callback", callback);
def("extract", extract_);
}
#include "module_tail.cpp"

54
test/auto_ptr.py Normal file
View File

@@ -0,0 +1,54 @@
'''
>>> from auto_ptr_ext import *
>>> x = X(42)
>>> x.value()
42
>>> look(x), look(x)
(42, 42)
>>> maybe_steal(x, 0)
42
>>> look(x)
42
>>> maybe_steal(x, 1)
42
>>> (not '--broken-auto-ptr' in sys.argv) and look(x) or -1
-1
>>> x = X(69)
>>> steal(x)
69
>>> (not '--broken-auto-ptr' in sys.argv) and look(x) or -1
-1
>>> if not '--broken-auto-ptr' in sys.argv:
... try: x.value()
... except TypeError: pass
... else: print 'expected a TypeError exception'
>>> x = make()
>>> look(x)
77
>>> y = callback(lambda y: y)
>>> y.value()
77
>>> extract(x).value()
77
'''
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])

View File

@@ -44,6 +44,10 @@ using boost::python::handle;
using boost::python::object;
using boost::python::borrowed;
// MSVC6 can't process this whole file at once, so we break it up into
// two parts. See test_builtin_converters2.cpp
#ifndef BOOST_PYTHON_WRAP_MORE_BUILTIN_CONVERTERS
// Used to test that arbitrary handle<>s can be returned
handle<PyTypeObject> get_type(handle<> x)
{
@@ -57,6 +61,8 @@ handle<> return_null_handle()
char const* rewrap_value_mutable_cstring(char* x) { return x; }
void wrap_more();
BOOST_PYTHON_MODULE(builtin_converters)
{
def("get_type", get_type);
@@ -74,10 +80,10 @@ BOOST_PYTHON_MODULE(builtin_converters)
def("rewrap_value_unsigned_long", by_value<unsigned long>::rewrap);
// using Python's macro instead of Boost's - we don't seem to get the
// config right all the time.
#ifdef HAVE_LONG_LONG
# ifdef HAVE_LONG_LONG
def("rewrap_value_long_long", by_value<LONG_LONG>::rewrap);
def("rewrap_value_unsigned_long_long", by_value<unsigned LONG_LONG>::rewrap);
#endif
# endif
def("rewrap_value_float", by_value<float>::rewrap);
def("rewrap_value_double", by_value<double>::rewrap);
def("rewrap_value_long_double", by_value<long double>::rewrap);
@@ -92,6 +98,14 @@ BOOST_PYTHON_MODULE(builtin_converters)
// Expose this to illustrate our failings ;-). See test_builtin_converters.py
def("rewrap_value_mutable_cstring", rewrap_value_mutable_cstring);
wrap_more();
}
#else // BOOST_PYTHON_WRAP_MORE_BUILTIN_CONVERTERS -- this part
// compiled into test_builtin_converters2.cpp
void wrap_more()
{
def("rewrap_const_reference_bool", by_const_reference<bool>::rewrap);
def("rewrap_const_reference_char", by_const_reference<char>::rewrap);
@@ -105,10 +119,10 @@ BOOST_PYTHON_MODULE(builtin_converters)
def("rewrap_const_reference_unsigned_long", by_const_reference<unsigned long>::rewrap);
// using Python's macro instead of Boost's - we don't seem to get the
// config right all the time.
#ifdef HAVE_LONG_LONG
# ifdef HAVE_LONG_LONG
def("rewrap_const_reference_long_long", by_const_reference<LONG_LONG>::rewrap);
def("rewrap_const_reference_unsigned_long_long", by_const_reference<unsigned LONG_LONG>::rewrap);
#endif
# endif
def("rewrap_const_reference_float", by_const_reference<float>::rewrap);
def("rewrap_const_reference_double", by_const_reference<double>::rewrap);
def("rewrap_const_reference_long_double", by_const_reference<long double>::rewrap);
@@ -124,3 +138,5 @@ BOOST_PYTHON_MODULE(builtin_converters)
def("rewrap_reference_object", by_reference<object>::rewrap);
}
#endif // BOOST_PYTHON_WRAP_MORE_BUILTIN_CONVERTERS

View File

@@ -0,0 +1,10 @@
// Copyright David Abrahams 2002. 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.
// This file just defines the rest of the tests that MSVC6 can't
// compile unless we break the file up. It's a hack, I'll admit...
#define BOOST_PYTHON_WRAP_MORE_BUILTIN_CONVERTERS
#include "test_builtin_converters.cpp"