diff --git a/doc/v2/HolderGenerator.html b/doc/v2/HolderGenerator.html new file mode 100755 index 00000000..1b9b8d89 --- /dev/null +++ b/doc/v2/HolderGenerator.html @@ -0,0 +1,71 @@ + + + + +Boost.Python - Holder Concept + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+

HolderGenerator Concept

+
+
+
+
Introduction
+
Concept Requirements
+
+
HolderGenerator Concept
+
+
+ +

Introduction

+ +

A HolderGenerator is a unary metafunction class which returns types +suitable for holding instances of its argument in a wrapped C++ class +instance. + +

Concept Requirements

+

HolderGenerator Concept

+ +

In the table below, G denotes an type which +models HolderGenerator, and X denotes a class +type. + + + + + + + + + + + +
ExpressionRequirements
G::apply<X>::typeA concrete subclass of instance_holder + which can hold objects of type X. +
+ +


+

Revised + + 20 May, 2002 + +

+

© Copyright Dave + Abrahams 2002. All Rights Reserved. + +

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. + + diff --git a/doc/v2/class.html b/doc/v2/class.html index 1c84c1c2..fd2b1434 100644 --- a/doc/v2/class.html +++ b/doc/v2/class.html @@ -319,9 +319,9 @@ class_& def_init(Args const& argument_types, CallPolicies policies); make_constructor<Args,Holder>(policies), respectively, to the Boost.Python extension class being defined under the name - "__init__". Holder is a model of Holder which contains the - HeldType. If the extension class + "__init__". Holder is a concrete subclass of instance_holder + which holds the HeldType. If the extension class already has an "__init__" attribute, the usual overloading procedure applies. diff --git a/doc/v2/errors.html b/doc/v2/errors.html index e36224fb..6e364e8f 100644 --- a/doc/v2/errors.html +++ b/doc/v2/errors.html @@ -28,7 +28,7 @@

-
Class error_already_set +
Class error_already_set
@@ -44,6 +44,7 @@
handle_exception
expect_non_null +
throw_error_already_set
Examples @@ -117,9 +118,7 @@ void handle_exception() throw(); an enclosing try block.
-PyObject* expect_non_null(PyObject* x);
-
-template <class T> T* expect_non_null(T* x);
+template <class T> T* expect_non_null(T* x);
 
@@ -135,6 +134,16 @@ template <class T> T* expect_non_null(T* x); return 0 on error.
+
+void throw_error_already_set();
+
+ +
+ +
Effects: throw error_already_set(); +
+

Examples

 #include <string>
diff --git a/doc/v2/instance_holder.html b/doc/v2/instance_holder.html
new file mode 100755
index 00000000..5f5a751a
--- /dev/null
+++ b/doc/v2/instance_holder.html
@@ -0,0 +1,209 @@
+
+
+    
+    
+    
+
+    Boost.Python - <boost/python/instance_holder.hpp>
+
+
+    
+      
+        
+

C++ Boost

+ +
+

Boost.Python

+ +

Header <boost/python/instance_holder.hpp>

+
+
+ +

Contents

+ +
+
Introduction + +
Classes + +
+
+
Class + instance_holder + +
+
+
Class + instance_holder synopsis + +
Class + instance_holder destructor + +
Class + instance_holder modifier functions + +
Class + instance_holder observer functions +
+
+ +
Example +
+
+ +

Introduction

+ +

<boost/python/instance_holder.hpp> provides + class instance_holder, the base class for types + which hold C++ instances of wrapped classes. + +

Classes

+ +

Class instance_holder

+ +

instance_holder is an abstract base class whose + concrete derived classes hold C++ class instances within their + Python object wrappers. To allow multiple inheritance in Python + from C++ class wrappers, each such Python object contains a chain + of instance_holders. When an __init__ + function for a wrapped C++ class is invoked, a new + instance_holder instance is created and installed in + the Python object using its install() + function. Each concrete class derived from + instance_holder must provide a holds() + implementation which allows Boost.Python to query it for the + type(s) it is holding. In order to support the held type's wrapped + constructor(s), the class must also provide constructors that can + accept an initial PyObject* argument referring to the + owning Python object, and which forward the rest of their + arguments to the constructor of the held type. The initial + argument is needed to enable virtual function overriding in + Python, and may be ignored, depending on the specific + instance_holder subclass. + +

Class instance_holder + synopsis

+
+namespace boost { namespace python
+{
+  class instance_holder : noncopyable
+  {
+   public:
+      // destructor
+      virtual ~instance_holder();
+
+      // instance_holder modifiers
+      void install(PyObject* inst) throw();
+
+      // instance_holder observers
+      virtual void* holds(type_info) = 0;
+  };
+}}
+
+ +

Class instance_holder + destructor

+
+virtual ~instance_holder();
+
+ +
+
Effects: destroys the object +
+ +

Class + instance_holder modifiers

+
+void install(PyObject* inst) throw();
+
+ +
+
Requires: inst is a Python instance of a + wrapped C++ class type, or is a type derived from a wrapped C++ + class type. +
Effects: installs the new instance at the head of the + Python object's chain of held instances. +
Throws: nothing +
+ +

Class instance_holder + observers

+
+virtual void* holds(type_info x) = 0;
+
+ +
+
Returns: A pointer to an object of the type described + by x if *this contains such an object, + 0 otherwise. +
+ +

Example

+ +The following is a simplified version of the instance holder template +used by Boost.Python to wrap classes held by smart pointers: +
+template <class SmartPtr, class Value>
+struct pointer_holder : instance_holder
+{
+   // construct from the SmartPtr type
+   pointer_holder(SmartPtr p)
+       :m_p(p)
+
+   // Forwarding constructors for the held type
+   pointer_holder(PyObject*)
+       :m_p(new Value())
+   {
+   }
+
+   template<class A0>
+   pointer_holder(PyObject*,A0 a0)
+       :m_p(new Value(a0))
+   {
+   }
+
+   template<class A0,class A1>
+   pointer_holder(PyObject*,A0 a0,A1 a1)
+       :m_p(new Value(a0,a1))
+   {
+   }
+   ...
+
+ private: // required holder implementation
+   void* holds(type_info dst_t)
+   {
+       // holds an instance of the SmartPtr type...
+       if (dst_t == python::type_id<SmartPtr>())
+           return &this->m_p;
+
+       // ...and an instance of the SmartPtr's element_type, if the
+       // pointer is non-null
+       return python::type_id<Value>() == dst_t ? &*this->m_p : 0;
+   }
+
+ private: // data members
+   SmartPtr m_p;
+};
+
+ +

Revised + + 19 November, 2002 + + + +

© Copyright Dave Abrahams 2002. All + Rights Reserved. + diff --git a/doc/v2/iterator.html b/doc/v2/iterator.html index fd5a1bae..944ccd29 100644 --- a/doc/v2/iterator.html +++ b/doc/v2/iterator.html @@ -95,7 +95,7 @@ C and creates a Python iterator that traverses [c.begin(), c.end()). The optional CallPolicies + href="CallPolicies.html">CallPolicies P can be used to control how elements are returned during iteration. diff --git a/doc/v2/make_function.html b/doc/v2/make_function.html index f3189672..c31144c9 100644 --- a/doc/v2/make_function.html +++ b/doc/v2/make_function.html @@ -78,12 +78,17 @@ objects::function* make_function(F f, Policies const& policies) template <class T, class ArgList, class Generator> objects::function* make_constructor(); + +template <class ArgList, class Generator, class Policies> +objects::function* make_constructor(Policies const& policies)

