mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
14 Commits
boost-1.82
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d6b042c4c | ||
|
|
55a7884912 | ||
|
|
2566e1dd3a | ||
|
|
9bca6982a4 | ||
|
|
c7e12ecf3d | ||
|
|
5031479fa2 | ||
|
|
fc9a6ac369 | ||
|
|
905074542e | ||
|
|
b7957da50a | ||
|
|
1b1620b62a | ||
|
|
0ed5af25a7 | ||
|
|
1dbcf12502 | ||
|
|
10c2fbd63a | ||
|
|
9b602d16b4 |
@@ -52,6 +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 + "/vector_wrapper.h",
|
||||
bpl_exa + "/richcmp1.cpp",
|
||||
bpl_exa + "/richcmp2.cpp",
|
||||
bpl_exa + "/richcmp3.cpp",
|
||||
bpl_exa + "/test_richcmp1.py",
|
||||
bpl_exa + "/test_richcmp2.py",
|
||||
bpl_exa + "/test_richcmp3.py",
|
||||
)
|
||||
|
||||
defs = (
|
||||
@@ -68,6 +75,9 @@ defs = (
|
||||
"noncopyable_import",
|
||||
"ivect",
|
||||
"dvect",
|
||||
"richcmp1",
|
||||
"richcmp2",
|
||||
"richcmp3",
|
||||
)
|
||||
|
||||
if (__name__ == "__main__"):
|
||||
|
||||
@@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost
|
||||
|
||||
PYEXE=/usr/local/Python-1.5.2/bin/python
|
||||
PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
||||
#PYEXE=/usr/local/Python-2.0/bin/python
|
||||
#PYINC=-I/usr/local/Python-2.0/include/python2.0
|
||||
#PYEXE=/usr/local/Python-2.1/bin/python
|
||||
#PYINC=-I/usr/local/Python-2.1/include/python2.1
|
||||
STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers
|
||||
|
||||
STDOPTS=
|
||||
@@ -46,7 +46,8 @@ DEPOBJ=$(OBJ) \
|
||||
do_it_yourself_converters.o \
|
||||
pickle1.o pickle2.o pickle3.o \
|
||||
noncopyable_export.o noncopyable_import.o \
|
||||
ivect.o dvect.o
|
||||
ivect.o dvect.o \
|
||||
richcmp1.o richcmp2.o richcmp3.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
@@ -58,7 +59,8 @@ all: libboost_python.a \
|
||||
do_it_yourself_converters.so \
|
||||
pickle1.so pickle2.so pickle3.so \
|
||||
noncopyable_export.so noncopyable_import.so \
|
||||
ivect.so dvect.so
|
||||
ivect.so dvect.so \
|
||||
richcmp1.so richcmp2.so richcmp3.so
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
rm -f libboost_python.a
|
||||
@@ -105,6 +107,15 @@ ivect.so: $(OBJ) ivect.o
|
||||
dvect.so: $(OBJ) dvect.o
|
||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.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
|
||||
|
||||
@@ -119,6 +130,9 @@ test:
|
||||
$(PYEXE) test_pickle2.py
|
||||
$(PYEXE) test_pickle3.py
|
||||
$(PYEXE) test_cross_module.py
|
||||
$(PYEXE) test_richcmp1.py
|
||||
$(PYEXE) test_richcmp2.py
|
||||
$(PYEXE) test_richcmp3.py
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||
@@ -135,6 +149,9 @@ clean:
|
||||
rm -f noncopyable_import.o noncopyable_import.so
|
||||
rm -f ivect.o ivect.so
|
||||
rm -f dvect.o dvect.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
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ PYEXE=PYTHONPATH=. /usr/bin/python
|
||||
PYINC=-I/usr/include/python1.5
|
||||
#PYEXE=/usr/local/Python-1.5.2/bin/python
|
||||
#PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
||||
#PYEXE=/usr/local/Python-2.0/bin/python
|
||||
#PYINC=-I/usr/local/Python-2.0/include/python2.0
|
||||
#PYEXE=/usr/local/Python-2.1/bin/python
|
||||
#PYINC=-I/usr/local/Python-2.1/include/python2.1
|
||||
|
||||
STDOPTS=-fPIC -ftemplate-depth-21
|
||||
WARNOPTS=
|
||||
@@ -47,7 +47,8 @@ DEPOBJ=$(OBJ) \
|
||||
do_it_yourself_converters.o \
|
||||
pickle1.o pickle2.o pickle3.o \
|
||||
noncopyable_export.o noncopyable_import.o \
|
||||
ivect.o dvect.o
|
||||
ivect.o dvect.o \
|
||||
richcmp1.o richcmp2.o richcmp3.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
@@ -59,7 +60,8 @@ all: libboost_python.a \
|
||||
do_it_yourself_converters.so \
|
||||
pickle1.so pickle2.so pickle3.so \
|
||||
noncopyable_export.so noncopyable_import.so \
|
||||
ivect.so dvect.so
|
||||
ivect.so dvect.so \
|
||||
richcmp1.so richcmp2.so richcmp3.so
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
rm -f libboost_python.a
|
||||
@@ -106,6 +108,15 @@ ivect.so: $(OBJ) ivect.o
|
||||
dvect.so: $(OBJ) dvect.o
|
||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.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
|
||||
|
||||
@@ -120,6 +131,9 @@ test:
|
||||
$(PYEXE) test_pickle2.py
|
||||
$(PYEXE) test_pickle3.py
|
||||
$(PYEXE) test_cross_module.py
|
||||
$(PYEXE) test_richcmp1.py
|
||||
$(PYEXE) test_richcmp2.py
|
||||
$(PYEXE) test_richcmp3.py
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||
@@ -136,6 +150,9 @@ clean:
|
||||
rm -f noncopyable_import.o noncopyable_import.so
|
||||
rm -f ivect.o ivect.so
|
||||
rm -f dvect.o dvect.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:
|
||||
|
||||
@@ -62,10 +62,11 @@ all: libboost_python.a \
|
||||
do_it_yourself_converters.pyd \
|
||||
pickle1.pyd pickle2.pyd pickle3.pyd \
|
||||
noncopyable_export.pyd noncopyable_import.pyd \
|
||||
ivect.pyd dvect.pyd
|
||||
ivect.pyd dvect.pyd \
|
||||
richcmp1.pyd richcmp2.pyd richcmp3.pyd
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
del libboost_python.a
|
||||
-del libboost_python.a
|
||||
ar r libboost_python.a $(OBJ)
|
||||
|
||||
DLLWRAPOPTS=-s --driver-name g++ -s \
|
||||
@@ -149,6 +150,24 @@ dvect.pyd: $(OBJ) dvect.o
|
||||
--def dvect.def \
|
||||
$(OBJ) dvect.o $(PYLIB)
|
||||
|
||||
richcmp1.pyd: $(OBJ) richcmp1.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--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
|
||||
|
||||
@@ -163,12 +182,15 @@ test:
|
||||
$(PYEXE) test_pickle2.py
|
||||
$(PYEXE) test_pickle3.py
|
||||
$(PYEXE) test_cross_module.py
|
||||
$(PYEXE) test_richcmp1.py
|
||||
$(PYEXE) test_richcmp2.py
|
||||
$(PYEXE) test_richcmp3.py
|
||||
|
||||
clean:
|
||||
del *.o
|
||||
del *.a
|
||||
del *.pyd
|
||||
del *.pyc
|
||||
-del *.o
|
||||
-del *.a
|
||||
-del *.pyd
|
||||
-del *.pyc
|
||||
|
||||
softlinks:
|
||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks
|
||||
|
||||
@@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost
|
||||
|
||||
PYEXE=/usr/local/Python-1.5.2/bin/python
|
||||
PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
||||
#PYEXE=/usr/local/Python-2.0/bin/python
|
||||
#PYINC=-I/usr/local/Python-2.0/include/python2.0
|
||||
#PYEXE=/usr/local/Python-2.1/bin/python
|
||||
#PYINC=-I/usr/local/Python-2.1/include/python2.1
|
||||
#STLPORTINC=-I/usr/local/STLport-4.1b3/stlport
|
||||
#STLPORTINC=-I/usr/local/STLport-4.1b4/stlport
|
||||
#STLPORTOPTS= \
|
||||
@@ -57,7 +57,8 @@ DEPOBJ=$(OBJ) \
|
||||
do_it_yourself_converters.o \
|
||||
pickle1.o pickle2.o pickle3.o \
|
||||
noncopyable_export.o noncopyable_import.o \
|
||||
ivect.o dvect.o
|
||||
ivect.o dvect.o \
|
||||
richcmp1.o richcmp2.o richcmp3.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
@@ -69,7 +70,8 @@ all: libboost_python.a \
|
||||
do_it_yourself_converters.so \
|
||||
pickle1.so pickle2.so pickle3.so \
|
||||
noncopyable_export.so noncopyable_import.so \
|
||||
ivect.so dvect.so
|
||||
ivect.so dvect.so \
|
||||
richcmp1.so richcmp2.so richcmp3.so
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
rm -f libboost_python.a
|
||||
@@ -120,6 +122,15 @@ ivect.so: $(OBJ) ivect.o
|
||||
dvect.so: $(OBJ) dvect.o
|
||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.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
|
||||
|
||||
@@ -134,6 +145,9 @@ test:
|
||||
$(PYEXE) test_pickle2.py
|
||||
$(PYEXE) test_pickle3.py
|
||||
$(PYEXE) test_cross_module.py
|
||||
$(PYEXE) test_richcmp1.py
|
||||
$(PYEXE) test_richcmp2.py
|
||||
$(PYEXE) test_richcmp3.py
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||
@@ -150,6 +164,9 @@ clean:
|
||||
rm -f noncopyable_import.o noncopyable_import.so
|
||||
rm -f ivect.o ivect.so
|
||||
rm -f dvect.o dvect.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
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ BOOST_UNIX=$(HOME)/boost
|
||||
PYEXE="C:\Program files\Python\python.exe"
|
||||
PYINC=/I"C:\Program files\Python\include"
|
||||
PYLIB="C:\Program files\Python\libs\python15.lib"
|
||||
#PYEXE="C:\Python21\python.exe"
|
||||
#PYINC=/I"C:\Python21\include"
|
||||
#PYLIB="C:\Python21\libs\python21.lib"
|
||||
|
||||
STDOPTS=/nologo /MD /GR /GX /Zm200
|
||||
WARNOPTS=
|
||||
@@ -43,7 +46,8 @@ all: boost_python.lib \
|
||||
do_it_yourself_converters.pyd \
|
||||
pickle1.pyd pickle2.pyd pickle3.pyd \
|
||||
noncopyable_export.pyd noncopyable_import.pyd \
|
||||
ivect.pyd dvect.pyd
|
||||
ivect.pyd dvect.pyd \
|
||||
richcmp1.pyd richcmp2.pyd richcmp3.pyd
|
||||
|
||||
boost_python.lib: $(OBJ)
|
||||
$(LD) -lib /nologo /out:boost_python.lib $(OBJ)
|
||||
@@ -87,6 +91,15 @@ ivect.pyd: $(OBJ) ivect.obj
|
||||
dvect.pyd: $(OBJ) dvect.obj
|
||||
$(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.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
|
||||
|
||||
@@ -101,14 +114,17 @@ test:
|
||||
$(PYEXE) test_pickle2.py
|
||||
$(PYEXE) test_pickle3.py
|
||||
$(PYEXE) test_cross_module.py --broken-auto-ptr
|
||||
$(PYEXE) test_richcmp1.py
|
||||
$(PYEXE) test_richcmp2.py
|
||||
$(PYEXE) test_richcmp3.py
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del *.lib
|
||||
del *.exp
|
||||
del *.idb
|
||||
del *.pyd
|
||||
del *.pyc
|
||||
-del *.obj
|
||||
-del *.lib
|
||||
-del *.exp
|
||||
-del *.idb
|
||||
-del *.pyd
|
||||
-del *.pyc
|
||||
|
||||
softlinks:
|
||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks
|
||||
|
||||
@@ -91,8 +91,8 @@ initialization. These bind the corresponding enum values to the appropriate
|
||||
names so they can be used from Python:
|
||||
|
||||
<blockquote><pre>
|
||||
mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
||||
mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
||||
mymodule.add(boost::python::make_ref(enum_value_1), "enum_value_1");
|
||||
mymodule.add(boost::python::make_ref(enum_value_2), "enum_value_2");
|
||||
...
|
||||
</pre></blockquote>
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ code before the last Python reference to it disappears:
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
PyObject* to_python(Foo* p)
|
||||
{
|
||||
return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p);
|
||||
return boost::python::python_extension_class_converters<Foo>::smart_ptr_to_python(p);
|
||||
}
|
||||
|
||||
PyObject* to_python(const Foo* p)
|
||||
|
||||
106
doc/richcmp.html
Normal file
106
doc/richcmp.html
Normal file
@@ -0,0 +1,106 @@
|
||||
<!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> when the Python 2.1
|
||||
(or higher) interpreter tries, e.g., <tt>a.__lt__(b)</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 that (currently) has
|
||||
to be provided by the user. For example:<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>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
template defines a whole raft of these conversions (for <code>T, T*,
|
||||
T&, std::auto_ptr<T></code>, etc.), using the same inline
|
||||
friend function technique employed by <a href=
|
||||
"http://www.boost.org/libs/utility/operators.htm">the boost operators
|
||||
"file:///c:/boost/site/libs/utility/operators.htm">the boost operators
|
||||
library</a>.
|
||||
<p>
|
||||
Because the <code>to_python</code> and <code>from_python</code> functions
|
||||
|
||||
@@ -20,6 +20,16 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
||||
# include <windows.h>
|
||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
||||
= _set_se_translator(structured_exception_translator);
|
||||
# endif
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(dvect)
|
||||
{
|
||||
try
|
||||
@@ -43,3 +53,4 @@ BOOST_PYTHON_MODULE_INIT(dvect)
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,16 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
||||
# include <windows.h>
|
||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
||||
= _set_se_translator(structured_exception_translator);
|
||||
# endif
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(ivect)
|
||||
{
|
||||
try
|
||||
@@ -43,3 +53,4 @@ BOOST_PYTHON_MODULE_INIT(ivect)
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,16 @@ namespace python = boost::python;
|
||||
|
||||
#include "noncopyable.h"
|
||||
|
||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
||||
# include <windows.h>
|
||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
||||
= _set_se_translator(structured_exception_translator);
|
||||
# endif
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(noncopyable_export)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -19,6 +19,16 @@ namespace { // Avoid cluttering the global namespace.
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
||||
# include <windows.h>
|
||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
||||
= _set_se_translator(structured_exception_translator);
|
||||
# endif
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(noncopyable_import)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace {
|
||||
{
|
||||
if(args.size() != 1 || keywords.size() != 0) {
|
||||
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
|
||||
throw boost::python::argument_error();
|
||||
throw boost::python::error_already_set();
|
||||
}
|
||||
const world& w = from_python(args[0].get(), type<const world&>());
|
||||
ref mydict = getattr(args[0], "__dict__");
|
||||
@@ -122,7 +122,7 @@ namespace {
|
||||
{
|
||||
if(args.size() != 2 || keywords.size() != 0) {
|
||||
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
|
||||
throw boost::python::argument_error();
|
||||
throw boost::python::error_already_set();
|
||||
}
|
||||
world& w = from_python(args[0].get(), type<world&>());
|
||||
ref mydict = getattr(args[0], "__dict__");
|
||||
|
||||
87
example/richcmp1.cpp
Normal file
87
example/richcmp1.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
// 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 vects {
|
||||
|
||||
struct dvect : public std::vector<double>
|
||||
{
|
||||
dvect() : std::vector<double>() {}
|
||||
dvect(size_t n) : std::vector<double>(n) {}
|
||||
dvect(boost::python::tuple tuple) : std::vector<double>(tuple.size())
|
||||
{
|
||||
std::vector<double>::iterator v_it = begin();
|
||||
for (std::size_t i = 0; i < tuple.size(); i++)
|
||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
||||
boost::python::type<double>());
|
||||
}
|
||||
|
||||
boost::python::tuple as_tuple() const
|
||||
{
|
||||
boost::python::tuple t(size());
|
||||
for (std::size_t i = 0; i < size(); i++)
|
||||
t.set_item(i,
|
||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
||||
return t;
|
||||
}
|
||||
|
||||
# define DVECT_BINARY_OPERATORS(oper) \
|
||||
friend std::vector<bool> \
|
||||
operator##oper(const dvect& lhs, const dvect& rhs) \
|
||||
{ \
|
||||
if (lhs.size() != rhs.size()) { \
|
||||
PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \
|
||||
throw boost::python::error_already_set(); \
|
||||
} \
|
||||
std::vector<bool> result(lhs.size()); \
|
||||
for (std::size_t i=0; i<lhs.size(); i++) { \
|
||||
result[i] = (lhs[i] ##oper rhs[i]); \
|
||||
} \
|
||||
return result; \
|
||||
}
|
||||
DVECT_BINARY_OPERATORS(<)
|
||||
DVECT_BINARY_OPERATORS(<=)
|
||||
DVECT_BINARY_OPERATORS(==)
|
||||
DVECT_BINARY_OPERATORS(!=)
|
||||
DVECT_BINARY_OPERATORS(>)
|
||||
DVECT_BINARY_OPERATORS(>=)
|
||||
# undef VECTOR_BINARY_OPERATORS
|
||||
};
|
||||
|
||||
} // namespace <anonymous>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void init_module(boost::python::module_builder& this_module)
|
||||
{
|
||||
(void) example::wrap_vector(this_module, "vector_of_bool", bool());
|
||||
|
||||
boost::python::class_builder<vects::dvect> py_dvect(this_module, "dvect");
|
||||
|
||||
py_dvect.def(boost::python::constructor<boost::python::tuple>());
|
||||
py_dvect.def(&vects::dvect::as_tuple, "as_tuple");
|
||||
|
||||
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_dvect.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 a separate function in order
|
||||
// to suppress a bogus VC60 warning.
|
||||
init_module(this_module);
|
||||
}
|
||||
catch (...) { boost::python::handle_exception(); }
|
||||
}
|
||||
65
example/richcmp2.cpp
Normal file
65
example/richcmp2.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
// 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;
|
||||
};
|
||||
|
||||
#if PYTHON_API_VERSION >= 1010
|
||||
boost::python::ref
|
||||
NotImplemented(const code&, const code&) {
|
||||
return
|
||||
boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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)>());
|
||||
#if PYTHON_API_VERSION >= 1010
|
||||
py_code.def(NotImplemented, "__lt__");
|
||||
py_code.def(NotImplemented, "__le__");
|
||||
py_code.def(NotImplemented, "__gt__");
|
||||
py_code.def(NotImplemented, "__ge__");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace <anonymous>
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(richcmp2)
|
||||
{
|
||||
try {
|
||||
boost::python::module_builder this_module("richcmp2");
|
||||
// The actual work is done in a separate function in order
|
||||
// to suppress a bogus VC60 warning.
|
||||
init_module(this_module);
|
||||
}
|
||||
catch (...) { boost::python::handle_exception(); }
|
||||
}
|
||||
178
example/richcmp3.cpp
Normal file
178
example/richcmp3.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter.
|
||||
// Comprehensive operator overloading for two vector types and scalars.
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include "vector_wrapper.h"
|
||||
#include "dvect.h"
|
||||
#include "ivect.h"
|
||||
|
||||
#define VECT_VECT_OPERATORS(result_type, vect_type1, oper, vect_type2) \
|
||||
namespace vects { \
|
||||
result_type \
|
||||
operator##oper (const vect_type1& lhs, const vect_type2& rhs) { \
|
||||
if (lhs.size() != rhs.size()) { \
|
||||
PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \
|
||||
throw boost::python::error_already_set(); \
|
||||
} \
|
||||
result_type result(lhs.size()); \
|
||||
for (std::size_t i=0; i<lhs.size(); i++) { \
|
||||
result[i] = (lhs[i] ##oper rhs[i]); \
|
||||
} \
|
||||
return result; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define VECT_SCALAR_OPERATORS(result_type, vect_type, oper, scalar_type) \
|
||||
namespace vects { \
|
||||
result_type \
|
||||
operator##oper (const vect_type& lhs, const scalar_type& rhs) { \
|
||||
result_type result(lhs.size()); \
|
||||
for (std::size_t i=0; i<lhs.size(); i++) { \
|
||||
result[i] = (lhs[i] ##oper rhs ); \
|
||||
} \
|
||||
return result; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SCALAR_VECT_OPERATORS(result_type, scalar_type, oper, vect_type) \
|
||||
namespace vects { \
|
||||
result_type \
|
||||
operator##oper (const scalar_type& lhs, const vect_type& rhs) { \
|
||||
result_type result(rhs.size()); \
|
||||
for (std::size_t i=0; i<rhs.size(); i++) { \
|
||||
result[i] = (lhs ##oper rhs[i]); \
|
||||
} \
|
||||
return result; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MATH_VECT_VECT_OPERATORS(result_type, vect_type1, vect_type2) \
|
||||
VECT_VECT_OPERATORS(result_type, vect_type1, +, vect_type2) \
|
||||
VECT_VECT_OPERATORS(result_type, vect_type1, -, vect_type2) \
|
||||
VECT_VECT_OPERATORS(result_type, vect_type1, *, vect_type2) \
|
||||
VECT_VECT_OPERATORS(result_type, vect_type1, /, vect_type2)
|
||||
|
||||
#define COMP_VECT_VECT_OPERATORS(vect_type1, vect_type2) \
|
||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, <, vect_type2) \
|
||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, <=, vect_type2) \
|
||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, ==, vect_type2) \
|
||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, !=, vect_type2) \
|
||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, >, vect_type2) \
|
||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, >=, vect_type2)
|
||||
|
||||
#define MATH_VECT_SCALAR_OPERATORS(result_type, vect_type, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(result_type, vect_type, +, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(result_type, vect_type, -, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(result_type, vect_type, *, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(result_type, vect_type, /, scalar_type)
|
||||
|
||||
#define COMP_VECT_SCALAR_OPERATORS(vect_type, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, <, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, <=, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, ==, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, !=, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, >, scalar_type) \
|
||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, >=, scalar_type)
|
||||
|
||||
#define MATH_SCALAR_VECT_OPERATORS(result_type, scalar_type, vect_type) \
|
||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, +, vect_type) \
|
||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, -, vect_type) \
|
||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, *, vect_type) \
|
||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, /, vect_type)
|
||||
|
||||
MATH_VECT_VECT_OPERATORS(dvect, dvect, dvect)
|
||||
COMP_VECT_VECT_OPERATORS( dvect, dvect)
|
||||
MATH_VECT_SCALAR_OPERATORS(dvect, dvect, double)
|
||||
COMP_VECT_SCALAR_OPERATORS( dvect, double)
|
||||
MATH_SCALAR_VECT_OPERATORS(dvect, double, dvect)
|
||||
// comparison operators not needed since Python uses reflection
|
||||
|
||||
MATH_VECT_VECT_OPERATORS(ivect, ivect, ivect)
|
||||
COMP_VECT_VECT_OPERATORS( ivect, ivect)
|
||||
MATH_VECT_SCALAR_OPERATORS(ivect, ivect, int)
|
||||
COMP_VECT_SCALAR_OPERATORS( ivect, int)
|
||||
MATH_SCALAR_VECT_OPERATORS(ivect, int, ivect)
|
||||
// comparison operators not needed since Python uses reflection
|
||||
|
||||
MATH_VECT_VECT_OPERATORS(dvect, dvect, ivect)
|
||||
COMP_VECT_VECT_OPERATORS( dvect, ivect)
|
||||
MATH_VECT_VECT_OPERATORS(dvect, ivect, dvect)
|
||||
COMP_VECT_VECT_OPERATORS( ivect, dvect)
|
||||
|
||||
#undef VECT_VECT_OPERATORS
|
||||
#undef SCALAR_VECT_OPERATORS
|
||||
#undef VECT_SCALAR_OPERATORS
|
||||
#undef MATH_VECT_VECT_OPERATORS
|
||||
#undef COMP_VECT_VECT_OPERATORS
|
||||
#undef MATH_VECT_SCALAR_OPERATORS
|
||||
#undef COMP_VECT_SCALAR_OPERATORS
|
||||
#undef MATH_SCALAR_VECT_OPERATORS
|
||||
|
||||
namespace {
|
||||
|
||||
void init_module(boost::python::module_builder& this_module)
|
||||
{
|
||||
(void) example::wrap_vector(this_module, "vector_of_bool", bool());
|
||||
|
||||
const long
|
||||
math_operators ( boost::python::op_mul | boost::python::op_add
|
||||
| boost::python::op_div | boost::python::op_sub);
|
||||
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);
|
||||
|
||||
boost::python::class_builder<vects::dvect>
|
||||
dvect_class(this_module, "dvect");
|
||||
boost::python::class_builder<vects::ivect>
|
||||
ivect_class(this_module, "ivect");
|
||||
|
||||
dvect_class.def(boost::python::constructor<boost::python::tuple>());
|
||||
dvect_class.def(&vects::dvect::as_tuple,"as_tuple");
|
||||
|
||||
dvect_class.def(boost::python::operators<math_operators>());
|
||||
dvect_class.def(boost::python::operators<math_operators>(),
|
||||
boost::python::right_operand<double>() );
|
||||
dvect_class.def(boost::python::operators<math_operators>(),
|
||||
boost::python::left_operand<double>() );
|
||||
dvect_class.def(boost::python::operators<math_operators>(),
|
||||
boost::python::right_operand<vects::ivect>() );
|
||||
|
||||
dvect_class.def(boost::python::operators<comp_operators>());
|
||||
dvect_class.def(boost::python::operators<comp_operators>(),
|
||||
boost::python::right_operand<double>() );
|
||||
// left_operand not needed since Python uses reflection
|
||||
dvect_class.def(boost::python::operators<comp_operators>(),
|
||||
boost::python::right_operand<vects::ivect>() );
|
||||
|
||||
ivect_class.def(boost::python::constructor<boost::python::tuple>());
|
||||
ivect_class.def(&vects::ivect::as_tuple,"as_tuple");
|
||||
|
||||
ivect_class.def(boost::python::operators<math_operators>());
|
||||
ivect_class.def(boost::python::operators<math_operators>(),
|
||||
boost::python::right_operand<int>() );
|
||||
ivect_class.def(boost::python::operators<math_operators>(),
|
||||
boost::python::left_operand<int>() );
|
||||
ivect_class.def(boost::python::operators<math_operators>(),
|
||||
boost::python::right_operand<vects::dvect>() );
|
||||
|
||||
ivect_class.def(boost::python::operators<comp_operators>());
|
||||
ivect_class.def(boost::python::operators<comp_operators>(),
|
||||
boost::python::right_operand<int>() );
|
||||
// left_operand not needed since Python uses reflection
|
||||
ivect_class.def(boost::python::operators<comp_operators>(),
|
||||
boost::python::right_operand<vects::dvect>() );
|
||||
}
|
||||
|
||||
} // namespace <anonymous>
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(richcmp3)
|
||||
{
|
||||
try {
|
||||
boost::python::module_builder this_module("richcmp3");
|
||||
// The actual work is done in a separate function in order
|
||||
// to suppress a bogus VC60 warning.
|
||||
init_module(this_module);
|
||||
}
|
||||
catch (...) { boost::python::handle_exception(); }
|
||||
}
|
||||
@@ -137,4 +137,4 @@ def run(args = None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(run())
|
||||
sys.exit(run()[0])
|
||||
|
||||
@@ -19,12 +19,12 @@ r'''>>> import pickle3
|
||||
... wd.z = 3. * number
|
||||
... pstr = pickle.dumps(wd)
|
||||
... wl = pickle.loads(pstr)
|
||||
... print wd.greet(), wd.get_secret_number(), wd.__dict__
|
||||
... print wl.greet(), wl.get_secret_number(), wl.__dict__
|
||||
Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||
Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||
Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||
Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||
... print wd.greet(), wd.get_secret_number(), wd.x, wd.y, wd.z
|
||||
... print wl.greet(), wl.get_secret_number(), wl.x, wl.y, wl.z
|
||||
Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0
|
||||
Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0
|
||||
Hello from California! 42 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0
|
||||
Hello from California! 0 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
|
||||
40
example/test_richcmp1.py
Normal file
40
example/test_richcmp1.py
Normal file
@@ -0,0 +1,40 @@
|
||||
r'''>>> import richcmp1
|
||||
>>> d1 = richcmp1.dvect((0, 1, 3, 3, 6, 7))
|
||||
>>> d2 = richcmp1.dvect((1, 2, 3, 4, 5, 6))
|
||||
>>> print d1.as_tuple()
|
||||
(0.0, 1.0, 3.0, 3.0, 6.0, 7.0)
|
||||
>>> print d2.as_tuple()
|
||||
(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
|
||||
>>> print (d1 < d2).as_tuple()
|
||||
(1, 1, 0, 1, 0, 0)
|
||||
>>> print (d1 <= d2).as_tuple()
|
||||
(1, 1, 1, 1, 0, 0)
|
||||
>>> print (d1 == d2).as_tuple()
|
||||
(0, 0, 1, 0, 0, 0)
|
||||
>>> print (d1 != d2).as_tuple()
|
||||
(1, 1, 0, 1, 1, 1)
|
||||
>>> print (d1 > d2).as_tuple()
|
||||
(0, 0, 0, 0, 1, 1)
|
||||
>>> print (d1 >= d2).as_tuple()
|
||||
(0, 0, 1, 0, 1, 1)
|
||||
>>> try: d1 == richcmp1.dvect((1, 2, 3, 4, 5))
|
||||
... except ValueError, e: print str(e)
|
||||
...
|
||||
vectors have different sizes
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_richcmp1
|
||||
return doctest.testmod(test_richcmp1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if ( hasattr(sys, 'version_info')
|
||||
and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1)
|
||||
or sys.version_info[0] > 2)):
|
||||
sys.exit(run()[0])
|
||||
else:
|
||||
print "Python version 2.1 or higher required. Test skipped."
|
||||
41
example/test_richcmp2.py
Normal file
41
example/test_richcmp2.py
Normal file
@@ -0,0 +1,41 @@
|
||||
r'''>>> import richcmp2
|
||||
>>> c1 = richcmp2.code(1)
|
||||
>>> c2 = richcmp2.code(2)
|
||||
>>> c3 = richcmp2.code(2)
|
||||
>>> print c1 == c2
|
||||
0
|
||||
>>> print c1 != c2
|
||||
1
|
||||
>>> print c2 == c3
|
||||
1
|
||||
>>> print c2 != c3
|
||||
0
|
||||
>>> print c1 < c2
|
||||
1
|
||||
>>> print c1 <= c2
|
||||
1
|
||||
>>> print c1 == c2
|
||||
0
|
||||
>>> print c1 != c2
|
||||
1
|
||||
>>> print c1 > c2
|
||||
0
|
||||
>>> print c1 >= c2
|
||||
0
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_richcmp1
|
||||
return doctest.testmod(test_richcmp1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if ( hasattr(sys, 'version_info')
|
||||
and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1)
|
||||
or sys.version_info[0] > 2)):
|
||||
sys.exit(run()[0])
|
||||
else:
|
||||
print "Python version 2.1 or higher required. Test skipped."
|
||||
77
example/test_richcmp3.py
Normal file
77
example/test_richcmp3.py
Normal file
@@ -0,0 +1,77 @@
|
||||
r'''>>> import richcmp3
|
||||
>>>
|
||||
>>> iv = richcmp3.ivect((1,2,3,4,5))
|
||||
>>> print iv.as_tuple()
|
||||
(1, 2, 3, 4, 5)
|
||||
>>> dv = richcmp3.dvect((2,-2,3,8,-5))
|
||||
>>> print dv.as_tuple()
|
||||
(2.0, -2.0, 3.0, 8.0, -5.0)
|
||||
>>>
|
||||
>>> print (iv+dv).as_tuple()
|
||||
(3.0, 0.0, 6.0, 12.0, 0.0)
|
||||
>>> print (iv+3).as_tuple()
|
||||
(4, 5, 6, 7, 8)
|
||||
>>> print (3+iv).as_tuple()
|
||||
(4, 5, 6, 7, 8)
|
||||
>>>
|
||||
>>> print "vect vs. vect Comparisons:"
|
||||
vect vs. vect Comparisons:
|
||||
>>> print (iv < dv).as_tuple()
|
||||
(1, 0, 0, 1, 0)
|
||||
>>> print (iv <= dv).as_tuple()
|
||||
(1, 0, 1, 1, 0)
|
||||
>>> print (iv == dv).as_tuple()
|
||||
(0, 0, 1, 0, 0)
|
||||
>>> print (iv != dv).as_tuple()
|
||||
(1, 1, 0, 1, 1)
|
||||
>>> print (iv > dv).as_tuple()
|
||||
(0, 1, 0, 0, 1)
|
||||
>>> print (iv >= dv).as_tuple()
|
||||
(0, 1, 1, 0, 1)
|
||||
>>>
|
||||
>>> print "vect vs. scalar Comparisons:"
|
||||
vect vs. scalar Comparisons:
|
||||
>>> print (iv < 3).as_tuple()
|
||||
(1, 1, 0, 0, 0)
|
||||
>>> print (iv <= 3).as_tuple()
|
||||
(1, 1, 1, 0, 0)
|
||||
>>> print (iv == 3).as_tuple()
|
||||
(0, 0, 1, 0, 0)
|
||||
>>> print (iv != 3).as_tuple()
|
||||
(1, 1, 0, 1, 1)
|
||||
>>> print (iv > 3).as_tuple()
|
||||
(0, 0, 0, 1, 1)
|
||||
>>> print (iv >= 3).as_tuple()
|
||||
(0, 0, 1, 1, 1)
|
||||
>>>
|
||||
>>> print "scalar vs. vect Comparisons:"
|
||||
scalar vs. vect Comparisons:
|
||||
>>> print (3 < iv).as_tuple()
|
||||
(0, 0, 0, 1, 1)
|
||||
>>> print (3 <= iv).as_tuple()
|
||||
(0, 0, 1, 1, 1)
|
||||
>>> print (3 == iv).as_tuple()
|
||||
(0, 0, 1, 0, 0)
|
||||
>>> print (3 != iv).as_tuple()
|
||||
(1, 1, 0, 1, 1)
|
||||
>>> print (3 > iv).as_tuple()
|
||||
(1, 1, 0, 0, 0)
|
||||
>>> print (3 >= iv).as_tuple()
|
||||
(1, 1, 1, 0, 0)
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_richcmp3
|
||||
return doctest.testmod(test_richcmp3)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if ( hasattr(sys, 'version_info')
|
||||
and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1)
|
||||
or sys.version_info[0] > 2)):
|
||||
sys.exit(run()[0])
|
||||
else:
|
||||
print "Python version 2.1 or higher required. Test skipped."
|
||||
@@ -87,12 +87,18 @@ if (__name__ == "__main__"):
|
||||
import sys, string
|
||||
broken_auto_ptr = 0
|
||||
n = 1
|
||||
if (len(sys.argv) > 1):
|
||||
if (sys.argv[1] == "--broken-auto-ptr"):
|
||||
broken_auto_ptr = 1
|
||||
if (len(sys.argv) > 2):
|
||||
n = string.atoi(sys.argv[2])
|
||||
else:
|
||||
n = string.atoi(sys.argv[1])
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
argv = []
|
||||
|
||||
for x in sys.argv:
|
||||
if x != '--broken-auto-ptr':
|
||||
argv.append(x)
|
||||
broken_auto_ptr = argv != sys.argv
|
||||
sys.argv = argv
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
n = string.atoi(sys.argv[1])
|
||||
|
||||
for i in xrange(n):
|
||||
f(broken_auto_ptr)
|
||||
|
||||
@@ -87,12 +87,18 @@ if (__name__ == "__main__"):
|
||||
import sys, string
|
||||
broken_auto_ptr = 0
|
||||
n = 1
|
||||
if (len(sys.argv) > 1):
|
||||
if (sys.argv[1] == "--broken-auto-ptr"):
|
||||
broken_auto_ptr = 1
|
||||
if (len(sys.argv) > 2):
|
||||
n = string.atoi(sys.argv[2])
|
||||
else:
|
||||
n = string.atoi(sys.argv[1])
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
argv = []
|
||||
|
||||
for x in sys.argv:
|
||||
if x != '--broken-auto-ptr':
|
||||
argv.append(x)
|
||||
broken_auto_ptr = argv != sys.argv
|
||||
sys.argv = argv
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
n = string.atoi(sys.argv[1])
|
||||
|
||||
for i in xrange(n):
|
||||
f(broken_auto_ptr)
|
||||
|
||||
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
|
||||
T
|
||||
getitem(const std::vector<T>& vec,
|
||||
std::size_t key)
|
||||
{
|
||||
if (key >= vec.size()) raise_vector_IndexError();
|
||||
return vec[key];
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
setitem(std::vector<T>& vec,
|
||||
std::size_t key,
|
||||
const T &value)
|
||||
{
|
||||
if (key >= vec.size()) raise_vector_IndexError();
|
||||
vec[key] = value;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
delitem(std::vector<T>& vec,
|
||||
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
|
||||
@@ -70,6 +70,14 @@ class instance
|
||||
PyObject* oct();
|
||||
PyObject* hex();
|
||||
|
||||
// Rich comparisons
|
||||
PyObject* lt(PyObject* other);
|
||||
PyObject* le(PyObject* other);
|
||||
PyObject* eq(PyObject* other);
|
||||
PyObject* ne(PyObject* other);
|
||||
PyObject* gt(PyObject* other);
|
||||
PyObject* ge(PyObject* other);
|
||||
|
||||
private: // noncopyable, without the size bloat
|
||||
instance(const instance&);
|
||||
void operator=(const instance&);
|
||||
@@ -169,6 +177,14 @@ class class_t
|
||||
PyObject* instance_number_float(PyObject*) const;
|
||||
PyObject* instance_number_oct(PyObject*) const;
|
||||
PyObject* instance_number_hex(PyObject*) const;
|
||||
|
||||
private: // Implement rich comparisons
|
||||
PyObject* instance_lt(PyObject*, PyObject*) const;
|
||||
PyObject* instance_le(PyObject*, PyObject*) const;
|
||||
PyObject* instance_eq(PyObject*, PyObject*) const;
|
||||
PyObject* instance_ne(PyObject*, PyObject*) const;
|
||||
PyObject* instance_gt(PyObject*, PyObject*) const;
|
||||
PyObject* instance_ge(PyObject*, PyObject*) const;
|
||||
|
||||
private: // Miscellaneous "special" methods
|
||||
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const;
|
||||
@@ -477,6 +493,42 @@ PyObject* class_t<T>::instance_number_hex(PyObject* obj) const
|
||||
return downcast<T>(obj)->hex();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_lt(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->lt(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_le(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->le(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_eq(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->eq(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_ne(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->ne(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_gt(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->gt(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_ge(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->ge(other);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
inline dictionary& class_base::dict()
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ typedef base_object<PyTypeObject> python_type;
|
||||
|
||||
|
||||
//
|
||||
// class_t template member function implementations
|
||||
// base_object member function implementations
|
||||
//
|
||||
template <class python_type>
|
||||
base_object<python_type>::base_object(PyTypeObject* type_obj)
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
# define BOOST_CSTD_ std
|
||||
# endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name()
|
||||
#else
|
||||
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name()
|
||||
|
||||
@@ -616,6 +616,12 @@ class extension_class
|
||||
choose_op<(which & op_and)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_xor)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_gt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ne)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
|
||||
@@ -645,6 +651,12 @@ class extension_class
|
||||
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_gt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ne)>::template args<Left,Right>::add(this);
|
||||
}
|
||||
|
||||
template <long which, class Left, class Right>
|
||||
|
||||
@@ -45,7 +45,7 @@ class type_object_base : public python_type
|
||||
|
||||
public:
|
||||
enum capability {
|
||||
hash, call, str, getattr, setattr, compare, repr,
|
||||
hash, call, str, getattr, setattr, compare, repr, richcompare,
|
||||
|
||||
mapping_length, mapping_subscript, mapping_ass_subscript,
|
||||
|
||||
@@ -115,6 +115,14 @@ class type_object_base : public python_type
|
||||
virtual PyObject* instance_number_float(PyObject*) const;
|
||||
virtual PyObject* instance_number_oct(PyObject*) const;
|
||||
virtual PyObject* instance_number_hex(PyObject*) const;
|
||||
|
||||
public: // Callbacks for rich comparisons
|
||||
virtual PyObject* instance_lt(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_le(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_eq(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_ne(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_gt(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_ge(PyObject*, PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -65,7 +65,13 @@ enum operator_id
|
||||
op_long = 0x20000,
|
||||
op_float = 0x40000,
|
||||
op_str = 0x80000,
|
||||
op_cmp = 0x100000
|
||||
op_cmp = 0x100000,
|
||||
op_gt = 0x200000,
|
||||
op_ge = 0x400000,
|
||||
op_lt = 0x800000,
|
||||
op_le = 0x1000000,
|
||||
op_eq = 0x2000000,
|
||||
op_ne = 0x4000000
|
||||
};
|
||||
|
||||
// Wrap the operators given by "which". Usage:
|
||||
@@ -301,6 +307,12 @@ namespace detail
|
||||
PY_DEFINE_BINARY_OPERATORS(and, &);
|
||||
PY_DEFINE_BINARY_OPERATORS(xor, ^);
|
||||
PY_DEFINE_BINARY_OPERATORS(or, |);
|
||||
PY_DEFINE_BINARY_OPERATORS(gt, >);
|
||||
PY_DEFINE_BINARY_OPERATORS(ge, >=);
|
||||
PY_DEFINE_BINARY_OPERATORS(lt, <);
|
||||
PY_DEFINE_BINARY_OPERATORS(le, <=);
|
||||
PY_DEFINE_BINARY_OPERATORS(eq, ==);
|
||||
PY_DEFINE_BINARY_OPERATORS(ne, !=);
|
||||
|
||||
PY_DEFINE_UNARY_OPERATORS(neg, -);
|
||||
PY_DEFINE_UNARY_OPERATORS(pos, +);
|
||||
|
||||
@@ -736,6 +736,36 @@ PyObject* instance::hex()
|
||||
return callback<PyObject*>::call_method(this, "__hex__");
|
||||
}
|
||||
|
||||
PyObject* instance::lt(PyObject* other)
|
||||
{
|
||||
return callback<PyObject*>::call_method(this, "__lt__", other);
|
||||
}
|
||||
|
||||
PyObject* instance::le(PyObject* other)
|
||||
{
|
||||
return callback<PyObject*>::call_method(this, "__le__", other);
|
||||
}
|
||||
|
||||
PyObject* instance::eq(PyObject* other)
|
||||
{
|
||||
return callback<PyObject*>::call_method(this, "__eq__", other);
|
||||
}
|
||||
|
||||
PyObject* instance::ne(PyObject* other)
|
||||
{
|
||||
return callback<PyObject*>::call_method(this, "__ne__", other);
|
||||
}
|
||||
|
||||
PyObject* instance::gt(PyObject* other)
|
||||
{
|
||||
return callback<PyObject*>::call_method(this, "__gt__", other);
|
||||
}
|
||||
|
||||
PyObject* instance::ge(PyObject* other)
|
||||
{
|
||||
return callback<PyObject*>::call_method(this, "__ge__", other);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct named_capability
|
||||
{
|
||||
@@ -747,6 +777,12 @@ namespace {
|
||||
{
|
||||
{ "__hash__", detail::type_object_base::hash },
|
||||
{ "__cmp__", detail::type_object_base::compare },
|
||||
{ "__gt__", detail::type_object_base::richcompare },
|
||||
{ "__ge__", detail::type_object_base::richcompare },
|
||||
{ "__lt__", detail::type_object_base::richcompare },
|
||||
{ "__le__", detail::type_object_base::richcompare },
|
||||
{ "__eq__", detail::type_object_base::richcompare },
|
||||
{ "__ne__", detail::type_object_base::richcompare },
|
||||
{ "__repr__", detail::type_object_base::repr },
|
||||
{ "__str__", detail::type_object_base::str },
|
||||
{ "__call__", detail::type_object_base::call },
|
||||
|
||||
@@ -15,6 +15,7 @@ def gen_extclass(args):
|
||||
// gen_extclass.python
|
||||
|
||||
// Revision History:
|
||||
// 17 Apr 01 Comment added with reference to cross_module.hpp (R.W. Grosse-Kunstleve)
|
||||
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
|
||||
// to_python (Dave Abrahams)
|
||||
|
||||
@@ -171,6 +172,14 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
// and U. T is the class the user really intends to wrap. U is a class derived
|
||||
// from T with some virtual function overriding boilerplate, or if there are no
|
||||
// virtual functions, U = held_instance<T>.
|
||||
//
|
||||
// A look-alike of this class in root/boost/python/cross_module.hpp
|
||||
// is used for the implementation of the cross-module support
|
||||
// (export_converters and import_converters). If from_python
|
||||
// and to_python converters are added or removed from the class
|
||||
// below, the class python_import_extension_class_converters has
|
||||
// to be modified accordingly.
|
||||
//
|
||||
template <class T, class U = boost::python::detail::held_instance<T> >
|
||||
class python_extension_class_converters
|
||||
{
|
||||
@@ -607,6 +616,12 @@ class extension_class
|
||||
choose_op<(which & op_and)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_xor)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_gt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ne)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
|
||||
@@ -636,6 +651,12 @@ class extension_class
|
||||
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_gt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ne)>::template args<Left,Right>::add(this);
|
||||
}
|
||||
|
||||
template <long which, class Left, class Right>
|
||||
|
||||
@@ -79,7 +79,8 @@ namespace detail {
|
||||
struct parameter_traits
|
||||
{
|
||||
private:
|
||||
typedef const_ref_selector<boost::is_reference<T>::value> selector;
|
||||
enum { is_ref = boost::is_reference<T>::value };
|
||||
typedef const_ref_selector<is_ref> selector;
|
||||
public:
|
||||
typedef typename selector::template const_ref<T>::type const_reference;
|
||||
};
|
||||
|
||||
@@ -159,6 +159,28 @@ static PyObject* do_instance_repr(PyObject* obj)
|
||||
return call(obj, &type_object_base::instance_repr);
|
||||
}
|
||||
|
||||
static PyObject* do_instance_richcompare(PyObject* obj, PyObject* other, int d)
|
||||
{
|
||||
#if PYTHON_API_VERSION >= 1010
|
||||
switch(d)
|
||||
{
|
||||
case Py_LT:
|
||||
return call(obj, &type_object_base::instance_lt, other);
|
||||
case Py_LE:
|
||||
return call(obj, &type_object_base::instance_le, other);
|
||||
case Py_EQ:
|
||||
return call(obj, &type_object_base::instance_eq, other);
|
||||
case Py_NE:
|
||||
return call(obj, &type_object_base::instance_ne, other);
|
||||
case Py_GT:
|
||||
return call(obj, &type_object_base::instance_gt, other);
|
||||
case Py_GE:
|
||||
return call(obj, &type_object_base::instance_ge, other);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_instance_compare(PyObject* obj, PyObject* other)
|
||||
{
|
||||
return call(obj, &type_object_base::instance_compare, other);
|
||||
@@ -406,7 +428,7 @@ namespace
|
||||
bool add_capability_general(type_object_base::capability capability, PyTypeObject* dest)
|
||||
{
|
||||
assert(dest != 0);
|
||||
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
ENABLE_GENERAL_CAPABILITY(hash);
|
||||
@@ -435,6 +457,20 @@ void create_method_table_if_null(T*& table)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
dest->tp_richcompare = &do_instance_richcompare;
|
||||
dest->tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define ENABLE_MAPPING_CAPABILITY(field) \
|
||||
case type_object_base::mapping_##field: \
|
||||
create_method_table_if_null(dest); \
|
||||
@@ -548,6 +584,8 @@ namespace detail {
|
||||
{
|
||||
if(add_capability_general(capability, dest_))
|
||||
return;
|
||||
if(add_capability_richcompare(capability, dest_))
|
||||
return;
|
||||
if(add_capability_mapping(capability, dest_->tp_as_mapping))
|
||||
return;
|
||||
if(add_capability_sequence(capability, dest_->tp_as_sequence))
|
||||
@@ -975,6 +1013,36 @@ PyObject* type_object_base::instance_number_hex(PyObject*) const
|
||||
return unimplemented("instance_number_hex");
|
||||
}
|
||||
|
||||
PyObject* type_object_base::instance_lt(PyObject*, PyObject*) const
|
||||
{
|
||||
return unimplemented("instance_lt");
|
||||
}
|
||||
|
||||
PyObject* type_object_base::instance_le(PyObject*, PyObject*) const
|
||||
{
|
||||
return unimplemented("instance_le");
|
||||
}
|
||||
|
||||
PyObject* type_object_base::instance_eq(PyObject*, PyObject*) const
|
||||
{
|
||||
return unimplemented("instance_eq");
|
||||
}
|
||||
|
||||
PyObject* type_object_base::instance_ne(PyObject*, PyObject*) const
|
||||
{
|
||||
return unimplemented("instance_ne");
|
||||
}
|
||||
|
||||
PyObject* type_object_base::instance_gt(PyObject*, PyObject*) const
|
||||
{
|
||||
return unimplemented("instance_gt");
|
||||
}
|
||||
|
||||
PyObject* type_object_base::instance_ge(PyObject*, PyObject*) const
|
||||
{
|
||||
return unimplemented("instance_ge");
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#ifdef TYPE_OBJECT_BASE_STANDALONE_TEST
|
||||
|
||||
@@ -19,10 +19,13 @@ Load up the extension module
|
||||
Automatic checking of the number and type of arguments. Foo's constructor takes
|
||||
a single long parameter.
|
||||
|
||||
>>> ext = Foo()
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
TypeError: function requires exactly 1 argument; 0 given
|
||||
>>> try:
|
||||
... ext = Foo()
|
||||
... except TypeError, err:
|
||||
... assert re.match(r'function .* exactly 1 argument;? \(?0 given\)?',
|
||||
... str(err))
|
||||
... else:
|
||||
... print 'no exception'
|
||||
|
||||
>>> try: ext = Foo('foo')
|
||||
... except TypeError, err:
|
||||
@@ -419,7 +422,7 @@ Some simple overloading tests:
|
||||
>>> try: r = Range('yikes')
|
||||
... except TypeError, e:
|
||||
... assert re.match(
|
||||
... 'No overloaded functions match [(]Range, string[)]\. Candidates are:\n.*\n.*',
|
||||
... 'No overloaded functions match [(]Range, str[a-z]*[)]\. Candidates are:\n.*\n.*',
|
||||
... str(e))
|
||||
... else: print 'no exception'
|
||||
|
||||
@@ -629,7 +632,7 @@ Testing overloaded free functions
|
||||
15
|
||||
>>> try: overloaded(1, 'foo')
|
||||
... except TypeError, err:
|
||||
... assert re.match("No overloaded functions match \(int, string\)\. Candidates are:",
|
||||
... assert re.match("No overloaded functions match \(int, str[a-z]*\)\. Candidates are:",
|
||||
... str(err))
|
||||
... else:
|
||||
... print 'no exception'
|
||||
@@ -659,7 +662,7 @@ Testing overloaded constructors
|
||||
5
|
||||
>>> try: over = OverloadTest(1, 'foo')
|
||||
... except TypeError, err:
|
||||
... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:",
|
||||
... assert re.match("No overloaded functions match \(OverloadTest, int, str[a-z]*\)\. Candidates are:",
|
||||
... str(err))
|
||||
... else:
|
||||
... print 'no exception'
|
||||
@@ -681,7 +684,7 @@ Testing overloaded methods
|
||||
5
|
||||
>>> try: over.overloaded(1,'foo')
|
||||
... except TypeError, err:
|
||||
... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:",
|
||||
... assert re.match("No overloaded functions match \(OverloadTest, int, str[a-z]*\)\. Candidates are:",
|
||||
... str(err))
|
||||
... else:
|
||||
... print 'no exception'
|
||||
@@ -1014,9 +1017,12 @@ test inheritB2
|
||||
-2
|
||||
>>> str(i)
|
||||
'2'
|
||||
>>> j = i/i
|
||||
Traceback (innermost last):
|
||||
TypeError: bad operand type(s) for /
|
||||
>>> try: j = i/i
|
||||
... except TypeError, err:
|
||||
... assert re.match(r'(bad|unsupported) operand type\(s\) for /',
|
||||
... str(err))
|
||||
... else: print 'no exception'
|
||||
|
||||
>>> j = abs(i)
|
||||
Traceback (innermost last):
|
||||
TypeError: bad operand type for abs()
|
||||
|
||||
Reference in New Issue
Block a user