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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()%)));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user