-
Requires: T is a class type. ArgList - is an MPL sequence of C++ - argument types (A1, A2,... AN) such that if +
Requires: T is a class + type. Policies is a model of CallPolicies. ArgList + is an MPL sequence + of C++ argument types (A1, A2,... AN) such that if a1, a2... aN are objects of type A1, A2,... AN respectively, the expression new Generator::apply<T>::type(a1, a2... aN) is @@ -94,8 +99,12 @@ objects::function* make_constructor(); from Python, expects its first argument to be a Boost.Python extension class object. It converts its remaining its arguments to C++ and passes them to the constructor of a dynamically-allocated - Generator::apply<T>::type object. The result is - installed in the extension class object. + Generator::apply<T>::type object, which is + then installed in the extension class object. In the second + form, the policies are applied to the arguments and + result (None) + of the Python callable object
Returns: The new Python callable object
diff --git a/doc/v2/reference.html b/doc/v2/reference.html index e79e0a45..71191cee 100644 --- a/doc/v2/reference.html +++ b/doc/v2/reference.html @@ -1,21 +1,29 @@ + - + Boost.Python - Reference + - +
-

-

+

C++ Boost +

-

Boost.Python

+

Boost.Python

-

Reference

+

Reference


@@ -23,209 +31,227 @@
Concepts -
-
CallPolicies
-
Dereferenceable
-
ResultConverter
-
ResultConverterGenerator
-
High Level Components -
Models of CallPolicies +
Function Invocation and Creation -
Models of ReturnHandlerGenerator +
+
+
Models of + CallPolicies + +
Models of + ResultConverterGenerator +
To/From Python Type Conversion -
Index By Name -
- +
Utility and Infrastructure -

High Level Components

+ +
+ + +

Concepts

+
+
CallPolicies + +
Dereferenceable + +
HolderGenerator + +
ResultConverter + +
ResultConverterGenerator +
+ +

High Level Components

+ +
+
class.hpp/class_fwd.hpp + +
+
+
Classes + +
+
+
class_ + +
bases + +
args +
+
+ +
errors.hpp + +
+
+
Classes + +
+
+
error_already_set +
+ +
Functions + +
+
+
handle_exception + +
expect_non_null +
+
+ +
iterator.hpp + +
+
+
Classes + +
+
+
iterator + +
iterators +
+ +
Functions + +
+
+
range +
+
+ +
module.hpp + +
+
+
Classes + +
+
+
module +
+
+ +
objects.hpp + +
+
+
Classes + +
+
+
not yet + documented +
+
+
+ +

Function Invocation and Creation

+
call.hpp +
- - -

General Purpose

-
- -
call.hpp -
-
-
Functions - -
-
-
call -
-
- -
call_method.hpp -
-
-
Functions - -
-
-
call_method -
-
- -
class.hpp/class_fwd.hpp +
Functions
-
Classes - -
-
-
class_ - -
bases - -
args -
-
- -
data_members.hpp - -
-
-
Functions - -
-
-
make_getter - -
make_setter -
-
- -
errors.hpp - -
-
-
Classes - -
-
-
error_already_set -
- -
Functions - -
-
-
handle_exception - -
expect_non_null -
-
- - -
iterator.hpp -
-
-
Classes -
-
-
iterator -
iterators -
- -
Functions - -
-
-
range -
-
- -
make_function.hpp - -
-
-
Functions - -
-
-
make_function - -
make_constructor -
-
- -
module.hpp - -
-
-
Classes - -
-
-
module -
-
- -
objects.hpp - -
-
-
Classes - -
-
-
not yet documented -
-
- -
pointee.hpp -
-
-
Classes - -
-
-
class template pointee -
-
- -
reference.hpp -
-
-
Classes - -
-
-
reference -
- -
Types - -
-
-
ref -
+
call
+
call_method.hpp - +
+
+
Functions + +
+
+
call_method +
+
+ +
data_members.hpp + +
+
+
Functions + +
+
+
make_getter + +
make_setter +
+
+ +
make_function.hpp + +
+
+
Functions + +
+
+
make_function + +
make_constructor +
+
+ +
ptr.hpp + +
+
+
Functions + +
+
+
ptr +
+ +
Classes + +
+
+
pointer_wrapper +
+ +
MetaFunctions + +
+
+
is_pointer_wrapper + +
unwrap_pointer +
+
+

Models of CallPolicies

@@ -235,15 +261,18 @@
-
Classes +
Classes
-
default_call_policies +
+ default_call_policies -
default_result_converter +
+ default_result_converter
@@ -252,25 +281,28 @@
-
Classes +
Classes
-
return_internal_reference
-
return_value_policy.hpp +
return_value_policy.hpp
-
Classes +
Classes
-
return_value_policy
@@ -280,34 +312,39 @@
-
Classes +
Classes
-
with_custodian_and_ward +
+ with_custodian_and_ward -
with_custodian_and_ward_postcall
- + -

Models of ReturnHandlerGenerator

+

Models of ResultConverterGenerator

-
copy_const_reference.hpp +
copy_const_reference.hpp
-
Classes +
Classes
-
copy_const_reference +
+ copy_const_reference
@@ -316,17 +353,19 @@
-
Classes +
Classes
-
copy_non_const_reference
-
manage_new_object.hpp +
manage_new_object.hpp
@@ -334,7 +373,7 @@
-
manage_new_object
@@ -344,11 +383,12 @@
-
Classes +
Classes
-
reference_existing_object
@@ -363,7 +403,7 @@
-
reference_from_python
+
- +

To/From Python Type + Conversion

-

To/From Python Type Conversion

+
+
from_python.hpp +
-
from_python.hpp +
Classes
-
Classes - -
-
-
from_python -
-
- -
has_back_reference.hpp -
-
-
Classes -
-
-
has_back_reference -
- -
- - -
implicit.hpp -
-
-
Functions - -
-
-
implicitly_convertible -
-
- -
ptr.hpp - -
-
-
Functions -
-
-
ptr -
- -
Classes -
-
-
pointer_wrapper -
- -
MetaFunctions -
-
-
is_pointer_wrapper -
unwrap_pointer -
- -
- -
to_python_converter.hpp - -
-
-
Classes - -
-
-
to_python_converter -
-
- -
to_python_indirect.hpp - -
-
-
Classes - -
-
-
to_python_indirect -
-
- -
to_python_value.hpp - -
-
-
Classes - -
-
-
to_python_value -
-
- -
type_from_python.hpp - -
-
-
Classes - -
-
-
type_from_python -
-
- -
value_from_python.hpp - -
-
-
Classes - -
-
-
value_from_python -
+
from_python
+
implicit.hpp + +
+
+
Functions + +
+
+
implicitly_convertible +
+
+ +
to_python_converter.hpp + +
+
+
Classes + +
+
+
to_python_converter +
+
+ +
to_python_indirect.hpp + +
+
+
Classes + +
+
+
to_python_indirect +
+
+ +
to_python_value.hpp + +
+
+
Classes + +
+
+
to_python_value +
+
+ +
type_from_python.hpp + +
+
+
Classes + +
+
+
type_from_python +
+
+ +
value_from_python.hpp + +
+
+
Classes + +
+
+
value_from_python +
+
+
+ +

Utility and Infrastructure

+ +
+
has_back_reference.hpp + +
+
+
Classes + +
+
+
has_back_reference +
+
+ +
instance_holder.hpp + +
+
+
Classes + +
+
+
+ instance_holder +
+
+ +
pointee.hpp + +
+
+
Classes + +
+
+
class template pointee +
+
+ +
reference.hpp + +
+
+
Classes + +
+
+
reference +
+ +
Types + +
+
+
ref +
+
+ +
type_id.hpp + +
+
+
Functions + +
+
+
type_id +
+ +
Classes + +
+
+
type_info +
+

@@ -514,6 +602,7 @@ -

© Copyright Dave - Abrahams 2002. All Rights Reserved. +

© Copyright Dave Abrahams 2002. All + Rights Reserved. diff --git a/doc/v2/return_value_policy.html b/doc/v2/return_value_policy.html index 950b024b..88a72a0c 100644 --- a/doc/v2/return_value_policy.html +++ b/doc/v2/return_value_policy.html @@ -69,7 +69,7 @@ Default - ResultConverterGenerator + ResultConverterGenerator A model of ResultConverterGenerator. diff --git a/doc/v2/type_id.html b/doc/v2/type_id.html new file mode 100755 index 00000000..6407f913 --- /dev/null +++ b/doc/v2/type_id.html @@ -0,0 +1,219 @@ + + + + + + + Boost.Python - <boost/python/type_id.hpp> + + + + +
+

