2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-25 18:32:24 +00:00

Initial attempt to fix problems

[SVN r10158]
This commit is contained in:
Dave Abrahams
2001-05-19 23:29:04 +00:00
parent 9261e2a3d9
commit 4d3079293d
26 changed files with 339 additions and 316 deletions

View File

@@ -22,6 +22,8 @@
namespace boost { namespace python {
enum semantics { search_namespace }; // Used to find to_python functions via koenig lookup.
// IMPORTANT: this function may only be called from within a catch block!
void handle_exception()
{
@@ -142,7 +144,7 @@ PyObject* integer_to_python(T value)
throw boost::python::error_already_set();
}
return to_python(value_as_long);
return to_python(boost::python::search_namespace, value_as_long);
}
int from_python(PyObject* p, boost::python::type<int> type)
@@ -150,7 +152,7 @@ int from_python(PyObject* p, boost::python::type<int> type)
return integer_from_python(p, type);
}
PyObject* to_python(unsigned int i)
PyObject* to_python(boost::python::semantics, unsigned int i)
{
return integer_to_python(i);
}
@@ -170,7 +172,7 @@ float from_python(PyObject* p, boost::python::type<float>)
return static_cast<float>(from_python(p, boost::python::type<double>()));
}
PyObject* to_python(unsigned short i)
PyObject* to_python(boost::python::semantics, unsigned short i)
{
return integer_to_python(i);
}
@@ -180,7 +182,7 @@ unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type
return integer_from_python(p, type);
}
PyObject* to_python(char c)
PyObject* to_python(boost::python::semantics, char c)
{
if (c == '\0') return PyString_FromString("");
return PyString_FromStringAndSize(&c, 1);
@@ -198,7 +200,7 @@ char from_python(PyObject* p, boost::python::type<char>)
return PyString_AsString(p)[0];
}
PyObject* to_python(unsigned char i)
PyObject* to_python(boost::python::semantics, unsigned char i)
{
return integer_to_python(i);
}
@@ -208,7 +210,7 @@ unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
return integer_from_python(p, type);
}
PyObject* to_python(signed char i)
PyObject* to_python(boost::python::semantics, signed char i)
{
return integer_to_python(i);
}
@@ -218,7 +220,7 @@ signed char from_python(PyObject* p, boost::python::type<signed char> type)
return integer_from_python(p, type);
}
PyObject* to_python(unsigned long x)
PyObject* to_python(boost::python::semantics, unsigned long x)
{
return integer_to_python(x);
}
@@ -244,7 +246,7 @@ const char* from_python(PyObject* p, boost::python::type<const char*>)
return s;
}
PyObject* to_python(const std::string& s)
PyObject* to_python(boost::python::semantics, const std::string& s)
{
return PyString_FromStringAndSize(s.data(), s.size());
}
@@ -268,12 +270,12 @@ bool from_python(PyObject* p, boost::python::type<bool>)
#ifdef BOOST_MSVC6_OR_EARLIER
// An optimizer bug prevents these from being inlined.
PyObject* to_python(double d)
PyObject* to_python(boost::python::semantics, double d)
{
return PyFloat_FromDouble(d);
}
PyObject* to_python(float f)
PyObject* to_python(boost::python::semantics, float f)
{
return PyFloat_FromDouble(f);
}

View File

@@ -42,7 +42,7 @@ namespace detail {
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
inline PyObject* to_python(boost::python::detail::operator_dispatcher* n) { return n; }
inline PyObject* to_python(boost::python::semantics, boost::python::detail::operator_dispatcher* n) { return n; }
BOOST_PYTHON_END_CONVERSION_NAMESPACE

View File

@@ -38,7 +38,7 @@ struct callback
%{ template <%(class A%n%:, %)>
%} static R call_method(PyObject* self, const char* name%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref p%n(to_python(search_namespace, a%n));%)
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
@@ -49,7 +49,7 @@ struct callback
%{ template <%(class A%n%:, %)>
%} static R call(PyObject* self%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref p%n(to_python(search_namespace, a%n));%)
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
detail::callback_adjust_refcount(result.get(), type<R>());
@@ -70,7 +70,7 @@ struct callback<void>
%{ template <%(class A%n%:, %)>
%} static void call_method(PyObject* self, const char* name%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref p%n(to_python(search_namespace, a%n));%)
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
@@ -79,7 +79,7 @@ struct callback<void>
%{ template <%(class A%n%:, %)>
%} static void call(PyObject* self%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref p%n(to_python(search_namespace, a%n));%)
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
}

