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:
@@ -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*);
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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> >());
|
||||
|
||||
20
test/Jamfile
20
test/Jamfile
@@ -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
70
test/auto_ptr.cpp
Normal 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
54
test/auto_ptr.py
Normal 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])
|
||||
@@ -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
|
||||
|
||||
|
||||
10
test/test_builtin_converters2.cpp
Normal file
10
test/test_builtin_converters2.cpp
Normal 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"
|
||||
Reference in New Issue
Block a user