2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-26 06:42:27 +00:00

This commit was manufactured by cvs2svn to create branch

'boost_python_friend_fixes'.

[SVN r10123]
This commit is contained in:
nobody
2001-05-18 15:12:31 +00:00
parent 9b602d16b4
commit 9261e2a3d9
95 changed files with 8404 additions and 925 deletions

View File

@@ -5,6 +5,11 @@
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// 04 Mar 01 Rolled in const_cast from Dragon fork (Dave Abrahams)
// 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve)
// 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function)
#include <boost/python/classes.hpp>
#include <boost/python/detail/functions.hpp>
@@ -67,8 +72,7 @@ namespace {
ref global_class_reduce()
{
static ref result(detail::new_wrapped_function(class_reduce));
return result;
return ref(detail::new_wrapped_function(class_reduce));
}
@@ -93,17 +97,41 @@ namespace {
ref getstate(PyObject_GetAttrString(obj, const_cast<char*>("__getstate__")),
ref::null_ok);
PyErr_Clear();
ref dict(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
PyErr_Clear();
if (getstate.get() != 0)
{
if (dict.get() != 0 && dictionary(dict).size() > 0)
{
ref getstate_manages_dict(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__getstate_manages_dict__")), ref::null_ok);
PyErr_Clear();
if (getstate_manages_dict.get() == 0)
{
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__getstate_manages_dict__ not set)");
throw error_already_set();
}
}
ref state = ref(PyEval_CallObject(getstate.get(), NULL));
return tuple(instance_class, initargs, state);
}
ref state(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
PyErr_Clear();
if (state.get() != 0 && dictionary(state).size() > 0)
if (getinitargs.get() == 0)
{
return tuple(instance_class, initargs, state);
ref dict_defines_state(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__dict_defines_state__")), ref::null_ok);
PyErr_Clear();
if (dict_defines_state.get() == 0)
{
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__dict_defines_state__ not set)");
throw error_already_set();
}
}
if (dict.get() != 0 && dictionary(dict).size() > 0)
{
return tuple(instance_class, initargs, dict);
}
return tuple(instance_class, initargs);
@@ -111,8 +139,7 @@ namespace {
ref global_instance_reduce()
{
static ref result(detail::new_wrapped_function(instance_reduce));
return result;
return ref(detail::new_wrapped_function(instance_reduce));
}
}
@@ -177,7 +204,7 @@ namespace detail {
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
{
ref target(as_object(this), ref::increment_count);
return new bound_function(target, global_class_reduce());
return bound_function::create(target, global_class_reduce());
}
ref local_attribute = m_name_space.get_item(string(name).reference());
@@ -348,7 +375,7 @@ PyObject* instance::getattr(const char* name, bool use_special_function)
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
{
return new detail::bound_function(ref(this, ref::increment_count), global_instance_reduce());
return detail::bound_function::create(ref(this, ref::increment_count), global_instance_reduce());
}
ref local_attribute = m_name_space.get_item(string(name).reference());
@@ -840,7 +867,27 @@ namespace {
void add_current_module_name(dictionary& name_space)
{
static string module_key("__module__", string::interned);
name_space.set_item(module_key, module_builder::name());
// If the user didn't specify a __module__ attribute already
if (name_space.get_item(module_key).get() == 0)
{
if (module_builder::initializing())
{
// The global __name__ is not properly set in this case
name_space.set_item(module_key, module_builder::name());
}
else
{
// Get the module name from the global __name__
PyObject *globals = PyEval_GetGlobals();
if (globals != NULL)
{
PyObject *module_name = PyDict_GetItemString(globals, const_cast<char*>("__name__"));
if (module_name != NULL)
name_space.set_item(module_key, module_name);
}
}
}
}
}

View File

@@ -5,6 +5,13 @@
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// 05 Apr 01 added: from_python std::string type checking (rwgk)
// 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve)
// 11 Mar 01 std::string *MAY* include nulls (Alex Martelli)
// 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams)
// 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve)
#include <boost/python/conversions.hpp>
#include <typeinfo>
@@ -44,6 +51,19 @@ void handle_exception()
}
}
namespace detail {
void expect_complex(PyObject* p)
{
if (!PyComplex_Check(p))
{
PyErr_SetString(PyExc_TypeError, "expected a complex number");
throw boost::python::argument_error();
}
}
} // namespace boost::python::detail
}} // namespace boost::python
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
@@ -132,7 +152,7 @@ int from_python(PyObject* p, boost::python::type<int> type)
PyObject* to_python(unsigned int i)
{
return integer_to_python(i);
return integer_to_python(i);
}
unsigned int from_python(PyObject* p, boost::python::type<unsigned int> type)
@@ -152,7 +172,7 @@ float from_python(PyObject* p, boost::python::type<float>)
PyObject* to_python(unsigned short i)
{
return integer_to_python(i);
return integer_to_python(i);
}
unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type)
@@ -160,9 +180,27 @@ unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type
return integer_from_python(p, type);
}
PyObject* to_python(char c)
{
if (c == '\0') return PyString_FromString("");
return PyString_FromStringAndSize(&c, 1);
}
char from_python(PyObject* p, boost::python::type<char>)
{
int l = -1;
if (PyString_Check(p)) l = PyString_Size(p);
if (l < 0 || l > 1) {
PyErr_SetString(PyExc_TypeError, "expected string of length 0 or 1");
throw boost::python::argument_error();
}
if (l == 0) return '\0';
return PyString_AsString(p)[0];
}
PyObject* to_python(unsigned char i)
{
return integer_to_python(i);
return integer_to_python(i);
}
unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
@@ -172,7 +210,7 @@ unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
PyObject* to_python(signed char i)
{
return integer_to_python(i);
return integer_to_python(i);
}
signed char from_python(PyObject* p, boost::python::type<signed char> type)
@@ -208,12 +246,16 @@ const char* from_python(PyObject* p, boost::python::type<const char*>)
PyObject* to_python(const std::string& s)
{
return PyString_FromString(s.c_str());
return PyString_FromStringAndSize(s.data(), s.size());
}
std::string from_python(PyObject* p, boost::python::type<std::string>)
{
return std::string(from_python(p, boost::python::type<const char*>()));
if (! PyString_Check(p)) {
PyErr_SetString(PyExc_TypeError, "expected a string");
throw boost::python::argument_error();
}
return std::string(PyString_AsString(p), PyString_Size(p));
}
bool from_python(PyObject* p, boost::python::type<bool>)