C++ Boost

+ +
+

Boost.Python

+ +

Header <boost/python/type_id.hpp>

+
+


+ +

Contents

+ +
+
Introduction + +
Classes + +
+
+
Class + type_info + +
+
+
Class + type_info synopsis + +
Class + type_info constructor + +
Class + type_info comparison functions + +
Class + type_info observer functions +
+
+ +
Functions + +
+
+
type_id +
+ +
Example +
+
+ +

Introduction

+ +

<boost/python/type_id.hpp> provides types and + functions for runtime type identification like those of of + <typeinfo>. It exists mostly to work around + certain compiler bugs and platform-dependent interactions with + shared libraries. + +

Classes

+ +

Class type_info

+ +

type_info instances identify a type. As + std::type_info is specified to (but unlike its + implementation in some compilers), + boost::python::type_info never represents top-level + references or cv-qualification (see section 5.2.8 in the C++ + standard). Unlike std::type_info, + boost::python::type_info instances are copyable, and + comparisons always work reliably across shared library boundaries. + +

Class type_info + synopsis

+
+namespace boost { namespace python
+{
+  class type_info : totally_ordered<type_info>
+  {
+   public:
+      // constructor
+      type_info(std::type_info const& = typeid(void));
+
+      // comparisons
+      bool operator<(type_info const& rhs) const;
+      bool operator==(type_info const& rhs) const;
+
+      // observers
+      char const* name() const;
+  };
+}}
+
+ +

Class type_info + constructor

+
+type_info(std::type_info const& = typeid(void));
+
+ +
+
Effects: constructs a type_info object + which identifies the same type as its argument. + +
Rationale: Since it is occasionally neccessary to make + an array of type_info objects a benign default + argument is supplied. Note: this + constructor does not correct for non-conformance of + compiler typeid() implementations. See type_id, below. +
+ +

Class + type_info comparisons

+
+bool operator<(type_info const& rhs) const;
+
+ +
+
Effects: yields a total order over + type_info objects. +
+
+bool operator==(type_info const& rhs) const;
+
+ +
+
Returns: true iff the two values describe + the same type. +
+ +
+
Note: The use of totally_ordered<type_info> + as a private base class supplies operators <=, + >=, >, and != +
+ +

Class type_info + observers

+
+char const* name() const;
+
+ +
+
Returns: The result of calling name() on + the argument used to construct the object. +
+ +

Functions

+
+std::ostream& operator<<(std::ostream&s, type_info const&x);
+
+ +
+
Effects: Writes a description of the type described by + to x into s. + +
Rationale: Not every C++ implementation provides a + truly human-readable type_info::name() string, but + for some we may be able to decode the string and produce a + reasonable representation. +
+
+template <class T> type_info type_id()
+
+ +
+
Returns: type_info(typeid(T)) + +
Note: On some non-conforming C++ implementations, the + code is not actually as simple as described above; the semantics + are adjusted to work as-if the C++ implementation were + conforming. +
+ +

Example

+ The following example, though silly, illustrates how the + type_id facility might be used +
+#include <boost/python/type_id.hpp>
+
+// Returns true iff the user passes an int argument
+template <class T>
+bool is_int(T x)
+{
+   using boost::python::type_id;
+   return type_id<T>() == type_id<int>();
+}
+
+ +

Revised + + 18 November, 2002 + + + +

