2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-28 07:22:31 +00:00

New: richcmp.html, richcmp1.cpp, richcmp2.cpp, richcmp3.cpp.

Still needs more testing. richcmp1.cpp does not compile under windows.


[SVN r10656]
This commit is contained in:
Ralf W. Grosse-Kunstleve
2001-07-18 03:14:48 +00:00
parent 905074542e
commit fc9a6ac369
17 changed files with 561 additions and 109 deletions

View File

@@ -52,8 +52,13 @@ bpl_exa + "/tst_dvect2.py",
bpl_exa + "/tst_ivect1.py",
bpl_exa + "/tst_ivect2.py",
bpl_exa + "/test_cross_module.py",
bpl_exa + "/richcmp.cpp",
bpl_exa + "/test_richcmp.py",
bpl_exa + "/vector_wrapper.h",
bpl_exa + "/richcmp1.cpp",
bpl_exa + "/richcmp2.cpp",
bpl_exa + "/richcmp3.cpp",
bpl_exa + "/tst_richcmp1.py",
bpl_exa + "/tst_richcmp2.py",
bpl_exa + "/tst_richcmp3.py",
)
defs = (
@@ -70,7 +75,9 @@ defs = (
"noncopyable_import",
"ivect",
"dvect",
"richcmp",
"richcmp1",
"richcmp2",
"richcmp3",
)
if (__name__ == "__main__"):

View File

@@ -47,7 +47,7 @@ DEPOBJ=$(OBJ) \
pickle1.o pickle2.o pickle3.o \
noncopyable_export.o noncopyable_import.o \
ivect.o dvect.o \
richcmp.o
richcmp1.o richcmp2.o richcmp3.o
.SUFFIXES: .o .cpp
@@ -60,7 +60,7 @@ all: libboost_python.a \
pickle1.so pickle2.so pickle3.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so \
richcmp.so
richcmp1.so richcmp2.so richcmp3.so
libboost_python.a: $(OBJ)
rm -f libboost_python.a
@@ -107,8 +107,14 @@ ivect.so: $(OBJ) ivect.o
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
richcmp.so: $(OBJ) richcmp.o
$(LD) $(LDOPTS) $(OBJ) richcmp.o -o richcmp.so
richcmp1.so: $(OBJ) richcmp1.o
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
richcmp2.so: $(OBJ) richcmp2.o
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
richcmp3.so: $(OBJ) richcmp3.o
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp
@@ -140,7 +146,9 @@ clean:
rm -f noncopyable_import.o noncopyable_import.so
rm -f ivect.o ivect.so
rm -f dvect.o dvect.so
rm -f richcmp.o richcmp.so
rm -f richcmp1.o richcmp1.so
rm -f richcmp2.o richcmp2.so
rm -f richcmp3.o richcmp3.so
rm -f so_locations *.pyc
rm -rf ii_files

View File

@@ -48,7 +48,7 @@ DEPOBJ=$(OBJ) \
pickle1.o pickle2.o pickle3.o \
noncopyable_export.o noncopyable_import.o \
ivect.o dvect.o \
richcmp.o
richcmp1.o richcmp2.o richcmp3.o
.SUFFIXES: .o .cpp
@@ -61,7 +61,7 @@ all: libboost_python.a \
pickle1.so pickle2.so pickle3.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so \
richcmp.so
richcmp1.so richcmp2.so richcmp3.so
libboost_python.a: $(OBJ)
rm -f libboost_python.a
@@ -108,8 +108,14 @@ ivect.so: $(OBJ) ivect.o
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
richcmp.so: $(OBJ) richcmp.o
$(LD) $(LDOPTS) $(OBJ) richcmp.o -o richcmp.so
richcmp1.so: $(OBJ) richcmp1.o
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
richcmp2.so: $(OBJ) richcmp2.o
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
richcmp3.so: $(OBJ) richcmp3.o
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp
@@ -141,7 +147,9 @@ clean:
rm -f noncopyable_import.o noncopyable_import.so
rm -f ivect.o ivect.so
rm -f dvect.o dvect.so
rm -f richcmp.o richcmp.so
rm -f richcmp1.o richcmp1.so
rm -f richcmp2.o richcmp2.so
rm -f richcmp3.o richcmp3.so
rm -f so_locations *.pyc
softlinks:

View File

@@ -63,7 +63,7 @@ all: libboost_python.a \
pickle1.pyd pickle2.pyd pickle3.pyd \
noncopyable_export.pyd noncopyable_import.pyd \
ivect.pyd dvect.pyd \
richcmp.pyd
richcmp1.pyd richcmp2.pyd richcmp3.pyd
libboost_python.a: $(OBJ)
del libboost_python.a
@@ -150,11 +150,23 @@ dvect.pyd: $(OBJ) dvect.o
--def dvect.def \
$(OBJ) dvect.o $(PYLIB)
richcmp.pyd: $(OBJ) richcmp.o
richcmp1.pyd: $(OBJ) richcmp1.o
dllwrap $(DLLWRAPOPTS) \
--dllname richcmp.pyd \
--def richcmp.def \
$(OBJ) richcmp.o $(PYLIB)
--dllname richcmp1.pyd \
--def richcmp1.def \
$(OBJ) richcmp1.o $(PYLIB)
richcmp2.pyd: $(OBJ) richcmp2.o
dllwrap $(DLLWRAPOPTS) \
--dllname richcmp2.pyd \
--def richcmp2.def \
$(OBJ) richcmp2.o $(PYLIB)
richcmp3.pyd: $(OBJ) richcmp3.o
dllwrap $(DLLWRAPOPTS) \
--dllname richcmp3.pyd \
--def richcmp3.def \
$(OBJ) richcmp3.o $(PYLIB)
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp

View File

@@ -58,7 +58,7 @@ DEPOBJ=$(OBJ) \
pickle1.o pickle2.o pickle3.o \
noncopyable_export.o noncopyable_import.o \
ivect.o dvect.o \
richcmp.o
richcmp1.o richcmp2.o richcmp3.o
.SUFFIXES: .o .cpp
@@ -71,7 +71,7 @@ all: libboost_python.a \
pickle1.so pickle2.so pickle3.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so \
richcmp.so
richcmp1.so richcmp2.so richcmp3.so
libboost_python.a: $(OBJ)
rm -f libboost_python.a
@@ -122,8 +122,14 @@ ivect.so: $(OBJ) ivect.o
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
richcmp.so: $(OBJ) richcmp.o
$(LD) $(LDOPTS) $(OBJ) richcmp.o -o richcmp.so
richcmp1.so: $(OBJ) richcmp1.o
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
richcmp2.so: $(OBJ) richcmp2.o
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
richcmp3.so: $(OBJ) richcmp3.o
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp
@@ -155,7 +161,9 @@ clean:
rm -f noncopyable_import.o noncopyable_import.so
rm -f ivect.o ivect.so
rm -f dvect.o dvect.so
rm -f richcmp.o richcmp.so
rm -f richcmp1.o richcmp1.so
rm -f richcmp2.o richcmp2.so
rm -f richcmp3.o richcmp3.so
rm -f so_locations *.pyc
rm -rf cxx_repository

View File

@@ -47,7 +47,7 @@ all: boost_python.lib \
pickle1.pyd pickle2.pyd pickle3.pyd \
noncopyable_export.pyd noncopyable_import.pyd \
ivect.pyd dvect.pyd \
richcmp.pyd
richcmp1.pyd richcmp2.pyd richcmp3.pyd
boost_python.lib: $(OBJ)
$(LD) -lib /nologo /out:boost_python.lib $(OBJ)
@@ -91,8 +91,14 @@ ivect.pyd: $(OBJ) ivect.obj
dvect.pyd: $(OBJ) dvect.obj
$(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd"
richcmp.pyd: $(OBJ) richcmp.obj
$(LD) $(LDOPTS) $(OBJ) richcmp.obj $(PYLIB) /export:initrichcmp /out:"richcmp.pyd"
richcmp1.pyd: $(OBJ) richcmp1.obj
$(LD) $(LDOPTS) $(OBJ) richcmp1.obj $(PYLIB) /export:initrichcmp1 /out:"richcmp1.pyd"
richcmp2.pyd: $(OBJ) richcmp2.obj
$(LD) $(LDOPTS) $(OBJ) richcmp2.obj $(PYLIB) /export:initrichcmp2 /out:"richcmp2.pyd"
richcmp3.pyd: $(OBJ) richcmp3.obj
$(LD) $(LDOPTS) $(OBJ) richcmp3.obj $(PYLIB) /export:initrichcmp3 /out:"richcmp3.pyd"
.cpp.obj:
$(CPP) $(CPPOPTS) /c $*.cpp

103
doc/richcmp.html Normal file
View File

@@ -0,0 +1,103 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>Rich Comparisons</title>
<div>
<img src="../../../c++boost.gif"
alt="c++boost.gif (8819 bytes)"
align="center"
width="277" height="86">
<hr>
<h1>Rich Comparisons</h1>
<hr>
In Python versions up to and including Python 2.0, support for
implementing comparisons on user-defined classes and extension types
was quite simple. Classes could implement a <tt>__cmp__</tt> method
that was given two instances of a class as arguments, and could only
return <tt>0</tt> if they were equal or <tt>+1</tt> or <tt>-1</tt> if
they were not. The method could not raise an exception or return
anything other than an integer value.
In Python 2.1, <b>Rich Comparisons</b> were added (see
<a href="http://python.sourceforge.net/peps/pep-0207.html">PEP 207</a>).
Python classes can now individually overload each of the &lt;, &lt;=,
&gt;, &gt;=, ==, and != operations.
<p>
For more detailed information, search for "rich comparison"
<a href="http://www.python.org/doc/current/ref/customization.html"
>here</a>.
<p>
Boost.Python supports both automatic overloading and manual overloading
of the Rich Comparison operators. The <b>compile-time</b> support is
independent of the Python version that is used when compiling
Boost.Python extension modules. That is, <tt>op_lt</tt> for example can
always be used, and the C++ <tt>operator&lt;</tt> will always be bound
to the Python method <tt>__lt__</tt>. However, the <b>run-time</b>
behavior will depend on the Python version.
<p>
With Python versions before 2.1, the Rich Comparison operators will not
be called by Python when any of the six comparison operators
(<tt>&lt;</tt>, <tt>&lt;=</tt>, <tt>==</tt>, <tt>!=</tt>,
<tt>&gt;</tt>, <tt>&gt;=</tt>) is used in an expression. The only way
to access the corresponding methods is to call them explicitly, e.g.
<tt>a.__lt__(b)</tt>. Only with Python versions 2.1 or higher will
expressions like <tt>a &lt; b</tt> work as expected.
<p>
To support Rich Comparisions, the Python C API was modified between
Python versions 2.0 and 2.1. A new slot was introduced in the
<tt>PyTypeObject</tt> structure: <tt>tp_richcompare</tt>. For backwards
compatibility, a flag (<tt>Py_TPFLAGS_HAVE_RICHCOMPARE</tt>) has to be
set to signal to the Python interpreter that Rich Comparisions are
supported by a particular type.
There is only one flag for all the six comparison operators.
When any of the six operators is wrapped automatically or
manually, Boost.Python will set this flag. Attempts to use comparison
operators at the Python level that are not defined at the C++ level
will then lead to an <tt>AttributeError</tt>. That is, in general all six
operators should be supplied. Automatically wrapped operators and
manually wrapped operators can be mixed. For example:<pre>
boost::python::class_builder&lt;code&gt; py_code(this_module, "code");
py_code.def(boost::python::constructor&lt;&gt;());
py_code.def(boost::python::constructor&lt;int&gt;());
py_code.def(boost::python::operators&lt;( boost::python::op_eq
| boost::python::op_ne)&gt;());
py_code.def(NotImplemented, "__lt__");
py_code.def(NotImplemented, "__le__");
py_code.def(NotImplemented, "__gt__");
py_code.def(NotImplemented, "__ge__");
</pre>
<tt>NotImplemented</tt> is a simple free function:<pre>
boost::python::ref
NotImplemented(const code&amp;, const code&amp;) {
return
boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
}
</pre>
See also:
<ul>
<li><a href="../example/richcmp1.cpp"><tt>../example/richcmp1.cpp</tt></a>
<li><a href="../example/richcmp2.cpp"><tt>../example/richcmp2.cpp</tt></a>
<li><a href="../example/richcmp3.cpp"><tt>../example/richcmp3.cpp</tt></a>
</ul>
<hr>
&copy; Copyright Nicholas K. Sauter &amp; Ralf W. Grosse-Kunstleve 2001.
Permission to copy, use, modify, sell and distribute this document is
granted provided this copyright notice appears in all copies. This
document is provided "as is" without express or implied warranty, and
with no claim as to its suitability for any purpose.
<p>
Updated: July 2001
</div>

View File

@@ -60,13 +60,27 @@
<b><tt class='method'>__str__</tt></b>(<i>self</i>)
<dd>
Create a string representation which is suitable for printing.
<dt>
<b><tt class='method'>__lt__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__le__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__eq__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__ne__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__gt__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__ge__</tt></b>(<i>self, other</i>)
<dd>
Rich Comparison methods.
New in Python 2.1.
See <a href="richcmp.html">Rich Comparisons</a>.
<dt>
<b><tt class='method'>__cmp__</tt></b>(<i>self, other</i>)
<dd>
Three-way compare function, used to implement comparison operators
(&lt; etc.) Should return a negative integer if <code> self < other
</code> , zero if <code> self == other </code> , a positive integer if
<code> self > other </code>.
Three-way compare function.
See <a href="richcmp.html">Rich Comparisons</a>.
<dt>
<b><tt class='method'>__hash__</tt></b>(<i>self</i>)
<dd>
@@ -544,17 +558,42 @@ Note that "__rrpow__" is an extension not present in plain Python.
<code>__cmp__, __rcmp__</code>
<td>
<code>cmp(left, right)</code><br>
<code>left &lt; right</code><br>
<code>left &lt;= right</code><br>
<code>left &gt; right</code><br>
<code>left &gt;= right</code><br>
<code>left == right</code><br>
<code>left != right</code>
<br>See <a href="richcmp.html">Rich Comparisons</a>.
<td>
<code>op_cmp</code>
<td>
<code>cpp_left &lt; cpp_right </code>
<br><code>cpp_right &lt; cpp_left</code>
<tr>
<td>
<code>__lt__</code>
<br><code>__le__</code>
<br><code>__eq__</code>
<br><code>__ne__</code>
<br><code>__gt__</code>
<br><code>__ge__</code>
<td>
<code>left &lt; right</code>
<br><code>left &lt;= right</code>
<br><code>left == right</code>
<br><code>left != right</code>
<br><code>left &gt; right</code>
<br><code>left &gt;= right</code>
<br>See <a href="richcmp.html">Rich Comparisons</a>
<td>
<code>op_lt</code>
<br><code>op_le</code>
<br><code>op_eq</code>
<br><code>op_ne</code>
<br><code>op_gt</code>
<br><code>op_ge</code>
<td>
<code>cpp_left &lt; cpp_right </code>
<br><code>cpp_left &lt;= cpp_right </code>
<br><code>cpp_left == cpp_right </code>
<br><code>cpp_left != cpp_right </code>
<br><code>cpp_left &gt; cpp_right </code>
<br><code>cpp_left &gt;= cpp_right </code>
<tr>
<td>

63
example/richcmp1.cpp Normal file
View File

@@ -0,0 +1,63 @@
// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter
// This example shows how to use rich comparisons for a vector type.
// It also shows how to template the entire wrapping of a std::vector.
// See vector_wrapper.h.
#include <boost/python/class_builder.hpp>
#include "vector_wrapper.h"
namespace std {
# define VECTOR_BINARY_OPERATORS(oper) \
template <class T> \
std::vector<bool> \
operator##oper(const std::vector<T>& a, const std::vector<T>& b) \
{ \
if (a.size()!=b.size()){throw boost::python::argument_error();} \
std::vector<bool> result(a.size()); \
for (std::size_t i=0; i<a.size(); i++) { \
result[i] = (a[i] ##oper b[i]); \
} \
return result; \
}
VECTOR_BINARY_OPERATORS(<)
VECTOR_BINARY_OPERATORS(<=)
VECTOR_BINARY_OPERATORS(==)
VECTOR_BINARY_OPERATORS(!=)
VECTOR_BINARY_OPERATORS(>)
VECTOR_BINARY_OPERATORS(>=)
# undef VECTOR_BINARY_OPERATORS
}
namespace {
void init_module(boost::python::module_builder& this_module)
{
(void)
example::wrap_vector(this_module, "vector_of_bool", bool());
boost::python::class_builder<
std::vector<double>, example::vector_wrapper<double> >
py_vector_of_double =
example::wrap_vector(this_module, "vector_of_double", double());
const long comp_operators =
( boost::python::op_lt | boost::python::op_le
| boost::python::op_eq | boost::python::op_ne
| boost::python::op_gt | boost::python::op_ge);
py_vector_of_double.def(boost::python::operators<comp_operators>());
}
} // namespace <anonymous>
BOOST_PYTHON_MODULE_INIT(richcmp1)
{
try {
boost::python::module_builder this_module("richcmp1");
// The actual work is done in separate function in order
// to suppress a bogus VC60 warning.
init_module(this_module);
}
catch(...){boost::python::handle_exception();}
}

61
example/richcmp2.cpp Normal file
View File

@@ -0,0 +1,61 @@
// Example by Ralf W. Grosse-Kunstleve
// This example shows how to use rich comparisons for a type that
// does not support all six operators (<, <=, ==, !=, >, >=).
// To keep the example simple, we are using a "code" type does
// not really require rich comparisons. __cmp__ would be sufficient.
// However, with a more complicated type the main point of this
// example would be in danger of getting lost.
#include <boost/python/class_builder.hpp>
namespace {
// suppose operator< and operator> are not meaningful for code
class code {
public:
code(int c = 0) : m_code(c) {}
inline friend bool operator==(const code& lhs, const code& rhs) {
return lhs.m_code == rhs.m_code;
}
inline friend bool operator!=(const code& lhs, const code& rhs) {
return lhs.m_code != rhs.m_code;
}
private:
int m_code;
};
boost::python::ref
NotImplemented(const code&, const code&) {
return
boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
}
}
namespace {
void init_module(boost::python::module_builder& this_module)
{
boost::python::class_builder<code> py_code(this_module, "code");
py_code.def(boost::python::constructor<>());
py_code.def(boost::python::constructor<int>());
py_code.def(boost::python::operators<( boost::python::op_eq
| boost::python::op_ne)>());
py_code.def(NotImplemented, "__lt__");
py_code.def(NotImplemented, "__le__");
py_code.def(NotImplemented, "__gt__");
py_code.def(NotImplemented, "__ge__");
}
} // namespace <anonymous>
BOOST_PYTHON_MODULE_INIT(richcmp2)
{
try {
boost::python::module_builder this_module("richcmp2");
// The actual work is done in separate function in order
// to suppress a bogus VC60 warning.
init_module(this_module);
}
catch(...){boost::python::handle_exception();}
}

7
example/richcmp.cpp → example/richcmp3.cpp Executable file → Normal file
View File

@@ -1,3 +1,6 @@
// Example by Nicholas K. Sauter & Ralf W. Grosse-Kunstleve.
// Comprehensive operator overloading for two vector types and scalars.
#include "dvect.h"
#include "ivect.h"
#include <boost/python/class_builder.hpp>
@@ -236,10 +239,10 @@ namespace {
} // namespace <anonymous>
BOOST_PYTHON_MODULE_INIT(richcmp)
BOOST_PYTHON_MODULE_INIT(richcmp3)
{
try {
boost::python::module_builder this_module("richcmp");
boost::python::module_builder this_module("richcmp3");
// The actual work is done in separate function in order
// to suppress a bogus VC60 warning.
init_module(this_module);

View File

@@ -1,63 +0,0 @@
import richcmp,sys
global dv,dv2
dv = richcmp.ivect((1,2,3,4,5))
print dv.as_tuple()
dv2 = richcmp.dvect((2,-2,3,8,-5))
print dv2.as_tuple()
print (dv+dv2).as_tuple()
print (dv+3).as_tuple()
print (3+dv).as_tuple()
def python_2_1():
print "\nvect vs. vect Comparisons:"
print (dv < dv2).as_tuple()
print (dv <= dv2).as_tuple()
print (dv == dv2).as_tuple()
print (dv != dv2).as_tuple()
print (dv > dv2).as_tuple()
print (dv >= dv2).as_tuple()
print "\nvect vs. scalar Comparisons:"
print (dv < 3).as_tuple()
print (dv <= 3).as_tuple()
print (dv == 3).as_tuple()
print (dv != 3).as_tuple()
print (dv > 3).as_tuple()
print (dv >= 3).as_tuple()
print "\nscalar vs. vect Comparisons:"
print (3 < dv).as_tuple()
print (3 <= dv).as_tuple()
print (3 == dv).as_tuple()
print (3 != dv).as_tuple()
print (3 > dv).as_tuple()
print (3 >= dv).as_tuple()
def python_pre_2_1():
print "\nvect vs. vect Comparisons:"
print (dv.__lt__(dv2)).as_tuple()
print (dv.__le__(dv2)).as_tuple()
print (dv.__eq__(dv2)).as_tuple()
print (dv.__ne__(dv2)).as_tuple()
print (dv.__gt__(dv2)).as_tuple()
print (dv.__ge__(dv2)).as_tuple()
print "\nvect vs. scalar Comparisons:"
print (dv.__lt__(3)).as_tuple()
print (dv.__le__(3)).as_tuple()
print (dv.__eq__(3)).as_tuple()
print (dv.__ne__(3)).as_tuple()
print (dv.__gt__(3)).as_tuple()
print (dv.__ge__(3)).as_tuple()
print "\nscalar vs. vect Comparisons:"
if __name__=='__main__':
try:
if sys.version_info[0]>=2 and sys.version_info[1]>=1:
python_2_1()
else:
python_pre_2_1()
except:
python_pre_2_1()

11
example/tst_richcmp1.py Normal file
View File

@@ -0,0 +1,11 @@
import richcmp1
d1 = richcmp1.vector_of_double((0, 1, 3, 3, 6, 7))
d2 = richcmp1.vector_of_double((1, 2, 3, 4, 5, 6))
print d1.as_tuple()
print d2.as_tuple()
print (d1 < d2).as_tuple()
print (d1 <= d2).as_tuple()
print (d1 == d2).as_tuple()
print (d1 != d2).as_tuple()
print (d1 > d2).as_tuple()
print (d1 >= d2).as_tuple()

14
example/tst_richcmp2.py Normal file
View File

@@ -0,0 +1,14 @@
import richcmp2
c1 = richcmp2.code(1)
c2 = richcmp2.code(2)
c3 = richcmp2.code(2)
print c1 == c2
print c1 != c2
print c2 == c3
print c2 != c3
print c1 < c2
print c1 <= c2
print c1 == c2
print c1 != c2
print c1 > c2
print c1 >= c2

60
example/tst_richcmp3.py Normal file
View File

@@ -0,0 +1,60 @@
import richcmp3,sys
global iv,dv
iv = richcmp3.ivect((1,2,3,4,5))
print iv.as_tuple()
dv = richcmp3.dvect((2,-2,3,8,-5))
print dv.as_tuple()
print (iv+dv).as_tuple()
print (iv+3).as_tuple()
print (3+iv).as_tuple()
def python_2_1():
print "\nvect vs. vect Comparisons:"
print (iv < dv).as_tuple()
print (iv <= dv).as_tuple()
print (iv == dv).as_tuple()
print (iv != dv).as_tuple()
print (iv > dv).as_tuple()
print (iv >= dv).as_tuple()
print "\nvect vs. scalar Comparisons:"
print (iv < 3).as_tuple()
print (iv <= 3).as_tuple()
print (iv == 3).as_tuple()
print (iv != 3).as_tuple()
print (iv > 3).as_tuple()
print (iv >= 3).as_tuple()
print "\nscalar vs. vect Comparisons:"
print (3 < iv).as_tuple()
print (3 <= iv).as_tuple()
print (3 == iv).as_tuple()
print (3 != iv).as_tuple()
print (3 > iv).as_tuple()
print (3 >= iv).as_tuple()
def python_pre_2_1():
print "\nvect vs. vect Comparisons:"
print (iv.__lt__(dv)).as_tuple()
print (iv.__le__(dv)).as_tuple()
print (iv.__eq__(dv)).as_tuple()
print (iv.__ne__(dv)).as_tuple()
print (iv.__gt__(dv)).as_tuple()
print (iv.__ge__(dv)).as_tuple()
print "\nvect vs. scalar Comparisons:"
print (iv.__lt__(3)).as_tuple()
print (iv.__le__(3)).as_tuple()
print (iv.__eq__(3)).as_tuple()
print (iv.__ne__(3)).as_tuple()
print (iv.__gt__(3)).as_tuple()
print (iv.__ge__(3)).as_tuple()
print "\nscalar vs. vect Comparisons:"
if __name__=='__main__':
if sys.version_info[0]>=2 and sys.version_info[1]>=1:
python_2_1()
else:
python_pre_2_1()

117
example/vector_wrapper.h Normal file
View File

@@ -0,0 +1,117 @@
// Based on wrapVector.hh by Mike Owen and Jeff Johnson.
// http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/spheral/src/src/BPLWraps/CXXWraps/
#ifndef BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H
#define BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H
#include <boost/python/class_builder.hpp>
namespace example {
// A wrapper is used to define additional constructors. This wrapper
// is templated on the template parameter for its corresponding vector.
template <typename T>
struct vector_wrapper: std::vector<T>
{
// Tell the compiler how to convert a base class object to
// this wrapper object.
vector_wrapper(PyObject*,
const std::vector<T>& vec):
std::vector<T>(vec) {}
vector_wrapper(PyObject* self):
std::vector<T>() {}
vector_wrapper(PyObject* self,
std::size_t n):
std::vector<T>(n) {}
vector_wrapper(PyObject* self,
boost::python::tuple tuple):
std::vector<T>(tuple.size())
{
std::vector<T>::iterator vec = begin();
for (std::size_t i = 0; i < tuple.size(); i++)
vec[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
boost::python::type<T>());
}
};
void raise_vector_IndexError() {
PyErr_SetString(PyExc_IndexError, "vector index out of range");
throw boost::python::error_already_set();
}
template <typename T>
struct vector_access
{
static
const T
getitem(const std::vector<T>& vec,
const std::size_t key)
{
if (key >= vec.size()) raise_vector_IndexError();
return vec[key];
}
static
void
setitem(std::vector<T>& vec,
const std::size_t key,
const T &value)
{
if (key >= vec.size()) raise_vector_IndexError();
vec[key] = value;
}
static
void
delitem(std::vector<T>& vec,
const std::size_t key)
{
if (key >= vec.size()) raise_vector_IndexError();
vec.erase(vec.begin() + key);
}
// Convert vector<T> to a regular Python tuple.
static
boost::python::tuple
as_tuple(const std::vector<T>& vec)
{
// Create a python type of size vec.size().
boost::python::tuple t(vec.size());
for (std::size_t i = 0; i < vec.size(); i++) {
t.set_item(i,
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python(vec[i])));
}
return t;
}
};
// This function will build a vector<T> and add it to the given
// module with the given name.
template <typename T>
boost::python::class_builder<std::vector<T>, vector_wrapper<T> >
wrap_vector(boost::python::module_builder& module,
const std::string& vector_name,
const T&)
{
// Add the vector<T> to the module.
boost::python::class_builder<std::vector<T>, vector_wrapper<T> >
py_vector(module, vector_name.c_str());
// Define constructors and methods for the vector<T>.
py_vector.def(boost::python::constructor<>());
py_vector.def(boost::python::constructor<std::size_t>());
py_vector.def(boost::python::constructor<boost::python::tuple>());
py_vector.def(&std::vector<T>::size, "__len__");
py_vector.def(&vector_access<T>::getitem, "__getitem__");
py_vector.def(&vector_access<T>::setitem, "__setitem__");
py_vector.def(&vector_access<T>::delitem, "__delitem__");
py_vector.def(&vector_access<T>::as_tuple, "as_tuple");
return py_vector;
}
}
#endif // BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H

View File

@@ -457,20 +457,15 @@ void create_method_table_if_null(T*& table)
}
}
#define ENABLE_RICHCOMPARE_CAPABILITY \
dest->tp_richcompare = &do_instance_richcompare; \
dest->tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE; \
return true
bool add_capability_richcompare(type_object_base::capability capability, PyTypeObject* dest)
{
assert(dest != 0);
if (capability == type_object_base::richcompare) {
#if PYTHON_API_VERSION >= 1010
ENABLE_RICHCOMPARE_CAPABILITY;
#else
return true;
dest->tp_richcompare = &do_instance_richcompare;
dest->tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
#endif
return true;
}
return false;