87
src/cross_module.cpp Normal file
View File

@@ -0,0 +1,87 @@
/* (C) Copyright Ralf W. Grosse-Kunstleve 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.
Revision History:
17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve)
*/
# include <boost/python/cross_module.hpp>
namespace python = boost::python;
# include <stdio.h> // MSVC6.0SP4 does not know std::fprintf
# include <string.h> // MSVC6.0SP4 does not know std::strcmp
namespace {
PyObject* get_module_dict(const char* module_name)
{
python::ref module_obj(PyImport_ImportModule((char*) module_name));
PyObject* module_dict = PyModule_GetDict(module_obj.get());
if (module_dict == 0) throw python::import_error();
return module_dict;
}
}
namespace boost { namespace python { namespace detail {
const char* converters_attribute_name = "__converters__";
void* import_converter_object(const std::string& module_name,
const std::string& py_class_name,
const std::string& attribute_name)
{
static std::string err;
PyObject* module_dict = get_module_dict(const_cast<char*>(module_name.c_str()));
PyObject* py_class = PyDict_GetItemString(module_dict, const_cast<char*>(py_class_name.c_str()));
if (py_class == 0) {
err = std::string("module ") + module_name + " has no attribute " + py_class_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
python::ref c_obj(PyObject_GetAttrString(py_class, const_cast<char*>(attribute_name.c_str())), ref::null_ok);
if (c_obj.get() == 0) {
err = std::string("object ") + module_name + "." + py_class_name
+ " has no attribute " + attribute_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
if (! PyCObject_Check(c_obj.get())) {
err = std::string("object ") + module_name + "." + py_class_name + "."
+ attribute_name + " is not a PyCObject";
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
return PyCObject_AsVoidPtr(c_obj.get());
}
void check_export_converters_api(const int importing_major,
const int importing_minor,
const int imported_major,
const int imported_minor)
{
if (importing_major != imported_major) {
// Python uses fprintf(stderr, ...) for API warnings.
fprintf(stderr,
"Fatal: export_converters_api mismatch:"
" Importing module = %d.%d"
" Imported module = %d.%d\n",
importing_major, importing_minor,
imported_major, imported_minor);
PyErr_SetString(PyExc_RuntimeError,
"Fatal: export_converters_api mismatch");
throw import_error();
}
if (importing_minor != imported_minor) {
// Python uses fprintf(stderr, ...) for API warnings.
fprintf(stderr,
"Warning: export_converters_api mismatch:"
" Importing module = %d.%d"
" Imported module = %d.%d\n",
importing_major, importing_minor,
imported_major, imported_minor);
}
}
}}} // namespace boost::python::detail

View File

@@ -5,6 +5,9 @@
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
#include <boost/python/detail/extension_class.hpp>
#include <cstring>
@@ -46,24 +49,19 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python {
namespace detail {
tuple standard_coerce(ref l, ref r)
{
// Introduced sequence points for exception-safety.
ref first(detail::operator_dispatcher::create(l, l));
ref second(r->ob_type == &detail::operator_dispatcher::type_obj
? r
: ref(detail::operator_dispatcher::create(r, ref())));
tuple extension_class_coerce(ref l, ref r)
{
// Introduced sequence points for exception-safety.
ref first(operator_dispatcher::create(l, l));
ref second;
if(r->ob_type == &operator_dispatcher::type_obj)
{
second = r;
}
else
{
second = ref(operator_dispatcher::create(r, ref()));
}
return boost::python::tuple(first, second);
}
return tuple(first, second);
}
namespace detail {
enum { unwrap_exception_code = -1000 };
@@ -451,8 +449,8 @@ operator_dispatcher::operator_dispatcher(const ref& o, const ref& s)
: m_object(o), m_self(s), m_free_list_link(0)
{
ob_refcnt = 1;
ob_type = &type_obj;
PyObject* self = this;
PyObject_INIT(self, &type_obj);
}
operator_dispatcher*
@@ -465,7 +463,9 @@ operator_dispatcher::create(const ref& object, const ref& self)
free_list = result->m_free_list_link;
result->m_object = object;
result->m_self = self;
Py_INCREF(result);
PyObject* result_as_pyobject = result;
PyObject_INIT(result_as_pyobject, &type_obj);
return result;
}

View File

@@ -5,6 +5,9 @@
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
#include <boost/python/detail/functions.hpp>
#include <boost/python/detail/types.hpp>
@@ -97,19 +100,6 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
return 0;
}
bound_function* bound_function::create(const ref& target, const ref& fn)
{
bound_function* const result = free_list;
if (result == 0)
return new bound_function(target, fn);
free_list = result->m_free_list_link;
result->m_target = target;
result->m_unbound_function = fn;
Py_INCREF(result);
return result;
}
// The instance class whose obj represents the type of bound_function
// objects in Python. bound_functions must be GetAttrable so the __doc__
// attribute of built-in Python functions can be accessed when bound.
@@ -123,6 +113,21 @@ private: // type_object<bound_function> hook override
void dealloc(bound_function*) const;
};
bound_function* bound_function::create(const ref& target, const ref& fn)
{
bound_function* const result = free_list;
if (result == 0)
return new bound_function(target, fn);
free_list = result->m_free_list_link;
result->m_target = target;
result->m_unbound_function = fn;
PyObject* self = result;
PyObject_INIT(self, type_object::instance());
return result;
}
bound_function::bound_function(const ref& target, const ref& fn)
: python_object(type_object::instance()),
m_target(target),

View File

@@ -6,12 +6,12 @@ from gen_singleton import *
from gen_extclass import *
def gen_all(args):
open('callback.h', 'w').write(gen_callback(args))
open('caller.h', 'w').write(gen_caller(args))
open('init_function.h', 'w').write(gen_init_function(args))
open('signatures.h', 'w').write(gen_signatures(args))
open('instance.h', 'w').write(gen_singleton(args))
open('extclass.h', 'w').write(gen_extclass(args))
open('callback.hpp', 'w').write(gen_callback(args))
open('caller.hpp', 'w').write(gen_caller(args))
open('init_function.hpp', 'w').write(gen_init_function(args))
open('signatures.hpp', 'w').write(gen_signatures(args))
open('singleton.hpp', 'w').write(gen_singleton(args))
open('extension_class.hpp', 'w').write(gen_extclass(args))
if __name__ == '__main__':
import sys

View File

@@ -14,6 +14,10 @@ def gen_extclass(args):
// This file automatically generated for %d-argument constructors by
// gen_extclass.python
// Revision History:
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
// to_python (Dave Abrahams)
#ifndef EXTENSION_CLASS_DWA052000_H_
# define EXTENSION_CLASS_DWA052000_H_
@@ -27,6 +31,7 @@ def gen_extclass(args):
# include <boost/python/detail/init_function.hpp>
# include <typeinfo>
# include <boost/smart_ptr.hpp>
# include <boost/type_traits.hpp>
namespace boost { namespace python {
@@ -66,7 +71,7 @@ T* check_non_null(T* p)
return p;
}
template <class T> class held_instance;
template <class Held> class held_instance;
typedef void* (*conversion_function_ptr)(void*);
@@ -138,6 +143,26 @@ class class_registry
static std::vector<derived_class_info> static_derived_class_info;
};
template <bool is_pointer>
struct is_null_helper
{
template <class Ptr>
static bool test(Ptr x) { return x == 0; }
};
template <>
struct is_null_helper<false>
{
template <class Ptr>
static bool test(const Ptr& x) { return x.get() == 0; }
};
template <class Ptr>
bool is_null(const Ptr& x)
{
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
}
}}} // namespace boost::python::detail
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
@@ -183,9 +208,9 @@ class python_extension_class_converters
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
return result.release();
}
// Convert to T*
friend T* from_python(PyObject* obj, boost::python::type<T*>)
friend
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
{
// downcast to an extension_instance, then find the actual T
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
@@ -206,9 +231,18 @@ class python_extension_class_converters
throw boost::python::argument_error();
}
// Convert to PtrType, where PtrType can be dereferenced to obtain a T.
// Convert to T*
friend T* from_python(PyObject* obj, 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.
template <class PtrType>
static PtrType& ptr_from_python(PyObject* obj, boost::python::type<PtrType>)
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
{
// downcast to an extension_instance, then find the actual T
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
@@ -225,9 +259,29 @@ 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
template <class PtrType>
static PyObject* ptr_to_python(PtrType x)
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
{
if (obj == Py_None)
{
static PtrType null_ptr;
return null_ptr;
}
return smart_ptr_reference(obj, boost::python::type<PtrType>());
}
template <class PtrType>
static PyObject* smart_ptr_to_python(PtrType x)
{
if (boost::python::detail::is_null(x))
{
return boost::python::detail::none();
}
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
result->add_implementation(
std::auto_ptr<boost::python::detail::instance_holder_base>(
@@ -259,7 +313,7 @@ class python_extension_class_converters
// Convert to T&
friend T& from_python(PyObject* p, boost::python::type<T&>)
{ return *boost::python::detail::check_non_null(from_python(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&
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
@@ -270,28 +324,28 @@ class python_extension_class_converters
{ return from_python(p, boost::python::type<T&>()); }
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
{ return smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<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)
{ return ptr_to_python(x); }
{ return smart_ptr_to_python(x); }
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
{ return smart_ptr_reference(p, boost::python::type<boost::shared_ptr<T> >()); }
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<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)
{ return ptr_to_python(x); }
{ return smart_ptr_to_python(x); }
};
// Convert T to_python, instantiated on demand and only if there isn't a
@@ -613,15 +667,15 @@ class extension_class
// A simple wrapper over a T which allows us to use extension_class<T> with a
// single template parameter only. See extension_class<T>, above.
template <class T>
class held_instance : public T
template <class Held>
class held_instance : public Held
{
// There are no member functions: we want to avoid inadvertently overriding
// any virtual functions in T.
// any virtual functions in Held.
public:"""
+ gen_functions("""%{
template <%(class A%n%:, %)>%}
held_instance(PyObject*%(, A%n% a%n%)) : T(%(a%n%:, %)) {}""", args)
held_instance(PyObject*%(, A%n% a%n%)) : Held(%(a%n%:, %)) {}""", args)
+ """
};
@@ -707,8 +761,6 @@ class extension_instance : public instance
// Template function implementations
//
tuple extension_class_coerce(ref l, ref r);
template <class T, class U>
extension_class<T, U>::extension_class()
: extension_class_base(typeid(T).name())
@@ -729,7 +781,7 @@ void extension_class<T, U>::def_standard_coerce()
ref coerce_fct = dict().get_item(string("__coerce__"));
if(coerce_fct.get() == 0) // not yet defined
this->def(&extension_class_coerce, "__coerce__");
this->def(&standard_coerce, "__coerce__");
}
template <class T, class U>

View File

@@ -14,10 +14,15 @@ namespace {
ref name_holder;
}
bool module_builder::initializing()
{
return name_holder.get() != 0;
}
string module_builder::name()
{
// If this fails, you haven't created a module_builder object
assert(name_holder.get() != 0);
assert(initializing());
return string(name_holder);
}
@@ -29,6 +34,11 @@ module_builder::module_builder(const char* name)
name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__")));
}
module_builder::~module_builder()
{
name_holder.reset();
}
void
module_builder::add(detail::function* x, const char* name)
{