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:
@@ -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__"):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
103
doc/richcmp.html
Normal 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 <, <=,
|
||||
>, >=, ==, 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<</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><</tt>, <tt><=</tt>, <tt>==</tt>, <tt>!=</tt>,
|
||||
<tt>></tt>, <tt>>=</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 < 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<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__");
|
||||
</pre>
|
||||
|
||||
<tt>NotImplemented</tt> is a simple free function:<pre>
|
||||
boost::python::ref
|
||||
NotImplemented(const code&, const code&) {
|
||||
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>
|
||||
© Copyright Nicholas K. Sauter & 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>
|
||||
@@ -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
|
||||
(< 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 < right</code><br>
|
||||
<code>left <= right</code><br>
|
||||
<code>left > right</code><br>
|
||||
<code>left >= 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 < cpp_right </code>
|
||||
<br><code>cpp_right < 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 < right</code>
|
||||
<br><code>left <= right</code>
|
||||
<br><code>left == right</code>
|
||||
<br><code>left != right</code>
|
||||
<br><code>left > right</code>
|
||||
<br><code>left >= 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 < cpp_right </code>
|
||||
<br><code>cpp_left <= cpp_right </code>
|
||||
<br><code>cpp_left == cpp_right </code>
|
||||
<br><code>cpp_left != cpp_right </code>
|
||||
<br><code>cpp_left > cpp_right </code>
|
||||
<br><code>cpp_left >= cpp_right </code>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
63
example/richcmp1.cpp
Normal file
63
example/richcmp1.cpp
Normal 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
61
example/richcmp2.cpp
Normal 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
7
example/richcmp.cpp → example/richcmp3.cpp
Executable file → Normal 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);
|
||||
@@ -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
11
example/tst_richcmp1.py
Normal 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
14
example/tst_richcmp2.py
Normal 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
60
example/tst_richcmp3.py
Normal 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
117
example/vector_wrapper.h
Normal 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
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user