View File

@@ -97,14 +97,14 @@ def gen_caller(member_function_args, free_function_args = None):
return (header % (member_function_args, free_function_args)
+ body_sections[0]
+ gen_functions(member_function, member_function_args,
'R', '', 'return to_python(', ');')
'R', '', 'return to_python(search_namespace, ', ');')
+ body_sections[1]
+ gen_functions(member_function, member_function_args,
'R', ' const', 'return to_python(', ');')
'R', ' const', 'return to_python(search_namespace, ', ');')
+ body_sections[2]
+ gen_functions(free_function, free_function_args,
'R', 'return to_python(', ');')
'R', 'return to_python(search_namespace, ', ');')
+ body_sections[3]
# specialized part for void return values begins here

View File

@@ -3,7 +3,7 @@ import string
def gen_extclass(args):
return (
"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
"""// (C) Copyright David Abrahams 2000-2001. 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.
@@ -171,35 +171,44 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
// and U. T is the class the user really intends to wrap. U is a class derived
// from T with some virtual function overriding boilerplate, or if there are no
// virtual functions, U = held_instance<T>.
//
// A look-alike of this class in root/boost/python/cross_module.hpp
// is used for the implementation of the cross-module support
// (export_converters and import_converters). If from_python
// and to_python converters are added or removed from the class
// below, the class python_import_extension_class_converters has
// to be modified accordingly.
//
template <class T, class U = boost::python::detail::held_instance<T> >
class python_extension_class_converters
{
public:
// Get an object which can be used to convert T to/from python. This is used
// as a kind of concept check by the global template
//
// PyObject* to_python(const T& x)
//
// below this class, to prevent the confusing messages that would otherwise
// pop up. Now, if T hasn't been wrapped as an extension class, the user
// will see an error message about the lack of an eligible
// py_extension_class_converters() function.
friend python_extension_class_converters py_extension_class_converters(boost::python::type<T>)
/// Get an object which can be used to convert T to/from python. This is used
/// as a kind of concept check by the free template function
///
/// PyObject* to_python(boost::python::semantics, const T& x)
///
/// below this class, to prevent the confusing messages that would otherwise
/// pop up. Now, if T hasn't been wrapped as an extension class, the user
/// will see an error message about the lack of an eligible
/// py_extension_class_converters() function.
friend python_extension_class_converters py_extension_class_converters(
boost::python::type<T>)
{
return python_extension_class_converters();
}
// This is a member function because in a conforming implementation, friend
// funcitons defined inline in the class body are all instantiated as soon
// as the enclosing class is instantiated. If T is not copyable, that causes
// a compiler error. Instead, we access this function through the global
// template
//
// PyObject* to_python(const T& x)
//
// defined below this class. Since template functions are instantiated only
// on demand, errors will be avoided unless T is noncopyable and the user
// writes code which causes us to try to copy a T.
/// This is a member function because in a conforming implementation, friend
/// funcitons defined inline in the class body are all instantiated as soon
/// as the enclosing class is instantiated. If T is not copyable, that causes
/// a compiler error. Instead, we access this function through the global
/// template
///
/// PyObject* to_python(boost::python::semantics, const T& x)
///
/// defined below this class. Since template functions are instantiated only
/// on demand, errors will be avoided unless T is noncopyable and the user
/// writes code which causes us to try to copy a T.
PyObject* to_python(const T& x) const
{
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
@@ -209,6 +218,7 @@ class python_extension_class_converters
return result.release();
}
/// Extract a pointer to T from the given PyObject. Will throw argument_error if obj == None.
friend
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
{
@@ -231,16 +241,19 @@ class python_extension_class_converters
throw boost::python::argument_error();
}
// Convert to T*
/// Convert obj to T*. If obj == None, returns 0.
friend T* from_python(PyObject* obj, boost::python::type<T*>)
{
// forward declaration needed for ordinary lookup.
T* non_null_from_python(PyObject*, boost::python::type<T*>);
if (obj == Py_None)
return 0;
else
return non_null_from_python(obj, boost::python::type<T*>());
}
// Extract from obj a mutable reference to the PtrType object which is holding a T.
/// Extract from obj a mutable reference to the PtrType object which is holding a T.
template <class PtrType>
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
{
@@ -259,10 +272,10 @@ class python_extension_class_converters
throw boost::python::argument_error();
}
// Extract from obj a reference to the PtrType object which is holding a
// T. If it weren't for auto_ptr, it would be a constant reference. Do not
// modify the referent except by copying an auto_ptr! If obj is None, the
// reference denotes a default-constructed PtrType
/// Extract from obj a reference to the PtrType object which is holding a
/// T. If it weren't for auto_ptr, it would be a constant reference. Do not
/// modify the referent except by copying an auto_ptr! If obj is None, the
/// reference denotes a default-constructed PtrType
template <class PtrType>
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
{
@@ -273,7 +286,9 @@ class python_extension_class_converters
}
return smart_ptr_reference(obj, boost::python::type<PtrType>());
}
/// Wrap x in a Python object which implements the functionality of a
/// regular wrapped T by dereferencing a copy of x.
template <class PtrType>
static PyObject* smart_ptr_to_python(PtrType x)
{
@@ -289,6 +304,9 @@ class python_extension_class_converters
return result.release();
}
/// Create a Python object which is an instance of the Python type wrapper
/// for T. The result does not actually contain the neccessary instance of
/// T. This function is an implementation detail.
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
{
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
@@ -299,15 +317,15 @@ class python_extension_class_converters
new boost::python::detail::extension_instance(class_object));
}
// Convert to const T*
/// Convert p to const T*
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
{ return from_python(p, boost::python::type<T*>()); }
// Convert to const T* const&
/// Convert p to const T* const&
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
{ return from_python(p, boost::python::type<const T*>()); }
// Convert to T* const&
/// Convert p to T* const&
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
{ return from_python(p, boost::python::type<T*>()); }
@@ -315,11 +333,11 @@ class python_extension_class_converters
friend T& from_python(PyObject* p, boost::python::type<T&>)
{ return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type<T*>())); }
// Convert to const T&
// Convert p to const T&
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
{ return from_python(p, boost::python::type<T&>()); }
// Convert to T
/// Convert p to T
friend const T& from_python(PyObject* p, boost::python::type<T>)
{ return from_python(p, boost::python::type<T&>()); }
@@ -332,7 +350,7 @@ class python_extension_class_converters
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
friend PyObject* to_python(std::auto_ptr<T> x)
friend PyObject* to_python(boost::python::semantics, std::auto_ptr<T> x)
{ return smart_ptr_to_python(x); }
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
@@ -344,7 +362,7 @@ class python_extension_class_converters
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
friend PyObject* to_python(boost::shared_ptr<T> x)
friend PyObject* to_python(boost::python::semantics, boost::shared_ptr<T> x)
{ return smart_ptr_to_python(x); }
};
@@ -353,7 +371,7 @@ class python_extension_class_converters
// T is a wrapped class. See the first 2 functions declared in
// python_extension_class_converters above for more info.
template <class T>
PyObject* to_python(const T& x)
PyObject* to_python(boost::python::semantics, const T& x)
{
return py_extension_class_converters(boost::python::type<T>()).to_python(x);
}

View File

@@ -49,9 +49,9 @@ PyObject* object::get() const
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
PyObject* to_python(const boost::python::tuple& x)
PyObject* to_python(boost::python::semantics, const boost::python::tuple& x)
{
return object_to_python(x);
return boost::python::object_to_python(x);
}
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple> type)
@@ -59,7 +59,7 @@ boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python:
return boost::python::object_from_python(p, type);
}
PyObject* to_python(const boost::python::list& x)
PyObject* to_python(boost::python::semantics, const boost::python::list& x)
{
return object_to_python(x);
}
@@ -69,7 +69,7 @@ boost::python::list from_python(PyObject* p, boost::python::type<boost::python::
return boost::python::object_from_python(p, type);
}
PyObject* to_python(const boost::python::dictionary& x)
PyObject* to_python(boost::python::semantics, const boost::python::dictionary& x)
{
return object_to_python(x);
}
@@ -79,7 +79,7 @@ boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::py
return boost::python::object_from_python(p, type);
}
PyObject* to_python(const boost::python::string& x)
PyObject* to_python(boost::python::semantics, const boost::python::string& x)
{
return object_to_python(x);
}