© Copyright Dave Abrahams 2002. All + Rights Reserved. + diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 16f6a4cf..50afba85 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -11,7 +11,7 @@ # include # include # include -# include +# include # include # include # include @@ -194,7 +194,7 @@ class class_ : public objects::class_base id_vector() { // Stick the derived class id into the first element of the array - ids[0] = converter::undecorated_type_id(); + ids[0] = type_id(); // Write the rest of the elements into succeeding positions. class_id* p = ids + 1; @@ -276,9 +276,9 @@ namespace detail typedef void type; // Here's the runtime behavior - static void execute(converter::undecorated_type_id_t** p) + static void execute(type_info** p) { - *(*p)++ = converter::undecorated_type_id(); + *(*p)++ = type_id(); } }; }; diff --git a/include/boost/python/converter/callback.hpp b/include/boost/python/converter/callback.hpp index 9e9c694f..ae399eed 100644 --- a/include/boost/python/converter/callback.hpp +++ b/include/boost/python/converter/callback.hpp @@ -6,7 +6,6 @@ #ifndef CALLBACK_DWA2002228_HPP # define CALLBACK_DWA2002228_HPP -# include # include # include # include diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index 40a75645..12740439 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -8,6 +8,7 @@ # include # include +# include # include # include # include diff --git a/include/boost/python/converter/lvalue_from_python_chain.hpp b/include/boost/python/converter/lvalue_from_python_chain.hpp index 2a86bcfa..7a064841 100644 --- a/include/boost/python/converter/lvalue_from_python_chain.hpp +++ b/include/boost/python/converter/lvalue_from_python_chain.hpp @@ -6,9 +6,11 @@ #ifndef LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP # define LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# include # include # include # include +# include namespace boost { namespace python { namespace converter { @@ -39,7 +41,7 @@ namespace detail template lvalue_from_python_registration*const& ref_lvalue_from_python_chain::value - = registry::lvalue_converters(undecorated_type_id()); + = registry::lvalue_converters(type_id()); template struct select_lvalue_from_python_chain diff --git a/include/boost/python/converter/pointee_to_python_function.hpp b/include/boost/python/converter/pointee_to_python_function.hpp index 0f1ae99e..039914a9 100644 --- a/include/boost/python/converter/pointee_to_python_function.hpp +++ b/include/boost/python/converter/pointee_to_python_function.hpp @@ -9,7 +9,6 @@ # include # include # include -# include # include # include # include diff --git a/include/boost/python/converter/pointer_type_id.hpp b/include/boost/python/converter/pointer_type_id.hpp index 79a30b02..01e55977 100644 --- a/include/boost/python/converter/pointer_type_id.hpp +++ b/include/boost/python/converter/pointer_type_id.hpp @@ -6,7 +6,7 @@ #ifndef POINTER_TYPE_ID_DWA2002222_HPP # define POINTER_TYPE_ID_DWA2002222_HPP -# include +# include # include namespace boost { namespace python { namespace converter { @@ -17,9 +17,9 @@ namespace detail struct pointer_typeid_select { template - static inline undecorated_type_id_t execute(T*(*)() = 0) + static inline type_info execute(T*(*)() = 0) { - return undecorated_type_id(); + return type_id(); } }; @@ -27,37 +27,37 @@ namespace detail struct pointer_typeid_select { template - static inline undecorated_type_id_t execute(T* const volatile&(*)() = 0) + static inline type_info execute(T* const volatile&(*)() = 0) { - return undecorated_type_id(); + return type_id(); } template - static inline undecorated_type_id_t execute(T*volatile&(*)() = 0) + static inline type_info execute(T*volatile&(*)() = 0) { - return undecorated_type_id(); + return type_id(); } template - static inline undecorated_type_id_t execute(T*const&(*)() = 0) + static inline type_info execute(T*const&(*)() = 0) { - return undecorated_type_id(); + return type_id(); } template - static inline undecorated_type_id_t execute(T*&(*)() = 0) + static inline type_info execute(T*&(*)() = 0) { - return undecorated_type_id(); + return type_id(); } }; } // Usage: pointer_type_id() // -// Returns an undecorated_type_id_t associated with the type pointed +// Returns a type_info associated with the type pointed // to by T, which may be a pointer or a reference to a pointer. template -undecorated_type_id_t pointer_type_id(T(*)() = 0) +type_info pointer_type_id(T(*)() = 0) { return detail::pointer_typeid_select< is_reference::value diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index 72676605..cf5daa5e 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -5,7 +5,7 @@ // to its suitability for any purpose. #ifndef REGISTRY_DWA20011127_HPP # define REGISTRY_DWA20011127_HPP -# include +# include # include # include # include @@ -19,22 +19,22 @@ struct rvalue_from_python_registration; // This namespace acts as a sort of singleton namespace registry { - BOOST_PYTHON_DECL lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t); - BOOST_PYTHON_DECL rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t); + BOOST_PYTHON_DECL lvalue_from_python_registration*& lvalue_converters(type_info); + BOOST_PYTHON_DECL rvalue_from_python_registration*& rvalue_converters(type_info); BOOST_PYTHON_DECL to_python_function_t const& - get_to_python_function(undecorated_type_id_t); + get_to_python_function(type_info); - BOOST_PYTHON_DECL void insert(to_python_function_t, undecorated_type_id_t); + BOOST_PYTHON_DECL void insert(to_python_function_t, type_info); // Insert an lvalue from_python converter - BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), undecorated_type_id_t); + BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info); // Insert an rvalue from_python converter BOOST_PYTHON_DECL void insert( void* (*convertible)(PyObject*) , constructor_function - , undecorated_type_id_t + , type_info ); // Insert an rvalue from_python converter at the tail of the @@ -42,10 +42,10 @@ namespace registry BOOST_PYTHON_DECL void push_back( void* (*convertible)(PyObject*) , constructor_function - , undecorated_type_id_t + , type_info ); - BOOST_PYTHON_DECL PyTypeObject*& class_object(undecorated_type_id_t key); + BOOST_PYTHON_DECL PyTypeObject*& class_object(type_info key); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/rvalue_from_python_chain.hpp b/include/boost/python/converter/rvalue_from_python_chain.hpp index c57ef564..4576e7fc 100644 --- a/include/boost/python/converter/rvalue_from_python_chain.hpp +++ b/include/boost/python/converter/rvalue_from_python_chain.hpp @@ -5,6 +5,7 @@ // to its suitability for any purpose. #ifndef RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP # define RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# include # include # include # include @@ -21,7 +22,7 @@ namespace detail template rvalue_from_python_registration*const& rvalue_from_python_chain_impl::value - = registry::rvalue_converters(undecorated_type_id()); + = registry::rvalue_converters(type_id()); } template diff --git a/include/boost/python/converter/to_python_function.hpp b/include/boost/python/converter/to_python_function.hpp index ff3891e2..0112463e 100644 --- a/include/boost/python/converter/to_python_function.hpp +++ b/include/boost/python/converter/to_python_function.hpp @@ -9,7 +9,7 @@ # include # include # include -# include +# include # include # include @@ -32,7 +32,7 @@ namespace detail template to_python_function_t const& to_python_function_base::value - = converter::registry::get_to_python_function(undecorated_type_id()); + = converter::registry::get_to_python_function(type_id()); } template diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp deleted file mode 100644 index 015e55e9..00000000 --- a/include/boost/python/converter/type_id.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright David Abrahams 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. -#ifndef TYPE_ID_DWA20011127_HPP -# define TYPE_ID_DWA20011127_HPP -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - - -namespace boost { namespace python { namespace converter { - -// for this compiler at least, cross-shared-library type_info -// comparisons don't work, so use typeid(x).name() instead. It's not -// yet clear what the best default strategy is. -# if defined(__GNUC__) && __GNUC__ >= 3 -# define BOOST_PYTHON_TYPE_ID_NAME -# endif - -// type ids which represent the same information as std::type_info -// (i.e. the top-level reference and cv-qualifiers are stripped), but -// which works across shared libraries. -struct undecorated_type_id_t : totally_ordered -{ - undecorated_type_id_t(std::type_info const&); - - // default constructor needed to build arrays, etc. - undecorated_type_id_t(); - - bool operator<(undecorated_type_id_t const& rhs) const; - bool operator==(undecorated_type_id_t const& rhs) const; - - char const* name() const; - friend BOOST_PYTHON_DECL std::ostream& operator<<( - std::ostream&, undecorated_type_id_t const&); - - private: // data members -# ifdef BOOST_PYTHON_TYPE_ID_NAME - typedef char const* base_id_t; -# else - typedef std::type_info const* base_id_t; -# endif - - base_id_t m_base_type; -}; - -struct type_id_t : totally_ordered -{ - enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; - - type_id_t(undecorated_type_id_t, decoration = decoration()); - - bool operator<(type_id_t const& rhs) const; - bool operator==(type_id_t const& rhs) const; - - friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); - - operator undecorated_type_id_t const&() const; - private: // type - typedef undecorated_type_id_t base_id_t; - - private: // data members - decoration m_decoration; - base_id_t m_base_type; -}; - -template -inline undecorated_type_id_t undecorated_type_id(boost::type* = 0) -{ - return undecorated_type_id_t( -# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) - typeid(T) -# else // strip the decoration which msvc and Intel mistakenly leave in - python::detail::msvc_typeid() -# endif - ); -} - -template -inline type_id_t type_id(boost::type* = 0) -{ - return type_id_t( - undecorated_type_id() - , type_id_t::decoration( - (is_const::value || python::detail::is_reference_to_const::value - ? type_id_t::const_ : 0) - | (is_volatile::value || python::detail::is_reference_to_volatile::value - ? type_id_t::volatile_ : 0) - | (is_reference::value ? type_id_t::reference : 0) - ) - ); -} - -inline undecorated_type_id_t::undecorated_type_id_t(std::type_info const& id) - : m_base_type( -# ifdef BOOST_PYTHON_TYPE_ID_NAME - id.name() -# else - &id -# endif - ) -{ -} - -inline undecorated_type_id_t::undecorated_type_id_t() - : m_base_type() -{ -} - -inline type_id_t::type_id_t(undecorated_type_id_t base_t, decoration decoration) - : m_decoration(decoration) - , m_base_type(base_t) -{ -} - -inline bool undecorated_type_id_t::operator<(undecorated_type_id_t const& rhs) const -{ -# ifdef BOOST_PYTHON_TYPE_ID_NAME - return std::strcmp(m_base_type, rhs.m_base_type) < 0; -# else - return m_base_type->before(*rhs.m_base_type); -# endif -} - -inline bool type_id_t::operator<(type_id_t const& rhs) const -{ - return m_decoration < rhs.m_decoration - || m_decoration == rhs.m_decoration - && m_base_type < rhs.m_base_type; -} - -inline bool undecorated_type_id_t::operator==(undecorated_type_id_t const& rhs) const -{ -# ifdef BOOST_PYTHON_TYPE_ID_NAME - return !std::strcmp(m_base_type, rhs.m_base_type); -# else - return *m_base_type == *rhs.m_base_type; -# endif -} - -inline bool type_id_t::operator==(type_id_t const& rhs) const -{ - return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type; -} - -inline type_id_t::operator undecorated_type_id_t const&() const -{ - return m_base_type; -} - -inline char const* undecorated_type_id_t::name() const -{ -# ifdef BOOST_PYTHON_TYPE_ID_NAME - return m_base_type; -# else - return m_base_type->name(); -# endif -} - - -BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, undecorated_type_id_t const&); -BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); - -}}} // namespace boost::python::converter - -#endif // TYPE_ID_DWA20011127_HPP diff --git a/include/boost/python/detail/decorated_type_id.hpp b/include/boost/python/detail/decorated_type_id.hpp new file mode 100755 index 00000000..f70e369a --- /dev/null +++ b/include/boost/python/detail/decorated_type_id.hpp @@ -0,0 +1,77 @@ +// 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. +#ifndef DECORATED_TYPE_ID_DWA2002517_HPP +# define DECORATED_TYPE_ID_DWA2002517_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +struct decorated_type_info : totally_ordered +{ + enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; + + decorated_type_info(type_info, decoration = decoration()); + + bool operator<(decorated_type_info const& rhs) const; + bool operator==(decorated_type_info const& rhs) const; + + friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, decorated_type_info const&); + + operator type_info const&() const; + private: // type + typedef type_info base_id_t; + + private: // data members + decoration m_decoration; + base_id_t m_base_type; +}; + +template +inline decorated_type_info decorated_type_id(boost::type* = 0) +{ + return decorated_type_info( + type_id() + , decorated_type_info::decoration( + (is_const::value || python::detail::is_reference_to_const::value + ? decorated_type_info::const_ : 0) + | (is_volatile::value || python::detail::is_reference_to_volatile::value + ? decorated_type_info::volatile_ : 0) + | (is_reference::value ? decorated_type_info::reference : 0) + ) + ); +} + +inline decorated_type_info::decorated_type_info(type_info base_t, decoration decoration) + : m_decoration(decoration) + , m_base_type(base_t) +{ +} + +inline bool decorated_type_info::operator<(decorated_type_info const& rhs) const +{ + return m_decoration < rhs.m_decoration + || m_decoration == rhs.m_decoration + && m_base_type < rhs.m_base_type; +} + +inline bool decorated_type_info::operator==(decorated_type_info const& rhs) const +{ + return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type; +} + +inline decorated_type_info::operator type_info const&() const +{ + return m_base_type; +} + +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, decorated_type_info const&); + +}}} // namespace boost::python::detail + +#endif // DECORATED_TYPE_ID_DWA2002517_HPP diff --git a/include/boost/python/implicit.hpp b/include/boost/python/implicit.hpp index f7146e40..a6e73eba 100644 --- a/include/boost/python/implicit.hpp +++ b/include/boost/python/implicit.hpp @@ -8,7 +8,7 @@ # include # include # include -# include +# include namespace boost { namespace python { @@ -20,7 +20,7 @@ void implicitly_convertible(boost::type* = 0, boost::type* = 0) converter::registry::push_back( &functions::convertible , &functions::construct - , converter::undecorated_type_id()); + , type_id()); } }} // namespace boost::python diff --git a/include/boost/python/instance_holder.hpp b/include/boost/python/instance_holder.hpp new file mode 100755 index 00000000..eb148431 --- /dev/null +++ b/include/boost/python/instance_holder.hpp @@ -0,0 +1,43 @@ +// 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. +#ifndef INSTANCE_HOLDER_DWA2002517_HPP +# define INSTANCE_HOLDER_DWA2002517_HPP + +# include +# include + +namespace boost { namespace python { + +// Base class for all holders +struct BOOST_PYTHON_DECL instance_holder : private noncopyable +{ + public: + instance_holder(); + virtual ~instance_holder(); + + // return the next holder in a chain + instance_holder* next() const; + + virtual void* holds(type_info) = 0; + + void install(PyObject* inst) throw(); + private: + instance_holder* m_next; +}; +// This macro is needed for implementation of derived holders +# define BOOST_PYTHON_UNFORWARD(N,ignored) (typename unforward::type)(a##N) + +// +// implementation +// +inline instance_holder* instance_holder::next() const +{ + return m_next; +} + +}} // namespace boost::python + +#endif // INSTANCE_HOLDER_DWA2002517_HPP diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index 5ce5ec7d..47579fd5 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -35,8 +35,8 @@ objects::function* make_function(F f, Policies const& policies) , detail::arg_tuple_size::value); } -template -objects::function* make_constructor(Holder* = 0, ArgList* = 0) +template +objects::function* make_constructor(HolderGenerator* = 0, ArgList* = 0) { enum { nargs = mpl::size::value }; @@ -44,13 +44,13 @@ objects::function* make_constructor(Holder* = 0, ArgList* = 0) objects::py_function( ::boost::bind(detail::caller(), objects::make_holder - ::template apply::execute + ::template apply::execute , _1, _2, default_call_policies())) , nargs + 1); } -template -objects::function* make_constructor(Policies const& policies, Holder* = 0, ArgList* = 0) +template +objects::function* make_constructor(Policies const& policies, HolderGenerator* = 0, ArgList* = 0) { enum { nargs = mpl::size::value }; @@ -58,7 +58,7 @@ objects::function* make_constructor(Policies const& policies, Holder* = 0, ArgLi objects::py_function( ::boost::bind(detail::caller(), objects::make_holder - ::template apply::execute + ::template apply::execute , _1, _2, policies)) , nargs + 1); } diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 4d8d3bbe..466b6e44 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -9,8 +9,9 @@ # include # include # include -# include +# include # include +# include # include namespace boost { namespace python { @@ -19,10 +20,8 @@ class module; namespace objects { -template struct holder; - // To identify a class, we don't need cv/reference decorations -typedef converter::undecorated_type_id_t class_id; +typedef type_info class_id; struct BOOST_PYTHON_DECL class_base : private noncopyable { @@ -46,25 +45,6 @@ struct BOOST_PYTHON_DECL class_base : private noncopyable BOOST_PYTHON_DECL ref registered_class_object(class_id id); -// Base class for all holders -struct BOOST_PYTHON_DECL instance_holder : private noncopyable -{ - public: - instance_holder(); - virtual ~instance_holder(); - - // return the next holder in a chain - instance_holder* next() const; - - virtual void* holds(converter::undecorated_type_id_t) = 0; - - void install(PyObject* inst) throw(); - private: - instance_holder* m_next; -}; -// This macro is needed for implementation of derived holders -# define BOOST_PYTHON_UNFORWARD(N,ignored) (typename unforward::type)(a##N) - // Each extension instance will be one of these struct instance { @@ -75,14 +55,6 @@ struct instance BOOST_PYTHON_DECL ref class_metatype(); BOOST_PYTHON_DECL ref class_type(); -// -// implementation -// -inline instance_holder* instance_holder::next() const -{ - return m_next; -} - }}} // namespace boost::python::objects #endif // CLASS_DWA20011214_HPP diff --git a/include/boost/python/object/class_object.hpp b/include/boost/python/object/class_object.hpp index 76960762..57a8ee5d 100644 --- a/include/boost/python/object/class_object.hpp +++ b/include/boost/python/object/class_object.hpp @@ -6,7 +6,7 @@ #ifndef CLASS_OBJECT_DWA200222_HPP # define CLASS_OBJECT_DWA200222_HPP -# include +# include # include namespace boost { namespace python { namespace objects { @@ -18,8 +18,8 @@ struct class_object }; template -PyTypeObject*& class_object::reference = converter::registry::class_object( - converter::undecorated_type_id()); +PyTypeObject*& class_object::reference + = converter::registry::class_object(python::type_id()); }}} // namespace boost::python::objects diff --git a/include/boost/python/object/find_instance.hpp b/include/boost/python/object/find_instance.hpp index 3db670fc..44c79550 100644 --- a/include/boost/python/object/find_instance.hpp +++ b/include/boost/python/object/find_instance.hpp @@ -6,14 +6,14 @@ #ifndef FIND_INSTANCE_DWA2002312_HPP # define FIND_INSTANCE_DWA2002312_HPP -# include +# include # include namespace boost { namespace python { namespace objects { -// Given an undecorated type_id, find the instance data which -// corresponds to it, or return 0 in case no such type is held. -BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::undecorated_type_id_t); +// Given a type_id, find the instance data which corresponds to it, or +// return 0 in case no such type is held. +BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, type_info); // This produces a function with the right signature for use in from_python conversions template @@ -21,14 +21,14 @@ struct instance_finder { instance_finder() { - converter::registry::insert(&execute, converter::undecorated_type_id()); + converter::registry::insert(&execute, python::type_id()); } static instance_finder const registration; private: static inline void* execute(PyObject* p) { - return find_instance_impl(p, converter::undecorated_type_id()); + return find_instance_impl(p, python::type_id()); } }; diff --git a/include/boost/python/object/inheritance.hpp b/include/boost/python/object/inheritance.hpp index ceeac8f9..5129e35e 100644 --- a/include/boost/python/object/inheritance.hpp +++ b/include/boost/python/object/inheritance.hpp @@ -6,13 +6,15 @@ #ifndef INHERITANCE_DWA200216_HPP # define INHERITANCE_DWA200216_HPP -# include +# include # include +# include +# include namespace boost { namespace python { namespace objects { -typedef converter::undecorated_type_id_t class_id; -using converter::undecorated_type_id; +typedef type_info class_id; +using python::type_id; // Types used to get address and id of most derived type typedef std::pair dynamic_id_t; @@ -70,7 +72,7 @@ struct non_polymorphic_id_generator { static dynamic_id_t execute(void* p_) { - return std::make_pair(p_, converter::undecorated_type_id()); + return std::make_pair(p_, python::type_id()); } }; @@ -91,7 +93,7 @@ void register_dynamic_id(T* = 0) { typedef typename dynamic_id_generator::type generator; register_dynamic_id_aux( - converter::undecorated_type_id(), &generator::execute); + python::type_id(), &generator::execute); } // @@ -154,8 +156,8 @@ inline void register_conversion( { typedef typename cast_generator::type generator; - add_cast(converter::undecorated_type_id() - , converter::undecorated_type_id() + add_cast(python::type_id() + , python::type_id() , &generator::execute , is_downcast); } diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index c3bffa2c..6d0ef81c 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -7,7 +7,7 @@ # define POINTER_HOLDER_DWA20011215_HPP # include -# include +# include # include # include # include @@ -46,7 +46,7 @@ struct pointer_holder : instance_holder BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_CONSTRUCT_POINTER_HOLDER,nil) private: // required holder implementation - void* holds(converter::undecorated_type_id_t); + void* holds(type_info); private: // data members Pointer m_p; @@ -84,45 +84,45 @@ struct pointer_holder_back_reference : instance_holder BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_CONSTRUCT_POINTER_HOLDER_BACK_REFERENCE,nil) private: // required holder implementation - void* holds(converter::undecorated_type_id_t); + void* holds(type_info); private: // data members Pointer m_p; }; template -pointer_holder::pointer_holder(Pointer p) +inline pointer_holder::pointer_holder(Pointer p) : m_p(p) { } template -pointer_holder_back_reference::pointer_holder_back_reference(Pointer p) +inline pointer_holder_back_reference::pointer_holder_back_reference(Pointer p) : m_p(p) { } template -void* pointer_holder::holds(converter::undecorated_type_id_t dst_t) +void* pointer_holder::holds(type_info dst_t) { - if (dst_t == converter::undecorated_type_id()) + if (dst_t == python::type_id()) return &this->m_p; - converter::type_id_t src_t = converter::undecorated_type_id(); + type_info src_t = python::type_id(); return src_t == dst_t ? &*this->m_p : find_dynamic_type(&*this->m_p, src_t, dst_t); } template -void* pointer_holder_back_reference::holds(converter::undecorated_type_id_t dst_t) +void* pointer_holder_back_reference::holds(type_info dst_t) { - if (dst_t == converter::undecorated_type_id()) + if (dst_t == python::type_id()) return &this->m_p; - if (dst_t == converter::undecorated_type_id()) + if (dst_t == python::type_id()) return &*this->m_p; - converter::type_id_t src_t = converter::undecorated_type_id(); + type_info src_t = python::type_id(); Value* p = &*this->m_p; return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t); } diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index 49251921..3543d61b 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -8,7 +8,7 @@ # include # include -# include +# include # include # include # include @@ -40,7 +40,7 @@ struct value_holder : instance_holder BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_CONSTRUCT_VALUE_HOLDER,nil) private: // required holder implementation - void* holds(converter::undecorated_type_id_t); + void* holds(type_info); private: // data members Held m_held; @@ -72,32 +72,32 @@ struct value_holder_back_reference : instance_holder BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_CONSTRUCT_VALUE_HOLDER_BACK_REFERENCE,nil) private: // required holder implementation - void* holds(converter::undecorated_type_id_t); + void* holds(type_info); private: // data members BackReferenceType m_held; }; template -void* value_holder::holds(converter::undecorated_type_id_t dst_t) +void* value_holder::holds(type_info dst_t) { - converter::undecorated_type_id_t src_t = converter::undecorated_type_id(); + type_info src_t = python::type_id(); return src_t == dst_t ? &m_held : find_static_type(&m_held, src_t, dst_t); } template void* value_holder_back_reference::holds( - converter::undecorated_type_id_t dst_t) + type_info dst_t) { - converter::undecorated_type_id_t src_t = converter::undecorated_type_id(); + type_info src_t = python::type_id(); if (src_t == dst_t) { Held* x = &m_held; return x; } - src_t = converter::undecorated_type_id(); + src_t = python::type_id(); return src_t == dst_t ? &m_held : find_static_type(&m_held, src_t, dst_t); diff --git a/include/boost/python/to_python_converter.hpp b/include/boost/python/to_python_converter.hpp index 47473419..f5155e58 100644 --- a/include/boost/python/to_python_converter.hpp +++ b/include/boost/python/to_python_converter.hpp @@ -8,7 +8,7 @@ # include # include -# include +# include namespace boost { namespace python { @@ -31,7 +31,7 @@ to_python_converter::to_python_converter() converter::registry::insert( &normalized::convert - , converter::undecorated_type_id()); + , type_id()); } }} // namespace boost::python diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index ffb68ada..8f3b0e22 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -7,7 +7,6 @@ # define TO_PYTHON_VALUE_DWA200221_HPP # include -# include # include # include # include diff --git a/include/boost/python/type_from_python.hpp b/include/boost/python/type_from_python.hpp index 38d2ceea..9fcd1f8f 100644 --- a/include/boost/python/type_from_python.hpp +++ b/include/boost/python/type_from_python.hpp @@ -6,6 +6,7 @@ #ifndef TYPE_FROM_PYTHON_DWA2002130_HPP # define TYPE_FROM_PYTHON_DWA2002130_HPP +# include # include # include @@ -16,9 +17,9 @@ namespace detail // Given a pointer-to-function of 1 parameter returning a reference // type, return the type_id of the function's return type. template - inline converter::undecorated_type_id_t extractor_type_id(T&(*)(U)) + inline type_info extractor_type_id(T&(*)(U)) { - return converter::undecorated_type_id(); + return type_id(); } // A function generator whose static execute() function is an lvalue diff --git a/include/boost/python/type_id.hpp b/include/boost/python/type_id.hpp new file mode 100755 index 00000000..fbceec66 --- /dev/null +++ b/include/boost/python/type_id.hpp @@ -0,0 +1,102 @@ +// 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. +#ifndef TYPE_ID_DWA2002517_HPP +# define TYPE_ID_DWA2002517_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { + +// for this compiler at least, cross-shared-library type_info +// comparisons don't work, so use typeid(x).name() instead. It's not +// yet clear what the best default strategy is. +# if defined(__GNUC__) && __GNUC__ >= 3 +# define BOOST_PYTHON_TYPE_ID_NAME +# endif + +// type ids which represent the same information as std::type_info +// (i.e. the top-level reference and cv-qualifiers are stripped), but +// which works across shared libraries. +struct type_info : private totally_ordered +{ + type_info(std::type_info const& = typeid(void)); + + bool operator<(type_info const& rhs) const; + bool operator==(type_info const& rhs) const; + + char const* name() const; + friend BOOST_PYTHON_DECL std::ostream& operator<<( + std::ostream&, type_info const&); + + private: // data members +# ifdef BOOST_PYTHON_TYPE_ID_NAME + typedef char const* base_id_t; +# else + typedef std::type_info const* base_id_t; +# endif + + base_id_t m_base_type; +}; + +template +inline type_info type_id(boost::type* = 0) +{ + return type_info( +# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) + typeid(T) +# else // strip the decoration which msvc and Intel mistakenly leave in + python::detail::msvc_typeid() +# endif + ); +} + +inline type_info::type_info(std::type_info const& id) + : m_base_type( +# ifdef BOOST_PYTHON_TYPE_ID_NAME + id.name() +# else + &id +# endif + ) +{ +} + +inline bool type_info::operator<(type_info const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return std::strcmp(m_base_type, rhs.m_base_type) < 0; +# else + return m_base_type->before(*rhs.m_base_type); +# endif +} + +inline bool type_info::operator==(type_info const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return !std::strcmp(m_base_type, rhs.m_base_type); +# else + return *m_base_type == *rhs.m_base_type; +# endif +} + +inline char const* type_info::name() const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return m_base_type; +# else + return m_base_type->name(); +# endif +} + + +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&); + +}} // namespace boost::python + +#endif // TYPE_ID_DWA2002517_HPP diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index cad00ba5..f0aa9b7c 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,7 @@ namespace registry::insert( &slot_rvalue_from_python::convertible , &slot_rvalue_from_python::construct - , undecorated_type_id() + , type_id() ); } @@ -280,7 +281,7 @@ void initialize_builtin_converters() slot_rvalue_from_python,complex_rvalue_from_python>(); // Add an lvalue converter for char which gets us char const* - registry::insert(convert_to_cstring,undecorated_type_id()); + registry::insert(convert_to_cstring,type_id()); // Register by-value converters to std::string slot_rvalue_from_python(); diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index 822812e3..3e0afdc2 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -30,7 +30,7 @@ namespace // PyTypeObject* m_class_object; }; - typedef std::map registry_t; + typedef std::map registry_t; registry_t& entries() { @@ -50,7 +50,7 @@ namespace // return registry; } - entry* find(undecorated_type_id_t type) + entry* find(type_info type) { return &entries()[type]; } @@ -67,12 +67,12 @@ namespace // namespace registry { to_python_function_t const& get_to_python_function( - undecorated_type_id_t key) + type_info key) { return find(key)->m_to_python_converter; } - void insert(to_python_function_t f, undecorated_type_id_t source_t) + void insert(to_python_function_t f, type_info source_t) { to_python_function_t& slot = find(source_t)->m_to_python_converter; assert(slot == 0); // we have a problem otherwise @@ -85,7 +85,7 @@ namespace registry } // Insert an lvalue from_python converter - void insert(void* (*convert)(PyObject*), undecorated_type_id_t key) + void insert(void* (*convert)(PyObject*), type_info key) { entry* found = find(key); lvalue_from_python_registration *registration = new lvalue_from_python_registration; @@ -99,7 +99,7 @@ namespace registry // Insert an rvalue from_python converter void insert(void* (*convertible)(PyObject*) , constructor_function construct - , undecorated_type_id_t key) + , type_info key) { entry* found = find(key); rvalue_from_python_registration *registration = new rvalue_from_python_registration; @@ -112,7 +112,7 @@ namespace registry // Insert an rvalue from_python converter void push_back(void* (*convertible)(PyObject*) , constructor_function construct - , undecorated_type_id_t key) + , type_info key) { rvalue_from_python_registration** found = &find(key)->m_rvalue_from_python; while (*found != 0) @@ -125,17 +125,17 @@ namespace registry *found = registration; } - PyTypeObject*& class_object(undecorated_type_id_t key) + PyTypeObject*& class_object(type_info key) { return find(key)->m_class_object; } - lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t key) + lvalue_from_python_registration*& lvalue_converters(type_info key) { return find(key)->m_lvalue_from_python; } - rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t key) + rvalue_from_python_registration*& rvalue_converters(type_info key) { return find(key)->m_rvalue_from_python; } diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index 904f30d0..74bcd39b 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -4,30 +4,33 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -#include +#include +#include #if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT # include #else # include #endif -namespace boost { namespace python { namespace converter { +namespace boost { namespace python { -BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, undecorated_type_id_t const& x) +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_info const& x) { return os << x.name(); } -BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_id_t const& x) +namespace detail { - os << x.m_base_type; - if (x.m_decoration & type_id_t::const_) - os << " const"; - if (x.m_decoration & type_id_t::volatile_) - os << " volatile"; - if (x.m_decoration & type_id_t::reference) - os << "&"; - return os; + BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, detail::decorated_type_info const& x) + { + os << x.m_base_type; + if (x.m_decoration & decorated_type_info::const_) + os << " const"; + if (x.m_decoration & decorated_type_info::volatile_) + os << " volatile"; + if (x.m_decoration & decorated_type_info::reference) + os << "&"; + return os; + } } - -}}} // namespace boost::python::converter +}} // namespace boost::python::converter diff --git a/src/object/class.cpp b/src/object/class.cpp index 2e1dca89..85fcb7d7 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -12,7 +12,7 @@ #include #include -namespace boost { namespace python { namespace objects { +namespace boost { namespace python { instance_holder::instance_holder() : m_next(0) @@ -35,269 +35,272 @@ type_is_gc(PyTypeObject *python_type) return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE; } -PyTypeObject class_metatype_object = { +static PyTypeObject class_metatype_object = { PyObject_HEAD_INIT(0)//&PyType_Type) - 0, - "Boost.Python.class", - PyType_Type.tp_basicsize, - 0, - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ + 0, + "Boost.Python.class", + PyType_Type.tp_basicsize, + 0, + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, //&PyType_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, // filled in with type_new /* tp_new */ - 0, // filled in with __PyObject_GC_Del /* tp_free */ - (inquiry)type_is_gc, /* tp_is_gc */ + | Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, //&PyType_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, // filled in with type_new /* tp_new */ + 0, // filled in with __PyObject_GC_Del /* tp_free */ + (inquiry)type_is_gc, /* tp_is_gc */ }; -// Get the metatype object for all extension classes. -BOOST_PYTHON_DECL ref class_metatype() -{ - if (class_metatype_object.tp_dict == 0) - { - class_metatype_object.ob_type = &PyType_Type; - class_metatype_object.tp_base = &PyType_Type; - if (PyType_Ready(&class_metatype_object)) - return ref(); - } - return ref((PyObject*)&class_metatype_object, ref::increment_count); -} - -extern "C" -{ - static void instance_dealloc(PyObject* inst) - { - instance* kill_me = (instance*)inst; - - for (instance_holder* p = kill_me->objects, *next; p != 0; p = next) - { - next = p->next(); - delete p; - } - - inst->ob_type->tp_free(inst); - } -} - -// Do we really need this? I'm beginning to think we don't! -PyTypeObject class_type_object = { - PyObject_HEAD_INIT(0) //&class_metatype_object) - 0, - "Boost.Python.instance", - sizeof(instance), - 0, - instance_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, //&PyBaseObject_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew -}; - -BOOST_PYTHON_DECL ref class_type() -{ - if (class_type_object.tp_dict == 0) - { - class_type_object.ob_type = (PyTypeObject*)class_metatype().release(); - class_type_object.tp_base = &PyBaseObject_Type; - if (PyType_Ready(&class_type_object)) - return ref(); - } - return ref((PyObject*)&class_type_object, ref::increment_count); -} - // Install the instance data for a C++ object into a Python instance // object. void instance_holder::install(PyObject* self) throw() { assert(self->ob_type->ob_type == &class_metatype_object); - m_next = ((instance*)self)->objects; - ((instance*)self)->objects = this; + m_next = ((objects::instance*)self)->objects; + ((objects::instance*)self)->objects = this; } -BOOST_PYTHON_DECL void* -find_instance_impl(PyObject* inst, converter::undecorated_type_id_t type) -{ - if (inst->ob_type->ob_type != &class_metatype_object) - return 0; - - instance* self = reinterpret_cast(inst); - for (instance_holder* match = self->objects; match != 0; match = match->next()) - { - void* const found = match->holds(type); - if (found) - return found; - } - return 0; -} - -namespace +namespace objects { - struct class_registry +// Get the metatype object for all extension classes. + BOOST_PYTHON_DECL ref class_metatype() { - public: - ref get(class_id id) const; - ref query(class_id id) const; - void set(class_id, ref class_object); - private: - typedef detail::map_entry entry; - std::vector m_impl; + if (class_metatype_object.tp_dict == 0) + { + class_metatype_object.ob_type = &PyType_Type; + class_metatype_object.tp_base = &PyType_Type; + if (PyType_Ready(&class_metatype_object)) + return ref(); + } + return ref((PyObject*)&class_metatype_object, ref::increment_count); + } + extern "C" + { + static void instance_dealloc(PyObject* inst) + { + instance* kill_me = (instance*)inst; + + for (instance_holder* p = kill_me->objects, *next; p != 0; p = next) + { + next = p->next(); + delete p; + } + + inst->ob_type->tp_free(inst); + } + } + + + static PyTypeObject class_type_object = { + PyObject_HEAD_INIT(0) //&class_metatype_object) + 0, + "Boost.Python.instance", + sizeof(instance), + 0, + instance_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC + | Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, //&PyBaseObject_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew }; - class_registry& registry() + BOOST_PYTHON_DECL ref class_type() { - static class_registry x; - return x; - } - - inline ref class_registry::query(class_id id) const - { - std::vector::const_iterator start = m_impl.begin(); - std::vector::const_iterator finish = m_impl.end(); - - std::vector::const_iterator p - = boost::detail::lower_bound(start, finish, id); - - return (p == finish || p->key != id) ? ref() : p->value; - } - - inline ref class_registry::get(class_id id) const - { - ref result(this->query(id)); - - if (result.get() == 0) + if (class_type_object.tp_dict == 0) { - string report("extension class wrapper for base class "); - (report += id.name()) += " has not been created yet"; - PyErr_SetObject(PyExc_RuntimeError, report.get()); - throw_error_already_set(); + class_type_object.ob_type = (PyTypeObject*)class_metatype().release(); + class_type_object.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&class_type_object)) + return ref(); } - return result; + return ref((PyObject*)&class_type_object, ref::increment_count); } - inline void class_registry::set(class_id id, ref object) + BOOST_PYTHON_DECL void* + find_instance_impl(PyObject* inst, type_info type) { - std::vector::iterator start = m_impl.begin(); - std::vector::iterator finish = m_impl.end(); - m_impl.insert( - boost::detail::lower_bound(start, finish, id) - , entry(id, object)); - converter::registry::class_object(id) = (PyTypeObject*)object.get(); + if (inst->ob_type->ob_type != &class_metatype_object) + return 0; + + instance* self = reinterpret_cast(inst); + + for (instance_holder* match = self->objects; match != 0; match = match->next()) + { + void* const found = match->holds(type); + if (found) + return found; + } + return 0; } -} -class_base::class_base( - char const* name, std::size_t num_types, class_id const* const types) -{ - class_registry& r = registry(); - assert(num_types >= 1); - tuple bases(std::max(num_types - 1, static_cast(1))); - if (num_types > 1) + namespace + { + struct class_registry { - for (std::size_t i = 1; i < num_types; ++i) - bases.set_item(i - 1, r.get(types[i])); - } - else + public: + ref get(class_id id) const; + ref query(class_id id) const; + void set(class_id, ref class_object); + private: + typedef detail::map_entry entry; + std::vector m_impl; + }; + + class_registry& registry() { - bases.set_item(0, class_type()); + static class_registry x; + return x; } + + inline ref class_registry::query(class_id id) const + { + std::vector::const_iterator start = m_impl.begin(); + std::vector::const_iterator finish = m_impl.end(); + + std::vector::const_iterator p + = boost::detail::lower_bound(start, finish, id); + + return (p == finish || p->key != id) ? ref() : p->value; + } + + inline ref class_registry::get(class_id id) const + { + ref result(this->query(id)); + + if (result.get() == 0) + { + string report("extension class wrapper for base class "); + (report += id.name()) += " has not been created yet"; + PyErr_SetObject(PyExc_RuntimeError, report.get()); + throw_error_already_set(); + } + return result; + } + + inline void class_registry::set(class_id id, ref object) + { + std::vector::iterator start = m_impl.begin(); + std::vector::iterator finish = m_impl.end(); + m_impl.insert( + boost::detail::lower_bound(start, finish, id) + , entry(id, object)); + converter::registry::class_object(id) = (PyTypeObject*)object.get(); + } + } + + class_base::class_base( + char const* name, std::size_t num_types, class_id const* const types) + { + class_registry& r = registry(); + assert(num_types >= 1); + tuple bases(std::max(num_types - 1, static_cast(1))); + if (num_types > 1) + { + for (std::size_t i = 1; i < num_types; ++i) + bases.set_item(i - 1, r.get(types[i])); + } + else + { + bases.set_item(0, class_type()); + } - tuple args(3); - args.set_item(0, string(name).reference()); - args.set_item(1, bases.reference()); - args.set_item(2, dictionary().reference()); + tuple args(3); + args.set_item(0, string(name).reference()); + args.set_item(1, bases.reference()); + args.set_item(2, dictionary().reference()); - m_object = ref(PyObject_CallObject(class_metatype().get(), args.get())); - r.set(types[0], m_object); -} + m_object = ref(PyObject_CallObject(class_metatype().get(), args.get())); + r.set(types[0], m_object); + } -extern "C" -{ - // This declaration needed due to broken Python 2.2 headers - extern DL_IMPORT(PyTypeObject) PyProperty_Type; -} + extern "C" + { + // This declaration needed due to broken Python 2.2 headers + extern DL_IMPORT(PyTypeObject) PyProperty_Type; + } -void class_base::add_property(char const* name, ref const& fget) -{ - ref property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "O", fget.get())); - setattr(name, property); -} + void class_base::add_property(char const* name, ref const& fget) + { + ref property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "O", fget.get())); + setattr(name, property); + } -void class_base::add_property(char const* name, ref const& fget, ref const& fset) -{ - ref property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "OO", fget.get(), fset.get())); - setattr(name, property); -} + void class_base::add_property(char const* name, ref const& fget, ref const& fset) + { + ref property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "OO", fget.get(), fset.get())); + setattr(name, property); + } -void class_base::setattr(char const* name, ref const& x) -{ - if (PyObject_SetAttrString(object().get(), const_cast(name), x.get()) < 0) - throw_error_already_set(); -} + void class_base::setattr(char const* name, ref const& x) + { + if (PyObject_SetAttrString(object().get(), const_cast(name), x.get()) < 0) + throw_error_already_set(); + } -BOOST_PYTHON_DECL ref registered_class_object(class_id id) -{ - return registry().query(id); -} + BOOST_PYTHON_DECL ref registered_class_object(class_id id) + { + return registry().query(id); + } +} // namespace objects -}}} // namespace boost::python::objects +}} // namespace boost::python diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index 91a37f02..6725b95d 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -4,7 +4,7 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. #include -#include +#include #include #include #include @@ -45,7 +45,7 @@ namespace // Here we put together the low-level data structures of the // casting graph representation. // - typedef python::converter::undecorated_type_id_t class_id; + typedef python::type_info class_id; // represents a graph of available casts diff --git a/test/pointer_type_id_test.cpp b/test/pointer_type_id_test.cpp index 24035709..e3314e0b 100644 --- a/test/pointer_type_id_test.cpp +++ b/test/pointer_type_id_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -6,8 +6,8 @@ int main() { using namespace boost::python::converter; - undecorated_type_id_t x - = undecorated_type_id(); + boost::python::type_info x + = boost::python::type_id(); assert(pointer_type_id() == x); diff --git a/test/select_from_python_test.cpp b/test/select_from_python_test.cpp index 7063767e..b5648447 100644 --- a/test/select_from_python_test.cpp +++ b/test/select_from_python_test.cpp @@ -1,15 +1,22 @@ #include -//#include -//#include -#include +#include #include +#if defined(__GNUC__) && __GNUC__ < 3 // 2.95.x linker seems to demand this definition +namespace boost { namespace python { +BOOST_PYTHON_DECL bool handle_exception_impl(function0) +{ + return true; +} +}} +#endif + int result; #define ASSERT_SAME(T1,T2) \ if (!is_same< T1, T2 >::value) { \ std::cout << "*********************\n"; \ - std::cout << type_id< T1 >() << " != " << type_id< T2 >() << "\n"; \ + std::cout << python::type_id< T1 >() << " != " << python::type_id< T2 >() << "\n"; \ std::cout << "*********************\n"; \ result = 1; \ }