diff --git a/Jamfile b/Jamfile deleted file mode 100644 index d5a9e729..00000000 --- a/Jamfile +++ /dev/null @@ -1,43 +0,0 @@ -subproject libs/python ; - -# bring in the rules for python -SEARCH on python.jam = $(BOOST_BUILD_PATH) ; -include python.jam ; - -local bpl-linkflags ; - -if $(UNIX) && ( $(OS) = AIX ) -{ - bpl-linkflags = "-e initlibbpl" ; -} - -dll bpl - : - src/list.cpp - src/long.cpp - src/dict.cpp - src/tuple.cpp - src/str.cpp - - src/aix_init_module.cpp - src/converter/from_python.cpp - src/converter/registry.cpp - src/converter/type_id.cpp - src/object/enum.cpp - src/object/class.cpp - src/object/function.cpp - src/object/inheritance.cpp - src/object/life_support.cpp - src/object/pickle_support.cpp - src/errors.cpp - src/module.cpp - src/converter/builtin_converters.cpp - src/converter/arg_to_python_base.cpp - src/object/iterator.cpp - src/object_protocol.cpp - src/object_operators.cpp - : - $(BOOST_PYTHON_V2_PROPERTIES) - BOOST_PYTHON_SOURCE - $(bpl-linkflags) - ; diff --git a/build/Jamfile b/build/Jamfile deleted file mode 100644 index 2b583d17..00000000 --- a/build/Jamfile +++ /dev/null @@ -1,169 +0,0 @@ -# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -# distribute this software is granted provided this copyright notice appears -# in all copies. This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. -# -# Boost.Python build and test Jamfile -# -# To run all tests quietly: jam test -# To run all tests with verbose output: jam -sPYTHON_TEST_ARGS=-v test -# -# Declares the following targets: -# 1. libboost_python.dll/.so, a dynamic library to be linked with all -# Boost.Python modules -# -# 2. pairs of test targets of the form .test and .run -# .test runs the test when it is out-of-date, and the "test" -# pseudotarget depends on it. .run runs -# a test unconditionally, and can be used to force a test to run.. Each -# test target builds one or more Boost.Python modules and runs a Python -# script to test them. The test names are: -# -# from ../test -# -# comprehensive - a comprehensive test of Boost.Python features -# -# from ../example: -# abstract - -# getting_started1 - -# getting_started2 - -# simple_vector - -# do_it_yourself_convts - -# pickle1 - -# pickle2 - -# pickle3 - -# -# dvect1 - -# dvect2 - -# ivect1 - -# ivect2 - -# noncopyable - -# -# subproject-specific environment/command-line variables: -# -# PYTHON - How to invoke the Python interpreter. Defaults to "python" -# -# PYTHON_ROOT - Windows only: where Python is installed. Defaults to "c:/tools/python" -# -# PYTHON_VERSION - Version of Python. Defaults to "2.1" on Windows, "1.5" on Unix -# -# PYTHON_TEST_ARGS - specifies arguments to be passed to test scripts on -# the command line. "-v" can be useful if you want to -# see the output of successful tests. -# -# PYTHON_VECT_ITERATIONS - specifies the number of test iterations to use for -# the dvect and ivect tests above. - -# declare the location of this subproject relative to the root -subproject libs/python/build ; - -# bring in the rules for python -SEARCH on python.jam = $(BOOST_BUILD_PATH) ; -include python.jam ; - -if [ check-python-config ] -{ - -local PYTHON_PROPERTIES = $(PYTHON_PROPERTIES) BOOST_PYTHON_DYNAMIC_LIB ; - -####################### -rule bpl-test ( test-name : sources + ) -{ - boost-python-test $(test-name) : $(sources) boost_python ; -} - -####################### - -# -# Declare the boost python static link library -# - -# Base names of the source files for libboost_python -local CPP_SOURCES = - types classes conversions extension_class functions - init_function module_builder objects cross_module errors - ; - -lib boost_python_static : ../src/$(CPP_SOURCES).cpp - # requirements - : $(BOOST_PYTHON_INCLUDES) - true - BOOST_PYTHON_STATIC_LIB=1 - [ difference $(PYTHON_PROPERTIES) : BOOST_PYTHON_DYNAMIC_LIB ] - : true # don't build this unless the user asks for it by name - ; - -dll boost_python - # $(SUFDLL[1]) - : ../src/$(CPP_SOURCES).cpp - # requirements - : $(BOOST_PYTHON_INCLUDES) - true - dynamic - $(PYTHON_PROPERTIES) - ; - -stage bin-stage : boost_python - : - "_debug" - "_pydebug" - : - debug release - ; - -############# comprehensive module and test ########### -bpl-test boost_python_test - : ../test/comprehensive.cpp ; - -boost-python-runtest comprehensive - : ../test/comprehensive.py boost_python_test boost_python ; - -############# simple tests from ../example ############ - -rule boost-python-example-runtest ( name ) -{ - bpl-test $(name) - : ../example/$(name).cpp ; - - boost-python-runtest $(name) - : ../example/test_$(name).py $(name) boost_python ; -} - - -boost-python-example-runtest abstract ; -boost-python-example-runtest getting_started1 ; -boost-python-example-runtest getting_started2 ; -boost-python-example-runtest simple_vector ; -boost-python-example-runtest do_it_yourself_convts ; -boost-python-example-runtest pickle1 ; -boost-python-example-runtest pickle2 ; -boost-python-example-runtest pickle3 ; - - -bpl-test ivect : ../example/ivect.cpp ; -bpl-test dvect : ../example/dvect.cpp ; -bpl-test noncopyable_export : ../example/noncopyable_export.cpp ; -bpl-test noncopyable_import : ../example/noncopyable_import.cpp ; - -############## cross-module tests from ../example ########## - -# A simple rule to build a test which depends on multiple modules in the PYTHONPATH -rule boost-python-multi-example-runtest ( test-name : modules + ) -{ - boost-python-runtest $(test-name) - : ../example/tst_$(test-name).py $(modules) boost_python - : : : $(PYTHON_VECT_ITERATIONS) ; -} - -PYTHON_VECT_ITERATIONS ?= 10 ; - -boost-python-multi-example-runtest dvect1 : ivect dvect ; -boost-python-multi-example-runtest dvect2 : ivect dvect ; - -boost-python-multi-example-runtest ivect1 : ivect dvect ; -boost-python-multi-example-runtest ivect2 : ivect dvect ; - -boost-python-multi-example-runtest - noncopyable : noncopyable_import noncopyable_export ; - -} \ No newline at end of file diff --git a/build/como.mak b/build/como.mak deleted file mode 100644 index edf05f83..00000000 --- a/build/como.mak +++ /dev/null @@ -1,59 +0,0 @@ -# Revision History: -# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve) UNTESTED! -# 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams) -# 04 Mar 01 Changed library name to libboost_python.a (David Abrahams) - -LIBSRC = \ - classes.cpp \ - conversions.cpp \ - cross_module.cpp \ - errors.cpp \ - extension_class.cpp \ - functions.cpp \ - init_function.cpp \ - module_builder.cpp \ - objects.cpp \ - types.cpp - -LIBOBJ = $(LIBSRC:.cpp=.o) -OBJ = $(LIBOBJ) - - -ifeq "$(OS)" "Windows_NT" -PYTHON_LIB=c:/tools/python/libs/python15.lib -INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -Ic:/tools/python/include -MODULE_EXTENSION=dll -else -INC = -I/usr/local/include/python1.5 -MODULE_EXTENSION=so -endif - -%.o: ../src/%.cpp - como --pic $(INC) -o $*.o -c $< - -%.d: ../src/%.cpp - @echo creating $@ - @set -e; como -M $(INC) -c $< \ - | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \ - [ -s $@ ] || rm -f $@ - -getting_started1: getting_started1.o libboost_python.a - como-dyn-link -o ../example/getting_started1.$(MODULE_EXTENSION) $(PYTHON_LIB) getting_started1.o -L. -lboost_python - ln -s ../test/doctest.py ../example - python ../example/test_getting_started1.py - -getting_started1.o: ../example/getting_started1.cpp - como --pic $(INC) -o $*.o -c $< - -clean: - rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out - -libboost_python.a: $(LIBOBJ) - rm -f libboost_python.a - ar cq libboost_python.a $(LIBOBJ) - -DEP = $(OBJ:.o=.d) - -ifneq "$(MAKECMDGOALS)" "clean" -include $(DEP) -endif diff --git a/build/filemgr.py b/build/filemgr.py deleted file mode 100644 index 93cef1cb..00000000 --- a/build/filemgr.py +++ /dev/null @@ -1,146 +0,0 @@ -# Revision history: -# 12 Apr 01 use os.path, shutil -# Initial version: R.W. Grosse-Kunstleve - -bpl_src = "/libs/python/src" -bpl_tst = "/libs/python/test" -bpl_exa = "/libs/python/example" -files = ( -bpl_src + "/classes.cpp", -bpl_src + "/conversions.cpp", -bpl_src + "/errors.cpp", -bpl_src + "/extension_class.cpp", -bpl_src + "/functions.cpp", -bpl_src + "/init_function.cpp", -bpl_src + "/module_builder.cpp", -bpl_src + "/objects.cpp", -bpl_src + "/types.cpp", -bpl_src + "/cross_module.cpp", -bpl_tst + "/comprehensive.cpp", -bpl_tst + "/comprehensive.hpp", -bpl_tst + "/comprehensive.py", -bpl_tst + "/doctest.py", -bpl_exa + "/abstract.cpp", -bpl_exa + "/getting_started1.cpp", -bpl_exa + "/getting_started2.cpp", -bpl_exa + "/simple_vector.cpp", -bpl_exa + "/do_it_yourself_convts.cpp", -bpl_exa + "/nested.cpp", -bpl_exa + "/pickle1.cpp", -bpl_exa + "/pickle2.cpp", -bpl_exa + "/pickle3.cpp", -bpl_exa + "/test_abstract.py", -bpl_exa + "/test_getting_started1.py", -bpl_exa + "/test_getting_started2.py", -bpl_exa + "/test_simple_vector.py", -bpl_exa + "/test_do_it_yourself_convts.py", -bpl_exa + "/test_nested.py", -bpl_exa + "/test_pickle1.py", -bpl_exa + "/test_pickle2.py", -bpl_exa + "/test_pickle3.py", -bpl_exa + "/noncopyable.h", -bpl_exa + "/noncopyable_export.cpp", -bpl_exa + "/noncopyable_import.cpp", -bpl_exa + "/dvect.h", -bpl_exa + "/dvect.cpp", -bpl_exa + "/dvect_conversions.cpp", -bpl_exa + "/dvect_defs.cpp", -bpl_exa + "/ivect.h", -bpl_exa + "/ivect.cpp", -bpl_exa + "/ivect_conversions.cpp", -bpl_exa + "/ivect_defs.cpp", -bpl_exa + "/tst_noncopyable.py", -bpl_exa + "/tst_dvect1.py", -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 = ( -"boost_python_test", -"abstract", -"getting_started1", -"getting_started2", -"simple_vector", -"do_it_yourself_convts", -"nested", -"pickle1", -"pickle2", -"pickle3", -"noncopyable_export", -"noncopyable_import", -"ivect", -"dvect", -"richcmp1", -"richcmp2", -"richcmp3", -) - -if (__name__ == "__main__"): - - import sys, os, shutil - - path = sys.argv[1] - mode = sys.argv[2] - if (not mode in ("softlinks", "unlink", "cp", "rm", "copy", "del")): - raise RuntimeError, \ - "usage: python filemgr.py path " - - if (mode in ("cp", "copy")): - for fn in files: - f = os.path.basename(fn) - print "Copying: " + f - shutil.copy(path + fn, ".") - - elif (mode == "softlinks"): - for fn in files: - f = os.path.basename(fn) - if (os.path.exists(f)): - print "File exists: " + f - else: - print "Linking: " + f - os.symlink(path + fn, f) - - elif (mode in ("rm", "del")): - for fn in files: - f = os.path.basename(fn) - if (os.path.exists(f)): - print "Removing: " + f - try: os.unlink(f) - except: pass - - elif (mode == "unlink"): - for fn in files: - f = os.path.basename(fn) - if (os.path.exists(f)): - if (os.path.islink(f)): - print "Unlinking: " + f - try: os.unlink(f) - except: pass - else: - print "Not a softlink: " + f - - if (mode in ("softlinks", "cp", "copy")): - for d in defs: - fn = d + ".def" - print "Creating: " + fn - f = open(fn, "w") - f.write("EXPORTS\n") - f.write("\tinit" + d + "\n") - f.close() - - if (mode in ("unlink", "rm", "del")): - for d in defs: - fn = d + ".def" - if (os.path.exists(fn)): - print "Removing: " + fn - try: os.unlink(fn) - except: pass diff --git a/build/gcc.mak b/build/gcc.mak deleted file mode 100644 index b818030e..00000000 --- a/build/gcc.mak +++ /dev/null @@ -1,88 +0,0 @@ -# Revision History - -# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve) -# 17 Apr 01 build shared library (patch provided by Dan Nuffer) -# 04 Mar 01 Changed library name to libboost_python.a, various cleanups, -# attempted Cygwin compatibility. Still needs testing on Linux -# (David Abrahams) - - -LIBSRC = \ - classes.cpp \ - conversions.cpp \ - cross_module.cpp \ - errors.cpp \ - extension_class.cpp \ - functions.cpp \ - init_function.cpp \ - module_builder.cpp \ - objects.cpp \ - types.cpp - -LIBOBJ = $(LIBSRC:.cpp=.o) -OBJ = $(LIBOBJ) - -LIBNAME = libboost_python -# libpython2.0.dll - -ifeq "$(OS)" "Windows_NT" -ROOT=c:/cygnus -INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -I$(PYTHON_INC) -MODULE_EXTENSION=dll -PYTHON_LIB=c:/cygnus/usr/local/lib/python2.0/config/libpython2.0.dll.a -SHARED_LIB = $(LIBNAME).dll -else -PYTHON_INC=$(ROOT)/usr/local/Python-2.0/include/python2.0 -BOOST_INC=../../.. -INC = -I$(BOOST_INC) -I$(PYTHON_INC) -MODULE_EXTENSION=so -VERSION=1 -SHARED_LIB = $(LIBNAME).so.$(VERSION) -endif - -%.o: ../src/%.cpp - g++ -fPIC -Wall -W $(INC) $(CXXFLAGS) -o $*.o -c $< - -%.d: ../src/%.cpp - @echo creating $@ - @set -e; g++ -M $(INC) -c $< \ - | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \ - [ -s $@ ] || rm -f $@ - - -PYTHON = python - -all: test $(SHARED_LIB) getting_started1 - -test: comprehensive.o $(LIBNAME).a $(SHARED_LIB) - g++ $(CXXFLAGS) -shared -o ../test/boost_python_test.$(MODULE_EXTENSION) comprehensive.o -L. -lboost_python $(PYTHON_LIB) - $(PYTHON) ../test/comprehensive.py - -comprehensive.o: ../test/comprehensive.cpp - g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $< - - -getting_started1: getting_started1.o $(LIBNAME).a - g++ $(CXXFLAGS) -shared -o ../example/getting_started1.$(MODULE_EXTENSION) getting_started1.o -L. -lboost_python $(PYTHON_LIB) - ln -s ../test/doctest.py ../example - $(PYTHON) ../example/test_getting_started1.py - -getting_started1.o: ../example/getting_started1.cpp - g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $< - - -clean: - rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out - -$(LIBNAME).a: $(LIBOBJ) - rm -f $@ - ar cqs $@ $(LIBOBJ) - -$(SHARED_LIB): $(LIBOBJ) - g++ $(CXXFLAGS) -shared -o $@ -Wl,--soname=$(LIBNAME).$(MODULE_EXTENSION) - -DEP = $(OBJ:.o=.d) - -ifneq "$(MAKECMDGOALS)" "clean" -include $(DEP) -endif diff --git a/build/irix_CC.mak b/build/irix_CC.mak deleted file mode 100644 index f7d6004e..00000000 --- a/build/irix_CC.mak +++ /dev/null @@ -1,184 +0,0 @@ -# Usage: -# -# Create a new empty directory anywhere (preferably not in the boost tree). -# Copy this Makefile to that new directory and rename it to "Makefile" -# Adjust the pathnames below. -# -# make softlinks Create softlinks to source code and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make unlink Remove softlinks -# -# Revision history: -# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) -# Initial version: R.W. Grosse-Kunstleve - -ROOT=$(HOME) -BOOST=$(ROOT)/boost - -#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python -#PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python -PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1 -STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers - -STDOPTS= -WARNOPTS=-woff 1001,1234,1682 -OPTOPTS=-g - -CPP=CC -LANG:std -n32 -mips4 -CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) $(OPTOPTS) -MAKEDEP=-M - -LD=CC -LANG:std -n32 -mips4 -LDOPTS=-shared - -OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o cross_module.o -DEPOBJ=$(OBJ) \ - comprehensive.o \ - abstract.o \ - getting_started1.o getting_started2.o \ - simple_vector.o \ - do_it_yourself_convts.o \ - nested.o \ - pickle1.o pickle2.o pickle3.o \ - noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o \ - richcmp1.o richcmp2.o richcmp3.o - -.SUFFIXES: .o .cpp - -all: libboost_python.a \ - boost_python_test.so \ - abstract.so \ - getting_started1.so getting_started2.so \ - simple_vector.so \ - do_it_yourself_convts.so \ - nested.so \ - pickle1.so pickle2.so pickle3.so \ - noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so \ - richcmp1.so richcmp2.so richcmp3.so - -libboost_python.a: $(OBJ) - rm -f libboost_python.a - $(CPP) -ar -o libboost_python.a $(OBJ) - -boost_python_test.so: $(OBJ) comprehensive.o - $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm - -abstract.so: $(OBJ) abstract.o - $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so - -getting_started1.so: $(OBJ) getting_started1.o - $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so - -getting_started2.so: $(OBJ) getting_started2.o - $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so - -simple_vector.so: $(OBJ) simple_vector.o - $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so - -do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so - -nested.so: $(OBJ) nested.o - $(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so - -pickle1.so: $(OBJ) pickle1.o - $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so - -pickle2.so: $(OBJ) pickle2.o - $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so - -pickle3.so: $(OBJ) pickle3.o - $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so - -noncopyable_export.so: $(OBJ) noncopyable_export.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_export.o -o noncopyable_export.so - -noncopyable_import.so: $(OBJ) noncopyable_import.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_import.o -o noncopyable_import.so - -ivect.so: $(OBJ) ivect.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so - -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 - -test: - $(PYEXE) comprehensive.py - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_convts.py - $(PYEXE) test_nested.py - $(PYEXE) test_pickle1.py - $(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 - rm -f comprehensive.o boost_python_test.so - rm -f abstract.o abstract.so - rm -f getting_started1.o getting_started1.so - rm -f getting_started2.o getting_started2.so - rm -f simple_vector.o simple_vector.so - rm -f do_it_yourself_convts.o do_it_yourself_convts.so - rm -f nested.o nested.so - rm -f pickle1.o pickle1.so - rm -f pickle2.o pickle2.so - rm -f pickle3.o pickle3.so - rm -f noncopyable_export.o noncopyable_export.so - 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 - -softlinks: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks - -unlink: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink - -cp: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp - -rm: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm - -depend: - @ cat Makefile.nodepend; \ - for obj in $(DEPOBJ); \ - do \ - bn=`echo "$$obj" | cut -d. -f1`; \ - $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ - done - diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak deleted file mode 100644 index 3b466e7d..00000000 --- a/build/linux_gcc.mak +++ /dev/null @@ -1,184 +0,0 @@ -# Usage: -# -# Create a new empty directory anywhere (preferably not in the boost tree). -# Copy this Makefile to that new directory and rename it to "Makefile" -# Adjust the pathnames below. -# -# make softlinks Create softlinks to source code and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make unlink Remove softlinks -# -# Revision history: -# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) -# Initial version: R.W. Grosse-Kunstleve - -ROOT=$(HOME) -BOOST=$(ROOT)/boost - -#PYEXE=PYTHONPATH=. /usr/bin/python -#PYINC=-I/usr/include/python1.5 -#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python -#PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python -PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1 - -STDOPTS=-fPIC -ftemplate-depth-21 -WARNOPTS= -OPTOPTS=-g - -CPP=g++ -CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) $(OPTOPTS) -MAKEDEP=-M - -LD=$(CPP) -LDOPTS=-shared - -OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o cross_module.o -DEPOBJ=$(OBJ) \ - comprehensive.o \ - abstract.o \ - getting_started1.o getting_started2.o \ - simple_vector.o \ - do_it_yourself_convts.o \ - nested.o \ - pickle1.o pickle2.o pickle3.o \ - noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o \ - richcmp1.o richcmp2.o richcmp3.o - -.SUFFIXES: .o .cpp - -all: libboost_python.a \ - boost_python_test.so \ - abstract.so \ - getting_started1.so getting_started2.so \ - simple_vector.so \ - do_it_yourself_convts.so \ - nested.so \ - pickle1.so pickle2.so pickle3.so \ - noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so \ - richcmp1.so richcmp2.so richcmp3.so - -libboost_python.a: $(OBJ) - rm -f libboost_python.a - ar r libboost_python.a $(OBJ) - -boost_python_test.so: $(OBJ) comprehensive.o - $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm - -abstract.so: $(OBJ) abstract.o - $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so - -getting_started1.so: $(OBJ) getting_started1.o - $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so - -getting_started2.so: $(OBJ) getting_started2.o - $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so - -simple_vector.so: $(OBJ) simple_vector.o - $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so - -do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so - -nested.so: $(OBJ) nested.o - $(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so - -pickle1.so: $(OBJ) pickle1.o - $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so - -pickle2.so: $(OBJ) pickle2.o - $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so - -pickle3.so: $(OBJ) pickle3.o - $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so - -noncopyable_export.so: $(OBJ) noncopyable_export.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_export.o -o noncopyable_export.so - -noncopyable_import.so: $(OBJ) noncopyable_import.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_import.o -o noncopyable_import.so - -ivect.so: $(OBJ) ivect.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so - -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 - -test: - $(PYEXE) comprehensive.py - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_convts.py - $(PYEXE) test_nested.py - $(PYEXE) test_pickle1.py - $(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 - rm -f comprehensive.o boost_python_test.so - rm -f abstract.o abstract.so - rm -f getting_started1.o getting_started1.so - rm -f getting_started2.o getting_started2.so - rm -f simple_vector.o simple_vector.so - rm -f do_it_yourself_convts.o do_it_yourself_convts.so - rm -f nested.o nested.so - rm -f pickle1.o pickle1.so - rm -f pickle2.o pickle2.so - rm -f pickle3.o pickle3.so - rm -f noncopyable_export.o noncopyable_export.so - 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: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks - -unlink: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink - -cp: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp - -rm: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm - -depend: - @ cat Makefile.nodepend; \ - for obj in $(DEPOBJ); \ - do \ - bn=`echo "$$obj" | cut -d. -f1`; \ - $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ - done - diff --git a/build/mingw32.mak b/build/mingw32.mak deleted file mode 100644 index d8c31b68..00000000 --- a/build/mingw32.mak +++ /dev/null @@ -1,222 +0,0 @@ -# Usage: -# -# make copy Copy the sources and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make del Remove the sources and tests -# -# Revision history: -# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) -# Initial version: R.W. Grosse-Kunstleve - -# To install mingw32, follow instructions at: -# http://starship.python.net/crew/kernr/mingw32/Notes.html -# In particular, install: -# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/gcc-2.95.2-msvcrt.exe -# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/fixes/quote-fix-msvcrt.exe -# http://starship.python.net/crew/kernr/mingw32/Python-1.5.2-mingw32.zip -# Unpack the first two archives in the default locations and update your PATH. -# Unpack the third archive in \usr. - -# Note: comprehensive.cpp generates compiler errors and later crashes. -# L:\boost\boost\python\detail\extension_class.hpp:643: warning: -# alignment of `vtable for class -# boost::python::detail::held_instance' -# is greater than maximum object file alignment. Using 16. -# Could this be fixed with compiler options? -# -fhuge-objects looks interesting, but requires recompiling the C++ library. -# (what exactly does that mean?) -# -fvtable-thunks eliminates the compiler warning, but -# "import boost_python_test" still causes a crash. - -ROOT=R: -BOOST_WIN="$(ROOT)\boost" -BOOST_UNIX=$(HOME)/boost - -PYEXE="C:\Program files\Python\python.exe" -PYINC=-I"C:\usr\include\python1.5" -PYLIB="C:\usr\lib\libpython15.a" -#PYEXE="C:\Python21\python.exe" -#PYINC=-I"C:\usr\include\python2.1" -#PYLIB="C:\usr\lib\libpython21.a" - -STDOPTS=-ftemplate-depth-21 -WARNOPTS= -OPTOPTS=-g - -CPP=g++ -CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) $(OPTOPTS) - -LD=g++ -LDOPTS=-shared - -OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o cross_module.o - -.SUFFIXES: .o .cpp - -all: libboost_python.a \ - abstract.pyd \ - getting_started1.pyd getting_started2.pyd \ - simple_vector.pyd \ - do_it_yourself_convts.pyd \ - nested.pyd \ - pickle1.pyd pickle2.pyd pickle3.pyd \ - noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd \ - richcmp1.pyd richcmp2.pyd richcmp3.pyd - -libboost_python.a: $(OBJ) - -del libboost_python.a - ar r libboost_python.a $(OBJ) - -DLLWRAPOPTS=-s --driver-name g++ -s \ - --entry _DllMainCRTStartup@12 --target=i386-mingw32 - -boost_python_test.pyd: $(OBJ) comprehensive.o - dllwrap $(DLLWRAPOPTS) \ - --dllname boost_python_test.pyd \ - --def boost_python_test.def \ - $(OBJ) comprehensive.o $(PYLIB) - -abstract.pyd: $(OBJ) abstract.o - dllwrap $(DLLWRAPOPTS) \ - --dllname abstract.pyd \ - --def abstract.def \ - $(OBJ) abstract.o $(PYLIB) - -getting_started1.pyd: $(OBJ) getting_started1.o - dllwrap $(DLLWRAPOPTS) \ - --dllname getting_started1.pyd \ - --def getting_started1.def \ - $(OBJ) getting_started1.o $(PYLIB) - -getting_started2.pyd: $(OBJ) getting_started2.o - dllwrap $(DLLWRAPOPTS) \ - --dllname getting_started2.pyd \ - --def getting_started2.def \ - $(OBJ) getting_started2.o $(PYLIB) - -simple_vector.pyd: $(OBJ) simple_vector.o - dllwrap $(DLLWRAPOPTS) \ - --dllname simple_vector.pyd \ - --def simple_vector.def \ - $(OBJ) simple_vector.o $(PYLIB) - -do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.o - dllwrap $(DLLWRAPOPTS) \ - --dllname do_it_yourself_convts.pyd \ - --def do_it_yourself_convts.def \ - $(OBJ) do_it_yourself_convts.o $(PYLIB) - -nested.pyd: $(OBJ) nested.o - dllwrap $(DLLWRAPOPTS) \ - --dllname nested.pyd \ - --def nested.def \ - $(OBJ) nested.o $(PYLIB) - -pickle1.pyd: $(OBJ) pickle1.o - dllwrap $(DLLWRAPOPTS) \ - --dllname pickle1.pyd \ - --def pickle1.def \ - $(OBJ) pickle1.o $(PYLIB) - -pickle2.pyd: $(OBJ) pickle2.o - dllwrap $(DLLWRAPOPTS) \ - --dllname pickle2.pyd \ - --def pickle2.def \ - $(OBJ) pickle2.o $(PYLIB) - -pickle3.pyd: $(OBJ) pickle3.o - dllwrap $(DLLWRAPOPTS) \ - --dllname pickle3.pyd \ - --def pickle3.def \ - $(OBJ) pickle3.o $(PYLIB) - -noncopyable_export.pyd: $(OBJ) noncopyable_export.o - dllwrap $(DLLWRAPOPTS) \ - --dllname noncopyable_export.pyd \ - --def noncopyable_export.def \ - $(OBJ) noncopyable_export.o $(PYLIB) - -noncopyable_import.pyd: $(OBJ) noncopyable_import.o - dllwrap $(DLLWRAPOPTS) \ - --dllname noncopyable_import.pyd \ - --def noncopyable_import.def \ - $(OBJ) noncopyable_import.o $(PYLIB) - -ivect.pyd: $(OBJ) ivect.o - dllwrap $(DLLWRAPOPTS) \ - --dllname ivect.pyd \ - --def ivect.def \ - $(OBJ) ivect.o $(PYLIB) - -dvect.pyd: $(OBJ) dvect.o - dllwrap $(DLLWRAPOPTS) \ - --dllname dvect.pyd \ - --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 - -test: -# $(PYEXE) comprehensive.py - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_convts.py - $(PYEXE) test_nested.py - $(PYEXE) test_pickle1.py - $(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 - -softlinks: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks - -unlink: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink - -cp: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp - -rm: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm - -copy: - $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy - -del: - $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak deleted file mode 100644 index a64927b1..00000000 --- a/build/tru64_cxx.mak +++ /dev/null @@ -1,199 +0,0 @@ -# Usage: -# -# Create a new empty directory anywhere (preferably not in the boost tree). -# Copy this Makefile to that new directory and rename it to "Makefile" -# Adjust the pathnames below. -# -# make softlinks Create softlinks to source code and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make unlink Remove softlinks -# -# Revision history: -# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) -# Initial version: R.W. Grosse-Kunstleve - -ROOT=$(HOME) -BOOST=$(ROOT)/boost - -#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python -#PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python -PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1 -#STLPORTINC=-I/usr/local/STLport-4.1b3/stlport -#STLPORTINC=-I/usr/local/STLport-4.1b4/stlport -#STLPORTOPTS= \ -# -D__USE_STD_IOSTREAM \ -# -D__STL_NO_SGI_IOSTREAMS \ -# -D__STL_USE_NATIVE_STRING \ -# -D__STL_NO_NEW_C_HEADERS \ -# -D_RWSTD_COMPILE_INSTANTIATE=1 -STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers - -STDOPTS=-std strict_ansi -# use -msg_display_number to obtain integer tags for -msg_disable -WARNOPTS=-msg_disable 186,450,1115 -OPTOPTS=-g - -CPP=cxx -CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) $(OPTOPTS) -MAKEDEP=-Em - -LD=cxx -LDOPTS=-shared -expect_unresolved 'Py*' -expect_unresolved '_Py*' - -#HIDDEN=-hidden - -OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o cross_module.o -DEPOBJ=$(OBJ) \ - comprehensive.o \ - abstract.o \ - getting_started1.o getting_started2.o \ - simple_vector.o \ - do_it_yourself_convts.o \ - nested.o \ - pickle1.o pickle2.o pickle3.o \ - noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o \ - richcmp1.o richcmp2.o richcmp3.o - -.SUFFIXES: .o .cpp - -all: libboost_python.a \ - boost_python_test.so \ - abstract.so \ - getting_started1.so getting_started2.so \ - simple_vector.so \ - do_it_yourself_convts.so \ - nested.so \ - pickle1.so pickle2.so pickle3.so \ - noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so \ - richcmp1.so richcmp2.so richcmp3.so - -libboost_python.a: $(OBJ) - rm -f libboost_python.a - cd cxx_repository; \ - ls -1 > ../libboost_python.a.input; \ - ar r ../libboost_python.a -input ../libboost_python.a.input - rm -f libboost_python.a.input - ar r libboost_python.a $(OBJ) - -boost_python_test.so: $(OBJ) comprehensive.o - $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm - -abstract.so: $(OBJ) abstract.o - $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so - -getting_started1.so: $(OBJ) getting_started1.o - $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so - -getting_started2.so: $(OBJ) getting_started2.o - $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so - -simple_vector.so: $(OBJ) simple_vector.o - $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so - -do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so - -nested.so: $(OBJ) nested.o - $(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so - -pickle1.so: $(OBJ) pickle1.o - $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so - -pickle2.so: $(OBJ) pickle2.o - $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so - -pickle3.so: $(OBJ) pickle3.o - $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so - -noncopyable_export.so: $(OBJ) noncopyable_export.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_export.o -o noncopyable_export.so - -noncopyable_import.so: $(OBJ) noncopyable_import.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_import.o -o noncopyable_import.so - -ivect.so: $(OBJ) ivect.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so - -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 - -test: - $(PYEXE) comprehensive.py - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_convts.py - $(PYEXE) test_nested.py - $(PYEXE) test_pickle1.py - $(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 - rm -f comprehensive.o boost_python_test.so - rm -f abstract.o abstract.so - rm -f getting_started1.o getting_started1.so - rm -f getting_started2.o getting_started2.so - rm -f simple_vector.o simple_vector.so - rm -f do_it_yourself_convts.o do_it_yourself_convts.so - rm -f nested.o nested.so - rm -f pickle1.o pickle1.so - rm -f pickle2.o pickle2.so - rm -f pickle3.o pickle3.so - rm -f noncopyable_export.o noncopyable_export.so - 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 - -softlinks: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks - -unlink: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink - -cp: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp - -rm: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm - -depend: - @ cat Makefile.nodepend; \ - for obj in $(DEPOBJ); \ - do \ - bn=`echo "$$obj" | cut -d. -f1`; \ - $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ - done - diff --git a/build/vc60.mak b/build/vc60.mak deleted file mode 100644 index 2903c0c7..00000000 --- a/build/vc60.mak +++ /dev/null @@ -1,154 +0,0 @@ -# Usage: -# -# Create a new empty directory anywhere (preferably not in the boost tree). -# Copy this Makefile to that new directory and rename it to "Makefile" -# Adjust the pathnames below. -# -# make copy Copy the sources and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make del Remove the sources and tests -# -# Revision history: -# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) -# Initial version: R.W. Grosse-Kunstleve - -ROOT=R: -BOOST_WIN="$(ROOT)\boost" -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 /Zm300 /DBOOST_PYTHON_STATIC_LIB -WARNOPTS= -OPTOPTS= - -CPP=cl.exe -CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) /I$(BOOST_WIN) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) $(OPTOPTS) - -LD=link.exe -LDOPTS=/nologo /dll /incremental:no - -OBJ=classes.obj conversions.obj errors.obj extension_class.obj functions.obj \ - init_function.obj module_builder.obj \ - objects.obj types.obj cross_module.obj - -.SUFFIXES: .obj .cpp - -all: boost_python.lib \ - boost_python_test.pyd \ - abstract.pyd \ - getting_started1.pyd getting_started2.pyd \ - simple_vector.pyd \ - do_it_yourself_convts.pyd \ - nested.pyd \ - pickle1.pyd pickle2.pyd pickle3.pyd \ - noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd \ - richcmp1.pyd richcmp2.pyd richcmp3.pyd - -boost_python.lib: $(OBJ) - $(LD) -lib /nologo /out:boost_python.lib $(OBJ) - -boost_python_test.pyd: $(OBJ) comprehensive.obj - $(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) /export:initboost_python_test /out:"boost_python_test.pyd" - -abstract.pyd: $(OBJ) abstract.obj - $(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) /export:initabstract /out:"abstract.pyd" - -getting_started1.pyd: $(OBJ) getting_started1.obj - $(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) /export:initgetting_started1 /out:"getting_started1.pyd" - -getting_started2.pyd: $(OBJ) getting_started2.obj - $(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) /export:initgetting_started2 /out:"getting_started2.pyd" - -simple_vector.pyd: $(OBJ) simple_vector.obj - $(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) /export:initsimple_vector /out:"simple_vector.pyd" - -do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.obj - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.obj $(PYLIB) /export:initdo_it_yourself_convts /out:"do_it_yourself_convts.pyd" - -nested.pyd: $(OBJ) nested.obj - $(LD) $(LDOPTS) $(OBJ) nested.obj $(PYLIB) /export:initnested /out:"nested.pyd" - -pickle1.pyd: $(OBJ) pickle1.obj - $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd" - -pickle2.pyd: $(OBJ) pickle2.obj - $(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) /export:initpickle2 /out:"pickle2.pyd" - -pickle3.pyd: $(OBJ) pickle3.obj - $(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) /export:initpickle3 /out:"pickle3.pyd" - -noncopyable_export.pyd: $(OBJ) noncopyable_export.obj - $(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) /export:initnoncopyable_export /out:"noncopyable_export.pyd" - -noncopyable_import.pyd: $(OBJ) noncopyable_import.obj - $(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) /export:initnoncopyable_import /out:"noncopyable_import.pyd" - -ivect.pyd: $(OBJ) ivect.obj - $(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) /export:initivect /out:"ivect.pyd" - -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 - -test: - $(PYEXE) comprehensive.py --broken-auto-ptr - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_convts.py - $(PYEXE) test_nested.py - $(PYEXE) test_pickle1.py - $(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 - -softlinks: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks - -unlink: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink - -cp: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp - -rm: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm - -copy: - $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy - -del: - $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del diff --git a/build/win32_mwcc.mak b/build/win32_mwcc.mak deleted file mode 100755 index c49af71c..00000000 --- a/build/win32_mwcc.mak +++ /dev/null @@ -1,149 +0,0 @@ -# Usage: -# -# make copy Copy the sources and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make del Remove the sources and tests -# -# Revision history: -# 14 Dec 01 derived from vc60.mak (R.W. Grosse-Kunstleve) - -ROOT=R: -BOOST_WIN="$(ROOT)\boost" -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=-gccinc -prefix UseDLLPrefix.h -DBOOST_PYTHON_STATIC_LIB -WARNOPTS=-warn on,nounusedexpr,nounused -OPTOPTS=-O - -CPP=mwcc -CPPOPTS=$(STDOPTS) $(WARNOPTS) $(OPTOPTS) \ - $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) - -LD=mwld -LDOPTS=-export dllexport -shared - -OBJ=classes.obj conversions.obj errors.obj extension_class.obj functions.obj \ - init_function.obj module_builder.obj \ - objects.obj types.obj cross_module.obj - -.SUFFIXES: .obj .cpp - -all: libboost_python.lib \ - boost_python_test.pyd \ - abstract.pyd \ - getting_started1.pyd getting_started2.pyd \ - simple_vector.pyd \ - do_it_yourself_convts.pyd \ - nested.pyd \ - pickle1.pyd pickle2.pyd pickle3.pyd \ - noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd \ - richcmp1.pyd richcmp2.pyd richcmp3.pyd - -libboost_python.lib: $(OBJ) - $(LD) -library -o libboost_python.lib $(OBJ) - -boost_python_test.pyd: $(OBJ) comprehensive.obj - $(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) -o boost_python_test.pyd - -abstract.pyd: $(OBJ) abstract.obj - $(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) -o abstract.pyd - -getting_started1.pyd: $(OBJ) getting_started1.obj - $(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) -o getting_started1.pyd - -getting_started2.pyd: $(OBJ) getting_started2.obj - $(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) -o getting_started2.pyd - -simple_vector.pyd: $(OBJ) simple_vector.obj - $(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) -o simple_vector.pyd - -do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.obj - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.obj $(PYLIB) -o do_it_yourself_convts.pyd - -nested.pyd: $(OBJ) nested.obj - $(LD) $(LDOPTS) $(OBJ) nested.obj $(PYLIB) -o nested.pyd - -pickle1.pyd: $(OBJ) pickle1.obj - $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) -o pickle1.pyd - -pickle2.pyd: $(OBJ) pickle2.obj - $(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) -o pickle2.pyd - -pickle3.pyd: $(OBJ) pickle3.obj - $(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) -o pickle3.pyd - -noncopyable_export.pyd: $(OBJ) noncopyable_export.obj - $(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) -o noncopyable_export.pyd - -noncopyable_import.pyd: $(OBJ) noncopyable_import.obj - $(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) -o noncopyable_import.pyd - -ivect.pyd: $(OBJ) ivect.obj - $(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) -o ivect.pyd - -dvect.pyd: $(OBJ) dvect.obj - $(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) -o dvect.pyd - -richcmp1.pyd: $(OBJ) richcmp1.obj - $(LD) $(LDOPTS) $(OBJ) richcmp1.obj $(PYLIB) -o richcmp1.pyd - -richcmp2.pyd: $(OBJ) richcmp2.obj - $(LD) $(LDOPTS) $(OBJ) richcmp2.obj $(PYLIB) -o richcmp2.pyd - -richcmp3.pyd: $(OBJ) richcmp3.obj - $(LD) $(LDOPTS) $(OBJ) richcmp3.obj $(PYLIB) -o richcmp3.pyd - -.cpp.obj: - $(CPP) $(CPPOPTS) -c $*.cpp - -test: - $(PYEXE) comprehensive.py - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_convts.py - $(PYEXE) test_nested.py - $(PYEXE) test_pickle1.py - $(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 *.obj - -del *.lib - -del *.exp - -del *.idb - -del *.pyd - -del *.pyc - -softlinks: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks - -unlink: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink - -cp: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp - -rm: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm - -copy: - $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy - -del: - $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del diff --git a/build/win32_mwcc_setup.bat b/build/win32_mwcc_setup.bat deleted file mode 100755 index 30f84be8..00000000 --- a/build/win32_mwcc_setup.bat +++ /dev/null @@ -1,2 +0,0 @@ -call "c:\program files\metrowerks\codewarrior\other metrowerks tools\command line tools\cwenv.bat" -set MWWinx86LibraryFiles=MSL_All-DLL_x86.lib;gdi32.lib;user32.lib;kernel32.lib diff --git a/doc/boost.css b/doc/boost.css deleted file mode 100644 index cf5c8a97..00000000 --- a/doc/boost.css +++ /dev/null @@ -1,59 +0,0 @@ -H1 -{ - FONT-SIZE: 200% - COLOR: #00007f -} -H2 -{ - FONT-SIZE: 150%; -} -H3 -{ - FONT-SIZE: 125%; -} -H4 -{ - FONT-SIZE: 108%; -} -BODY -{ - FONT-SIZE: 100%; - BACKGROUND-COLOR: #ffffff -} -PRE -{ - MARGIN-LEFT: 2pc; - FONT-SIZE: 80%; - BACKGROUND-COLOR: #dfffff -} -CODE -{ - FONT-SIZE: 95%; - white-space: pre -} -.index -{ - TEXT-ALIGN: left -} -.page-index -{ - TEXT-ALIGN: left -} -.definition -{ - TEXT-ALIGN: left -} -.footnote -{ - FONT-SIZE: 66%; - VERTICAL-ALIGN: super; - TEXT-DECORATION: none -} -.function-semantics -{ - CLEAR: left -} -.metafunction-semantics -{ - CLEAR: left -} diff --git a/doc/building.html b/doc/building.html deleted file mode 100644 index cdca6b97..00000000 --- a/doc/building.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - Building an Extension Module - -
-

c++boost.gif (8819 bytes)Building an - Extension Module

- -

Building Boost.Python

- -

Every Boost.Python extension module must be linked with the - boost_python shared library. To build - boost_python, use Boost.Build in the - usual way from the libs/python/build subdirectory - of your boost installation (if you have already built boost from - the top level this may have no effect, since the work is already - done). - -

Configuration

- You may need to configure the following variables to point Boost.Build at your Python installation: - - - - - - - - - - -
Variable Name Semantics Default Notes -
PYTHON_ROOT - The root directory of your Python installation - Windows: c:/tools/python - Unix: /usr/local - On Unix, this is the --with-prefix= directory - used to configure Python - -
PYTHON_VERSION - The The 2-part python Major.Minor version number - Windows: 2.1 - Unix: 1.5 - Be sure not to include a third number, e.g. not - "2.2.1", even if that's the version you - have. - -
PYTHON_INCLUDES - path to Python #include directories - Autoconfigured from PYTHON_ROOT - -
PYTHON_LIB_PATH - path to Python library object. - Autoconfigured from PYTHON_ROOT - -
PYTHON_STDLIB_PATH - path to Python standard library modules - Autoconfigured from PYTHON_ROOT - -
CYGWIN_ROOT - path to the user's Cygwin installation - - Cygwin only. This and the following two settings are - useful when building with multiple toolsets on Windows, since - Cygwin requires a different build of Python. - -
GCC_PYTHON_ROOT - path to the user's Cygwin Python installation - $(CYGWIN_ROOT)/usr/local - Cygwin only - -
GCC_DEBUG_PYTHON_ROOT - path to the user's Cygwin pydebug build - $(CYGWIN_ROOT)/usr/local/pydebug - Cygwin only - -
- -

Results

-

The build process will create a - libs/python/build/bin-stage subdirectory of the - boost root (or of $(ALL_LOCATE_TARGET), - if you have set that variable), containing the built - libraries. The libraries are actually built to unique - directories for each toolset and variant elsewhere in the - filesystem, and copied to the - bin-stage directory as a convenience, so if you - build with multiple toolsets at once, the product of later - toolsets will overwrite that of earlier toolsets in - bin-stage. - -

Testing

-

To build and test Boost.Python from within the - libs/python/build directory, invoke -

-
-bjam -sTOOLS=toolset test
-
-
-This will -update all of the Boost.Python v1 test and example targets. The tests -are relatively quiet by default. To get more-verbose output, you might try -
-
-bjam -sTOOLS=toolset -sPYTHON_TEST_ARGS=-v test
-
-
-which will print each test's Python code with the expected output as -it passes. - -

Building your Extension Module

- - Though there are other approaches, the easiest way to build an - extension module using Boost.Python is with Boost.Build. Until - Boost.Build v2 is released, cross-project build dependencies are - not supported, so it works most smoothly if you add a new - subproject to your boost installation. The - libs/python/example subdirectory of your boost - installation contains a minimal example (along with many extra - sources). To copy the example subproject: - -
    -
  1. Create a new subdirectory in, libs/python, say - libs/python/my_project. - -
  2. Copy libs/python/example/Jamfile - to your new directory. - -
  3. Edit the Jamfile as appropriate for your project. You'll - want to change the "subproject" rule - invocation at the top, and the names of some of the source files - and/or targets. - -
- - If you can't modify or copy your boost installation, the - alternative is to create your own Boost.Build project. A similar - example you can use as a starting point is available in this archive. You'll - need to edit the Jamfile and Jamrules files, depending on the - relative location of your Boost installation and the new - project. Note that automatic testing of extension modules is not - available in this configuration. - -

Build Variants

- - Three variant - configurations of all python-related targets are supported, and - can be selected by setting the BUILD - variable: - -
    -
  • release (optimization, -DNDEBUG) - -
  • debug (no optimization -D_DEBUG) - -
  • debug-python (no optimization, -D_DEBUG - -DBOOST_DEBUG_PYTHON) -
- -

The first two variants of the boost_python - library are built by default, and are compatible with the - default Python distribution. The debug-python - variant corresponds to a specially-built debugging version of - Python. On Unix platforms, this python is built by adding - --with-pydebug when configuring the Python - build. On Windows, the debugging version of Python is generated - by the "Win32 Debug" target of the - PCBuild.dsw Visual C++ 6.0 project in the - PCBuild subdirectory of your Python distribution. - - Extension modules built with Python debugging enabled are not - link-compatible with a non-debug build of Python. Since few - people actually have a debug build of Python (it doesn't come - with the standard distribution), the normal - debug variant builds modules which are compatible - with ordinary Python. - - -

On many windows compilers, when extension modules are built - with - -D_DEBUG, Python defaults to force linking with a - special debugging version of the Python DLL. Since this debug DLL - isn't supplied with the default Python installation for Windows, - Boost.Python uses boost/python/detail/wrap_python.hpp - to temporarily undefine _DEBUG when Python.h is - #included - unless BOOST_DEBUG_PYTHON is defined. - -

If you want the extra runtime checks available with the - debugging version of the library, #define - BOOST_DEBUG_PYTHON to re-enable python debuggin, and link - with the debug-python variant of - boost_python. - -

If you do not #define BOOST_DEBUG_PYTHON, be sure that - any source files in your extension module #include <boost/python/detail/wrap_python.hpp> - instead of the usual Python.h, or you will have link - incompatibilities.
- -


- Next: Wrapping Enums Previous: A Peek Under the Hood Up: Top - -
-

© Copyright David Abrahams 2002. 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. - -

Updated: May 15, 2002 (David Abrahams) -

diff --git a/doc/comparisons.html b/doc/comparisons.html deleted file mode 100644 index 57cec744..00000000 --- a/doc/comparisons.html +++ /dev/null @@ -1,231 +0,0 @@ - - - Comparisons with Other Systems - -
-

- c++boost.gif (8819 bytes)
- Comparisons with - Other Systems -

- -

CXX

-

- Like Boost.Python, CXX attempts to - provide a C++-oriented interface to Python. In most cases, as with the - boost library, it relieves the user from worrying about - reference-counts. Both libraries automatically convert thrown C++ - exceptions into Python exceptions. As far as I can tell, CXX has no - support for subclassing C++ extension types in Python. An even - more significant difference is that a user's C++ code is still basically - ``dealing with Python objects'', though they are wrapped in - C++ classes. This means such jobs as argument parsing and conversion are - still left to be done explicitly by the user. - -

- CXX claims to interoperate well with the C++ Standard Library - (a.k.a. STL) by providing iterators into Python Lists and Dictionaries, - but the claim is unfortunately unsupportable. The problem is that in - general, access to Python sequence and mapping elements through - iterators requires the use of proxy objects as the return value of - iterator dereference operations. This usage conflicts with the basic - ForwardIterator requirements in - section 24.1.3 of the standard (dereferencing must produce a - reference). Although you may be able to use these iterators with some - operations in some standard library implementations, it is neither - guaranteed to work nor portable. - -

- As far as I can tell, CXX enables one to write what is essentially - idiomatic Python code in C++, manipulating Python objects through the - same fully-generic interfaces we use in Python. While you're hardly - programming directly to the ``bare metal'' with CXX, it basically - presents a ``C++-ized'' version of the Python 'C' API. Some fraction of - that capability is available in Boost.Python through boost/python/objects.hpp, - which provides C++ objects corresponding to Python lists, tuples, - strings, and dictionaries, and through boost/python/callback.hpp, - which allows you to call back into python with C++ arguments. - -

- Paul F. Dubois, the original - author of CXX, has told me that what I've described is only half of the - picture with CXX, but I never understood his explanation well-enough to - fill in the other half. Here is his response to the commentary above: - -

-``My intention with CXX was not to do what you are doing. It was to enable a -person to write an extension directly in C++ rather than C. I figured others had -the wrapping business covered. I thought maybe CXX would provide an easier -target language for those making wrappers, but I never explored -that.''
-Paul Dubois -
- -

SWIG

-

- SWIG is an impressively mature tool - for exporting an existing ANSI 'C' interface into various scripting - languages. Swig relies on a parser to read your source code and produce - additional source code files which can be compiled into a Python (or - Perl or Tcl) extension module. It has been successfully used to create - many Python extension modules. Like Boost.Python, SWIG is trying to allow an - existing interface to be wrapped with little or no change to the - existing code. The documentation says ``SWIG parses a form of ANSI C - syntax that has been extended with a number of special directives. As a - result, interfaces are usually built by grabbing a header file and - tweaking it a little bit.'' For C++ interfaces, the tweaking has often - proven to amount to more than just a little bit. One user - writes: - -

``The problem with swig (when I used it) is that it - couldnt handle templates, didnt do func overloading properly etc. For - ANSI C libraries this was fine. But for usual C++ code this was a - problem. Simple things work. But for anything very complicated (or - realistic), one had to write code by hand. I believe Boost.Python doesn't have - this problem[sic]... IMHO overloaded functions are very important to - wrap correctly.''
-Prabhu Ramachandran -
- -

- By contrast, Boost.Python doesn't attempt to parse C++ - the problem is simply - too complex to do correctly. Technically, one does - write code by hand to use Boost.Python. The goal, however, has been to make - that code nearly as simple as listing the names of the classes and - member functions you want to expose in Python. - -

SIP

-

- SIP - is a system similar to SWIG, though seemingly more - C++-oriented. The author says that like Boost.Python, SIP supports overriding - extension class member functions in Python subclasses. It appears to - have been designed specifically to directly support some features of - PyQt/PyKDE, which is its primary client. Documentation is almost - entirely missing at the time of this writing, so a detailed comparison - is difficult. - -

ILU

-

- ILU - is a very ambitious project which tries to describe a module's interface - (types and functions) in terms of an Interface - Specification Language (ISL) so that it can be uniformly interfaced - to a wide range of computer languages, including Common Lisp, C++, C, - Modula-3, and Python. ILU can parse the ISL to generate a C++ language - header file describing the interface, of which the user is expected to - provide an implementation. Unlike Boost.Python, this means that the system - imposes implementation details on your C++ code at the deepest level. It - is worth noting that some of the C++ names generated by ILU are supposed - to be reserved to the C++ implementation. It is unclear from the - documentation whether ILU supports overriding C++ virtual functions in Python. - -

GRAD

-

- GRAD - is another very ambitious project aimed at generating Python wrappers for - interfaces written in ``legacy languages'', among which C++ is the first one - implemented. Like SWIG, it aims to parse source code and automatically - generate wrappers, though it appears to take a more sophisticated approach - to parsing in general and C++ in particular, so it should do a much better - job with C++. It appears to support function overloading. The - documentation is missing a lot of information I'd like to see, so it is - difficult to give an accurate and fair assessment. I am left with the - following questions: -

    -
  • Does it support overriding of virtual functions? -
  • What about overriding private or protected virtual functions (the documentation indicates -that only public interfaces are supported)? -
  • Which C++ language constructs are supportd? -
  • Does it support implicit conversions between wrapped C++ classes that have -an inheritance relationship? -
  • Does it support smart pointers? -
-

- Anyone in the possession of the answers to these questions will earn my - gratitude for a write-up ;-) - -

Zope ExtensionClasses

-

- - ExtensionClasses in Zope use the same underlying mechanism as Boost.Python - to support subclassing of extension types in Python, including - multiple-inheritance. Both systems support pickling/unpickling of - extension class instances in very similar ways. Both systems rely on the - same ``Don - Beaudry Hack'' that also inspired Don's MESS System. -

- The major differences are: -

    -
  • Zope is entirely 'C' language-based. It doesn't require a C++ - compiler, so it's much more portable than Boost.Python, which stresses - the limits of even some modern C++ implementations. - -
  • - Boost.Python lifts the burden on the user to parse and convert function - argument types. Zope provides no such facility. -
  • - Boost.Python lifts the burden on the user to maintain Python - reference-counts. -
  • - Boost.Python supports function overloading; Zope does not. -
  • - Boost.Python supplies a simple mechanism for exposing read-only and - read/write access to data members of the wrapped C++ type as Python - attributes. -
  • - Writing a Zope ExtensionClass is significantly more complex than - exposing a C++ class to python using Boost.Python (mostly a summary of the - previous 4 items). A - Zope Example illustrates the differences. -
  • - Zope's ExtensionClasses are specifically motivated by ``the need for a - C-based persistence mechanism''. Boost.Python's are motivated by the desire - to simply reflect a C++ API into Python with as little modification as - possible. -
  • - The following Zope restriction does not apply to Boost.Python: ``At most one - base extension direct or indirect super class may define C data - members. If an extension subclass inherits from multiple base - extension classes, then all but one must be mix-in classes that - provide extension methods but no data.'' -
  • - Zope requires use of the somewhat funky inheritedAttribute (search for - ``inheritedAttribute'' on this page) - method to access base class methods. In Boost.Python, base class methods can - be accessed in the usual way by writing - ``BaseClass.method''. -
  • - Zope supplies some creative but esoteric idioms such as - Acquisition. No specific support for this is built into Boost.Python. -
  • - Zope's ComputedAttribute support is designed to be used from Python. - The analogous feature of - Boost.Python can be used from C++ or Python. The feature is arguably - easier to use in Boost.Python. -
-

- Next: A Simple Example Using Boost.Python - Previous: A Brief Introduction to writing Python Extension Modules - Up: Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Mar 6, 2001 -

- diff --git a/doc/cross_module.html b/doc/cross_module.html deleted file mode 100644 index 08c39bfe..00000000 --- a/doc/cross_module.html +++ /dev/null @@ -1,336 +0,0 @@ - - -Cross-extension-module dependencies - -
- -c++boost.gif (8819 bytes) - -
-

Cross-extension-module dependencies

- -It is good programming practice to organize large projects as modules -that interact with each other via well defined interfaces. With -Boost.Python it is possible to reflect this organization at the C++ -level at the Python level. This is, each logical C++ module can be -organized as a separate Python extension module. - -

-At first sight this might seem natural and straightforward. However, it -is a fairly complex problem to establish cross-extension-module -dependencies while maintaining the same ease of use Boost.Python -provides for classes that are wrapped in the same extension module. To -a large extent this complexity can be hidden from the author of a -Boost.Python extension module, but not entirely. - -


-

The recipe

- -Suppose there is an extension module that exposes certain instances of -the C++ std::vector template library such that it can be used -from Python in the following manner: - -
-import std_vector
-v = std_vector.double([1, 2, 3, 4])
-v.push_back(5)
-v.size()
-
- -Suppose the std_vector module is done well and reflects all -C++ functions that are useful at the Python level, for all C++ built-in -data types (std_vector.int, std_vector.long, etc.). - -

-Suppose further that there is statistic module with a C++ class that -has constructors or member functions that use or return a -std::vector. For example: - -

-class xy {
-  public:
-    xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
-    const std::vector<double>& x() const { return m_x; }
-    const std::vector<double>& y() const { return m_y; }
-    double correlation();
-  private:
-    std::vector<double> m_x;
-    std::vector<double> m_y;
-}
-
- -What is more natural than reusing the std_vector extension -module to expose these constructors or functions to Python? - -

-Unfortunately, what seems natural needs a little work in both the -std_vector and the statistics module. - -

-In the std_vector extension module, -std::vector<double> is exposed to Python in the usual -way with the class_builder<> template. To also enable the -automatic conversion of std::vector<double> function -arguments or return values in other Boost.Python C++ modules, the -converters that convert a std::vector<double> C++ object -to a Python object and vice versa (i.e. the to_python() and -from_python() template functions) have to be exported. For -example: - -

-  #include <boost/python/cross_module.hpp>
-  //...
-  class_builder<std::vector<double> > v_double(std_vector_module, "double");
-  export_converters(v_double);
-
- -In the extension module that wraps class xy we can now import -these converters with the import_converters<> template. -For example: - -
-  #include <boost/python/cross_module.hpp>
-  //...
-  import_converters<std::vector<double> > v_double_converters("std_vector", "double");
-
- -That is all. All the attributes that are defined for -std_vector.double in the std_vector Boost.Python -module will be available for the returned objects of xy.x() -and xy.y(). Similarly, the constructor for xy will -accept objects that were created by the std_vectormodule. - -
-

Placement of import_converters<> template instantiations

- -import_converts<> can be viewed as a drop-in replacement -for class_wrapper<>, and the recommendations for the -placement of class_wrapper<> template instantiations -also apply to to import_converts<>. In particular, it is -important that an instantiation of class_wrapper<> is -visible to any code which wraps a C++ function with a T, -T*, const T&, etc. parameter or return value. -Therefore you may want to group all class_wrapper<> and -import_converts<> instantiations at the top of your -module's init function, then def() the member functions later -to avoid problems with inter-class dependencies. - -
-

Non-copyable types

- -export_converters() instantiates C++ template functions that -invoke the copy constructor of the wrapped type. For a type that is -non-copyable this will result in compile-time error messages. In such a -case, export_converters_noncopyable() can be used to export -the converters that do not involve the copy constructor of the wrapped -type. For example: - -
-class_builder<store> py_store(your_module, "store");
-export_converters_noncopyable(py_store);
-
- -The corresponding import_converters<> statement does not -need any special attention: - -
-import_converters<store> py_store("noncopyable_export", "store");
-
- -
-

Python module search path

- -The std_vector and statistics modules can now be used -in the following way: - -
-import std_vector
-import statistics
-x = std_vector.double([1, 2, 3, 4])
-y = std_vector.double([2, 4, 6, 8])
-xy = statistics.xy(x, y)
-xy.correlation()
-
- -In this example it is clear that Python has to be able to find both the -std_vector and the statistics extension module. In -other words, both extension modules need to be in the Python module -search path (sys.path). - -

-The situation is not always this obvious. Suppose the -statistics module has a random() function that -returns a vector of random numbers with a given length: - -

-import statistics
-x = statistics.random(5)
-y = statistics.random(5)
-xy = statistics.xy(x, y)
-xy.correlation()
-
- -A naive user will not easily anticipate that the std_vector -module is used to pass the x and y vectors around. If -the std_vector module is in the Python module search path, -this form of ignorance is of no harm. On the contrary, we are glad -that we do not have to bother the user with details like this. - -

-If the std_vector module is not in the Python module search -path, a Python exception will be raised: - -

-Traceback (innermost last):
-  File "foo.py", line 2, in ?
-    x = statistics.random(5)
-ImportError: No module named std_vector
-
- -As is the case with any system of a non-trivial complexity, it is -important that the setup is consistent and complete. - -
-

Two-way module dependencies

- -Boost.Python supports two-way module dependencies. This is best -illustrated by a simple example. - -

-Suppose there is a module ivect that implements vectors of -integers, and a similar module dvect that implements vectors -of doubles. We want to be able do convert an integer vector to a double -vector and vice versa. For example: - -

-import ivect
-iv = ivect.ivect((1,2,3,4,5))
-dv = iv.as_dvect()
-
- -The last expression will implicitly import the dvect module in -order to enable the conversion of the C++ representation of -dvect to a Python object. The analogous is possible for a -dvect: - -
-import dvect
-dv = dvect.dvect((1,2,3,4,5))
-iv = dv.as_ivect()
-
- -Now the ivect module is imported implicitly. - -

-Note that the two-way dependencies are possible because the -dependencies are resolved only when needed. This is, the initialization -of the ivect module does not rely on the dvect -module, and vice versa. Only if as_dvect() or -as_ivect() is actually invoked will the corresponding module -be implicitly imported. This also means that, for example, the -dvect module does not have to be available at all if -as_dvect() is never used. - -


-

Clarification of compile-time and link-time dependencies

- -Boost.Python's support for resolving cross-module dependencies at -runtime does not imply that compile-time dependencies are eliminated. -For example, the statistics extension module in the example above will -need to #include <vector>. This is immediately obvious -from the definition of class xy. - -

-If a library is wrapped that consists of both header files and compiled -components (e.g. libdvect.a, dvect.lib, etc.), both -the Boost.Python extension module with the -export_converters() statement and the module with the -import_converters<> statement need to be linked against -the object library. Ideally one would build a shared library (e.g. -libdvect.so, dvect.dll, etc.). However, this -introduces the issue of having to configure the search path for the -dynamic loading correctly. For small libraries it is therefore often -more convenient to ignore the fact that the object files are loaded -into memory more than once. - -


-

Summary of motivation for cross-module support

- -The main purpose of Boost.Python's cross-module support is to allow for -a modular system layout. With this support it is straightforward to -reflect C++ code organization at the Python level. Without the -cross-module support, a multi-purpose module like std_vector -would be impractical because the entire wrapper code would somehow have -to be duplicated in all extension modules that use it, making them -harder to maintain and harder to build. - -

-Another motivation for the cross-module support is that two extension -modules that wrap the same class cannot both be imported into Python. -For example, if there are two modules A and B that -both wrap a given class X, this will work: - -

-import A
-x = A.X()
-
- -This will also work: - -
-import B
-x = B.X()
-
- -However, this will fail: - -
-import A
-import B
-python: /net/cci/rwgk/boost/boost/python/detail/extension_class.hpp:866:
-static void boost::python::detail::class_registry<X>::register_class(boost::python::detail::extension_class_base *):
-Assertion `static_class_object == 0' failed.
-Abort
-
- -A good solution is to wrap class X only once. Depending on the -situation, this could be done by module A or B, or an -additional small extension module that only wraps and exports -class X. - -

-Finally, there can be important psychological or political reasons for -using the cross-module support. If a group of classes is lumped -together with many others in a huge module, the authors will have -difficulties in being identified with their work. The situation is -much more transparent if the work is represented by a module with a -recognizable name. This is not just a question of strong egos, but also -of getting credit and funding. - -


-

Why not use export_converters() universally?

- -There is some overhead associated with the Boost.Python cross-module -support. Depending on the platform, the size of the code generated by -export_converters() is roughly 10%-20% of that generated -by class_builder<>. For a large extension module with -many wrapped classes, this could mean a significant difference. -Therefore the general recommendation is to use -export_converters() only for classes that are likely to -be used as function arguments or return values in other modules. - -
-© Copyright 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. - -

-Updated: April 2001 - -

diff --git a/doc/data_structures.txt b/doc/data_structures.txt deleted file mode 100644 index 90e41b91..00000000 --- a/doc/data_structures.txt +++ /dev/null @@ -1,192 +0,0 @@ -Given a real Python class 'A', a wrapped C++ class 'B', and this definition: - - class C(A, B): - def __init__(self): - B.__init__(self) - self.x = 1 - ... - - c = C() - -this diagram describes the internal structure of an instance of 'C', including -its inheritance relationships. Note that ExtensionClass is derived from -Class, and is in fact identical for all intents and purposes. - - MetaClass - +---------+ +---------+ -types.ClassType: | | | | - | | | | - | | | | - +---------+ +---------+ - ^ ^ ^ - PyClassObject | ExtensionClass | | - A: +------------+ | B: +------------+ | | - | ob_type -+-+ | ob_type -+-----+ | - | | ()<--+- __bases__ | | - | | | __dict__ -+->{...} | - | | 'B'<-+- __name__ | | - +------------+ +------------+ | - ^ ^ | - | | | - +-----+ +-------------+ | - | | | - | | Class | - | | C: +------------+ | - | | | ob_type -+------------+ - tuple:(*, *)<--+- __bases__ | - | __dict__ -+->{__module__, } - 'C' <-+- __name__ | - +------------+ - ^ (in case of inheritance from more than one - | extension class, this vector would contain - +---------------+ a pointer to an instance holder for the data - | of each corresponding C++ class) - | ExtensionInstance - | c: +---------------------+ std::vector - +----+- __class__ | +---+-- - | m_wrapped_objects -+->| * | ... - {'x': 1}<-+- __dict__ | +-|-+-- - +---------------------+ | InstanceValueHolder - | +--------------------------------+ - +-->| (contains a C++ instance of B) | - +--------------------------------+ - - - - - - -In our inheritance test cases in extclass_demo.cpp/test_extclass.py, we have the -following C++ inheritance hierarchy: - - +-----+ +----+ - | A1 | | A2 | - +-----+ +----+ - ^ ^ ^ ^ ^ - | | | | | - +-----+ | +---------+-----+ - | | | | - | +---+----------+ - .......!...... | | - : A_callback : +-+--+ +-+--+ - :............: | B1 | | B2 | - +----+ +----+ - ^ - | - +-------+---------+ - | | - +-+-+ ......!....... - | C | : B_callback : - +---+ :............: - - -A_callback and B_callback are used as part of the wrapping mechanism but not -represented in Python. C is also not represented in Python but is delivered -there polymorphically through a smart pointer. - -This is the data structure in Python. - - ExtensionClass - A1: +------------+ - ()<--+- __bases__ | - | __dict__ -+->{...} - +------------+ - ^ - | ExtensionInstance - | a1: +---------------------+ vec InstanceValueHolder - +---------+- __class__ | +---+ +---------------------+ - | | m_wrapped_objects -+->| *-+-->| contains A_callback | - | +---------------------+ +---+ +---------------------+ - | - | ExtensionInstance - | pa1_a1: +---------------------+ vec InstancePtrHolder,A1> - +---------+- __class__ | +---+ +---+ - | | m_wrapped_objects -+->| *-+-->| *-+-+ A1 - | +---------------------+ +---+ +---+ | +---+ - | +->| | - | ExtensionInstance +---+ - | pb1_a1: +---------------------+ vec InstancePtrHolder,A1> - +---------+- __class__ | +---+ +---+ - | | m_wrapped_objects -+->| *-+-->| *-+-+ B1 - | +---------------------+ +---+ +---+ | +---+ - | +->| | - | ExtensionInstance +---+ - | pb2_a1: +---------------------+ vec InstancePtrHolder,A1> - +---------+- __class__ | +---+ +---+ - | | m_wrapped_objects -+->| *-+-->| *-+-+ B2 - | +---------------------+ +---+ +---+ | +---+ - | +->| | - | +---+ - | ExtensionClass - | A2: +------------+ - | ()<--+- __bases__ | - | | __dict__ -+->{...} - | +------------+ - | ^ - | | ExtensionInstance - | a2: | +---------------------+ vec InstanceValueHolder - | +-+- __class__ | +---+ +-------------+ - | | | m_wrapped_objects -+->| *-+-->| contains A2 | - | | +---------------------+ +---+ +-------------+ - | | - | | ExtensionInstance - | pa2_a2: | +---------------------+ vec InstancePtrHolder,A2> - | +-+- __class__ | +---+ +---+ - | | | m_wrapped_objects -+->| *-+-->| *-+-+ A2 - | | +---------------------+ +---+ +---+ | +---+ - | | +->| | - | | ExtensionInstance +---+ - | pb1_a2: | +---------------------+ vec InstancePtrHolder,A2> - | +-+- __class__ | +---+ +---+ - | | | m_wrapped_objects -+->| *-+-->| *-+-+ B1 - | | +---------------------+ +---+ +---+ | +---+ - | | +->| | - | | +---+ - | | - | +---------------+------------------------------+ - | | | - +------+-------------------------+-|----------------------------+ | - | | | | | - | Class | | ExtensionClass | | ExtensionClass - | DA1: +------------+ | | B1: +------------+ | | B2: +------------+ -(*,)<---+- __bases__ | (*,*)<---+- __bases__ | (*,*)<---+- __bases__ | - | __dict__ -+->{...} | __dict__ -+->{...} | __dict__ -+->{...} - +------------+ +------------+ +------------+ - ^ ^ ^ - | ExtensionInstance | | - | da1: +---------------------+ | vec InstanceValueHolder - +-------+- __class__ | | +---+ +---------------------+ | - | m_wrapped_objects -+--|-->| *-+-->| contains A_callback | | - +---------------------+ | +---+ +---------------------+ | - +--------------------------------------+ | - | ExtensionInstance | - b1: | +---------------------+ vec InstanceValueHolder | - +-+- __class__ | +---+ +---------------------+ | - | | m_wrapped_objects -+->| *-+-->| contains B_callback | | - | +---------------------+ +---+ +---------------------+ | - | | - | ExtensionInstance | -pb1_b1: | +---------------------+ vec InstancePtrHolder,B1> | - +-+- __class__ | +---+ +---+ | - | | m_wrapped_objects -+->| *-+-->| *-+-+ B1 | - | +---------------------+ +---+ +---+ | +---+ | - | +->| | | - | ExtensionInstance +---+ | - pc_b1: | +---------------------+ vec InstancePtrHolder,B1> | - +-+- __class__ | +---+ +---+ | - | | m_wrapped_objects -+->| *-+-->| *-+-+ C | - | +---------------------+ +---+ +---+ | +---+ | - | +->| | | - | +---+ | - | | - | Class +---------------------------------------+ - | DB1: +------------+ | ExtensionInstance - (*,)<---+- __bases__ | a2: | +---------------------+ vec InstanceValueHolder - | __dict__ -+->{...} +-+- __class__ | +---+ +-------------+ - +------------+ | m_wrapped_objects -+->| *-+-->| contains A2 | - ^ +---------------------+ +---+ +-------------+ - | ExtensionInstance - db1: | +---------------------+ vec InstanceValueHolder - +-+- __class__ | +---+ +----------------------+ - | m_wrapped_objects -+-->| *-+-->| contains B1_callback | - +---------------------+ +---+ +----------------------+ diff --git a/doc/enums.html b/doc/enums.html deleted file mode 100644 index c58ca34d..00000000 --- a/doc/enums.html +++ /dev/null @@ -1,120 +0,0 @@ - - - Wrapping enums - -
-

- c++boost.gif (8819 bytes)
- Wrapping enums -

- -

Because there is in general no way to deduce that a value of arbitrary type T -is an enumeration constant, the Boost Python Library cannot automatically -convert enum values to and from Python. To handle this case, you need to decide -how you want the enum to show up in Python (since Python doesn't have -enums). Once you have done that, you can write some simple -from_python() and to_python() functions. - -

If you are satisfied with a Python int as a way to represent your enum -values, we provide a shorthand for these functions. You just need to cause -boost::python::enum_as_int_converters<EnumType> to be -instantiated, where -EnumType is your enumerated type. There are two convenient ways to do this: - -

    -
  1. Explicit instantiation: - -
    -  template class boost::python::enum_as_int_converters<my_enum>;
    -
    - -Some buggy C++ implementations require a class to be instantiated in the same -namespace in which it is defined. In that case, the simple incantation above becomes: - -
    -
    -   ...
    -} // close my_namespace
    -
    -// drop into namespace python and explicitly instantiate
    -namespace boost { namespace python {
    -  template class enum_as_int_converters<my_enum_type>;
    -}} // namespace boost::python
    -
    -namespace my_namespace { // re-open my_namespace
    -   ...
    -
    -
    - - -
  2. If you have such an implementation, you may find this technique more convenient -
    -// instantiate as base class in any namespace
    -struct EnumTypeConverters
    -    : boost::python::enum_as_int_converters<EnumType>
    -{
    -};
    -
    -
- -

Either of the above is equivalent to the following declarations: -

-BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
-
-  MyEnumType from_python(PyObject* x, boost::python::type<MyEnumType>)
-  {
-      return static_cast<MyEnum>(
-        from_python(x, boost::python::type<long>()));
-  }
-
-  MyEnumType from_python(PyObject* x, boost::python::type<const MyEnumType&>)
-  {
-      return static_cast<MyEnum>(
-        from_python(x, boost::python::type<long>()));
-  }
-
-  PyObject* to_python(MyEnumType x)
-  {
-      return to_python(static_cast<long>(x));
-  }
-BOOST_PYTHON_END_CONVERSION_NAMESPACE
-
- -

This technique defines the conversions of -MyEnumType in terms of the conversions for the built-in - long type. - -You may also want to add a bunch of lines like this to your module -initialization. These bind the corresponding enum values to the appropriate -names so they can be used from Python: - -

-mymodule.add(boost::python::make_ref(enum_value_1), "enum_value_1");
-mymodule.add(boost::python::make_ref(enum_value_2), "enum_value_2");
-...
-
- -You can also add these to an extension class definition, if your enum happens to -be local to a class and you want the analogous interface in Python: - -
-my_class_builder.add(boost::python::to_python(enum_value_1), "enum_value_1");
-my_class_builder.add(boost::python::to_python(enum_value_2), "enum_value_2");
-...
-
-

- Next: Pointers and Smart Pointers - Previous: Building an Extension Module - Up: Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Mar 6, 2001 -

- diff --git a/doc/example1.html b/doc/example1.html deleted file mode 100644 index ee01e72c..00000000 --- a/doc/example1.html +++ /dev/null @@ -1,75 +0,0 @@ - - - A Simple Example - -
-

- - -

-

- A Simple Example -

-

- Suppose we have the following C++ API which we want to expose in - Python: -

-
-#include <string>
-
-namespace { // Avoid cluttering the global namespace.
-
-  // A couple of simple C++ functions that we want to expose to Python.
-  std::string greet() { return "hello, world"; }
-  int square(int number) { return number * number; }
-}
-
-
-
-

- Here is the C++ code for a python module called getting_started1 - which exposes the API. -

-
-#include <boost/python/class_builder.hpp>
-namespace python = boost::python;
-
-BOOST_PYTHON_MODULE_INIT(getting_started1)
-{
-    // Create an object representing this extension module.
-    python::module_builder this_module("getting_started1");
-
-    // Add regular functions to the module.
-    this_module.def(greet, "greet");
-    this_module.def(square, "square");
-}
-
-
-

- That's it! If we build this shared library and put it on our - PYTHONPATH we can now access our C++ functions from - Python. -

-
->>> import getting_started1
->>> print getting_started1.greet()
-hello, world
->>> number = 11
->>> print number, '*', number, '=', getting_started1.square(number)
-11 * 11 = 121
-
-

- Next: Exporting Classes - Previous: Comparisons with other systems Up: - Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Mar 6, 2000 -

- diff --git a/doc/exporting_classes.html b/doc/exporting_classes.html deleted file mode 100644 index cbeb8a9e..00000000 --- a/doc/exporting_classes.html +++ /dev/null @@ -1,143 +0,0 @@ - - - Exporting Classes - -
-

- - -

-

- Exporting Classes -

-

- Now let's expose a C++ class to Python: - -

-#include <iostream>
-#include <string>
-
-namespace { // Avoid cluttering the global namespace.
-
-  // A friendly class.
-  class hello
-  {
-    public:
-      hello(const std::string& country) { this->country = country; }
-      std::string greet() const { return "Hello from " + country; }
-    private:
-      std::string country;
-  };
-
-  // A function taking a hello object as an argument.
-  std::string invite(const hello& w) {
-    return w.greet() + "! Please come soon!";
-  }
-}
-
-

- To expose the class, we use a class_builder in addition to the - module_builder from the previous example. Class member functions - are exposed by using the def() member function on the - class_builder: -

-#include <boost/python/class_builder.hpp>
-namespace python = boost::python;
-
-BOOST_PYTHON_MODULE_INIT(getting_started2)
-{
-    // Create an object representing this extension module.
-    python::module_builder this_module("getting_started2");
-
-    // Create the Python type object for our extension class.
-    python::class_builder<hello> hello_class(this_module, "hello");
-
-    // Add the __init__ function.
-    hello_class.def(python::constructor<std::string>());
-    // Add a regular member function.
-    hello_class.def(&hello::greet, "greet");
-
-    // Add invite() as a regular function to the module.
-    this_module.def(invite, "invite");
-
-    // Even better, invite() can also be made a member of hello_class!!!
-    hello_class.def(invite, "invite");
-}
-
-

-Now we can use the class normally from Python: - -

->>> from getting_started2 import *
->>> hi = hello('California')
->>> hi.greet()
-'Hello from California'
->>> invite(hi)
-'Hello from California! Please come soon!'
->>> hi.invite()
-'Hello from California! Please come soon!'
-
- -Notes:
    -
  • We expose the class' constructor by calling def() on the - class_builder with an argument whose type is - constructor<params>, where params - matches the list of constructor argument types: - - -
  • Regular member functions are defined by calling def() with a - member function pointer and its Python name: - -
  • Any function added to a class whose initial argument matches the class (or -any base) will act like a member function in Python. - -
  • To define a nested class, just pass the enclosing -class_builder (instead of a module_builder) as the -first argument to the nested class_builder's constructor. - - -
-

- We can even make a subclass of hello.world: - -

->>> class wordy(hello):
-...     def greet(self):
-...         return hello.greet(self) + ', where the weather is fine'
-...
->>> hi2 = wordy('Florida')
->>> hi2.greet()
-'Hello from Florida, where the weather is fine'
->>> invite(hi2)
-'Hello from Florida! Please come soon!'
-
-

- Pretty cool! You can't do that with an ordinary Python extension type! - - Of course, you may now have a slightly empty feeling in the pit of - your little pythonic stomach. Perhaps you wanted to see the following - wordy invitation: - -

-'Hello from Florida, where the weather is fine! Please come soon!'
-
- - After all, invite calls hello::greet(), and you - reimplemented that in your Python subclass, wordy. If so, read on... - -

- Next: Overridable virtual functions - Previous: A Simple Example Up: - Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Mar 6, 2001 -

- diff --git a/doc/extending.html b/doc/extending.html deleted file mode 100644 index 8839ab43..00000000 --- a/doc/extending.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - A Brief Introduction to writing Python extension modules - -

- c++boost.gif (8819 bytes) -

-

- A Brief Introduction to writing Python extension modules -

-

- Interfacing any language to Python involves building a module which can - be loaded by the Python interpreter, but which isn't written in Python. - This is known as an extension module. Many of the built-in Python - libraries are constructed in 'C' this way; Python even supplies its - fundamental - types using the same mechanism. An extension module can be statically - linked with the Python interpreter, but it more commonly resides in a - shared library or DLL. -

- As you can see from The Python Extending - and Embedding Tutorial, writing an extension module normally means - worrying about -

- This last item typically occupies a great deal of code in an extension - module. Remember that Python is a completely dynamic language. A callable - object receives its arguments in a tuple; it is up to that object to extract - those arguments from the tuple, check their types, and raise appropriate - exceptions. There are numerous other tedious details that need to be - managed; too many to mention here. The Boost Python Library is designed to - lift most of that burden.
-
- -

- Another obstacle that most people run into eventually when extending - Python is that there's no way to make a true Python class in an extension - module. The typical solution is to create a new Python type in the - extension module, and then write an additional module in 100% Python. The - Python module defines a Python class which dispatches to an instance of - the extension type, which it contains. This allows users to write - subclasses of the class in the Python module, almost as though they were - sublcassing the extension type. Aside from being tedious, it's not really - the same as having a true class, because there's no way for the user to - override a method of the extension type which is called from the - extension module. Boost.Python solves this problem by taking advantage of Python's metaclass - feature to provide objects which look, walk, and hiss almost exactly - like regular Python classes. Boost.Python classes are actually cleaner than - Python classes in some subtle ways; a more detailed discussion will - follow (someday).

-

Next: Comparisons with Other Systems Up: Top

-

- © Copyright David Abrahams 2000. 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.

- diff --git a/doc/index.html b/doc/index.html deleted file mode 100644 index fffe13e9..00000000 --- a/doc/index.html +++ /dev/null @@ -1,205 +0,0 @@ - - - The Boost Python Library (Boost.Python) - -

- c++boost.gif (8819 bytes)
The Boost Python Library (Boost.Python) -

- -

Synopsis

-

- Use the Boost Python Library to quickly and easily export a C++ library to Python such that the Python interface is - very similar to the C++ interface. It is designed to be minimally - intrusive on your C++ design. In most cases, you should not have to alter - your C++ classes in any way in order to use them with Boost.Python. The system - should simply ``reflect'' your C++ classes and functions into - Python. - -

- - -
Note: this is the last official release of -Boost.Python v1. Development of this version of the library has -stopped; it will be retired soon in favor of the redesigned and -improved version 2. A summary of the development goals is available on -the Python C++-sig -page, which also serves as a mailing list for users of both versions -of the library. A preview of the v2 documentation is available here, -and instructions for getting started with a prerelease are available -upon request. -
- -

Supported Platforms

-

Boost.Python is known to have been tested -against Python 2.2.1 using -the following compilers: - -

- -

-Note that pickling doesn't work with Python 2.2 -due to a core language bug. This is fixed in -2.2.1. - -

-Boost.Python has also been used with other versions of Python back to -Python 1.5.2. It is expected that the older Python releases still work, -but we are not regularly testing for backward compatibility. - -

Credits

-
    -
  • David Abrahams originated - and wrote most of the library, and continues to coordinate development. - -
  • Ullrich Koethe - had independently developed a similar system. When he discovered Boost.Python, - he generously contributed countless hours of coding and much insight into - improving it. He is responsible for an early version of the support for function overloading and wrote the support for - reflecting C++ inheritance - relationships. He has helped to improve error-reporting from both - Python and C++, and has designed an extremely easy-to-use way of - exposing numeric operators, including - a way to avoid explicit coercion by means of overloading. - -
  • Ralf W. - Grosse-Kunstleve contributed pickle support - and numerous other small improvements. He's working on a way to allow - types exported by multiple modules to interact. - -
  • The members of the boost mailing list and the Python community - supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans, - Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott took the - brave step of trying to use Boost.Python while it was still in early - stages of development. - -
  • The development of Boost.Python wouldn't have been possible without - the generous support of Dragon - Systems/Lernout and Hauspie, Inc who supported its development as an - open-source project. -
- -

Table of Contents

- -
    -
  1. A Brief Introduction to writing Python - extension modules - -
  2. Comparisons between Boost.Python and other - systems for extending Python - -
  3. A Simple Example - -
  4. Exporting Classes - -
  5. Overridable Virtual Functions - -
  6. Function Overloading - -
  7. Inheritance - -
  8. Special Method and Operator Support - -
  9. A Peek Under the Hood - -
  10. Building an Extension Module - -
  11. Pickle Support - -
  12. Cross-Extension-Module Dependencies - -
  13. Wrapping Enums - -
  14. Pointers and Smart Pointers - -
  15. Internal Data Structures - -
- -

- Documentation is a major ongoing project; assistance is greatly - appreciated! In the meantime, useful examples of every Boost.Python feature should - be evident in the regression test files test/comprehensive.[py/hpp/cpp] - -

- Questions should be directed to the Python C++ SIG. - -

- © Copyright David Abrahams 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. -

- Updated: Apr 2002 - diff --git a/doc/inheritance.html b/doc/inheritance.html deleted file mode 100644 index 56e96872..00000000 --- a/doc/inheritance.html +++ /dev/null @@ -1,166 +0,0 @@ - - - Inheritance - -

-

- c++boost.gif (8819 bytes)Inheritance -

- -

Inheritance in Python

- -

- Boost.Python extension classes support single and multiple-inheritance in - Python, just like regular Python classes. You can arbitrarily mix - built-in Python classes with extension classes in a derived class' - tuple of bases. Whenever a Boost.Python extension class is among the bases for a - new class in Python, the result is an extension class: -

-
->>> class MyPythonClass:
-...     def f(): return 'MyPythonClass.f()'
-...
->>> import my_extension_module
->>> class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
-...     '''This is an extension class'''
-...     pass
-...
->>> x = Derived()
->>> x.f()
-'MyPythonClass.f()'
->>> x.g()
-'MyExtensionClass.g()'
-
-
- -

Reflecting C++ Inheritance Relationships

-

- Boost.Python also allows us to represent C++ inheritance relationships so that - wrapped derived classes may be passed where values, pointers, or - references to a base class are expected as arguments. The - declare_base member function of - class_builder<> is used to establish the relationship - between base and derived classes: - -

-
-#include <memory> // for std::auto_ptr<>
-
-struct Base {
-    virtual ~Base() {}
-    virtual const char* name() const { return "Base"; }
-};
-
-struct Derived : Base {
-    Derived() : x(-1) {}
-    virtual const char* name() const { return "Derived"; }
-    int x;
-};
-
-std::auto_ptr<Base> derived_as_base() {
-    return std::auto_ptr<Base>(new Derived);
-}
-
-const char* get_name(const Base& b) {
-    return b.name();
-}
-
-int get_derived_x(const Derived& d) {
-    return d.x;
-}
-    
-#include <boost/python/class_builder.hpp> - -// namespace alias for code brevity -namespace python = boost::python; - -BOOST_PYTHON_MODULE_INIT(my_module) -{ -    python::module_builder my_module("my_module"); - -    python::class_builder<Base> base_class(my_module, "Base"); -    base_class.def(python::constructor<>()); - -    python::class_builder<Derived> derived_class(my_module, "Derived"); -    derived_class.def(python::constructor<>()); - // Establish the inheritance relationship between Base and Derived - derived_class.declare_base(base_class); - - my_module.def(derived_as_base, "derived_as_base"); - my_module.def(get_name, "get_name"); - my_module.def(get_derived_x, "get_derived_x"); -} -
-
- -

- Then, in Python: -

-
->>> from my_module import *
->>> base = Base()
->>> derived = Derived()
->>> get_name(base)
-'Base'
-
-
-objects of wrapped class Derived may be passed where Base is expected -
-
->>> get_name(derived) 
-'Derived'
-
-
-objects of wrapped class Derived can be passed where Derived is -expected but where type information has been lost. -
-
->>> get_derived_x(derived_as_base()) 
--1
-
-
- -

Inheritance Without Virtual Functions

- -

- If for some reason your base class has no virtual functions but you still want - to represent the inheritance relationship between base and derived classes, - pass the special symbol boost::python::without_downcast as the 2nd parameter - to declare_base: - -

-
-struct Base2 {};
-struct Derived2 { int f(); };
-
- ... -   python::class_builder<Base> base2_class(my_module, "Base2"); -   base2_class.def(python::constructor<>()); - -   python::class_builder<Derived2> derived2_class(my_module, "Derived2"); -   derived2_class.def(python::constructor<>()); - derived_class.declare_base(base_class, python::without_downcast); -
-
- -

This approach will allow Derived2 objects to be passed where - Base2 is expected, but does not attempt to implicitly convert (downcast) - smart-pointers to Base2 into Derived2 pointers, - references, or values. - -

- Next: Special Method and Operator Support - Previous: Function Overloading - Up: Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/new-conversions.html b/doc/new-conversions.html deleted file mode 100644 index cd8a5b19..00000000 --- a/doc/new-conversions.html +++ /dev/null @@ -1,326 +0,0 @@ - - - - -A New Type Conversion Mechanism for Boost.Python - - - - -

- -

A New Type Conversion Mechanism for Boost.Python

- -

By David Abrahams. - -

Introduction

- -This document describes a redesign of the mechanism for automatically -converting objects between C++ and Python. The current implementation -uses two functions for any type T: - -
-U from_python(PyObject*, type<T>);
-void to_python(V);
-
- -where U is convertible to T and T is convertible to V. These functions -are at the heart of C++/Python interoperability in Boost.Python, so -why would we want to change them? There are many reasons: - -

Bugs

-

Firstly, the current mechanism relies on a common C++ compiler -bug. This is not just embarrassing: as compilers get to be more -conformant, the library stops working. The issue, in detail, is the -use of inline friend functions in templates to generate -conversions. It is a very powerful, and legal technique as long as -it's used correctly: - -

-template <class Derived>
-struct add_some_functions
-{
-     friend return-type some_function1(..., Derived cv-*-&-opt, ...);
-     friend return-type some_function2(..., Derived cv-*-&-opt, ...);
-};
-
-template <class T>
-struct some_template : add_some_functions<some_template<T> >
-{
-};
-
- -The add_some_functions template generates free functions -which operate on Derived, or on related types. Strictly -speaking the related types are not just cv-qualified Derived -values, pointers and/or references. Section 3.4.2 in the standard -describes exactly which types you must use as parameters to these -functions if you want the functions to be found -(there is also a less-technical description in section 11.5.1 of -C++PL3 [1]). Suffice it to say that -with the current design, the from_python and -to_python functions are not supposed to be callable under any -conditions! - -

Compilation and Linking Time

- -The conversion functions generated for each wrapped class using the -above technique are not function templates, but regular functions. The -upshot is that they must all be generated regardless of whether -they are actually used. Generating all of those functions can slow -down module compilation, and resolving the references can slow down -linking. - -

Efficiency

- -The conversion functions are primarily used in (member) function -wrappers to convert the arguments and return values. Being functions, -converters have no interface which allows us to ask "will the -conversion succeed?" without calling the function. Since the -return value of the function must be the object to be passed as an -argument, Boost.Python currently uses C++ exception-handling to detect -an unsuccessful conversion. It's not a particularly good use of -exception-handling, since the failure is not handled very far from -where it occurred. More importantly, it means that C++ exceptions are -thrown during overload resolution as we seek an overload that matches -the arguments passed. Depending on the implementation, this approach -can result in significant slowdowns. - -

It is also unclear that the current library generates a minimal -amount of code for any type conversion. Many of the conversion -functions are nontrivial, and partly because of compiler limitations, -they are declared inline. Also, we could have done a better -job separating the type-specific conversion code from the code which -is type-independent. - -

Cross-module Support

- -The current strategy requires every module to contain the definition -of conversions it uses. In general, a new module can never supply -conversion code which is used by another module. Ralf Grosse-Kunstleve -designed a clever system which imports conversions directly from one -library into another using some explicit declarations, but it has some -disadvantages also: - -
    -
  1. The system Ullrich Koethe designed for implicit conversion between -wrapped classes related through inheritance does not currently work if -the classes are defined in separate modules. - -
  2. The writer of the importing module is required to know the name of -the module supplying the imported conversions. - -
  3. There can be only one way to extract any given C++ type from a -Python object in a given module. -
- -The first item might be addressed by moving Boost.Python into a shared -library, but the other two cannot. Ralf turned the limitation in item -two into a feature: the required module is loaded implicitly when a -conversion it defines is invoked. We will probably want to provide -that functionality anyway, but it's not clear that we should require -the declaration of all such conversions. The final item is a more -serious limitation. If, for example, new numeric types are defined in -separate modules, and these types can all be converted to -doubles, we have to choose just one conversion method. - -

Ease-of-use

- -One persistent source of confusion for users of Boost.Python has been -the fact that conversions for a class are not be visible at -compile-time until the declaration of that class has been seen. When -the user tries to expose a (member) function operating on or returning -an instance of the class in question, compilation fails...even though -the user goes on to expose the class in the same translation unit! - -

-The new system lifts all compile-time checks for the existence of -particular type conversions and replaces them with runtime checks, in -true Pythonic style. While this might seem cavalier, the compile-time -checks are actually not much use in the current system if many classes -are wrapped in separate modules, since the checks are based only on -the user's declaration that the conversions exist. - -

The New Design

- -

Motivation

- -The new design was heavily influenced by a desire to generate as -little code as possible in extension modules. Some of Boost.Python's -clients are enormous projects where link time is proportional to the -amount of object code, and there are many Python extension modules. As -such, we try to keep type-specific conversion code out of modules -other than the one the converters are defined in, and rely as much as -possible on centralized control through a shared library. - -

The Basics

- -The library contains a registry which maps runtime type -identifiers (actually an extension of std::type_info which -preserves references and constness) to entries containing type -converters. An entry can contain only one converter from C++ to Python -(wrapper), but many converters from Python to C++ -(unwrappers). What should happen if -multiple modules try to register wrappers for the same type?. Wrappers -and unwrappers are known as body objects, and are accessed -by the user and the library (in its function-wrapping code) through -corresponding handle (wrap<T> and -unwrap<T>) objects. The handle objects are -extremely lightweight, and delegate all of their operations to -the corresponding body. - -

-When a handle object is constructed, it accesses the -registry to find a corresponding body that can convert the -handle's constructor argument. Actually the registry record for any -type -Tused in a module is looked up only once and stored in a -static registration<T> object for efficiency. For -example, if the handle is an unwrap<Foo&> object, -the entry for Foo& is looked up in the -registry, and each unwrapper it contains is queried -to determine if it can convert the -PyObject* with which the unwrap was constructed. If -a body object which can perform the conversion is found, a pointer to -it is stored in the handle. A body object may at any point store -additional data in the handle to speed up the conversion process. - -

-Now that the handle has been constructed, the user can ask it whether -the conversion can be performed. All handles can be tested as though -they were convertible to bool; a true value -indicates success. If the user forges ahead and tries to do the -conversion without checking when no conversion is possible, an -exception will be thrown as usual. The conversion itself is performed -by the body object. - -

Handling complex conversions

- -

Some conversions may require a dynamic allocation. For example, -when a Python tuple is converted to a std::vector<double> -const&, we need some storage into which to construct the -vector so that a reference to it can be formed. Furthermore, multiple -conversions of the same type may need to be "active" -simultaneously, so we can't keep a single copy of the storage -anywhere. We could keep the storage in the body object, and -have the body clone itself in case the storage is used, but in that -case the storage in the body which lives in the registry is never -used. If the storage was actually an object of the target type (the -safest way in C++), we'd have to find a way to construct one for the -body in the registry, since it may not have a default constructor. - -

-The most obvious way out of this quagmire is to allocate the object using a -new-expression, and store a pointer to it in the handle. Since -the body object knows everything about the data it needs to -allocate (if any), it is also given responsibility for destroying that -data. When the handle is destroyed it asks the body -object to tear down any data it may have stored there. In many ways, -you can think of the body as a "dynamically-determined -vtable" for the handle. - -

Eliminating Redundancy

- -If you look at the current Boost.Python code, you'll see that there -are an enormous number of conversion functions generated for each -wrapped class. For a given class T, functions are generated -to extract the following types from_python: - -
-T*
-T const*
-T const* const&
-T* const&
-T&
-T const&
-T
-std::auto_ptr<T>&
-std::auto_ptr<T>
-std::auto_ptr<T> const&
-boost::shared_ptr<T>&
-boost::shared_ptr<T>
-boost::shared_ptr<T> const&
-
- -Most of these are implemented in terms of just a few conversions, and -if you're lucky, they will be inlined and cause no extra -overhead. In the new system, however, a significant amount of data -will be associated with each type that needs to be converted. We -certainly don't want to register a separate unwrapper object for all -of the above types. - -

Fortunately, much of the redundancy can be eliminated. For example, -if we generate an unwrapper for T&, we don't need an -unwrapper for T const& or T. Accordingly, the user's -request to wrap/unwrap a given type is translated at compile-time into -a request which helps to eliminate redundancy. The rules used to -unwrap a type are: - -

    -
  1. Treat built-in types specially: when unwrapping a value or - constant reference to one of these, use a value for the target - type. It will bind to a const reference if neccessary, and more - importantly, avoids having to dynamically allocate room for - an lvalue of types which can be cheaply copied. -
  2. - Reduce everything else to a reference to an un-cv-qualified type - where possible. Since cv-qualification is lost on Python - anyway, there's no point in trying to convert to a - const&. What about conversions - to values like the tuple->vector example above? It seems to me - that we don't want to make a vector<double>& - (non-const) converter available for that case. We may need to - rethink this slightly. -
- -

To handle the problem described above in item 2, we modify the -procedure slightly. To unwrap any non-scalar T, we seek an -unwrapper for add_reference<T>::type. Unwrappers for -T const& always return T&, and are -registered under both T & and -T const&. - -

For compilers not supporting partial specialization, unwrappers for -T const& must return T const& -(since constness can't be stripped), but a separate unwrapper object -need to be registered for T & and -T const& anyway, for the same reasons. - -We may want to make it possible to compile as -though partial specialization were unavailable even on compilers where -it is available, in case modules could be compiled by different -compilers with compatible ABIs (e.g. Intel C++ and MSVC6). - -

Efficient Argument Conversion

- -Since type conversions are primarily used in function wrappers, an -optimization is provided for the case where a group of conversions are -used together. Each handle class has a corresponding -"_more" class which does the same job, but has a -trivial destructor. Instead of asking each "_more" -handle to destroy its own body, it is linked into an endogenous list -managed by the first (ordinary) handle. The wrap and -unwrap destructors are responsible for traversing that list -and asking each body class to tear down its -handle. This mechanism is also used to determine if all of -the argument/return-value conversions can succeed with a single -function call in the function wrapping code. We -might need to handle return values in a separate step for Python -callbacks, since the availablility of a conversion won't be known -until the result object is retrieved. - -
-
-

References

- -

[1]B. Stroustrup, The C++ Programming Language -Special Edition Addison-Wesley, ISBN 0-201-70073-5. - -


-

Revised 19 December 2001

-

© Copyright David Abrahams, 2001

- - - - diff --git a/doc/new-conversions.txt b/doc/new-conversions.txt deleted file mode 100644 index 1540e199..00000000 --- a/doc/new-conversions.txt +++ /dev/null @@ -1,111 +0,0 @@ -This hierarchy contains converter handle classes. - - - +-------------+ - | noncopyable | - +-------------+ - ^ - | A common base class used so that - +--------+--------+ conversions can be linked into a - | conversion_base | chain for efficient argument - +-----------------+ conversion - ^ - | - +---------+-----------+ - | | -+-----------+----+ +------+-------+ only used for -| unwrap_more | | wrap_more | chaining, and don't manage any -+----------------+ +--------------+ resources. - ^ ^ - | | - +-----+-----+ +-------+-+ These converters are what users - | unwrap | | wrap | actually touch, but they do so - +-----------+ +---------+ through a type generator which - minimizes the number of converters - that must be generated, so they - - -Each unwrap, unwrap_more, wrap, wrap_more converter holds -a reference to an appropriate converter object - -This hierarchy contains converter body classes - - Exposes use/release which - are needed in case the converter - +-----------+ in the registry needs to be - | converter | cloned. That occurs when a - +-----------+ unwrap target type is not - ^ contained within the Python object. - | - +------------------+-----+ - | | - +--------+-------+ Exposes | - | unwrapper_base | convertible() | - +----------------+ | - ^ | - | | - +--------+----+ +-----+-----+ - | unwrapper| | wrapper| - +-------------+ +-----------+ - Exposes T convert(PyObject*) Exposes PyObject* convert(T) - - -unwrap: - - constructed with a PyObject*, whose reference count is - incremented. - - find the registry entry for the target type - - look in the collection of converters for one which claims to be - able to convert the PyObject to the target type. - - stick a pointer to the unwrapper in the unwrap object - - when unwrap is queried for convertibility, it checks to see - if it has a pointer to an unwrapper. - - on conversion, the unwrapper is asked to allocate an - implementation if the unwrap object isn't already holding - one. The unwrap object "takes ownership" of the unwrapper's - implementation. No memory allocation will actually take place - unless this is a value conversion. - - on destruction, the unwrapper is asked to free any implementation - held by the unwrap object. No memory deallocation actually - takes place unless this is a value conversion - - on destruction, the reference count on the held PyObject is - decremented. - - We need to make sure that by default, you can't instantiate - callback<> for reference and pointer return types: although the - unwrappers may exist, they may convert by-value, which would cause - the referent to be destroyed upon return. - -wrap: - - find the registry entry for the source type - - see if there is a converter. If found, stick a pointer to it in - the wrap object. - - when queried for convertibility, it checks to see if it has a - pointer to a converter. - - on conversion, a reference to the target PyObject is held by the - converter. Generally, the PyObject will have been created by the - converter, but in certain cases it may be a pre-existing object, - whose reference count will have been incremented. - - when a wrap x is used to return from a C++ function, - x.release() is returned so that x no longer holds a reference to - the PyObject when destroyed. - - Otherwise, on destruction, any PyObject still held has its - reference-count decremented. - - -When a converter is created by the user, the appropriate element must -be added to the registry; when it is destroyed, it must be removed -from the registry. diff --git a/doc/overloading.html b/doc/overloading.html deleted file mode 100644 index 242e023f..00000000 --- a/doc/overloading.html +++ /dev/null @@ -1,155 +0,0 @@ - - - Function Overloading - -
-

- c++boost.gif (8819 bytes)Function Overloading -

- -

An Example

-

- To expose overloaded functions in Python, simply def() each - one with the same Python name: -

-
-inline int f1() { return 3; }
-inline int f2(int x) { return x + 1; }
-
-class X {
-public:
-    X() : m_value(0) {}
-    X(int n) : m_value(n) {}
-    int value() const { return m_value; }
-    void value(int v) { m_value = v; }
-private:
-    int m_value;
-};
-  ...
-
-BOOST_PYTHON_MODULE_INIT(overload_demo)
-{
-    try
-    {
-        boost::python::module_builder overload_demo("overload_demo");
-        // Overloaded functions at module scope
-        overload_demo.def(f1, "f");
-        overload_demo.def(f2, "f");
-
-        boost::python::class_builder<X> x_class(overload_demo, "X");
-        // Overloaded constructors
-        x_class.def(boost::python::constructor<>());
-        x_class.def(boost::python::constructor<int>());
-
-        // Overloaded member functions
-        x_class.def((int (X::*)() const)&X::value, "value");
-        x_class.def((void (X::*)(int))&X::value, "value");
-  ...
-
-
- -

- Now in Python: -

-
->>> from overload_demo import *
->>> x0 = X()
->>> x1 = X(1)
->>> x0.value()
-0
->>> x1.value()
-1
->>> x0.value(3)
->>> x0.value()
-3
->>> X('hello')
-TypeError: No overloaded functions match (X, string). Candidates are:
-void (*)()
-void (*)(int)
->>> f()
-3
->>> f(4)
-5
-
-
- -

Discussion

-

- Notice that overloading in the Python module was produced three ways:

    -
  1. by combining the non-overloaded C++ functions int f1() - and int f2(int) and exposing them as f in Python. -
  2. by exposing the overloaded constructors of class X -
  3. by exposing the overloaded member functions X::value. -
-

- Techniques 1. and 3. above are really alternatives. In case 3, you need - to form a pointer to each of the overloaded functions. The casting - syntax shown above is one way to do that in C++. Case 1 does not require - complicated-looking casts, but may not be viable if you can't change - your C++ interface. N.B. There's really nothing unsafe about casting an - overloaded (member) function address this way: the compiler won't let - you write it at all unless you get it right. - -

An Alternative to Casting

-

- This approach is not neccessarily better, but may be preferable for some - people who have trouble writing out the types of (member) function - pointers or simply prefer to avoid all casts as a matter of principle: -

-
-// Forwarding functions for X::value
-inline void set_x_value(X& self, int v) { self.value(v); }
-inline int get_x_value(X& self) { return self.value(); }
-   ...
-        // Overloaded member functions
-        x_class.def(set_x_value, "value");
-        x_class.def(get_x_value, "value");
-
-
-

Here we are taking advantage of the ability to expose C++ functions at -namespace scope as Python member functions. - -

Overload Resolution

-

- The function overload resolution mechanism works as follows: - -

    - -
  • Attribute lookup for extension classes proceeds in the - usual Python way using a depth-first, left-to-right search. When a - class is found which has a matching attribute, only functions overloaded - in the context of that class are candidates for overload resolution. In - this sense, overload resolution mirrors the C++ mechanism, where a name - in a derived class ``hides'' all functions with the same name from a base - class. -

    - -

  • Within a name-space context (extension class or module), overloaded - functions are tried in the same order they were - def()ed. The first function whose signature can be made to - match each argument passed is the one which is ultimately called. - This means in particular that you cannot overload the same function on - both ``int'' and ``float'' because Python - automatically converts either of the two types into the other one. - If the ``float'' overload is found first, it is used - also used for arguments of type ``int'' as well, and the - ``int'' version of the function is never invoked. -
- -

- Next: Inheritance - Previous: Overridable Virtual Functions - Up: Top -

- © Copyright David Abrahams 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. -

- Updated: Mar 6, 2001 -

- diff --git a/doc/overriding.html b/doc/overriding.html deleted file mode 100644 index 085d5a7f..00000000 --- a/doc/overriding.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - Overridable Virtual Functions - - c++boost.gif (8819 bytes) - -

Overridable Virtual Functions

- -

- In the previous example we exposed a simple - C++ class in Python and showed that we could write a subclass. We even - redefined one of the functions in our derived class. Now we will learn - how to make the function behave virtually when called from C++. - - -

Example

- -

In this example, it is assumed that hello::greet() is a virtual -member function: - -

-class hello
-{
- public:
-    hello(const std::string& country) { this->country = country; }
-    virtual std::string greet() const { return "Hello from " + country; }
-    virtual ~hello(); // Good practice 
-    ...
-};
-
- -

- We'll need a derived class* to help us - dispatch the call to Python. In our derived class, we need the following - elements: - -

    - -
  1. A PyObject* data member (usually - called self) that holds a pointer to the Python object corresponding - to our C++ hello instance. - -
  2. For each exposed constructor of the - base class T, a constructor which takes the same parameters preceded by an initial - PyObject* argument. The initial argument should be stored in the self data - member described above. - -
  3. If the class being wrapped is ever returned by - value from a wrapped function, be sure you do the same for the - T's copy constructor: you'll need a constructor taking arguments - (PyObject*, const T&). - -
  4. An implementation of each virtual function you may - wish to override in Python which uses - callback<return-type>::call_method(self, "name", args...) to call - the Python override. - -
  5. For each non-pure virtual function meant to be - overridable from Python, a static member function (or a free function) taking - a reference or pointer to the T as the first parameter and which - forwards any additional parameters neccessary to the default - implementation of the virtual function. See also this - note if the base class virtual function is private. - -
- -
-struct hello_callback : hello
-{
-    // hello constructor storing initial self_ parameter
-    hello_callback(PyObject* self_, const std::string& x) // 2
-        : hello(x), self(self_) {}
-
-    // In case hello is returned by-value from a wrapped function
-    hello_callback(PyObject* self_, const hello& x) // 3
-        : hello(x), self(self_) {}
-
-    // Override greet to call back into Python
-    std::string greet() const // 4
-        { return boost::python::callback<std::string>::call_method(self, "greet"); }
-
-    // Supplies the default implementation of greet
-    static std::string default_greet(const hello& self_) const // 5
-        { return self_.hello::greet(); }
- private:
-    PyObject* self; // 1
-};
-
- -

- Finally, we add hello_callback to the - class_builder<> declaration in our module initialization - function, and when we define the function, we must tell Boost.Python about the default - implementation: - -

-// Create the Python type object for our extension class
-boost::python::class_builder<hello,hello_callback> hello_class(hello, "hello");
-// Add a virtual member function
-hello_class.def(&hello::greet, "greet", &hello_callback::default_greet);
-
- -

- Now our Python subclass of hello behaves as expected: - -

->>> class wordy(hello):
-...     def greet(self):
-...         return hello.greet(self) + ', where the weather is fine'
-...
->>> hi2 = wordy('Florida')
->>> hi2.greet()
-'Hello from Florida, where the weather is fine'
->>> invite(hi2)
-'Hello from Florida, where the weather is fine! Please come soon!'
-
-

- *You may ask, "Why do we need this derived - class? This could have been designed so that everything gets done right - inside of hello." One of the goals of Boost.Python is to be - minimally intrusive on an existing C++ design. In principle, it should be - possible to expose the interface for a 3rd party library without changing - it. To unintrusively hook into the virtual functions so that a Python - override may be called, we must use a derived class. - -

Pure Virtual Functions

- -

- A pure virtual function with no implementation is actually a lot easier to - deal with than a virtual function with a default implementation. First of - all, you obviously don't need to supply - a default implementation. Secondly, you don't need to call - def() on the extension_class<> instance - for the virtual function. In fact, you wouldn't want to: if the - corresponding attribute on the Python class stays undefined, you'll get an - AttributeError in Python when you try to call the function, - indicating that it should have been implemented. For example: -

-
-struct baz {
-    virtual int pure(int) = 0;
-    int calls_pure(int x) { return pure(x) + 1000; }
-};
-
-struct baz_callback {
-    int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
-};
-
-BOOST_PYTHON_MODULE_INIT(foobar)
-{
-     boost::python::module_builder foobar("foobar");                          
-     boost::python::class_builder<baz,baz_callback> baz_class("baz");   
-     baz_class.def(&baz::calls_pure, "calls_pure"); 
-}
-
-
-

- Now in Python: -

-
->>> from foobar import baz
->>> x = baz()
->>> x.pure(1)
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-AttributeError: pure
->>> x.calls_pure(1)
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-AttributeError: pure
->>> class mumble(baz):
-...    def pure(self, x): return x + 1
-...
->>> y = mumble()
->>> y.pure(99)
-100
->>> y.calls_pure(99)
-1100
-
- -

Private Non-Pure Virtual Functions

- -

This is one area where some minor intrusiveness on the wrapped library is -required. Once it has been overridden, the only way to call the base class -implementation of a private virtual function is to make the derived class a -friend of the base class. You didn't hear it from me, but most C++ -implementations will allow you to change the declaration of the base class in -this limited way without breaking binary compatibility (though it will certainly -break the ODR). - -


-

- Next: Function Overloading - Previous: Exporting Classes - Up: Top -

- © Copyright David Abrahams 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. -

- Updated: Mar 21, 2001 - diff --git a/doc/pickle.html b/doc/pickle.html deleted file mode 100644 index 994a78ab..00000000 --- a/doc/pickle.html +++ /dev/null @@ -1,272 +0,0 @@ - - -Boost.Python Pickle Support - -

- -c++boost.gif (8819 bytes) - -
-

Boost.Python Pickle Support

- -Pickle is a Python module for object serialization, also known -as persistence, marshalling, or flattening. - -

-It is often necessary to save and restore the contents of an object to -a file. One approach to this problem is to write a pair of functions -that read and write data from a file in a special format. A powerful -alternative approach is to use Python's pickle module. Exploiting -Python's ability for introspection, the pickle module recursively -converts nearly arbitrary Python objects into a stream of bytes that -can be written to a file. - -

-The Boost Python Library supports the pickle module by emulating the -interface implemented by Jim Fulton's ExtensionClass module that is -included in the -ZOPE -distribution. -This interface is similar to that for regular Python classes as -described in detail in the -Python Library Reference for pickle. - -


-

The Boost.Python Pickle Interface

- -At the user level, the Boost.Python pickle interface involves three special -methods: - -
-
-__getinitargs__ -
- When an instance of a Boost.Python extension class is pickled, the - pickler tests if the instance has a __getinitargs__ method. - This method must return a Python tuple (it is most convenient to use - a boost::python::tuple). When the instance is restored by the - unpickler, the contents of this tuple are used as the arguments for - the class constructor. - -

- If __getinitargs__ is not defined, the class constructor - will be called without arguments. - -

-

-__getstate__ - -
- When an instance of a Boost.Python extension class is pickled, the - pickler tests if the instance has a __getstate__ method. - This method should return a Python object representing the state of - the instance. - -

- If __getstate__ is not defined, the instance's - __dict__ is pickled (if it is not empty). - -

-

-__setstate__ - -
- When an instance of a Boost.Python extension class is restored by the - unpickler, it is first constructed using the result of - __getinitargs__ as arguments (see above). Subsequently the - unpickler tests if the new instance has a __setstate__ - method. If so, this method is called with the result of - __getstate__ (a Python object) as the argument. - -

- If __setstate__ is not defined, the result of - __getstate__ must be a Python dictionary. The items of this - dictionary are added to the instance's __dict__. - -

- -If both __getstate__ and __setstate__ are defined, -the Python object returned by __getstate__ need not be a -dictionary. The __getstate__ and __setstate__ methods -can do what they want. - -
-

Pitfalls and Safety Guards

- -In Boost.Python extension modules with many extension classes, -providing complete pickle support for all classes would be a -significant overhead. In general complete pickle support should only be -implemented for extension classes that will eventually be pickled. -However, the author of a Boost.Python extension module might not -anticipate correctly which classes need support for pickle. -Unfortunately, the pickle protocol described above has two important -pitfalls that the end user of a Boost.Python extension module might not -be aware of: - -
-
-Pitfall 1: -Both __getinitargs__ and __getstate__ are not defined. - -
- In this situation the unpickler calls the class constructor without - arguments and then adds the __dict__ that was pickled by - default to that of the new instance. - -

- However, most C++ classes wrapped with Boost.Python will have member - data that are not restored correctly by this procedure. To alert the - user to this problem, a safety guard is provided. If both - __getinitargs__ and __getstate__ are not defined, - Boost.Python tests if the class has an attribute - __dict_defines_state__. An exception is raised if this - attribute is not defined: - -

-    RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
-
- - In the rare cases where this is not the desired behavior, the safety - guard can deliberately be disabled. The corresponding C++ code for - this is, e.g.: - -
-    class_builder<your_class> py_your_class(your_module, "your_class");
-    py_your_class.dict_defines_state();
-
- - It is also possible to override the safety guard at the Python level. - E.g.: - -
-    import your_bpl_module
-    class your_class(your_bpl_module.your_class):
-      __dict_defines_state__ = 1
-
- -

-

-Pitfall 2: -__getstate__ is defined and the instance's __dict__ is not empty. - -
- The author of a Boost.Python extension class might provide a - __getstate__ method without considering the possibilities - that: - -

-

    -
  • - his class is used in Python as a base class. Most likely the - __dict__ of instances of the derived class needs to be - pickled in order to restore the instances correctly. - -

    -

  • - the user adds items to the instance's __dict__ directly. - Again, the __dict__ of the instance then needs to be - pickled. - -
-

- - To alert the user to this highly unobvious problem, a safety guard is - provided. If __getstate__ is defined and the instance's - __dict__ is not empty, Boost.Python tests if the class has - an attribute __getstate_manages_dict__. An exception is - raised if this attribute is not defined: - -

-    RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
-
- - To resolve this problem, it should first be established that the - __getstate__ and __setstate__ methods manage the - instances's __dict__ correctly. Note that this can be done - both at the C++ and the Python level. Finally, the safety guard - should intentionally be overridden. E.g. in C++: - -
-    class_builder<your_class> py_your_class(your_module, "your_class");
-    py_your_class.getstate_manages_dict();
-
- - In Python: - -
-    import your_bpl_module
-    class your_class(your_bpl_module.your_class):
-      __getstate_manages_dict__ = 1
-      def __getstate__(self):
-        # your code here
-      def __setstate__(self, state):
-        # your code here
-
-
- -
-

Practical Advice

- -
    -
  • - Avoid using __getstate__ if the instance can also be - reconstructed by way of __getinitargs__. This automatically - avoids Pitfall 2. - -

    -

  • - If __getstate__ is required, include the instance's - __dict__ in the Python object that is returned. - -
- -
-

Examples

- -There are three files in boost/libs/python/example that -show how so provide pickle support. - -

pickle1.cpp

- - The C++ class in this example can be fully restored by passing the - appropriate argument to the constructor. Therefore it is sufficient - to define the pickle interface method __getinitargs__. - -

pickle2.cpp

- - The C++ class in this example contains member data that cannot be - restored by any of the constructors. Therefore it is necessary to - provide the __getstate__/__setstate__ pair of - pickle interface methods. - -

- For simplicity, the __dict__ is not included in the result - of __getstate__. This is not generally recommended, but a - valid approach if it is anticipated that the object's - __dict__ will always be empty. Note that the safety guards - will catch the cases where this assumption is violated. - -

pickle3.cpp

- - This example is similar to pickle2.cpp. However, the - object's __dict__ is included in the result of - __getstate__. This requires more code but is unavoidable - if the object's __dict__ is not always empty. - -
-© Copyright 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. - -

-Updated: March 21, 2001 -

diff --git a/doc/pointers.html b/doc/pointers.html deleted file mode 100644 index 11cfd8d9..00000000 --- a/doc/pointers.html +++ /dev/null @@ -1,148 +0,0 @@ - - - Pointers - -
-

- c++boost.gif (8819 bytes)Pointers -

- -

The Problem With Pointers

- -

-In general, raw pointers passed to or returned from functions are problematic -for Boost.Python because pointers have too many potential meanings. Is it an iterator? -A pointer to a single element? An array? When used as a return value, is the -caller expected to manage (delete) the pointed-to object or is the pointer -really just a reference? If the latter, what happens to Python references to the -referent when some C++ code deletes it? -

-There are a few cases in which pointers are converted automatically: -

    - -
  • Both const- and non-const pointers to wrapped class instances can be passed -to C++ functions. - -
  • Values of type const char* are interpreted as -null-terminated 'C' strings and when passed to or returned from C++ functions are -converted from/to Python strings. - -
- -

Can you avoid the problem?

- -

My first piece of advice to anyone with a case not covered above is -``find a way to avoid the problem.'' For example, if you have just one -or two functions that return a pointer to an individual const -T, and T is a wrapped class, you may be able to write a ``thin -converting wrapper'' over those two functions as follows: - -

-const Foo* f(); // original function
-const Foo& f_wrapper() { return *f(); }
-  ...
-my_module.def(f_wrapper, "f");
-
-

-Foo must have a public copy constructor for this technique to work, since Boost.Python -converts const T& values to_python by copying the T -value into a new extension instance. - -

Dealing with the problem

- -

The first step in handling the remaining cases is to figure out what the pointer -means. Several potential solutions are provided in the examples that follow: - -

Returning a pointer to a wrapped type

- -

Returning a const pointer

- -

If you have lots of functions returning a const T* for some -wrapped T, you may want to provide an automatic -to_python conversion function so you don't have to write lots of -thin wrappers. You can do this simply as follows: - -

-BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
-  PyObject* to_python(const Foo* p) {
-     return to_python(*p); // convert const Foo* in terms of const Foo&
-  }
-BOOST_PYTHON_END_CONVERSION_NAMESPACE
-
- -

If you can't (afford to) copy the referent, or the pointer is non-const

- -

If the wrapped type doesn't have a public copy constructor, if copying is -extremely costly (remember, we're dealing with Python here), or if the -pointer is non-const and you really need to be able to modify the referent from -Python, you can use the following dangerous trick. Why dangerous? Because python -can not control the lifetime of the referent, so it may be destroyed by your C++ -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>::smart_ptr_to_python(p);
-  }
-
-  PyObject* to_python(const Foo* p)
-  {
-      return to_python(const_cast<Foo*>(p));
-  }
-BOOST_PYTHON_END_CONVERSION_NAMESPACE
-
- -This will cause the Foo* to be treated as though it were an owning smart -pointer, even though it's not. Be sure you don't use the reference for anything -from Python once the pointer becomes invalid, though. Don't worry too much about -the const_cast<> above: Const-correctness is completely lost -to Python anyway! - -

[In/]Out Parameters and Immutable Types

- -

If you have an interface that uses non-const pointers (or references) as -in/out parameters to types which in Python are immutable (e.g. int, string), -there simply is no way to get the same interface in Python. You must -resort to transforming your interface with simple thin wrappers as shown below: -

-const void f(int* in_out_x); // original function
-const int f_wrapper(int in_x) { f(in_x); return in_x; }
-  ...
-my_module.def(f_wrapper, "f");
-
- -

Of course, [in/]out parameters commonly occur only when there is already a -return value. You can handle this case by returning a Python tuple: -

-typedef unsigned ErrorCode;
-const char* f(int* in_out_x); // original function
- ...
-#include <boost/python/objects.hpp>
-const boost::python::tuple f_wrapper(int in_x) { 
-  const char* s = f(in_x); 
-  return boost::python::tuple(s, in_x);
-}
-  ...
-my_module.def(f_wrapper, "f");
-
-

Now, in Python: -

->>> str,out_x = f(3)
-
- -

- Previous: Enums - Up: Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/richcmp.html b/doc/richcmp.html deleted file mode 100644 index d9ab7044..00000000 --- a/doc/richcmp.html +++ /dev/null @@ -1,106 +0,0 @@ - - -Rich Comparisons - -
- -c++boost.gif (8819 bytes) - -
-

Rich Comparisons

- -
-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 __cmp__ method -that was given two instances of a class as arguments, and could only -return 0 if they were equal or +1 or -1 if -they were not. The method could not raise an exception or return -anything other than an integer value. -In Python 2.1, Rich Comparisons were added (see -PEP 207). -Python classes can now individually overload each of the <, <=, ->, >=, ==, and != operations. - -

-For more detailed information, search for "rich comparison" -here. - -

-Boost.Python supports both automatic overloading and manual overloading -of the Rich Comparison operators. The compile-time support is -independent of the Python version that is used when compiling -Boost.Python extension modules. That is, op_lt for example can -always be used, and the C++ operator< will always be bound -to the Python method __lt__. However, the run-time -behavior will depend on the Python version. - -

-With Python versions before 2.1, the Rich Comparison operators will not -be called by Python when any of the six comparison operators -(<, <=, ==, !=, ->, >=) is used in an expression. The only way -to access the corresponding methods is to call them explicitly, e.g. -a.__lt__(b). Only with Python versions 2.1 or higher will -expressions like a < b work as expected. - -

-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 -PyTypeObject structure: tp_richcompare. For backwards -compatibility, a flag (Py_TPFLAGS_HAVE_RICHCOMPARE) 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 AttributeError when the Python 2.1 -(or higher) interpreter tries, e.g., a.__lt__(b). That -is, in general all six operators should be supplied. Automatically -wrapped operators and manually wrapped operators can be mixed. For -example:

-    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__");
-
- -NotImplemented is a simple free function that (currently) has -to be provided by the user. For example:
-  boost::python::ref
-  NotImplemented(const code&, const code&) {
-    return
-    boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
-  }
-
- -See also: - - -
-© 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. - -

-Updated: July 2001 - -

diff --git a/doc/special.html b/doc/special.html deleted file mode 100644 index d53ec712..00000000 --- a/doc/special.html +++ /dev/null @@ -1,973 +0,0 @@ - - - Special Method and Operator Support - -
-

- c++boost.gif (8819 bytes)Special Method and - Operator Support -

-

- Overview -

-

- Boost.Python supports all of the standard - special method names supported by real Python class instances - except __complex__ (more on the reasons below). In addition, it can quickly and easily expose - suitable C++ functions and operators as Python operators. The following - categories of special method names are supported: -

- -

Basic Customization

- - -

- Python provides a number of special operators for basic customization of a - class. Only a brief description is provided below; more complete - documentation can be found here. - -

-
- __init__(self) -
- Initialize the class instance. For extension classes not subclassed in - Python, __init__ is defined by - -
    my_class.def(boost::python::constructor<...>())
- - (see section "A Simple Example Using Boost.Python").

-

- __del__(self) -
- Called when the extension instance is about to be destroyed. For extension classes - not subclassed in Python, __del__ is always defined automatically by - means of the class' destructor. -
- __repr__(self) -
- Create a string representation from which the object can be - reconstructed. -
- __str__(self) -
- Create a string representation which is suitable for printing. -
- __lt__(self, other) -
- __le__(self, other) -
- __eq__(self, other) -
- __ne__(self, other) -
- __gt__(self, other) -
- __ge__(self, other) -
- Rich Comparison methods. - New in Python 2.1. - See Rich Comparisons. -
- __cmp__(self, other) -
- Three-way compare function. - See Rich Comparisons. -
- __hash__(self) -
- Called for the key object for dictionary operations, and by the - built-in function hash(). Should return a 32-bit integer usable as a - hash value for dictionary operations (only allowed if __cmp__ is also - defined) -
- __nonzero__(self) -
- called if the object is used as a truth value (e.g. in an if - statement) -
- __call__ (self[, args...]) -
-Called when the instance is ``called'' as a function; if this method -is defined, x(arg1, arg2, ...) is a shorthand for -x.__call__(arg1, arg2, ...). -
- - If we have a suitable C++ function that supports any of these features, - we can export it like any other function, using its Python special name. - For example, suppose that class Foo provides a string - conversion function: -
-std::string to_string(Foo const& f)
-{
-    std::ostringstream s;
-    s << f;
-    return s.str();
-}
-
- This function would be wrapped like this: -
-boost::python::class_builder<Foo> foo_class(my_module, "Foo");
-foo_class.def(&to_string, "__str__");
-
- Note that Boost.Python also supports automatic wrapping of - __str__ and __cmp__. This is explained in the next section and the Table of - Automatically Wrapped Methods. - -

Numeric Operators

- -

- Numeric operators can be exposed manually, by defing C++ - [member] functions that support the standard Python numeric - protocols. This is the same basic technique used to expose - to_string() as __str__() above, and is covered in detail below. Boost.Python also supports - automatic wrapping of numeric operators whenever they have already - been defined in C++. - -

Exposing C++ Operators Automatically

- -

-Supose we wanted to expose a C++ class - BigNum which supports addition. That is, in C++ we can write: -

-BigNum a, b, c;
-...
-c = a + b;
-
-

- To enable the same functionality in Python, we first wrap the - BigNum class as usual: -

-boost::python::class_builder<BigNum> bignum_class(my_module, "BigNum");
-bignum_class.def(boost::python::constructor<>());
-...
-
- Then we export the addition operator like this: - -
-bignum_class.def(boost::python::operators<boost::python::op_add>());
-
- - Since BigNum also supports subtraction, multiplication, and division, we - want to export those also. This can be done in a single command by - ``or''ing the operator identifiers together (a complete list of these - identifiers and the corresponding operators can be found in the Table of Automatically Wrapped Methods): -
-bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>());
-
- [Note that the or-expression must be enclosed in parentheses.] - -

This form of operator definition can be used to wrap unary and - homogeneous binary operators (a homogeneous operator has left and - right operands of the same type). Now suppose that our C++ library also - supports addition of BigNums and plain integers: - -

-BigNum a, b;
-int i;
-...
-a = b + i;
-a = i + b;
-
- To wrap these heterogeneous operators, we need to specify a different type for - one of the operands. This is done using the right_operand - and left_operand templates: -
-bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>());
-bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>());
-
- Boost.Python uses overloading to register several variants of the same - operation (more on this in the context of - coercion). Again, several operators can be exported at once: -
-bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(),
-                 boost::python::right_operand<int>());
-bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(), 
-                 boost::python::left_operand<int>());
-
- The type of the operand not mentioned is taken from the class being wrapped. In - our example, the class object is bignum_class, and thus the - other operand's type is ``BigNum const&''. You can override - this default by explicitly specifying a type in the - operators template: -
-bignum_class.def(boost::python::operators<boost::python::op_add, BigNum>(), boost::python::right_operand<int>());
-
-

- Note that automatic wrapping uses the expression - ``left + right'' and can be used uniformly - regardless of whether the C++ operators are supplied as free functions - -

-BigNum operator+(BigNum, BigNum)
-
- - or as member functions - -
-BigNum::operator+(BigNum).
-
- -

- For the Python built-in functions pow() and - abs(), there is no corresponding C++ operator. Instead, - automatic wrapping attempts to wrap C++ functions of the same name. This - only works if those functions are known in namespace - python. On some compilers (e.g. MSVC) it might be - necessary to add a using declaration prior to wrapping: - -

-namespace boost { namespace python { 
-  using my_namespace::pow;
-  using my_namespace::abs;
-}
-
- -

Wrapping Numeric Operators Manually

-

- In some cases, automatic wrapping of operators may be impossible or - undesirable. Suppose, for example, that the modulo operation for BigNums - is defined by a set of functions called mod(): - -

-BigNum mod(BigNum const& left, BigNum const& right);
-BigNum mod(BigNum const& left, int right);
-BigNum mod(int left, BigNum const& right);
-
- -

- For automatic wrapping of the modulo function, operator%() would be needed. - Therefore, the mod()-functions must be wrapped manually. That is, we have - to export them explicitly with the Python special name "__mod__": - -

-bignum_class.def((BigNum (*)(BigNum const&, BigNum const&))&mod, "__mod__");
-bignum_class.def((BigNum (*)(BigNum const&, int))&mod, "__mod__");
-
- -

- The third form of mod() (with int as left operand) cannot - be wrapped directly. We must first create a function rmod() with the - operands reversed: - -

-BigNum rmod(BigNum const& right, int left)
-{
-    return mod(left, right);
-}
-
- - This function must be wrapped under the name "__rmod__" (standing for "reverse mod"): - -
-bignum_class.def(&rmod,  "__rmod__");
-
- - Many of the possible operator names can be found in the Table of Automatically Wrapped Methods. Special treatment is - necessary to export the ternary pow operator. - -

- Automatic and manual wrapping can be mixed arbitrarily. Note that you - cannot overload the same operator for a given extension class on both - ``int'' and ``float'', because Python implicitly - converts these types into each other. Thus, the overloaded variant - found first (be it ``int`` or ``float'') will be - used for either of the two types. - -

Inplace Operators

-

- Boost.Python can also be used to expose inplace numeric operations - (i.e., += and so forth). These operators must be wrapped - manually, as described in the previous section. For example, suppose - the class BigNum has an operator+=: - -

-BigNum& operator+= (BigNum const& right);
-
- - This can be exposed by first writing a wrapper function: - -
-BigNum& iadd (BigNum& self, const BigNum& right)
-{
-  return self += right;
-}
-
- - and then exposing the wrapper with - -
-bignum_class.def(&iadd, "__iadd__");
-
- - - - -

Coercion

- - - Plain Python can only execute operators with identical types on the left - and right hand side. If it encounters an expression where the types of - the left and right operand differ, it tries to coerce these types to a - common type before invoking the actual operator. Implementing good - coercion functions can be difficult if many type combinations must be - supported. -

- Boost.Python solves this problem the same way that C++ does: with overloading. This technique drastically - simplifies the code neccessary to support operators: you just register - operators for all desired type combinations, and Boost.Python automatically - ensures that the correct function is called in each case; there is no - need for user-defined coercion functions. To enable operator - overloading, Boost.Python provides a standard coercion which is implicitly - registered whenever automatic operator wrapping is used. -

- If you wrap all operator functions manually, but still want to use - operator overloading, you have to register the standard coercion - function explicitly: - -

-// this is not necessary if automatic operator wrapping is used
-bignum_class.def_standard_coerce();
-
- - If you encounter a situation where you absolutely need a customized - coercion, you can still define the "__coerce__" operator manually. The signature - of a coercion function should look like one of the following (the first is - the safest): - -
-boost::python::tuple custom_coerce(boost::python::reference left, boost::python::reference right);
-boost::python::tuple custom_coerce(PyObject* left, PyObject* right);
-PyObject* custom_coerce(PyObject* left, PyObject* right);
-
- - The resulting tuple must contain two elements which - represent the values of left and right - converted to the same type. Such a function is wrapped as usual: - -
-// this must be called before any use of automatic operator  
-// wrapping or a call to some_class.def_standard_coerce()
-some_class.def(&custom_coerce, "__coerce__");
-
- - Note that the standard coercion (defined by use of automatic - operator wrapping on a class_builder or a call to - class_builder::def_standard_coerce()) will never be applied if - a custom coercion function has been registered. Therefore, in - your coercion function you should call - -
-boost::python::standard_coerce(left, right);
-
- - for all cases that you don't want to handle yourself. - -

The Ternary pow() Operator

- -

- In addition to the usual binary pow(x, y) operator (meaning - xy), Python also provides a ternary variant that implements - xy mod z, presumably using a more efficient algorithm than - concatenation of power and modulo operators. Automatic operator wrapping - can only be used with the binary variant. Ternary pow() must - always be wrapped manually. For a homgeneous ternary pow(), - this is done as usual: - -

-BigNum power(BigNum const& first, BigNum const& second, BigNum const& modulus);
-typedef BigNum (ternary_function1)(const BigNum&, const BigNum&, const BigNum&);
-...
-bignum_class.def((ternary_function1)&power,  "__pow__");
-
- - If you want to support this function with non-uniform argument - types, wrapping is a little more involved. Suppose you have to wrap: - -
-BigNum power(BigNum const& first, int second, int modulus);
-BigNum power(int first, BigNum const& second, int modulus);
-BigNum power(int first, int second, BigNum const& modulus);
-
- - The first variant can be wrapped as usual: - -
-typedef BigNum (ternary_function2)(const BigNum&, int, int);
-bignum_class.def((ternary_function2)&power,  "__pow__");
-
- - In the second variant, however, BigNum appears only as second - argument, and in the last one it's the third argument. These functions - must be presented to Boost.Python such that that the BigNum - argument appears in first position: - -
-BigNum rpower(BigNum const& second, int first, int modulus)
-{
-    return power(first, second, modulus);
-}
-
-BigNum rrpower(BigNum const& modulus, int first, int second)
-{
-    return power(first, second, modulus);
-}
-
- -

These functions must be wrapped under the names "__rpow__" and "__rrpow__" - respectively: - -

-bignum_class.def((ternary_function2)&rpower,  "__rpow__");
-bignum_class.def((ternary_function2)&rrpower,  "__rrpow__");
-
- -Note that "__rrpow__" is an extension not present in plain Python. - -

Table of Automatically Wrapped Methods

-

- Boost.Python can automatically wrap the following - special methods: - -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- Python Operator Name - - Python Expression - - C++ Operator Id - - C++ Expression Used For Automatic Wrapping
- with cpp_left = from_python(left, - type<Left>()),
- cpp_right = from_python(right, - type<Right>()),
- and cpp_oper = from_python(oper, type<Oper>()) -
- __add__, __radd__ - - left + right - - op_add - - cpp_left + cpp_right -
- __sub__, __rsub__ - - left - right - - op_sub - - cpp_left - cpp_right -
- __mul__, __rmul__ - - left * right - - op_mul - - cpp_left * cpp_right -
- __div__, __rdiv__ - - left / right - - op_div - - cpp_left / cpp_right -
- __mod__, __rmod__ - - left % right - - op_mod - - cpp_left % cpp_right -
- __divmod__, __rdivmod__ - - (quotient, remainder)
- = divmod(left, right)
-
- op_divmod - - cpp_left / cpp_right -
cpp_left % cpp_right -
- __pow__, __rpow__ - - pow(left, right)
- (binary power) -
- op_pow - - pow(cpp_left, cpp_right) -
- __rrpow__ - - pow(left, right, modulo)
- (ternary power modulo) -
- no automatic wrapping, special treatment - required -
- __lshift__, __rlshift__ - - left << right - - op_lshift - - cpp_left << cpp_right -
- __rshift__, __rrshift__ - - left >> right - - op_rshift - - cpp_left >> cpp_right -
- __and__, __rand__ - - left & right - - op_and - - cpp_left & cpp_right -
- __xor__, __rxor__ - - left ^ right - - op_xor - - cpp_left ^ cpp_right -
- __or__, __ror__ - - left | right - - op_or - - cpp_left | cpp_right - -
- __cmp__, __rcmp__ - - cmp(left, right)
-
See Rich Comparisons. -
- op_cmp - - cpp_left < cpp_right  -
cpp_right < cpp_left -
- __lt__ -
__le__ -
__eq__ -
__ne__ -
__gt__ -
__ge__ -
- left < right -
left <= right -
left == right -
left != right -
left > right -
left >= right -
See Rich Comparisons -
- op_lt -
op_le -
op_eq -
op_ne -
op_gt -
op_ge -
- cpp_left < cpp_right  -
cpp_left <= cpp_right  -
cpp_left == cpp_right  -
cpp_left != cpp_right  -
cpp_left > cpp_right  -
cpp_left >= cpp_right  - -
- __neg__ - - -oper  (unary negation) - - op_neg - - -cpp_oper -
- __pos__ - - +oper  (identity) - - op_pos - - +cpp_oper -
- __abs__ - - abs(oper)  (absolute value) - - op_abs - - abs(cpp_oper) -
- __invert__ - - ~oper  (bitwise inversion) - - op_invert - - ~cpp_oper -
- __int__ - - int(oper)  (integer conversion) - - op_int - - long(cpp_oper) -
- __long__ - - long(oper) 
- (infinite precision integer conversion) -
- op_long - - PyLong_FromLong(cpp_oper) -
- __float__ - - float(oper)  (float conversion) - - op_float - - double(cpp_oper) -
- __str__ - - str(oper)  (string conversion) - - op_str - - std::ostringstream s; s << oper; -
- __coerce__ - - coerce(left, right) - - usually defined automatically, otherwise - special treatment required -
- -

Sequence and Mapping Operators

- -

- Sequence and mapping operators let wrapped objects behave in accordance - to Python's iteration and access protocols. These protocols differ - considerably from the ones found in C++. For example, Python's typical - iteration idiom looks like - -

-for i in S:
-
- - while in C++ one writes - -
-for (iterator i = S.begin(), end = S.end(); i != end; ++i)
-
- -

One could try to wrap C++ iterators in order to carry the C++ idiom into - Python. However, this does not work very well because - -

    -
  1. It leads to - non-uniform Python code (wrapped sequences support a usage different from - Python built-in sequences) and - -
  2. Iterators (e.g. std::vector::iterator) are often implemented as plain C++ - pointers which are problematic for any automatic - wrapping system. -
- -

- It is a better idea to support the standard Python - sequence and mapping protocols for your wrapped containers. These - operators have to be wrapped manually because there are no corresponding - C++ operators that could be used for automatic wrapping. The Python - documentation lists the relevant - container operators. In particular, expose __getitem__, __setitem__ - and remember to raise the appropriate Python exceptions - (PyExc_IndexError for sequences, - PyExc_KeyError for mappings) when the requested item is not - present. - -

- In the following example, we expose std::map<std::size_t,std::string>: -

-
-typedef std::map<std::size_t, std::string> StringMap;
-
-// A helper function for dealing with errors. Throw a Python exception
-// if p == m.end().
-void throw_key_error_if_end(
-        const StringMap& m, 
-        StringMap::const_iterator p, 
-        std::size_t key)
-{
-    if (p == m.end())
-    {
-        PyErr_SetObject(PyExc_KeyError, boost::python::converters::to_python(key));
-        boost::python::throw_error_already_set();
-    }
-}
-
-// Define some simple wrapper functions which match the Python  protocol
-// for __getitem__, __setitem__, and __delitem__.  Just as in Python, a
-// free function with a ``self'' first parameter makes a fine class method.
-
-const std::string& get_item(const StringMap& self, std::size_t key)
-{
-    const StringMap::const_iterator p = self.find(key);
-    throw_key_error_if_end(self, p, key);
-    return p->second;
-}
-
-// Sets the item corresponding to key in the map.
-void StringMapPythonClass::set_item(StringMap& self, std::size_t key, const std::string& value)
-{
-    self[key] = value;
-}
-
-// Deletes the item corresponding to key from the map.
-void StringMapPythonClass::del_item(StringMap& self, std::size_t key)
-{
-    const StringMap::iterator p = self.find(key);
-    throw_key_error_if_end(self, p, key);
-    self.erase(p);
-}
-
-class_builder<StringMap> string_map(my_module, "StringMap");
-string_map.def(boost::python::constructor<>());
-string_map.def(&StringMap::size, "__len__");
-string_map.def(get_item, "__getitem__");
-string_map.def(set_item, "__setitem__");
-string_map.def(del_item, "__delitem__");
-
-
-

- Then in Python: -

-
->>> m = StringMap()
->>> m[1]
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-KeyError: 1
->>> m[1] = 'hello'
->>> m[1]
-'hello'
->>> del m[1]
->>> m[1]            # prove that it's gone
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-KeyError: 1
->>> del m[2]
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-KeyError: 2
->>> len(m)
-0
->>> m[0] = 'zero'
->>> m[1] = 'one'
->>> m[2] = 'two'
->>> m[3] = 'three'
->>> len(m)
-4
-
-
- -

Customized Attribute Access

- -

- Just like built-in Python classes, Boost.Python extension classes support special - the usual attribute access methods __getattr__, - __setattr__, and __delattr__. - Because writing these functions can - be tedious in the common case where the attributes being accessed are - known statically, Boost.Python checks the special names - -

    -
  • - __getattr__<name>__ -
  • - __setattr__<name>__ -
  • - __delattr__<name>__ -
- - to provide functional access to the attribute <name>. This - facility can be used from C++ or entirely from Python. For example, the - following shows how we can implement a ``computed attribute'' in Python: -
-
->>> class Range(AnyBoost.PythonExtensionClass):
-...    def __init__(self, start, end):
-...        self.start = start
-...        self.end = end
-...    def __getattr__length__(self):
-...        return self.end - self.start
-...
->>> x = Range(3, 9)
->>> x.length
-6
-
-
-

- Direct Access to Data Members -

-

- Boost.Python uses the special - __xxxattr__<name>__ functionality described above - to allow direct access to data members through the following special - functions on class_builder<> and - extension_class<>: -

    -
  • - def_getter(pointer-to-member, name) // - read access to the member via attribute name -
  • - def_setter(pointer-to-member, name) // - write access to the member via attribute name -
  • - def_readonly(pointer-to-member, name) - // read-only access to the member via attribute name -
  • - def_read_write(pointer-to-member, - name) // read/write access to the member via attribute - name -
-

- Note that the first two functions, used alone, may produce surprising - behavior. For example, when def_getter() is used, the - default functionality for setattr() and - delattr() remains in effect, operating on items in the extension - instance's name-space (i.e., its __dict__). For that - reason, you'll usually want to stick with def_readonly and - def_read_write. -

- For example, to expose a std::pair<int,long> we - might write: -

-
-typedef std::pair<int,long> Pil;
-int first(const Pil& x) { return x.first; }
-long second(const Pil& x) { return x.second; }
-   ...
-my_module.def(first, "first");
-my_module.def(second, "second");
-
-class_builder<Pil> pair_int_long(my_module, "Pair");
-pair_int_long.def(boost::python::constructor<>());
-pair_int_long.def(boost::python::constructor<int,long>());
-pair_int_long.def_read_write(&Pil::first, "first");
-pair_int_long.def_read_write(&Pil::second, "second");
-
-
-

- Now your Python class has attributes first and - second which, when accessed, actually modify or reflect the - values of corresponding data members of the underlying C++ object. Now - in Python: -

-
->>> x = Pair(3,5)
->>> x.first
-3
->>> x.second
-5
->>> x.second = 8
->>> x.second
-8
->>> second(x) # Prove that we're not just changing the instance __dict__
-8
-
-
-

- And what about __complex__? -

-

- That, dear reader, is one problem we don't know how to solve. The - Python source contains the following fragment, indicating the - special-case code really is hardwired: -

-
-/* XXX Hack to support classes with __complex__ method */
-if (PyInstance_Check(r)) { ...
-
-
-

-Next: A Peek Under the Hood -Previous: Inheritance -Up: Top -

- © Copyright David Abrahams and Ullrich Köthe 2000. - 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. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/under-the-hood.html b/doc/under-the-hood.html deleted file mode 100644 index ee0ecdfb..00000000 --- a/doc/under-the-hood.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - A Peek Under the Hood - -

- c++boost.gif (8819 bytes) -

-

- A Peek Under the Hood -

-

- Declaring a class_builder<T> causes the instantiation - of an extension_class<T> to which it forwards all - member function calls and which is doing most of the real work. - extension_class<T> is a subclass of - PyTypeObject, the struct which Python's 'C' API uses - to describe a type. An instance of the - extension_class<> becomes the Python type object - corresponding to hello::world. When we add it to the module it goes into the - module's dictionary to be looked up under the name "world". -

- Boost.Python uses C++'s template argument deduction mechanism to determine the - types of arguments to functions (except constructors, for which we must - provide an argument list - because they can't be named in C++). Then, it calls the appropriate - overloaded functions PyObject* - to_python(S) and - S'from_python(PyObject*, - type<S>) which convert between any C++ - type S and a PyObject*, the type which represents a - reference to any Python object in its 'C' API. The extension_class<T> - template defines a whole raft of these conversions (for T, T*, - T&, std::auto_ptr<T>, etc.), using the same inline - friend function technique employed by the boost operators - library. -

- Because the to_python and from_python functions - for a user-defined class are defined by - extension_class<T>, it is important that an instantiation of - extension_class<T> is visible to any code which wraps - a C++ function with a T, T*, const T&, etc. parameter or - return value. In particular, you may want to create all of the classes at - the top of your module's init function, then def the member - functions later to avoid problems with inter-class dependencies. -

- Next: Building a Module with Boost.Python - Previous: Special Method and Operator Support - Up: Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Nov 26, 2000 - diff --git a/doc/v2/Apr2002.html b/doc/v2/Apr2002.html deleted file mode 100644 index 5789b3f8..00000000 --- a/doc/v2/Apr2002.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - -Boost.Python - April 2002 Progress Report - - - - - - - -
-

-

-
-

Boost.Python

-

April 2002 Progress Report

-
-


-

Contents

-
-
Accomplishments
-
-
Arbitrary Arity Support
-
New Callback Interface
-
Call Policies for Construtors
-
Real Users, Real Bugs
-
New Insights
-
Boost.Python V1 Maintenance
-
- -
What's Missing
- -
- -

Accomplishments

- -April was a short month as far as Boost.Python was concerned, since -the spring ISO C++ Committee Meeting (and associated vacation) -occupied me for the 2nd half of the month. However, a suprising amount -of work got done... - -

Arbitrary Arity Support

- -I began using the Boost.Preprocessor -metaprogramming library to generate support for functions and member -functions of arbitrary arity, which was, to say the least, quite an -adventure. The feedback cycle resulting from my foray into -Boost.Preprocessor resulted in several improvements to the library, -most notably in its documentation. - -

- -Boost.Python now supports calls of up to 17 arguments on most -compilers. Because most EDG-based compilers have dismal preprocessor -performance, I had to "manually" expand the metaprograms for -arities from zero to fifteen arguments, and EDG-based compilers with -__EDG_VERSION__ <= 245 only support 15 -arguments by default. If some crazy program finds a need for more than -the default arity support, users can increase the base support by -setting the BOOST_PYTHON_MAX_ARITY preprocessor symbol. - -

New Callback Interface

- -I mentioned in last month's report that I -wasn't pleased with the interface for the interface for calling into -Python, so now it has been redesigned. The new interface is outlined -in this -message (though the GCC 2.95.3 bugs have been fixed). - -

Call Policies for Constructors

- -On April 2nd, I announced -support for the use of call policies with constructors. - -

Real Users, Real Bugs

- -At least two people outside of Kull began actually using Boost.Python -v2 in earnest this month. Peter Bienstman and Pearu Pearson both -provided valuable real-world bug reports that helped me to improve the -library's robustness. - -

New Insights

- -Answering some of Pearu's questions about explicitly converting -objects between Python and C++ actually led me to a new understanding -of the role of the current conversion facilities. In Boost.Python v1, -all conversions between Python and C++ were handled by a single family -of functions, called to_python() and -from_python(). Since the primary role of Boost.Python is -to wrap C++ functions in Python, I used these names for the first kind -of converters I needed: those that extract C++ objects to be used as -function arguments and which C++ function return values to -Python. The better-considered approach in Boost.Python v2 uses a -completely different mechanism for conversions used when calling -Python from C++, as in wrapped virtual function implementations. I -usually think of this as a "callback", as in "calling -back into Python", and I named the converters used in callbacks -accordingly: to_python_callback and -from_python_callback. However, as it turns out, the -behavior of the "callback" converters is the appropriate one -for users who want to explicitly extract a C++ value from a Python -object, or create a Python object from a C++ value. The upshot is that -it probably makes sense to change the name of the existing to_python and -from_python so those names are available for the -user-friendly explicit converters. - -

-Another -of Pearu's questions pushes momentum further in the direction of a -more-sophisticated overloading mechanism than the current -simple-minded "first match" approach, as I suggested last month. - -

Boost.Python V1 Maintenance

- -As much as I'm looking forward to retiring Boost.Python v1, a -significant amount of effort has been being spent dealing with support -problems; the saying that code rots when left alone is true, and -Boost.Python is no exception. Eventually it became obvious to me that -we were going to have to invest some effort in keeping V1 healthy -while working on V2. Ralf and I have expanded support for various -compilers and stabilized the V1 codebase considerably. We discarded -the obsolete Visual Studio projects which were causing so much -confusion. Still to do before the next Boost release: -
    -
  1. Update the build/test documentation with detailed instructions for -configuring various toolsets. -
  2. Provide some links to Boost.Python v2 to let people know what's -coming. -
- - -

What's Missing

- -Last month I announced that I would implement the following which are -not yet complete: -
    -
  1. Document all implemented features -
  2. Implement conversions for char types. This is -implemented but not tested, so we have to assume it doesn't work. -
- -These are my first priority for this month (especially the -documentation). - -

Revised - - 3 May, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/CallPolicies.html b/doc/v2/CallPolicies.html deleted file mode 100644 index 3c2b98fd..00000000 --- a/doc/v2/CallPolicies.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - -Boost.Python - CallPolicies Concept - - - - - - - -
-

C++ Boost

-
-

Boost.Python

-

CallPolicies Concept

-
-
-
-
Introduction
-
CallPolicies Composition
-
Concept Requirements
-
-
CallPolicies Concept
-
-
- -

Introduction

- -

Models of the CallPolicies concept are used to specialize the -behavior of Python callable objects generated by Boost.Python to -wrapped C++ objects like function and member function -pointers, providing three behaviors: -

    -
  1. precall - Python argument tuple management before -the wrapped object is invoked -
  2. result_converter - C++ return value handling -
  3. postcall - Python argument tuple and result -management after the wrapped object is invoked -
- -

CallPolicies Composition

- -In order to allow the use of multiple models of CallPolicies in the -same callable object, Boost.Python's CallPolicies class templates -provide a chaining interface which allows them to be recursively -composed. This interface takes the form of an optional template -parameter, Base which defaults to -default_call_policies. By convention, the -precall function of the -Base is invoked after the precall -function supplied by the outer template, and the postcall -function of the Base is invoked before the -postcall function of the outer template. If a -result_converter is supplied by the outer template, it -replaces any result_converter supplied by the -Base. For an example, see -return_internal_reference. - -

Concept Requirements

-

CallPolicies Concept

- -

In the table below, x denotes an object whose -type P is a model of CallPolicies, -a denotes a PyObject* pointing to -a Python argument tuple object, and r denotes a -PyObject* referring to a "preliminary" result -object. - - - - - - - - - - - - - - - -
ExpressionTypeResult/Semantics
x.precall(a)convertible to bool - returns false and PyErr_Occurred() != 0 - upon failure, true otherwise. - -
P::result_converterA model of ResultConverterGenerator. - An MPL unarymetafunction object used produce the - "preliminary" result object. - -
x.postcall(a, r)convertible to PyObject* - 0 0 and PyErr_Occurred() != 0 - upon failure. Must "conserve references" even in the - event of an exception. In other words, if r is not - returned, its reference count must be decremented; if another - existing object is returned, its reference count must be - incremented. -
- -Models of CallPolicies are required to be CopyConstructible. - -


-

Revised - - 19 May, 2002 - -

-

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

Permission to copy, use, modify, sell - and distribute this software is granted provided this copyright notice appears - in all copies. This software is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose. - - diff --git a/doc/v2/Dereferenceable.html b/doc/v2/Dereferenceable.html deleted file mode 100644 index 60ff06c2..00000000 --- a/doc/v2/Dereferenceable.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -Boost.Python - Dereferenceable Concept - - - - - - - -
-

C++ Boost

-
-

Boost.Python

-

Dereferenceable Concept

-
-


-
-
Introduction
-
Concept Requirements
-
-
Dereferenceable Concept
-
-
- -

Introduction

- -

Instances of a dereferenceable type can be used like a pointer to access an lvalue. - -

Concept Requirements

-

Dereferenceable Concept

- -

In the table below, x denotes an object whose -type is a model of Dereferenceable. - - - - - - - - - - - -
ExpressionRequirements
*xAn lvalue -
- -


-

Revised - - 10 May, 2002 - -

-

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

Permission to copy, use, modify, sell - and distribute this software is granted provided this copyright notice appears - in all copies. This software is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose. - - diff --git a/doc/v2/Extractor.html b/doc/v2/Extractor.html deleted file mode 100755 index 97ef6fd4..00000000 --- a/doc/v2/Extractor.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - -Boost.Python - Extractor Concept - - - - - - - -
-

C++ Boost

-
-

Boost.Python

-

Extractor Concept

-
-


-
-
Introduction
-
Concept Requirements
-
-
Extractor Concept
-
-
Notes
-
- -

Introduction

- -

An Extractor is a class which Boost.Python can use to extract C++ -objects from Python objects, and is typically used by facilities that -define from_python conversions for -"traditional" Python extension types. - -

Concept Requirements

-

Extractor Concept

- -

In the table below, X denotes a model of -Extractor and a denotes an instance of a Python -object type. - - - - - - - - - - - - - - - - - - -
ExpressionTypeSemantics
X::execute(a)non-void - Returns the C++ object being extracted. The - execute function must not be overloaded. -
&a.ob_type - PyTypeObject** - Points to the ob_type field of an object which is - layout-compatible with PyObject -
- -

Notes

- -Informally, an Extractor's execute member must be a -non-overloaded static function whose single argument is a Python -object type. Acceptable Python object types include those publicly (and -unambiguously) derived from PyObject, and POD types which -are layout-compatible with PyObject. - -
-

Revised - - 22 May, 2002 - -

-

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

Permission to copy, use, modify, sell - and distribute this software is granted provided this copyright notice appears - in all copies. This software is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose. - - diff --git a/doc/v2/HolderGenerator.html b/doc/v2/HolderGenerator.html deleted file mode 100755 index 1b9b8d89..00000000 --- a/doc/v2/HolderGenerator.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - -Boost.Python - Holder Concept - - - - - - - -
-

C++ Boost

-
-

Boost.Python

-

HolderGenerator Concept

-
-


-
-
Introduction
-
Concept Requirements
-
-
HolderGenerator Concept
-
-
- -

Introduction

- -

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

Concept Requirements

-

HolderGenerator Concept

- -

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


-

Revised - - 20 May, 2002 - -

-

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

Permission to copy, use, modify, sell - and distribute this software is granted provided this copyright notice appears - in all copies. This software is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose. - - diff --git a/doc/v2/Jun2002.html b/doc/v2/Jun2002.html deleted file mode 100644 index 7863ff27..00000000 --- a/doc/v2/Jun2002.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - -Boost.Python - June 2002 Progress Report - - - - - - - -
-

-

-
-

Boost.Python

-

June 2002 Progress Report

-
-


-

Contents

-
-
Introduction
-
handle<T>
-
object
-
-
object operators
-
object conversions
-
-
list
-
Numerics
-
Community
-
What's Next
-
- -

Introduction

- -July was mostly focused on allowing expressive manipulation of -individual Python objects, or what Ralf Grosse-Kunstleve calls -"Writing Python in C++". The work began with this posting, -which outlines the issues and intention. - -

handle<T>

- -The most basic element needed was a replacement for the -reference<> class template and the -ref typedef from Boost.Python v1, a simple smart -pointer to a Python object. The old v1 typedef -"ref" (for -reference<PyObject>) had to be retired because I -thought it would be too confusing given the importance of boost::ref() to this -library. I began a discussionof -possible names, and it was eventually decided -to rename reference to handle and supply a -default argument so that ref could be spelled -handle<> without an additional typedef. There -were also some interface changes to make it safer and more-efficient -to interface with the raw -PyObject*s forced on us by Python's 'C' API. A -discussion of those protocols can be found here. - -

object

- -It is intended that users will seldom need or want to work with -handle<>; its major distinguishing features are -that it gives direct access to the underlying object representation -through operator* and operator->, and -that can be NULL, both sources of danger. Instead the -library provides a class called object, which -encapsulates a valid Python object and provides a similar interface to -Python's. - -

object operators

- -The first challenge was to provide support for object manipulations -using a Python-like syntax, mostly in the form of operator overloads: - - - - - - - - - - - - - -
Python C++ - -
y = x.foo y = x.attr("foo"); -
x.foo = 1 x.attr("foo") = 1; - -
y = x[z] y = x[z]; -
x[z] = 1 x[z] = 1; - -
y = x[3:-1] y = x.slice(3,-1); - -
y = x[3:] y = x.slice(3,_); - -
y = x[:-2] y = x.slice(_,-2); - -
z = x(1, y) z = x(1, y); -
z = x.f(1, y) z = x.attr("f")(1, y); - -
not x !x - -
x and y x and y -
- -I'm still a unsatisfied with the interface for attribute access. There -original proposal used a syntax like this one: -
-y = x._("foo"); 
-x._("foo") = 1; 
-
- -which was only marginally better than what we've got. Niki Spahiev -then pointed -out a potential conflict with the macro which GNU Gettext suggests -people define. This unfortunate state of affairs forced us into using -attr instead. I'd still like to find a better interface, -but the lack of overloadable C++ operators which aren't already used -in Python is an obstacle. The comma operator is still a possibility, -but it has the wrong precedence: -
-y = x,"foo"    // error
-x,"foo" = 1;   // error
-
-y = (x,"foo"); // ok
-(x,"foo") = 1; // ok
-
- -Well, I guess we could consider adding that to the interface without -removing attr(), to see how it plays out... - -

object conversions

- -The object class also provided an opportunity to replace -Boost.Python v1's to_python() as a user-level -interface. Instead, object has a templated constructor -which can be used to convert any C++ object to Python using the same -underlying mechanisms used for the arguments to call<>. - -

Incidentally, the implementation of operator and conversion support -for object uncovered an inordinate number of compiler bugs in our -targeted platforms. It was a lot more "interesting" than it -should have been. - -

list

- -With object implemented, it was time to begin replacing -the ad-hoc implementations of list, string, -and dictionary supplied by Boost.Python v1 with something -more robust. I started with list as an example. Because -object already provides all of the requisite operators, -publicly deriving list from object seemed like a good -choice. The remaining issues were what do do about the one-argument -list constructor (which in Python attempts to convert its argument to -a list), and how to deal converting with list arguments -to wrapped functions. Some of the issues are laid out in this -thread. Ultimately, it was decided that list(x) -should do the same thing in C++ as in Python (conversion), while -list arguments should only match Python -lists (and list subclasses). The -implementation worked well, and provided a roadmap -for the protocol to be used for implementation of the other built-in -types. - -

Numerics

- -Support for C++ long long and unsigned long -long -(and __int64 on MSVC) to/from python conversions was -added this month. We also improved handling of numeric overflows when -converting, e.g., a Python int to a type with a more limited range of -representation. - -

Community

- - - -Deep thanks to all the Boost.Python contributors! This project -wouldn't be possible without your participation. - -

What's Next

- -As I write this we are already well into the month of July, so I -suggest you consult the Mailing -List Archive if you want to know what's been happening. Otherwise -you'll just have to wait till next month (hopefully the beginning). - -

Revised - - 19 July, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/Mar2002.html b/doc/v2/Mar2002.html deleted file mode 100644 index 0425c3e5..00000000 --- a/doc/v2/Mar2002.html +++ /dev/null @@ -1,234 +0,0 @@ - - - - -Boost.Python - March 2002 Progress Report - - - - - - - -
-

-

-
-

Boost.Python

-

March 2002 Progress Report

-
-
-

Contents

-
-
Accomplishments
-
-
Calling Python from C++
-
Virtual Functions
-
Abstract Classes
-
C++ Implicit Conversions
-
C++ Data Members
-
Miscellaneous
-
- -
The Near future
- -
Notes
- -
- -

Accomplishments

- -March was mostly devoted to the reimplementation of features from -Boost.Python v1, and some new features. Re-examination of the features -from Boost.Python v1 allowed me to make significant improvements. - -

Calling Python from C++

- -The ability to call Python from C++ is crucial for virtual function -support. Implementing this feature well for V2 proved to be more -interesting than I expected. You can review most of the relevant -design decisions -here. - -

-One point which isn't emphasized in that document is that there -are subtle differences in the way from_python conversions -work when used for C++ function arguments and Python function return -values. In particular, while T const& arguments may -invoke rvalue converters, a reference-to-const return value requires -an lvalue converter, since a temporary conversion result would leave -the returned reference dangling. - -

I'm not particularly pleased with the current callback interface, -since it usually results in constructs like: -

-return returning<X&>::call(f, obj);
-
-However, I think the following may be possible and I plan to investigate: -
-return apply<X&>(f, obj);
-
-I'm open to suggestion for better names (and syntaxes)! - -

Virtual Functions

- -Once Python callbacks were implemented, it was just a short step to -implementing virtual functions. Python extension class exposing a C++ -class whose virtual functions are overridable in Python must actually -hold a C++ instance of a class derived from the one exposed to -Python. Needing some way for users to specify that class, I added an -optional template argument to value_holder_generator and -pointer_holder_generator<> to specify the class -actually held. This move began to put pressure on the -class_<> interface, since the need for the user to -produce complicated instantations of -class_<> was increased: - -
-class<Foo, bases<>, value_holder_generator<Foo_callback> >("Foo")
-.def("hello", &Foo::hello)
-...
-
- -

Abstract Classes

- -Normally when a C++ class is exposed to Python, the library registers -a conversion function which allows users to wrap functions returning -values of that type. Naturally, these return values are temporaries, -so the conversion function must make a copy in some -dynamically-allocated storage (a "holder") which is managed -by the corresponding Python object. - -

Unfortunately, in the case of abstract classes (and other types -without a publicly-accessible copy constructor), instantiating this -conversion function causes a compilation error. In order to support -non-copyable classes, there had to be some way to prevent the library -from trying to instantiate the conversion function. The only practical -approach I could think of was to add an additional template parameter -to the class_<> interface. When the number of -template parameters with useful defaults begins to grow, it is often -hard to choose an order which allows users to take advantage of the -defaults. - -

- -This was the straw that broke the -class_<> interface's back and caused the redesign -whose outcome is detailed here. -The approach allows the user to supply the optional parameters in an -arbitrary order. It was inspired by the use of named -template parameters in the Boost Iterator Adaptor -Library, though in this case it is possible to deduce the meaning -of the template parameters entirely from their type properties, -resulting in a simpler interface. Although the move from a -policy-based design to what resembles a configuration DSL usually -implies a loss of flexibility, in this case I think any costs are far -outweighed by the advantages. - -

Note: working around the limitations of the various compilers I'm -supporting was non-trivial, and resulted in a few messy implementation -details. It might be a good idea to switch to a more-straightforward -approach once Metrowerks CodeWarrior Pro8 is released. - -

C++ Implicit Conversions

- -Support for C++ implicit conversion involves creating -from_python converters for a type U which in -turn use from_python converters registered for a type -T where there exists a implicit conversion from -T to U. The current implementation is -subject to two inefficiencies: -
    - -
  1. Because an rvalue from_python converter produces two -pieces of data (a function and a void*) from its -convertible() function, we end up calling the function -for T twice: once when the converter is looked up in the -registry, and again when the conversion is actually performed. - -
  2. A vector is used to mark the "visited" converters, preventing -infinite recursion as T to -U and U to T converters -continually search through one-another. - -
- -I consider the former to be a minor issue. The second may or may not -prove to be computationally significant, but I believe that -architecturally, it points toward a need for more sophisticated -overload resolution. It may be that we want CLOS-style multimethod -dispatching along with C++ style rules that prevent more than one -implicit conversion per argument. - -

C++ Data Members

- -To supply the ability to directly access data members, I was able to -hijack the new Python property -type. I had hoped that I would also be able to re-use the work of make_function to create callable python -objects from C++ functions which access a data member of a given -class. C++ facilities for specifying data member pointer non-type -template arguments require the user to explicitly specify the type of -the data member and this under-utilized feature is also not -well-implemented on all compilers, so passing the member pointer as a -runtime value is the only practical approach. The upshot is that any -such entity would actually have to be a function object, and I -haven't implemented automatic wrapping of C++ callable function -objects yet, so there is less re-use in the implementation than I'd -like. I hope to implement callable object wrapping and refactor this -code one day. I also hope to implement static data member support, -for which Python's property will not be an appropriate descriptor. - -

Miscellaneous

-
    -
  • Moved args<> and bases<> from unnamed namespace to boost::python in their own header files. -
  • Convert NULL pointers returned from wrapped C++ functions to None. -
  • Improved some compile-time error checks. -
  • Eliminated boost/python/detail/eval.hpp in favor of -more-general boost/mpl/apply.hpp. -
  • General code cleanup and refactoring. -
  • Works with Microsoft Visual C++ 7.0 -
  • Warning suppression for many compilers -
  • Elegant interface design for exporting enum types. -
-
- -

The Near Future

- -Before April 15th I plan to -
    -
  1. Document all implemented features -
  2. Implement a CallPolicy interface for constructors of wrapped -classes -
  3. Implement conversions for char types. -
  4. Implement automated code generation for all headers containing -families of overloaded functions to handle arbitrary arity. -
- -I also hope to implement a mechanism for generating conversions -between arbitrary Python sequences and C++ containers, if time permits -(and others haven't already done it)! - -

Notes

- -The older version of KCC used by Kull is generating lots of warnings -about a construct I use to instantiate static members of various class -templates. I'm thinking of moving to an idiom which uses a function -template to suppress it, but worry about bloating the size of debug -builds. Since KCC users may be moving to GCC, I'm not sure that it's -worth doing anything about it. - -

Revised - - 1 April, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/May2002.html b/doc/v2/May2002.html deleted file mode 100644 index d94481cb..00000000 --- a/doc/v2/May2002.html +++ /dev/null @@ -1,309 +0,0 @@ - - - - -Boost.Python - May 2002 Progress Report - - - - - - - -
-

-

-
-

Boost.Python

-

May 2002 Progress Report

-
-
-

Contents

-
-
Introduction
-
New Features
-
-
Shared Library Support for AIX
-
Class Enhancements
-
-
Operators
-
Iterators
-
Properties
-
setattr
-
__module__ Attribute
-
-
back_reference
-
- -
Documentation
-
Miscellaneous
-
-
Converters
-
Checkins Mailing List
-
Shared Libraries
-
- -
What's Next
-
- -

Introduction

- -Aside from library development, work on Boost.Python in May was -focused on reducing the support burden. In recent weeks, responding to -requests for support, espcially surrounding building the library, had -begun to impede progress on development. There was a major push to -release a stable 1.28.0 of Boost, including documentation of Boost.Build and specific -instructions for building Boost.Python -v1. The documentation for Boost.Python v2 was also updated as -described here. - -

New Features

- -

Shared Library Support for AIX

- - The Kull group required the ability to build and test Boost.Python - extensions on AIX, a platform with "creatively designed" - shared library semantics. Making this work was a multi-pronged - effort, involving changes to Boost.Build and some great research by - Martin Casado which uncovered the key mechanism required to allow - shared libraries to use functions from the Python executable. The - current solution used in Boost.Build relies on a Python - Script as part of the build process. This is not a problem for - Boost.Python, as Python will be available. However, the commands - issued by the script are so simple that a 100%-pure-Boost.Jam - solution is surely possible. Linking on AIX is sufficiently - interesting to have skewed the Boost.Python development schedule a - bit. - -

Class Enhancements

- -

Operators

- -Support for exposing C++ operators and functions as the corresponding -Python special methods was added. Thinking that the Boost.Python -v1 interface was a little too -esoteric (especially the use of -left_operand<...>/right_operand<...> for -asymmetric operands), I introduced a simple form of expression -templates which allow users to simply write the expressions that -should be wrapped, as in this example. - -

Iterators

- -Python iterator support as required by the Kull project resulted in a -highly flexible interface allowing: - -
- -
Direct exposure of a class' begin() and -end() functions: - -
-    ...
-    .def("__iter__", iterator<list_int>())
-
-
- -
Creation of iterators from member functions... -
-    ...
-    .def("__iter__"
-         , range(&my_class::x_begin, &my_class::x_end))
-    )
-
-
- -
...and member data: -
-    ...
-    .def("__iter__"
-         , range(&std::pair<char*,char*>::first, &std::pair<char*,char*>::second))
-    )
-
-
- -
The ability to specify CallPolicies, e.g. to prevent copying of -heavyweight values: - -
-    ...
-    .def("__iter__", 
-         , range<return_value_policy<copy_non_const_reference> >(
-               &my_sequence<heavy>::begin
-             , &my_sequence<heavy>::end))
-
-
- -
- -

Properties

- -The Kull iteration interfaces also required the ability to iterate -over a sequence specified by an instance's attribute: -
->>> f = field()
->>> for e in f.elements:
-...     print e,
-
- -This forced the exposure of the property - interface used internally to implement the data member exposure - facility described in March. Properties are an - incredibly useful idiom, so it's good to be able to provide them - at little new development cost. - -

setattr

- -class_<> acquired a setattr member -function which allows users to easily add new Python objects as class -attributes. - -

__module__ Attribute

- -Ralf Grosse-Kunstleve has been working on pickling support for v2. To -make it work correctly, he had to make sure that a class' -__module__ attribute was set correctly. - -

back_reference

- -The new back_reference<T> template can be used as a -function parameter when the user needs access to both a T -argument and to the Python object which manages it. The function will -only match in the overload resolution process if it would match the -same function signature with T substituted for -back_reference<T>. This feature is not yet -documented. - -

Documentation

- -In a major effort to prepare Boost.Python v2 to replace v1, many pages -of new reference documentation were added: - -
- -
-
CallPolicies.html
-
Dereferenceable.html
-
Extractor.html
-
HolderGenerator.html
-
ResultConverter.html
-
call_method.html
-
callbacks.html
-
data_members.html
-
has_back_reference.html
-
implicit.html
-
instance_holder.html
-
operators.html
-
ptr.html
-
type_id.html
-
with_custodian_and_ward.html
-
- -
-Major updates were made to the following pages: - - -
-
-
call.html
updated
-
class.html
-
reference.html
-
-
- - As usual, careful documentation forces one to consider the - interface again, and there were many interface changes - associated with this effort, including the elevation of the - following components from implementation detail to - first-class library citizen: - -
-
-
type_id.hpp
-
pointee.hpp
-
lvalue_from_pytype.hpp
- -
- -

Miscellaneous

- -

Converters

- -It appears that the world of C++ <==> Python conversion rules is -an endlessly-rich area of exploration. Completing the conversions for -char and char const* types, as described at -the end of April's report, -uncovered some interesting new shades to the problem. It turns out to -be worth distinguishing mutable and immutable lvalue conversions, -because despite the fact that Python doesn't understand -const, it does understand immutability (c.f. Python -strings, which expose an immutable char pointer). It is -also worth recognizing types which represent lvalue sequences, -to prevent Python "foobar" from being silently -truncated to C++ 'f'. More details on this insight can be -found in the mailing list -archive. I don't plan to do anything about this immediately, but I -do think it's the right direction to go in the long run. - -

Checkins Mailing List

- -In order to better coordinate changes made by multiple developers, I -enabled syncmail -for the Boost.Python CVS trees, and established an associated mailing -list. Subscribe to this list to receive notices of each new -checkin. - -

Shared Libraries

- -Beyond the vagaries of dynamic linking on AIX, I have been -participating in a more-general discussion of dynamic linking for -C++. Needless to say, C++ dynamic linking is of critical importance to -Boost.Python: all extension modules are normally built as shared -libraries, and Boost.Python extension modules share a common library -as well. - -In fact, there are at least two separate conversations. One -in the C++ standard extensions mailing list concerns what can be -standardized for C++ and shared libraries; the other, mostly on the gcc mailing list, concerns the -behavior of GCC on Posix/ELF platforms. - -Some of the GCC threads are here: - -
-http://gcc.gnu.org/ml/gcc/2002-05/msg02002.html
-http://gcc.gnu.org/ml/gcc/2002-05/msg02945.html
-http://gcc.gnu.org/ml/gcc/2002-05/msg01758.html -
- -

What's Next

- -Development is focused on what's needed to be able to retire -Boost.Python v1. At the moment, that means deciding the user-friendly -interfaces for to_/from_python conversion, and formally exposing the -Python object smart pointers and object wrapper classes. Quite a few -questions have also been showing up recently about how to embed Python -with Boost.Python, and how to link with it statically; the solutions -to these issues will probably have to be formalized before long. - -

Revised - - 11 June, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/ResultConverter.html b/doc/v2/ResultConverter.html deleted file mode 100644 index 08d81b1a..00000000 --- a/doc/v2/ResultConverter.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - -Boost.Python - ResultConverter Concept - - - - - - - -
-

C++ Boost

-
-

Boost.Python

-

ResultConverter Concept

-
-
-
-
Introduction
-
Concept Requirements
-
-
ResultConverter Concept
-
ResultConverterGenerator Concept
-
-
- -

Introduction

- -

A ResultConverter for a type T is a type whose -instances can be used to convert C++ return values of type -T to_python. A ResultConverterGenerator is -an MPL unary metafunction class which, given the return type of a C++ -function, returns a ResultConverter for that type. ResultConverters in -Boost.Python generally inspect library's registry of converters to -find a suitable converter, but converters which don't use the registry -are also possible. - -

Concept Requirements

-

ResultConverter Concept

- -

In the table below, C denotes a ResultConverter -type for a type R , c denotes -an object of type C , and r -denotes an object of type R. - - - - - - - - - - - - - - - - - - - - - - - - -
ExpressionTypeSemantics
C c; - Constructs a C object. -
c.convertible()convertible to boolfalse iff no conversion from any R value - to a Python object is possible.
c(r)convertible to PyObject*A pointer to a Python object corresponding to r, - or 0 iff r could not be converted - to_python, in which case PyErr_Occurred - should return non-zero.
- -

ResultConverterGenerator Concept

-

In the table below, G denotes a -ResultConverterGenerator type and R denotes a possible -C++ function return type. - - - - - - - - - -
ExpressionRequirements
G::apply<R>::typeA ResultConverter type for R.
- -


-

Revised - - 09 May, 2002 - -

-

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

Permission to copy, use, modify, sell - and distribute this software is granted provided this copyright notice appears - in all copies. This software is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose. - - diff --git a/doc/v2/acknowledgments.html b/doc/v2/acknowledgments.html deleted file mode 100644 index 071919e3..00000000 --- a/doc/v2/acknowledgments.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - -Boost.Python - Acknowledgments - - - - - - - -
-

-

-
-

Boost.Python

-

Acknowledgments

-
-


-{{text}} -
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/bibliography.html b/doc/v2/bibliography.html deleted file mode 100644 index b59320d9..00000000 --- a/doc/v2/bibliography.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - -Boost.Python - Bibliography - - - - - - - -
-

-

-
-

Boost.Python

-

Bibliography

-
-
-{{bibliographical information}} -
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/call.html b/doc/v2/call.html deleted file mode 100644 index e959b1ce..00000000 --- a/doc/v2/call.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -Boost.Python - <call.hpp> - - - - - - - -
-

-

-
-

Boost.Python

-

Header <call.hpp>

-
-
-

Contents

-
-
Introduction
-
Functions
-
-
call
-
- -
Example(s)
- -
-
-

Introduction

-

- <boost/python/call.hpp> defines the call family of overloaded function - templates, used to invoke Python callable objects from C++. - -

Functions

-
-template <class R, class A1, class A2, ... class An>
-R call(PyObject* callable, A1 const&, A2 const&, ... An const&)
-
-
-
Requires: R is a pointer type, reference - type, or a complete type with an accessible copy constructor
- -
Effects: Invokes callable(a1, a2, ...an) in - Python, where a1...an are the arguments to - call(), converted to Python objects. -
Returns: The result of the Python call, converted to the C++ type R.
- - -
Rationale: For a complete semantic description and - rationale, see this page. -
-
- -

Example(s)

- -The following C++ function applies a Python callable object to its two -arguments and returns the result. If a Python exception is raised or -the result can't be converted to a double, an exception -is thrown. - -
-double apply2(PyObject* func, double x, double y)
-{
-   return boost::python::call<double>(func, x, y);
-}
-
- -

Revised - - 9 May, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/call_method.html b/doc/v2/call_method.html deleted file mode 100644 index f2c52a9b..00000000 --- a/doc/v2/call_method.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - -Boost.Python - <call_method.hpp> - - - - - - - -
-

-

-
-

Boost.Python

-

Header <call_method.hpp>

-
-
-

Contents

-
-
Introduction
-
Functions
-
-
call_method
-
- -
Example(s)
- -
-
-

Introduction

-

- <boost/python/call_method.hpp> defines the call_method family of overloaded function - templates, used to invoke callable attributes of Python objects from C++. - -

Functions

-
-template <class R, class A1, class A2, ... class An>
-R call_method(PyObject* self, char const* method, A1 const&, A2 const&, ... An const&)
-
-
-
Requires: R is a pointer type, reference - type, or a complete type with an accessible copy constructor
- -
Effects: Invokes self.method(a1, a2, ...an) in - Python, where a1...an are the arguments to - call_method(), converted to Python objects. For a - complete semantic description, see this - page. - -
Returns: The result of the Python call, converted to the - C++ type R.
- - -
Rationale: call_method is critical to - implementing C++ virtual functions which are overridable in Python, - as shown by the example below. -
-
- -

Example(s)

- -The following C++ illustrates the use of call_method in -wrapping a class with a virtual function that can be overridden in -Python: - -

C++ Module Definition

-
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/utility.hpp>
-#include <cstring>
-
-// class to be wrapped
-class Base
-{
- public:
-   virtual char const* class_name() const { return "Base"; }
-   virtual ~Base();
-};
-
-bool is_base(Base* b)
-{
-   return !std::strcmp(b->class_name(), "Base");
-}
-
-// Wrapper code begins here
-using namespace boost::python;
-
-// Callback class
-class Base_callback : public Base
-{
- public:
-   Base_callback(PyObject* self) : m_self(self) {}
-
-   char const* class_name() const { return call_method(m_self, "class_name"); }
-   char const* Base_name() const { return Base::class_name(); }
- private:
-   PyObject* m_self;
-};
-
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(my_module)
-{
-   module("my_module")
-      .def("is_base", is_base)
-      .add(
-         class_<Base,Base_callback, noncopyable>("Base")
-             .def("class_name", Base_callback::Base_name);
-         )
-       ;
-}
-
- -

Python Code

-
->>> from my_module import *
->>> class Derived(Base):
-...    def __init__(self):
-...       Base.__init__(self)
-...    def class_name(self):
-...       return self.__class__.__name__
-...
->>> is_base(Base()) # calls the class_name() method from C++
-1
->>> is_base(Derived())
-0
-
-

Revised - - 10 May, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/callbacks.html b/doc/v2/callbacks.html deleted file mode 100644 index f001984d..00000000 --- a/doc/v2/callbacks.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - -Boost.Python - Calling Python Functions and Methods - - - - - - - -
-

-

-
-

Boost.Python

-

Calling Python Functions and Methods

-
-
-

Contents

-
-
Introduction
-
Argument Handling
-
Result Handling
-
Rationale
-
-
- -

Introduction

-

-Boost.Python provides two families of function templates, -call and call_method, for -invoking Python functions and methods respectively. The interface for -calling a Python function object (or any Python callable object) looks -like: - -

-call<ResultType>(callable_object, a1, a2... aN);
-
- -Calling a method of a Python object is similarly easy: - -
-call_method<ResultType>(self_object, "method-name", a1, a2... aN);
-
- - -

Argument Handling

-

- -Arguments are converted to Python according to their type. By default, -the arguments a1...aN are copied into -new Python objects, but this behavior can be overridden by the use of -ptr() and ref(): - -

-class X : boost::noncopyable
-{
-   ...
-};
-
-void apply(PyObject* callable, X& x)
-{
-   // Invoke callable, passing a Python object which holds a reference to x
-   boost::python::call<void>(callable, boost::ref(x));
-}
-
- -In the table below, x denotes the actual argument -object and cv denotes an optional -cv-qualification: "const", -"volatile", or "const -volatile". - - - - - - - -
Argument Type - - Behavior - -
T cv&
- T cv - -
The Python argument is created by the same means used - for the return value of a wrapped C++ function returning - T. When - T is a class type, that normally means - *x is copy-constructed into the new Python - object. - -
T* - - If x == 0, the Python argument will - be None. Otherwise, - the Python argument is created by the same means used for the - return value of a wrapped C++ function returning - T. When - T is a class type, that normally means - *x is copy-constructed into the new Python - object. - -
boost::reference_wrapper<T> - - The Python argument contains a pointer to, rather than a - copy of, x.get(). Note: failure to ensure that no - Python code holds a reference to the resulting object beyond - the lifetime of *x.get() may result in a - crash! - -
pointer_wrapper<T> - - If x.get() == 0, the Python - argument will be None. - Otherwise, the Python argument contains a pointer to, rather - than a copy of, *x.get(). Note: failure to ensure - that no Python code holds a reference to the resulting object - beyond the lifetime of *x.get() may result in - a crash! - -
- -

Result Handling

- -In general, call<ResultType>() and -call_method<ResultType>() return -ResultType by exploiting all lvalue and rvalue -from_python converters registered for ResultType and -returning a copy of the result. However, when -ResultType is a pointer or reference type, Boost.Python -searches only for lvalue converters. To prevent dangling pointers and -references, an exception will be thrown if the Python result object -has only a single reference count. - -

Rationale

- -In general, to get Python arguments corresponding to -a1...aN, a new Python object must be -created for each one; should the C++ object be copied into that Python -object, or should the Python object simply hold a reference/pointer to -the C++ object? In general, the latter approach is unsafe, since the -called function may store a reference to the Python object -somewhere. If the Python object is used after the C++ object is -destroyed, we'll crash Python. - -

In keeping with the philosophy that users on the Python side -shouldn't have to worry about crashing the interpreter, the default -behavior is to copy the C++ object, and to allow a non-copying -behavior only if the user writes boost::ref(a1) instead of a1 -directly. At least this way, the user doesn't get dangerous behavior -"by accident". It's also worth noting that the non-copying -("by-reference") behavior is in general only available for -class types, and will fail at runtime with a Python exception if used -otherwise[1]. - -

-However, pointer types present a problem: one approach is to refuse -to compile if any aN has pointer type: after all, a user can always pass -*aN to pass "by-value" or ref(*aN) -to indicate a pass-by-reference behavior. However, this creates a -problem for the expected null pointer to -None conversion: it's illegal to dereference a null -pointer value. - -

- -The compromise I've settled on is this: - -

    -
  1. The default behavior is pass-by-value. If you pass a non-null - pointer, the pointee is copied into a new Python object; otherwise - the corresponding Python argument will be None. - -
  2. if you want by-reference behavior, use ptr(aN) if - aN is a pointer and ref(aN) otherwise. If - a null pointer is passed to ptr(aN), the corresponding - Python argument will be None. -
- -

-As for results, we have a similar problem: if ResultType -is allowed to be a pointer or reference type, the lifetime of the -object it refers to is probably being managed by a Python object. When -that Python object is destroyed, our pointer dangles. The problem is -particularly bad when the ResultType is char const* - the -corresponding Python String object is typically uniquely-referenced, -meaning that the pointer dangles as soon as call<char -const*>(...) returns. - -

-The old Boost.Python v1 deals with this issue by refusing to compile -any uses of call<char const*>(), but this goes both -too far and not far enough. It goes too far because there are cases -where the owning Python string object survives beyond the call (just -for instance, when it's the name of a Python class), and it goes not -far enough because we might just as well have the same problem with a -returned pointer or reference of any other type. - -

- -In Boost.Python v2 this is dealt with by: - -

    -
  1. lifting the compile-time restriction on const - char* callback returns - - -
  2. detecting the case when the reference count on the result - Python object is 1 and throwing an exception inside of - call<U>(...) when U is a pointer - or reference type. -
- -This should be acceptably safe because users have to explicitly -specify a pointer/reference for U in -call<U>, and they will be protected against dangles -at runtime, at least long enough to get out of the -call<U>(...) invocation. - -
- -[1] It would be possible to make it fail at compile-time for non-class -types such as int and char, but I'm not sure it's a good idea to impose -this restriction yet. - -

Revised - - 17 April, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/callbacks.txt b/doc/v2/callbacks.txt deleted file mode 100644 index a58ca0ea..00000000 --- a/doc/v2/callbacks.txt +++ /dev/null @@ -1,88 +0,0 @@ -Here's the plan: - -I aim to provide an interface similar to that of Boost.Python v1's -callback<>::call(...) for dealing with callbacks. The interface will -look like: - - returning::call("method_name", self_object, a1, a2...); - -or - - returning::call(callable_object, a1, a2...); - -ARGUMENT HANDLING - -There is an issue concerning how to make Python objects from the -arguments a1...aN. A new Python object must be created; should the C++ -object be copied into that Python object, or should the Python object -simply hold a reference/pointer to the C++ object? In general, the -latter approach is unsafe, since the called function may store a -reference to the Python object somewhere. If the Python object is used -after the C++ object is destroyed, we'll crash Python. - -I plan to make the copying behavior the default, and to allow a -non-copying behavior if the user writes boost::ref(a1) instead of a1 -directly. At least this way, the user doesn't get dangerous behavior "by -accident". It's also worth noting that the non-copying ("by-reference") -behavior is in general only available for class types, and will fail at -runtime with a Python exception if used otherwise** - -However, pointer types present a problem: My first thought is to refuse -to compile if any aN has pointer type: after all, a user can always pass -*aN to pass "by-value" or ref(*aN) to indicate a pass-by-reference -behavior. However, this creates a problem for the expected NULL pointer -=> None conversion: it's illegal to dereference a null pointer value. - -We could use another construct, say "ptr(aN)", to deal with null -pointers, but then what does it mean? We know what it does when aN is -NULL, but it might either have by-value or by-reference behavior when aN -is non-null. - -The compromise I've settled on is this: - -1. The default behavior is pass-by-value. If you pass a non-null - pointer, the pointee is copied into a new Python object; otherwise - the corresponding Python argument will be None. - -2. if you want by-reference behavior, use ptr(aN) if aN is a pointer - and ref(aN) otherwise. If a null pointer is passed to ptr(aN), the - corresponding Python argument will be None. - -RESULT HANDLING - -As for results, we have a similar problem: if ResultType is allowed to -be a pointer or reference type, the lifetime of the object it refers to -is probably being managed by a Python object. When that Python object is -destroyed, our pointer dangles. The problem is particularly bad when the -ResultType is char const* - the corresponding Python String object is -typically uniquely-referenced, meaning that the pointer dangles as soon -as returning::call() returns. - -Boost.Python v1 deals with this issue by refusing to compile any uses of -callback::call(), but IMO this goes both too far and not -far enough. It goes too far because there are cases where the owning -String object survives beyond the call (just for instance when it's the -name of a Python class), and it goes not far enough because we might -just as well have the same problem with any returned pointer or -reference. - -I propose to address this in Boost.Python v2 by - - 1. lifting the compile-time restriction on const - char* callback returns - - 2. detecting the case when the reference count on the - result Python object is 1 and throwing an exception - inside of returning::call() when U is a pointer or - reference type. - -I think this is acceptably safe because users have to explicitly specify -a pointer/reference for U in returning, and they will be protected -against dangles at runtime, at least long enough to get out of the -returning::call() invocation. - --Dave - -**It would be possible to make it fail at compile-time for non-class -types such as int and char, but I'm not sure it's a good idea to impose -this restriction yet. diff --git a/doc/v2/class.html b/doc/v2/class.html deleted file mode 100644 index 0496d2ca..00000000 --- a/doc/v2/class.html +++ /dev/null @@ -1,589 +0,0 @@ - - - - - - Boost.Python - <boost/python/class.hpp>, - <boost/python/class_fwd.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Headers <boost/python/class.hpp>, - <boost/python/class_fwd.hpp>

-
-
- -

Contents

- -
-
Introduction - -
Classes - -
-
-
Class template class_ - -
-
-
Class class_ - synopsis - -
Class class_ - constructors - -
Class class_ - modifier functions - -
Class class_ - observer functions -
- -
Class template bases - -
-
-
Class bases - synopsis -
- -
Class template args - -
-
-
Class args - synopsis -
-
- -
Example(s) -
-
- -

Introduction

- -

<boost/python/class.hpp> defines the interface - through which users expose their C++ classes to Python. It declares the - class_ class template, which is parameterized on the - class type being exposed. It also exposes the args - and bases utility class templates, which are used in - conjunction with class_. - -

<boost/python/class_fwd.hpp> contains a forward - declaration of the class_ class template. - -

Classes

- -

Class template class_<T, Bases, HeldType, NonCopyable>

- -

Creates a Python class associated with the C++ type passed as - its first parameter. Although it has four template parameters, - only the first one is required. The three optional arguments can - actually be supplied in any - order; Boost.Python determines the role of the argument - from its type.
-
- - - - - - - -
Template Parameter - - Requirements - - Semantics - - Default - -
T - - A class type. - - The class being wrapped - -
Bases - - A specialization of bases<...> which - specifies previously-exposed C++ base classes of T[1]. - - Registers from_python conversions from - wrapped T instances to each of its exposed direct - and indirect bases. For each polymorphic base B, - registers conversions from indirectly-held wrapped - B instances to T. - - bases<> - -
HeldType - - Must be T, a class derived - from T, or a Dereferenceable type for which - pointee<HeldType>::type - is T or a class derived from T. - - - Specifies the type which is actually embedded in a Python - object wrapping a T instance. More details below. - - T - -
NonCopyable - - If supplied, must be boost::noncopyable. - - Suppresses automatic registration of to_python - conversions which copy - T instances. Required when T has no - publicly-accessible copy constructor. - - An unspecified type other than boost::noncopyable. - -
- -

HeldType Semantics

- -
    -
  1. - If HeldType is derived from T, its - exposed constructor(s) must accept an initial - PyObject* argument which refers back to the Python - object that contains it, as shown in this example. This argument is - not included in the argument list type passed to def_init(), below, nor is - it passed explicitly by users when Python instances of - T are created. This is the idiom which allows C++ virtual - functions to be overridden in Python. Boost.Python automatically - registers additional converters which allow wrapped instances of - T to be passed to wrapped C++ functions expecting - HeldType arguments. - -
  2. Because Boost.Python will always allow - wrapped instances of T to be passed in place of - HeldType arguments, specifying a smart pointer for - HeldType allows users to pass Python - T instances where a smart pointer-to-T is - expected. Smart pointers such as std::auto_ptr<> - or boost::shared_ptr<> - which contain a nested type element_type designating - the referent type are automatically supported; additional smart - pointer types can be supported by specializing pointee<HeldType>. - -
  3. - As in case 1 above, when HeldType is a smart pointer to - a class derived from T, the initial - PyObject* argument must be supplied by all exposed - constructors. - -
  4. - Except in cases 1 and 3, users may optionally specify that T itself - gets initialized with a similar initial PyObject* - argument by specializing has_back_reference. -
- -

Class template - class_ synopsis

-
-namespace boost { namespace python
-{
-  template <class T
-            , class Bases = bases<>
-            , class HeldType = T
-            , class NonCopyable = unspecified
-           >
-  class class_
-  {
-    class_();
-    class_(char const* name);
-
-    // exposing constructors
-    class_& def_init();
-
-    template <class Args>
-    class_& def_init(Args const& = Args());
-
-    template <class Args, class CallPolicy>
-    class_& def_init(Args const&, CallPolicy policy);
-
-    // exposing member functions
-    template <class F>
-    class_& def(char const* name, F f);
-
-    template <class Fn, class CallPolies>
-    class_& def(char const* name, Fn fn, CallPolies);
-
-    // exposing operators
-    template <unspecified>
-    class_& def(detail::operator_<unspecified>);
-
-    // exposing data members
-    template <class D>
-    class_& def_readonly(char const* name, D T::*pm);
-
-    template <class D>
-    class_& def_readwrite(char const* name, D T::*pm);
-
-    // Raw attribute modification
-    class_& setattr(char const* name, ref const&);
-
-    // property creation
-    void add_property(char const* name, ref const& fget);
-    void add_property(char const* name, ref const& fget, ref const& fset);
-
-    // accessing the Python class object
-    ref object() const;
-  };
-}}
-
- -

Class template class_ constructors

- -
-class_();
-
- -
-
Requires: The platform's std::type_info::name() - implementation produces a string which corresponds to the type's - declaration in C++ - -
Effects: Constructs a class_ object which - generates a Boost.Python extension class with the same name as - T. - -
Rationale: Many platforms can generate reasonable names for - Python classes without user intervention. -
-
-class_(char const* name);
-
- -
-
Requires: name is a ntbs which conforms to - Python's identifier - naming rules. - -
Effects: Constructs a class_ object which - generates a Boost.Python extension class named name. - -
Rationale: Gives the user full control over class naming. -
- -

Class template class_ - modifier functions

- -
-class_& def_init();
-
-template <class Args>
-class_& def_init(Args const& argument_types);
-
-template <class Args, class CallPolicies>
-class_& def_init(Args const& argument_types, CallPolicies policies);
-
- -
-
Requires: Args is an MPL sequence of C++ argument - types (A1, A2,... AN) such that if - a1, a2... aN are objects of type - A1, A2,... AN respectively, the expression - T(a1, a2... aN) is valid. In the first form, - the expression T() must be valid. - -
Effects: Adds the result of - -make_constructor<args<>,Holder>(), - -make_constructor<Args,Holder>(), or - -make_constructor<Args,Holder>(policies), - respectively, to the Boost.Python extension class being defined under the name - "__init__". Holder is a concrete subclass of instance_holder - which holds the HeldType. If the extension class - already has an "__init__" attribute, the usual overloading procedure applies. - -
Returns: *this - -
Rationale: Allows users to easily expose a class' constructor - to Python. -
- -
- -
-template <class F>
-class_& def(char const* name, F f);
-
-template <class Fn, class CallPolicies>
-class_& def(char const* name, Fn f, CallPolicies policies);
-
- -
-
Requires: f is a non-null - pointer-to-function or pointer-to-member-function, or a callable - Python object passed as a PyObject* or ref. name - is a ntbs which conforms to Python's identifier - naming rules. In the first form, the return type of - f is not a reference and is not a pointer other - than char const* or PyObject*. In the - second form policies is a model of CallPolicies. - -
Effects: Adds the result of make_function(f) or make_function(f, policies) to - the Boost.Python extension class being defined, with the given - name. If the extension class already has an attribute named - name, the usual overloading procedure applies. - -
Returns: *this -
- -
-template <unspecified>
-class_& def(detail::operator_<unspecified>);
-
- -
-
Effects: Adds a Python special - method as described here. - -
Returns: *this -
- -
-template <class F>
-class_& setattr(char const* name, ref x);
-
- -
-
Requires: name is a ntbs which conforms to - Python's identifier - naming rules. - -
Effects: PyObject_SetAttrString(this->object(), name, x.get()); - -
Returns: *this -
- -
- -
-void add_property(char const* name, ref const& fget);
-void add_property(char const* name, ref const& fget, ref const& fset);
-
-
- -
Requires: name is a ntbs which conforms to - Python's identifier - naming rules. - -
Effects: Creates a new Python property - class instance, passing fget.get() (and - fset.get() in the second form) to its constructor, - then adds that property to the Python class object under - construction with the given attribute name. - -
Returns: *this - -
Rationale: Allows users to easily expose a class' - data member such that it can be inspected from Python with a - natural syntax. -
- -
-
-    template <class D>
-    class_& def_readonly(char const* name, D T::*pm);
-
- -
- -
Requires: name is a ntbs which conforms to - Python's identifier - naming rules. - -
Effects: -
-this->add_property(name, ref(make_getter(pm)));
-
- -
Returns: *this - -
Rationale: Allows users to easily expose a class' - data member such that it can be inspected from Python with a - natural syntax. -
- -
- -
-template <class D>
-class_& def_readwrite(char const* name, D T::*pm);
-
- -
- -
Effects: -
-ref fget(make_getter(pm));
-ref fset(make_setter(pm));
-this->add_property(name, fget, fset);
-
- -
Returns: *this - -
Rationale: Allows users to easily expose a class' - data member such that it can be inspected and set from Python with a - natural syntax. - -

Class template class_ - observer functions

-
-ref object() const;
-
- -
-
Returns: A ref object which holds a reference to - the Boost.Python extension class object created by the - class_ constructor. - -
Rationale: Mostly not needed by users, since module::add() uses this to insert the - extension class in the module. -
- -

Class template - args<T1, T2,...TN>

- -

A conveniently-named MPL sequence which - users pass to def_init calls to make - their code more readable. - -

Class template args - synopsis

-
-namespace boost { namespace python
-{
-  template <T1 = unspecified,...TN = unspecified>
-  struct args
-  {};
-}}
-
- -

Class template - bases<T1, T2,...TN>

- -

An MPL sequence which - can be used in class_<...> - instantiations indicate a list of base classes. Although users - can pass any MPL sequence in place of args, above, the use of - bases to indicate base classes is mandatory. - -

Class template bases - synopsis

-
-namespace boost { namespace python
-{
-  template <T1 = unspecified,...TN = unspecified>
-  struct bases
-  {};
-}}
-
- -

Example(s)

- -

Given a C++ class declaration: -

-class Foo : public Bar, public Baz
-{
- public:
-   Foo(int, char const*);
-   Foo(double);
-
-   std::string const& name() { return m_name; }
-   void name(char const*);
-
-   double value; // public data
- private:
-   ...
-};
-
- - A corresponding Boost.Python extension class can be created with: -
-using namespace boost::python;
-
-ref foo = class_<Foo,bases<Bar,Baz> >()
-   .def_init(args<int,char const*>())
-   .def_init(args<double>())
-   .def("get_name", &Foo::get_name, return_internal_reference<>())
-   .def("set_name", &Foo::set_name)
-   .def_readwrite("value", &Foo::value)
-   .object();
-
- -
- -[1] By "previously-exposed" we mean that the for each -B in bases, an instance of -class_<B> must have already been -constructed. Ensuring this in a portable manner when a class and its -bases are exposed in the same module entails using separate -full-expressions, rather than chaining consecutive definitions with -".add(...). - -
-module m("module_name");
-m.add(class_<Base>()
-        .def_init());
-m.add(class_<Derived, bases<Base>>()
-        .def_init());
-
- - Revised - - 09 May, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/configuration.html b/doc/v2/configuration.html deleted file mode 100644 index bb6b7344..00000000 --- a/doc/v2/configuration.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - -Boost.Python - Configuration - - - - - - - -
-

-

-
-

Boost.Python

-

Configuration

-
-


-
-
Introduction
-
Application Defined Macros
-
Public Library Defined Macros
-
Library Defined Implementation Macros
-
-

Introduction

-

Boost.Python uses several configuration macros in <boost/config.hpp>, - as well as configuration macros meant to be supplied by the application. These - macros are documented here.

-

Application Defined Macros

-

These are the macros that may be defined by an application using Boost.Python.

- - - - - - - - - - - - - -
MacroMeaning
{{macro}}{{meaning}}
{{macro}}{{meaning}}
-

Public Library Defined Macros

-

These macros are defined by Boost.Python but are expected to be used by application - code.

- - - - - - - - - - - - - -
MacroMeaning
{{macro}}{{meaning}}
{{macro}}{{meaning}}
-

Library Defined Implementation Macros

-

These macros are defined by Boost.Python and are implementation details of interest - only to implementers.

- - - - - - - - - - - - - -
MacroMeaning
{{macro}}{{meaning}}
{{macro}}{{meaning}}
-
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/copy_const_reference.html b/doc/v2/copy_const_reference.html deleted file mode 100644 index 70da135b..00000000 --- a/doc/v2/copy_const_reference.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - Boost.Python - <boost/python/copy_const_reference.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header - <boost/python/copy_const_reference.hpp>

-
-
- -

Contents

- -
-
Classes - -
-
-
Class - copy_const_reference - -
-
-
Class - copy_const_reference synopsis - -
Class - copy_const_reference metafunctions -
-
- -
Example -
-
- -

Classes

- -

Class - copy_const_reference

- -

copy_const_reference is a model of ResultConverterGenerator which can be - used to wrap C++ functions returning a reference-to-const type such that - the referenced value is copied into a new Python object. - -

Class - copy_const_reference synopsis

-
-namespace boost { namespace python
-{
-    struct copy_const_reference
-    {
-        template <class T> struct apply;
-    };
-}}
-
- -

Class - copy_const_reference metafunctions

-
-template <class T> struct apply
-
- -
-
Requires: T is U const& for some - U. - -
Returns: typedef to_python_value<T> - type; -
- -

Example

- -

C++ Module Definition

-
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/copy_const_reference.hpp>
-#include <boost/python/return_value_policy.hpp>
-
-// classes to wrap
-struct Bar { int x; }
-
-struct Foo {
-   Foo(int x) : { b.x = x; }
-   Bar const& get_bar() const { return b; }
- private:
-   Bar b;
-};
-
-// Wrapper code
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(my_module)
-{
-   module m("my_module")
-      .add(
-         class_<Bar>()
-         )
-      .add(
-         class_<Foo>()
-            .def_init(args<int>())
-            .def("get_bar", &Foo::get_bar
-                , return_value_policy<copy_const_reference>())
-         )
-       ;
-}
-
-

Python Code

-
->>> from my_module import *
->>> f = Foo(3)         # create a Foo object
->>> b = f.get_bar()    # make a copy of the internal Bar object
-
- -

Revised - - 15 February, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/copy_non_const_reference.html b/doc/v2/copy_non_const_reference.html deleted file mode 100644 index ffa728db..00000000 --- a/doc/v2/copy_non_const_reference.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - Boost.Python - - <boost/python/copy_non_const_reference.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header - <boost/python/copy_non_const_reference.hpp>

-
-


- -

Contents

- -
-
Classes - -
-
-
Class - copy_non_const_reference - -
-
-
Class - copy_non_const_reference synopsis - -
Class - copy_non_const_reference metafunctions -
-
- -
Example -
-
- -

Classes

- -

Class - copy_non_const_reference

- -

copy_non_const_reference is a model of ResultConverterGenerator which can be - used to wrap C++ functions returning a reference-to-non-const type such - that the referenced value is copied into a new Python object. - -

Class - copy_non_const_reference synopsis

-
-namespace boost { namespace python
-{
-    struct copy_non_const_reference
-    {
-        template <class T> struct apply;
-    };
-}}
-
- -

Class - copy_non_const_reference metafunctions

-
-template <class T> struct apply
-
- -
-
Requires: T is U& for some - non-const U. - -
Returns: typedef to_python_value<T> - type; -
- -

Example

- -

C++ code: -

-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/copy_non_const_reference.hpp>
-#include <boost/python/return_value_policy.hpp>
-
-// classes to wrap
-struct Bar { int x; }
-
-struct Foo {
-   Foo(int x) : { b.x = x; }
-   Bar& get_bar() { return b; }
- private:
-   Bar b;
-};
-
-// Wrapper code
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(my_module)
-{
-   module("my_module")
-      .add(
-         class_<Bar>()
-         )
-      .add(
-         class_<Foo>()
-            .def_init(args<int>())
-            .def("get_bar", &Foo::get_bar
-                , return_value_policy<copy_non_const_reference>())
-         );
-}
-
- Python Code: -
->>> from my_module import *
->>> f = Foo(3)         # create a Foo object
->>> b = f.get_bar()    # make a copy of the internal Bar object
-
- -

Revised - - 05 November, 2001 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/data_members.html b/doc/v2/data_members.html deleted file mode 100644 index 820bb1d4..00000000 --- a/doc/v2/data_members.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - Boost.Python - <boost/python/data_members.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/data_members.hpp>

-
-


- -

Contents

- -
-
Introduction - -
Functions - -
-
-
make_getter - -
make_setter -
- -
Example -
-
- -

Introduction

- -

make_getter() and - make_setter() are - the functions used internally by class_<>::def_readonly and - class_<>::def_readwrite to - produce Python callable objects which wrap C++ data members. - -

Functions

- -
-template <class C, class D>
-objects::function* make_getter(D C::*pm);
-
-template <class C, class D, class Policies>
-objects::function* make_getter(D C::*pm, Policies const& policies);
-
- -
-
Requires: Policies is a model of CallPolicies. - -
Effects: Creates a Python callable object which - accepts a single argument that can be converted - from_python to C*, and returns the - corresponding member D member of the C - object, converted to_python. If - policies is supplied, it will be applied to the - function as described here. - -
Returns: A pointer convertible to PyObject* which - refers to the new Python callable object. -
-
-template <class C, class D>
-objects::function* make_setter(D C::*pm);
-
-template <class C, class D, class Policies>
-objects::function* make_setter(D C::*pm, Policies const& policies);
-
- -
-
Requires: Policies is a model of CallPolicies. - -
Effects: Creates a Python callable object which, when - called from Python, expects two arguments which can be converted - from_python to C* and - D const&, respectively, and sets the - corresponding D member of the C - object. If policies is supplied, it will be applied - to the function as described here. - -
Returns: A pointer convertible to - PyObject* which refers to the new Python callable - object. -
- -

Example

- -

The code below uses make_getter and make_setter to expose a - data member as functions: - -

-#include <boost/python/data_members.hpp>
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-
-struct X
-{
-    X(int x) : y(x) {}
-    int y;
-};
-
-using namespace boost::python;
-
-BOOST_PYTHON_MODULE_INIT(data_members_example)
-{
-    module("data_members_example")
-        .add(
-            class_<X>("X")
-               .def_init(args<int>())
-               .def("get", make_getter(&X::y))
-               .def("set", make_setter(&X::y))
-        )
-        ;
-}
-
- It can be used this way in Python: -
->>> from data_members_example import *
->>> x = X(1)
->>> x.get()
-1
->>> x.set(2)
->>> x.get()
-2
-
- -

- - 8 May 2002 - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/default_call_policies.html b/doc/v2/default_call_policies.html deleted file mode 100644 index 058b13e2..00000000 --- a/doc/v2/default_call_policies.html +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - Boost.Python - - <boost/python/default_call_policies.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header - <boost/python/default_call_policies.hpp>

-
-


- -

Contents

- -
-
Classes - -
-
-
Class - default_call_policies - -
-
-
Class - default_call_policies synopsis - -
Class - default_call_policies static functions -
- -
Class - default_result_converter - -
-
-
Class - default_result_converter synopsis - -
Class - default_result_converter metafunctions -
-
- -
Example -
-
- -

Classes

- -

Class - default_call_policies

- -

default_call_policies is a model of CallPolicies with no precall or - postcall behavior and a result_converter which - handles by-value returns. Wrapped C++ functions and member functions use - default_call_policies unless otherwise specified. You may find - it convenient to derive new models of CallPolicies from - default_call_policies. - -

Class - default_call_policies synopsis

-
-namespace boost { namespace python
-{
-    struct default_call_policies
-    {
-        static bool precall(PyObject*);
-        static PyObject* postcall(PyObject*, PyObject* result);
-        typedef default_result_converter result_converter;
-    };
-}}
-
- -

Class - default_call_policies static functions

-
-bool precall(PyObject*);
-
- -
-
Returns: true - -
Throws: nothing -
-
-PyObject* postcall(PyObject*, PyObject* result);
-
- -
-
Returns: result - -
Throws: nothing -
- -

Class - default_result_converter

- -

default_result_converter is a model of ResultConverterGenerator which can be - used to wrap C++ functions returning non-pointer types, char - const*, and PyObject*, by-value. - -

Class - default_result_converter synopsis

-
-namespace boost { namespace python
-{
-    struct default_result_converter
-    {
-        template <class T> struct apply;
-    };
-}}
-
- -

Class - default_result_converter metafunctions

-
-template <class T> struct apply
-
- -
-
Requires: T is not a reference type. If - T is a pointer type, T is const - char* or PyObject*. - -
Returns: typedef to_python_value<T - const&> type; -
- -

Example

- -

This example comes from the Boost.Python implementation itself. Because - the return_value_policy - class template does not implement precall or - postcall behavior, its default base class is - default_call_policies: -

-template <class Handler, class Base = default_call_policies>
-struct return_value_policy : Base
-{
-   typedef Handler result_converter;
-};
-
- -

Revised - - 05 November, 2001 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/definitions.html b/doc/v2/definitions.html deleted file mode 100644 index 839608bc..00000000 --- a/doc/v2/definitions.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - -Boost.Python - Definitions - - - - - - - -
-

-

-
-

Boost.Python

-

Definitions

-
-


-
-
{{term}}: {{definition}}
-
{{term}}: {{definition}}
-
-
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/errors.html b/doc/v2/errors.html deleted file mode 100644 index 6e364e8f..00000000 --- a/doc/v2/errors.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Boost.Python - <boost/python/errors.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/errors.hpp>

-
-
- -

Contents

- -
-
Introduction - -
Classes - -
-
-
Class error_already_set - -
-
-
Class - error_already_set synopsis -
-
- -
Functions - -
-
-
handle_exception - -
expect_non_null -
throw_error_already_set -
- -
Examples -
-
- -

Introduction

- -

<boost/python/errors.hpp> provides types and - functions for managing and translating between Python and C++ exceptions. - This is relatively low-level functionality that is mostly used internally - by Boost.Python. Users should seldom need it. - -

Classes

- -

Class - error_already_set

- -

error_already_set is an exception type which can be thrown - to indicate that a Python error has occurred. If thrown, the precondition - is that PyErr_Occurred() - returns a value convertible to true. - -

Class error_already_set synopsis

-
-namespace boost { namespace python
-{
-    class error_already_set {};
-}}
-
- -

Functions

-
-template <class T> bool handle_exception(T f) throw();
-
-void handle_exception() throw();
-
- -
-
Requires: The first form requires that the expression function0<void>(f) - is valid. The second form requires that a C++ exception is currently - being handled (see section 15.1 in the C++ standard). - -
Effects: The first form calls f() inside a - try block whose catch clauses set an - appropriate Python exception for the C++ exception caught, returning - true if an exception was caught, false - otherwise. The second form passes a function which rethrows the exception - currently being handled to the first form. - -
Postconditions: No exception is being handled - -
Throws: nothing - -
Rationale: At inter-language boundaries it is important to - ensure that no C++ exceptions escape, since the calling language usually - doesn't have the equipment neccessary to properly unwind the stack. Use - handle_exception to manage exception translation whenever - your C++ code is called directly from the Python API. This is done for - you automatically by the usual function wrapping facilities: make_function(), make_constructor(), module::def and class_::def). The second form can be more - convenient to use (see the example below), but - various compilers have problems when exceptions are rethrown from within - an enclosing try block. -
-
-template <class T> T* expect_non_null(T* x);
-
- -
-
Returns: x - -
Throws: error_already_set() iff x == - 0. - -
Rationale: Simplifies error-handling when calling many - functions in the Python/C API, which - return 0 on error. -
- -
-void throw_error_already_set();
-
- -
- -
Effects: throw error_already_set(); -
- -

Examples

-
-#include <string>
-#include <boost/python/errors.hpp>
-#include <boost/python/reference.hpp>
-
-// Returns a std::string which has the same value as obj's "__name__"
-// attribute.
-std::string get_name(boost::python::ref obj)
-{
-   // throws if there's no __name__ attribute
-   PyObject* p = boost::python::expect_non_null(
-      PyObject_GetAttrString(obj.get(), "__name__"));
-
-   // throws if it's not a Python string
-   std::string result(
-      boost::python::expect_non_null(
-         PyString_AsString(p)));
-
-   Py_XDECREF(p); // Done with p
-   
-   return result;
-}
-
-//
-// Demonstrate form 1 of handle_exception
-//
-
-// Place a Python Int object whose value is 1 if a and b have
-// identical "__name__" attributes, 0 otherwise.
-void same_name_impl(PyObject*& result, PyObject* a, PyObject* b)
-{
-   result = PyInt_FromLong(
-      get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
-}
-
-// This is an example Python 'C' API interface function
-extern "C" PyObject*
-same_name(PyObject* args, PyObject* keywords)
-{
-   PyObject* a1;
-   PyObject* a2;
-   PyObject* result = 0;
-
-   if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
-      return 0;
-   
-   // Use boost::bind to make an object compatible with
-   // boost::Function0<void>
-   if (boost::python::handle_exception(
-         boost::bind<void>(same_name_impl, boost::ref(result), a1, a2)))
-   {
-      // an exception was thrown; the Python error was set by
-      // handle_exception()
-      return 0;
-   }
-
-   return result;
-}
-
-//
-// Demonstrate form 2 of handle_exception. Not well-supported by all
-// compilers.
-//
-extern "C" PyObject*
-same_name2(PyObject* args, PyObject* keywords)
-{
-   PyObject* a1;
-   PyObject* a2;
-   PyObject* result = 0;
-
-   if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
-      return 0;
-   try {
-      return PyInt_FromLong(
-         get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
-   }
-   catch(...)
-   {
-      // If an exception was thrown, translate it to Python
-      boost::python::handle_exception();
-      return 0;
-   }
-}
-
- -

Revised - - 17 November, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/faq.html b/doc/v2/faq.html deleted file mode 100644 index 78a3940f..00000000 --- a/doc/v2/faq.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - -Boost.Python - FAQ - - - - - - - -
-

-

-
-

Boost.Python

-

Frequently Asked Questions (FAQs)

-
-


-
-
{{question}}
-
{{question}}
-
-

{{question}}

-

{{answer}}

-

{{question}}

-

{{answer}}

-
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/feb2002.html b/doc/v2/feb2002.html deleted file mode 100644 index e7bc3dd9..00000000 --- a/doc/v2/feb2002.html +++ /dev/null @@ -1,366 +0,0 @@ - - - - - Boost.Python - February 2002 Progress Report - - - - -
-

-

- -
-

Boost.Python

- -

February 2002 Progress Report

-
-
- -

Contents

- -
-
Python10 Conference Report - -
Boost.Python v2 Progress - -
-
-
Documentation - -
Overhaul of - to_python/from_python - conversion mechanism - -
Miscellaneous -
-
- -

Python10 Conference Report

- I spent the first week of February at the Python10 conference - in Alexandria, VA. I'm including this experience report - for two reasons: firstly, it documents where my time was - used. Secondly, a public presence for Boost.Python and - interaction between the Python and C++ communities is - important to the future of Boost.Python, which in turn is - important to the Kull Project. - -

Andy Koenig, of all people, was the keynote speaker of - this year's opening plenary session. He presented his - "impressions of a polyglot outsider", which - studiously avoided any mention of C++ until the end of his - talk, when he was asked about standardization. I was - surprised to learn that the C++ community at large wanted a - few more years before beginning but when ANSI accepted - HP's request for a standard, the process was forced to - start: it was a matter of participating or having - standardization proceed without one's input. Andy managed - to highlight very effectively the balance of strengths in - Python, one of the most important being its support for - extension via libraries. In many ways that makes Python a - good analogue for C++ in the interpreted world - -

There were several kind mentions of the Boost.Python - library from people who found it indispensable. I was - particularly happy that Karl MacMillan, Michael Droettboom, - and Ichiro Fujinaga from Johns Hopkins is using it to do OCR - on a vast library of music notation, since in a previous life - I was an author of music notation software. These guys are - also drawing on Ullrich Koethe's VIGRA library for image - manipulation (Ullrich has been a major contributor to - Boost.Python). They also have a system for writing the - Boost.Python wrapper code in C++ comments, which allows them - to keep all of the code in one place. I've asked them to - send me some information on that. - -

The development of Swig has been gaining momentum again - (the basic description at - www.boost.org/libs/python/doc/comparisons.html still - applies). The talk given about it by David Beazly was very - well-attended, and they appear to have quite a few users. - Swig's strengths (coverage of many langauages) and - weaknesses (incomplete C++ language support) haven't - changed, although the C++ support seems to have improved - considerably - they now claim to have a complete model of the - C++ type system. It seems to be mostly geared at wrapping - what Walter Landry calls "C-Tran": C++ code which - traffics in built-in types with little use of abstraction. - I'm not knocking that, either: I'm sure a lot of that - code exists, so it's a valuable service. One feature Swig - has which I'd like to steal is the ability to unwrap a - single Python argument into multiple C++ arguments, for - example, by converting a Python string into a pointer and - length. When his talk was over, David approached me about a - possible joint workshop on language binding, which sounds - like a fun idea to me. - -

I spent some considerable time talking with Steven Knight, - the leader of the Scons build tool effort. We had a lot to - share with one another, and I gained a much better - appreciation for many of the Scons design decisions. Scons - seems to be concentrating on being the ultimate build system - substrate, and Steve seemed to think that we were on the - right track with our high-level design. We both hope that the - Boost.Build V2 high-level architecture can eventually be - ported to run on top of Scons. - -

They also have a highly-refined and successful development - procedure which I'd like to emulate for Boost.Build V2. - Among many other things they do, their source-control system - automatically ensures that when you check in a new test, it - is automatically run on the currently checked-in state of the - code, and is expected to fail -- a relatively obvious good - idea which I've never heard before. - -

Guido Van Rossum's "State of the Python - Union" address was full of questions for the community - about what should be done next, but the one idea Guido seemed - to stress was that core language stability and continuing - library development would be a good idea (sound familiar?) I - mentioned the Boost model as a counterpoint to the idea of - something like CPAN (the massive Perl library archives), and - it seemed to generate some significant interest. I've - offered to work with anyone from the Python community who - wants to set up something like Boost. - -

There was some discussion of "string - interpolation" (variable substitution in strings), and - Guido mentioned that he had some thoughts about the - strengths/weaknesses of Python's formatting interface. It - might be useful for those working on formatting for boost to - contact him and find out what he has to say. - -

Ka-Ping Yee demoed a Mailman discussion thread weaver. - This tool weaves the various messages in a discussion thread - into a single document so you can follow the entire - conversation. Since we're looking very seriously at - moving Boost to Mailman, this could be a really useful thing - for us to have. If we do this, we'll move the yahoogroups - discussions into the mailman archive so old discussions can - be easily accessed in the same fashion. - -

And, just because it's cool, though perhaps not - relevant: http://homepages.ulb.ac.be/~arigo/psyco/ is a - promising effort to accelerate the execution of Python code - to speeds approaching those of compiled languages. It - reminded me a lot of Todd Veldhuizen's research into - moving parts of C++ template compilation to runtime, only - coming from the opposite end of things. - -

Boost.Python v2 Progress

- Here's what actually got accomplished. - -

Documentation

- -

My first priority upon returning from Python10 was to get - some documentation in place. After wasting an unfortunate - amount of time looking at automatic documentation tools which - don't quite work, I settled down to use Bill Kempf's - HTML templates designed to be a boost standard. While they - are working well, it is highly labor-intensive. - -

I decided to begin with the high-level reference material, - as opposed to tutorial, narrative, or nitty-gritty details of - the framework. It seemed more important to have a precise - description of the way the commonly-used components work than - to have examples in HTML (since we already have some test - modules), and since the low-level details are much - less-frequently needed by users it made sense for me to - simply respond to support requests for the time being. - -

After completing approximately 60% of the high-level docs - (currently checked in to libs/python/doc/v2), I found myself - ready to start documenting the mechanisms for creating - to-/from-python converters. This caused a dilemma: I had - realized during the previous week that a much simpler, - more-efficient, and easier-to-use implementation was - possible, but I hadn't planned on implementing it right - away, since what was already in place worked adequately. I - had also received my first query on the C++-sig about how to - write such a converter - -

Given the labor-intensive nature of documentation writing, - I decided it would be a bad idea to document the conversion - mechanism if I was just going to rewrite it. Often the best - impetus for simplifying a design is the realization that - understandably documenting its current state would be too - difficult, and this was no exception. - -

Overhaul of - to_python/from_python conversion - mechanism

- -

There were two basic realizations involved here: - -

    -
  1. to_python conversion could be a one-step - process, once an appropriate conversion function is found. - This allows elimination of the separate indirect - convertibility check - -
  2. There are basically two categories of from_python - conversions: those which lvalues stored within or held by - the Python object (essentially extractions), like what - happens when an instance of a C++ class exposed with class_ - is used as the target of a wrapped member function), and - those in which a new rvalue gets created, as when a Python - Float is converted to a C++ - complex<double> or a Python tuple is - converted to a C++ std::vector<>. From - the client side, there are two corresponding categories of - conversion: those which demand an lvalue conversion and - those which can accept an lvalue or an rvalue conversion. -
- The latter realization allowed the following collapse, which - considerably simplified things: - -
- - - - - - - - - - - - - - - - - -
Target Type - - Eligible Converters - -
T - - T rvalue or lvalue - -
T const - -
T volatile - -
T const volatile - -
T const& - -
T const* - - T lvalue - -
T volatile* - -
T const volatile* - -
T& - -
T volatile& - -
T const volatile& - -
T* const& - -
T const* const& - -
T volatile*const& - -
T const volatile*const& -
-
- This job included the following additional enhancements: - -
    -
  • Elimination of virtual functions, which cause object - code bloat - -
  • Registration of a single converter function for all - lvalue conversions, two for all rvalue conversions - -
  • Killed lots of unneeded code - -
  • Increased opacity of registry interface - -
  • Eliminated all need for decorated runtime type - identifiers - -
  • Updated test modules to reflect new interface - -
  • Eliminated the need for users to worry about converter - lifetime issues Additional Builtin Conversion Enhancements - -
  • Support for complex<float>, - complex<double>, and complex<long double> - conversions - -
  • Support for bool conversions - -
  • NULL pointers representable by None in Python - -
  • Support for conversion of Python classic classes to - numeric types -
- -

Miscellaneous

- These don't fit easily under a large heading: - -
    -
  • Support CallPolicies for class member functions - -
  • from_python_data.hpp: revamped type alignment - metaprogram so that it's fast enough for KCC - -
  • classfwd.hpp header forward-declares class_<T> - -
  • indirect_traits.hpp: - -
  • added is_pointer_to_reference - -
  • fixed bugs - -
  • Reduced recompilation dependencies - -
  • msvc_typeinfo works around broken MS/Intel typeid() - implementation - -
  • Many fixes and improvements to the type_traits library - in order to work around compiler bugs and suppress warnings - -
  • Eliminated the need for explicit acquisition of - converter registrations - -
  • Expanded constructor support to 6 arguments - -
  • Implemented generalized pointer lifetime support - -
  • Updated code generation for returning.hpp - -
  • Tracked down and fixed cycle GC bugs - -
  • Added comprehensive unit tests for destroy_reference, - pointer_type_id, select_from_python, complex<T>, - bool, and classic class instance conversions -
- -

Revised - - 4 April, 2002 - - - -

© Copyright Dave Abrahams - 2002. All Rights Reserved. - diff --git a/doc/v2/from_python.html b/doc/v2/from_python.html deleted file mode 100644 index 8bc2eda9..00000000 --- a/doc/v2/from_python.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - Boost.Python - <boost/python/from_python.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/from_python.hpp>

-
-


- -

Contents

- -
-
Introduction - -
Classes - -
-
-
Class - Templatefrom_python - -
-
-
Class Template - from_python synopsis - -
Class Template - from_python constructor - -
Class Template - from_python observer functions -
-
- -
Example -
-
- -

Introduction

- -

<boost/python/from_python.hpp> introduces a class - template from_python<T> for extracting a C++ object of - type T from a Python object. - -

Classes

- -

Class Template - from_python<class T>

- -

from_python<T> is the type used internally by - Boost.Python to extract C++ function arguments from a Python argument tuple - when calling a wrapped function. It can also be used directly to make - similar conversions in other contexts. - -

Class Template - from_python synopsis

-
-namespace boost { namespace python
-{
-   template <class T>
-   struct from_python : private boost::noncopyable // Exposition only.
-       // from_python<T> meets the NonCopyable requirements
-   {
-      from_python(PyObject*);
-      bool convertible() const;
-      convertible-to-T operator()(PyObject*) const;
-   };
-}
-
- -

Class Template - from_python constructor

-
-from_python(PyObject* p);
-
- -
-
Requires: p != 0 - -
Effects: Constructs a from_python object suitable - for extracting a C++ object of type T from p. -
- -

Class Template - from_python observer functions

-
-bool convertible() const;
-
- -
-
Returns: false if the conversion cannot succeed. - This indicates that either: - -
-
    -
  1. No from_python_converter was registered for - T, or - -
  2. any such converter rejected the constructor argument - p by returning 0 from its - convertible() function -
- Note that conversion may still fail in operator() due to - an exception. - -
Throws: nothing - -
Rationale: Because from_python<> is used in - overload resolution, and throwing an exception can be slow, it is useful - to be able to rule out a broad class of unsuccessful conversions without - throwing an exception. -
-
-convertible-to-T operator()(PyObject* p) const;
-
- -
-
Requires: *p refers to the same object which was - passed to the constructor, and convertible() returns - true. - -
Effects: performs the conversion - -
Returns: an object convertible to T. -
- -

Example

-
-#include <string>
-#include <boost/python/from_python.hpp>
-
-// If a std::string can be extracted from p, return its
-// length. Otherwise, return 0.
-std::size_t length_if_string(PyObject* p)
-{
-   from_python<std::string> converter(p);
-   if (!converter.convertible())
-      return 0;
-   else
-      return converter(p).size();
-}
-
- -

Revised - - 05 November, 2001 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/has_back_reference.html b/doc/v2/has_back_reference.html deleted file mode 100644 index a31cf448..00000000 --- a/doc/v2/has_back_reference.html +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - - Boost.Python - - <boost/python/has_back_reference.hpp> - - - - -
-

C++ Boost

- -
-

Boost.Python

- -

Header - <boost/python/has_back_reference.hpp>

-
-


- -

Contents

- -
-
Introduction - -
Classes - -
-
-
Class template - has_back_reference - -
-
-
Class template - has_back_reference synopsis -
- -
Example(s) -
-
-
- -

Introduction

- -

<boost/python/has_back_reference.hpp> - defines the traits class template - has_back_reference<>, which can be - specialized by the user to indicate that a wrapped class - instance holds a PyObject* corresponding to a - Python object. - -

Classes

- -

Class template - has_back_reference

- -

A unary metafunction whose value is true iff - its argument is a pointer_wrapper<>. - -

Class - template has_back_reference synopsis

-
-namespace boost { namespace python
-{
-    template<class WrappedClass> class has_back_reference
-    { 
-        static unspecified value = false;
-    };
-}}
-
- -

A "traits - class" which is inspected by Boost.Python to - determine how wrapped classes can be constructed. - -

- -
value is an integral constant convertible - to bool of unspecified type. - -
Specializations may substitute a value convertible to - true for value iff for each invocation of - class_<WrappedClass>::def_init(args<type-sequence...>()), - there exists a corresponding constructor - WrappedClass::WrappedClass(PyObject*, type-sequence...). If - such a specialization exists, the WrappedClass - constructors will be called with a "back reference" pointer - to the corresponding Python object whenever they are invoked from - Python. - -
- -

Example

- -

C++ module definition

- -
-#include <boost/python/class.hpp>
-#include <boost/python/module.hpp>
-#include <boost/python/has_back_reference.hpp>
-#include <boost/shared_ptr.hpp>
-
-using namespace boost::python;
-
-struct X
-{
-    X(PyObject* self) : m_self(self), m_x(0) {}
-    X(PyObject* self, int x) : m_self(self), m_x(x) {}
-    
-    PyObject* self() { return m_self; }
-    int get() { return m_x; }
-    void set(int x) { m_x = x; }
-
-    PyObject* m_self;
-    int x;
-};
-
-// specialize has_back_reference for X
-namespace boost { namespace python
-{
-  template <>
-  struct has_back_reference<X>
-  {
-     enum { value = true; }
-  }
-}}
-
-struct Y
-{
-    Y() : m_x(0) {}
-    Y(int x) : m_x(x) {}
-    int get() { return m_x; }
-    void set(int x) { m_x = x; }
-
-    int x;
-};
-
-boost::shared_ptr<Y> Y_self(boost::shared_ptr<Y> self) const { return self; }
-
-BOOST_PYTHON_MODULE_INIT(back_references)
-{
-    module("back_references")
-        .add(
-            class_<X>("X")
-               .def_init()
-               .def_init(args<int>())
-               .def("self", &X::self)
-               .def("get", &X::get)
-               .def("set", &X::set)
-            )
-        .add(
-            class_<Y, shared_ptr<Y> >("Y")
-               .def_init()
-               .def_init(args<int>())
-               .def("get", &Y::get)
-               .def("set", &Y::set)
-               .def("self", Y_self)
-            )
-        ;
-}
-
- -The following Python session illustrates that x.self() -returns the same Python object on which it is invoked, while -y.self() must create a new Python object which refers to -the same Y instance. - -

Python code

- -
->>> from back_references import *
->>> x = X(1)
->>> x2 = x.self()
->>> x2 is x
-1
->>> (x.get(), x2.get())
-(1, 1)
->>> x.set(10)
->>> (x.get(), x2.get())
-(10, 10)
->>>
->>>
->>> y = Y(2)
->>> y2 = y.self()
->>> y2 is y
-0
->>> (y.get(), y2.get())
-(2, 2)
->>> y.set(20)
->>> (y.get(), y2.get())
-(20, 20)
-
- -

Revised - - 07 May, 2002 - - - -

© Copyright Dave Abrahams - 2002. All Rights Reserved. - diff --git a/doc/v2/header.html b/doc/v2/header.html deleted file mode 100644 index 7b65547d..00000000 --- a/doc/v2/header.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - Boost.Python - <{{header}}> - - - -
-

-

- -
-

Boost.Python

- -

Header <{{header}}>

-
-


- -

Contents

- -
-
Introduction - -
Macros - -
-
-
{{macro name}} -
- -
Values - -
-
-
{{value name}} -
- -
Types - -
-
-
{{type name}} -
- -
Classes - -
-
-
Class {{name}} - -
-
-
Class {{name}} synopsis - -
Class {{name}} - constructors and destructor - -
Class {{name}} comparison functions - -
Class {{name}} modifier functions - -
Class {{name}} observer functions - -
Class {{name}} static functions -
-
- -
Functions - -
-
-
{{function name}} -
- -
Objects - -
-
-
{{object name}} -
- -
Example(s) -
-
- -

Introduction

- -

{{Introductory text}} - -

Macros

- -

{{Macro specifications}} - -

Values

- -

{{Value specifications}} - -

Types

- -

{{Type specifications}} - -

Classes

- -

Class {{name}}

- -

{{class overview text}} - -

Class {{name}} synopsis

-
-namespace boost
-{
-    class {{name}}
-  {
-  };
-};
-
- -

Class {{name}} constructors and - destructor

-
-{{constructor}}
-
- -
-
Requires: {{text}} - -
Effects: {{text}} - -
Postconditions: {{text}} - -
Returns: {{text}} - -
Throws: {{text}} - -
Complexity: {{text}} - -
Rationale: {{text}} -
-
-{{destructor}}
-
- -
-
Requires: {{text}} - -
Effects: {{text}} - -
Postconditions: {{text}} - -
Returns: {{text}} - -
Throws: {{text}} - -
Complexity: {{text}} - -
Rationale: {{text}} -
- -

Class {{name}} comparison - functions

-
-{{function}}
-
- -
-
Requires: {{text}} - -
Effects: {{text}} - -
Postconditions: {{text}} - -
Returns: {{text}} - -
Throws: {{text}} - -
Complexity: {{text}} - -
Rationale: {{text}} -
- -

Class {{name}} modifier - functions

-
-{{function}}
-
- -
-
Requires: {{text}} - -
Effects: {{text}} - -
Postconditions: {{text}} - -
Returns: {{text}} - -
Throws: {{text}} - -
Complexity: {{text}} - -
Rationale: {{text}} -
- -

Class {{name}} observer - functions

-
-{{function}}
-
- -
-
Requires: {{text}} - -
Effects: {{text}} - -
Postconditions: {{text}} - -
Returns: {{text}} - -
Throws: {{text}} - -
Complexity: {{text}} - -
Rationale: {{text}} -
- -

Class {{name}} static functions

-
-{{function}}
-
- -
-
Requires: {{text}} - -
Effects: {{text}} - -
Postconditions: {{text}} - -
Returns: {{text}} - -
Throws: {{text}} - -
Complexity: {{text}} - -
Rationale: {{text}} -
- -

Functions

-
-
-
-{{function}}
-
- -
-
Requires: {{text}} - -
Effects: {{text}} - -
Postconditions: {{text}} - -
Returns: {{text}} - -
Throws: {{text}} - -
Complexity: {{text}} - -
Rationale: {{text}} -
- -

Objects

- -

{{Object specifications}} - -

Example(s)

- -

{{Example(s)}} - -

Revised - - 05 November, 2001 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/implicit.html b/doc/v2/implicit.html deleted file mode 100644 index 99ce9ad8..00000000 --- a/doc/v2/implicit.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - Boost.Python - <boost/python/implicit.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/implicit.hpp>

-
-


- -

Contents

- -
-
Introduction - - -
Functions - -
-
-
Function Template implicitly_convertible - -
- -
Example -
-
- -

Introduction

- - implicitly_convertible allows Boost.Python to - implicitly take advantage of a C++ implicit or explicit conversion - when matching Python objects to C++ argument types. - -

Functions

- -

Function template implicitly_convertible

-
-template <class Source, class Target>
-void implicitly_convertible();
-
- - - - - - - -
- implicitly_convertible template parameters
-
Parameter - Description - -
Source - The source type of the implicit conversion - -
Target - The target type of the implicit conversion -
- -
-
Requires: The expression Target(s), - where s is of type Source, is valid. - -
Effects: registers an rvalue from_python - converter to Target which can succeed for any - PyObject* p iff there exists any registered - converter which can produce Source rvalues - -
Rationale: C++ users expect to be able to take - advantage of the same sort of interoperability in Python as they - do in C++. -
- - -

Example

- - -

C++ module definition

- -
-#include <boost/python/class.hpp>
-#include <boost/python/implicit.hpp>
-#include <boost/python/module.hpp>
-
-using namespace boost::python;
-
-struct X
-{
-    X(int x) : v(x) {}
-    operator int() { return v; }
-    int v;
-};
-
-int x_value(X const& x)
-{
-    return x.v;
-}
-
-X make_x(int n) { return X(n); }
-
-BOOST_PYTHON_MODULE_INIT(implicit_ext)
-{
-    module("implicit_ext")
-        .def("x_value", x_value)
-        .def("make_x", make_x)
-        .add(
-            class_<X>("X")
-            .def_init(args<int>())
-            )
-        ;
-    implicitly_convertible<X,int>();
-    implicitly_convertible<int,X>();
-}
-
- -

Python code

- -
->>> from implicit_ext import *
->>> x_value(X(42))
-42
->>> x_value(42)
-42
->>> x = make_x(X(42))
->>> x_value(x)
-42
-
- -

Revised - - 08 May, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/index.html b/doc/v2/index.html deleted file mode 100644 index d1c1c0c0..00000000 --- a/doc/v2/index.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - -Boost.Python - - - - - - - -
-

-

-
-

Boost.Python

-

Index

-
-


-

Contents

-
-
Overview
-
Reference
-
Configuration Information
-
Rationale
-
Definitions
-
Frequently Asked Questions (FAQs)
-
Progress Reports
-
Bibliography
-
Acknowledgments
-
-
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/instance_holder.html b/doc/v2/instance_holder.html deleted file mode 100755 index db524825..00000000 --- a/doc/v2/instance_holder.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - Boost.Python - <boost/python/instance_holder.hpp> - - - - -
-

C++ Boost

- -
-

Boost.Python

- -

Header <boost/python/instance_holder.hpp>

-
-
- -

Contents

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

Introduction

- -

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

Classes

- -

Class instance_holder

- -

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

Class instance_holder - synopsis

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

Class instance_holder - destructor

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

Class - instance_holder modifiers

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

Class instance_holder - observers

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

Example

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

Revised - - 29 May, 2002 - - - -

© Copyright Dave Abrahams 2002. All - Rights Reserved. - diff --git a/doc/v2/iterator.html b/doc/v2/iterator.html deleted file mode 100644 index 1e367cce..00000000 --- a/doc/v2/iterator.html +++ /dev/null @@ -1,364 +0,0 @@ - - - - - - Boost.Python - <boost/python/iterator.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/iterator.hpp>

-
-


- -

Contents

- -
-
Introduction - -
Classes - -
-
-
Class template iterator - -
-
-
Class - iterator synopsis - -
Class template iterator - constructor -
-
- -
-
Class template iterators - -
-
-
Class - iterators synopsis -
Class template - iterators nested types -
Class template - iterators static functions -
-
- -
Functions - -
-
-
range -
- -
Examples -
-
- -

Introduction

- -

<boost/python/iterator.hpp> provides types - and functions for creating Python - iterators from C++ - Containers and Iterators. Note - that if your class_ supports random-access iterators, - implementing - __getitem__ - (also known as the Sequence Protocol) may serve you better than - using this facility: Python will automatically create an iterator - type for you (see iter()), - and each access can be range-checked, leaving no possiblity of - accessing through an invalidated C++ iterator. - -

Classes

- -

Class Template iterator

- -

Instances of iterator<C,P> hold a reference - to a callable Python object which, when invoked from Python, - expects a single argument c convertible to - C and creates a Python iterator that traverses - [c.begin(), - c.end()). The optional CallPolicies - P can be used to control how elements are returned - during iteration. - -

In the table below, c is an instance of Container. - - - - - -
Template Parameter - - Requirements - - Semantics - - Default - -
Container - - [c.begin(),c.end()) is a valid Iterator - range. - - The result will convert its argument to - c and call - c.begin() and c.end() to acquire - iterators. To invoke Container's - const begin() and end() - functions, make it const. - - -
NextPolicies - - A default-constructible model of CallPolicies. - - Applied to the resulting iterators' next() method. - - An unspecified model of CallPolicies - which always makes a copy of the - result of deferencing the underlying C++ iterator - -
- -

Class Template iterator synopsis

-
-namespace boost { namespace python
-{
-  template <class Container
-             , class NextPolicies = unspecified>
-  struct iterator : reference<PyObject*>
-  {
-      iterator();
-  };
-}}
-
-

Class Template - iterator constructor

- -
-iterator()
-
- -
-
Effects: Initializes its base class with the result - of: -
-range<NextPolicies>(&iterators<Container>::begin, &iterators<Container>::end)
-
- -
Postconditions: this->get() points to - a Python callable object which creates a Python iterator as - described above. - -
Rationale: Provides an easy way to create iterators - for the common case where a C++ class being wrapped provides - begin() and end(). -
- - - -

Class Template iterators

- -

A utility class template which provides a way to reliably call - its argument's begin() and end() member - functions. Note that there is no portable way to take the address - of a member function of a C++ standard library container, so - iterators<> can be particularly helpful when - wrapping them. - - -

In the table below, x is an instance of C. - - - - - -
Required Valid Expression - - Type - -
x.begin() - - Convertible to C::const_iterator if C is a - const type; convertible to C::iterator otherwise. - -
x.end() - - Convertible to C::const_iterator if C is a - const type; convertible to C::iterator otherwise. - -
- -

Class Template iterators synopsis

-
-namespace boost { namespace python
-{
-  template <class C>
-  struct iterators
-  {
-      typedef typename C::[const_]iterator iterator;
-      static iterator begin(C& x);
-      static iterator end(C& x);
-  };
-}}
-
-
-

Class Template - iterators nested types

- -If C is a const type, -
-typedef typename C::const_iterator iterator;
-
-Otherwise: -
-typedef typename C::iterator iterator;
-
- -

Class Template - iterators static functions

- -
-static iterator begin(C&);
-
- -
-
Returns: x.begin() -
- -
-static iterator end(C&);
-
- -
-
Returns: x.end() -
- - - -

Functions

-
-template <class NextPolicies, class Target, class Accessor1, class Accessor2>
-reference<PyObject*> range(Accessor1 start, Accessor2 finish);
-
-template <class NextPolicies, class Accessor1, class Accessor2>
-reference<PyObject*> range(Accessor1 start, Accessor2 finish);
-
-template <class Accessor1, class Accessor2>
-reference<PyObject*> range(Accessor1 start, Accessor2 finish);
-
- -
-
Requires: NextPolicies is a - default-constructible model of CallPolicies. - -
Effects:
- -The first form creates a Python callable - object which, when invoked, converts its argument to a - Target object - x, and creates a Python iterator which traverses - [bind(start,_1)(x)bind(finish,_1)(x)), - applying NextPolicies to the iterator's - next() function. -
-
The second form is identical to - the first, except that Target is deduced from - Accessor1 as follows: -
    -
  1. If Accessor1 is a function type, - Target is the type of its first argument. -
  2. If Accessor1 is a data member pointer of the - form R (T::*), Target is - identical to T. -
  3. If Accessor1 is a member function pointer of - the form - R (T::*)(arguments...) cv-opt, - where cv-opt is an optional cv-qualifier, - Target is identical to T. -
-
- -
The third form is identical to the second, except that - NextPolicies is an unspecified model of CallPolicies - which always makes a copy of the - result of deferencing the underlying C++ iterator
-
- - -
Rationale: The use of boost::bind() allows - C++ iterators to be accessed through functions, member functions - or data member pointers. Customization of - NextPolicies (e.g. using return_internal_reference) is useful when it is - expensive to copy sequence elements of a wrapped class - type. Customization of Target is useful when - Accessor1 is a function object, or when a base - class of the intended target type would otherwise be deduced. -
- -

Examples

- -
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/return_internal_reference.hpp>
-#include <vector>
-
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(demo)
-{
-   module("demo")
-      .add(
-         class_<std::vector<double> >("dvec")
-            .def("__iter__", iterator<std::vector<double> >())
-            ...
-         )
-      ;
-}
-
- -A more comprehensive example can be found in: -
-
libs/python/test/iterator.cpp
-
libs/python/test/input_iterator.cpp
-
libs/python/test/input_iterator.py
- - -

Revised - - 17 May, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/lvalue_from_pytype.html b/doc/v2/lvalue_from_pytype.html deleted file mode 100755 index 8b3cb49e..00000000 --- a/doc/v2/lvalue_from_pytype.html +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - Boost.Python - <boost/python/lvalue_from_python.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/lvalue_from_pytype.hpp>

-
-


- -

Contents

- -
-
Introduction - - -
Classes - -
-
-
Class Template lvalue_from_pytype - -
-
- -
Class Template - lvalue_from_pytype synopsis - -
Class Template - lvalue_from_pytype constructor -
-
- -
-
Class Template extract_identity -
-
- -
Class Template - extract_identity synopsis - -
Class Template - extract_identity static functions -
-
Class Template extract_member -
-
- -
Class Template - extract_member synopsis - -
Class Template - extract_member static functions -
-
- -
Example -
-
- -

Introduction

- - <boost/python/lvalue_from_pytype.hpp> supplies - a facility for extracting C++ objects from within Python instances - of a given type. This is typically useful for dealing with - "traditional" Python extension types. - -

Classes

- -

Class template lvalue_from_pytype

- -

Class template lvalue_from_pytype will register - from_python converters which, given an object of the given Python - type, can extract references and pointers to a particular C++ - type. Its template arguments are: - -

- - - - - - - -
- lvalue_from_pytype Requirements
- - In the table below, x denotes an object of type PythonObject& - -
Parameter - - Requirements - - Semantics - -
Extractor - - a model of Extractor whose - execute function returns a reference type. - - Extracts the lvalue from the Python object once its type has been confirmed - -
python_type - - A compile-time constant PyTypeObject* - - The Python type of instances convertible by this - converter. Python subtypes are also convertible. - -
- -

Class template lvalue_from_pytype synopsis

-
-namespace boost { namespace python
-{
-   template <class Extractor, PyTypeObject const* python_type>
-   struct lvalue_from_pytype
-   {
-       lvalue_from_pytype();
-   };
-}}
-
- -

Class template lvalue_from_pytype constructor

-
-lvalue_from_pytype();
-
- -
- -
Effects: Registers converters which can convert - Python objects of the given type to lvalues of the type returned - by Extractor::execute. - -
- -

Class template extract_identity

- -

extract_identity is a model of Extractor which can be - used in the common case where the C++ type to be extracted is the - same as the Python object type. - -

Class template - extract_identity synopsis

-
-namespace boost { namespace python
-{
-   template <class InstanceType>
-   struct extract_identity
-   {
-      static InstanceType& execute(InstanceType& c);
-   };
-}}
-
- -

Class template extract_identity static functions

-
-InstanceType& execute(InstanceType& c);
-
- -
- -
Returns: c - -
- - -

Class template extract_member

- -

extract_member is a model of Extractor which can be - used in the common case in the common case where the C++ - type to be extracted is a member of the Python object. - -

Class template extract_member synopsis

-
-namespace boost { namespace python
-{
-   template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
-   struct extract_member
-   {
-      static MemberType& execute(InstanceType& c);
-   };
-}}
-
- -

Class template extract_member static functions

-
-static MemberType& execute(InstanceType& c);
-
- -
- -
Returns: c.*member - -
- -

Example

- -This example presumes that someone has implemented the standard noddy -example module from the Python documentation, and we want to build -a module which manipulates Noddys. Since -noddy_NoddyObject is so simple that it carries no -interesting information, the example is a bit contrived: it assumes -you want to keep track of one particular object for some reason. This -module would have to be dynamically linked to the module which defines -noddy_NoddyType. - -

C++ module definition

- -
-#include <boost/python/reference.hpp>
-#include <boost/python/module.hpp>
-
-// definition lifted from the Python docs
-typedef struct {
-   PyObject_HEAD
-} noddy_NoddyObject;
-
-using namespace boost::python;
-static reference<PyObject> cache;
-
-bool is_cached(noddy_NoddyObject* x)
-{
-   return x == cache.get();
-}
-
-void set_cache(noddy_NoddyObject* x)
-{
-   cache.reset((PyObject*)x, ref::increment_count);
-}
-
-BOOST_PYTHON_MODULE_INIT(noddy_cache)
-{
-   module noddy_cache("noddy_cache")
-      .def("is_cached", is_cached)
-      .def("set_cache", set_cache)
-      ;
-
-   // register Noddy lvalue converter
-   lvalue_from_pytype<extract_identity<noddy_NoddyObject>,&noddy_NoddyType>();
-}
-
- -

Python code

- -
->>> import noddy
->>> n = noddy.new_noddy()
->>> import noddy_cache
->>> noddy_cache.is_cached(n)
-0
->>> noddy_cache.set_cache(n)
->>> noddy_cache.is_cached(n)
-1
->>> noddy_cache.is_cached(noddy.new_noddy())
-0
-
- -

Revised - - 05 November, 2001 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/make_function.html b/doc/v2/make_function.html deleted file mode 100644 index c31144c9..00000000 --- a/doc/v2/make_function.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - Boost.Python - <boost/python/make_function.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/make_function.hpp>

-
-


- -

Contents

- -
-
Introduction - -
Functions - -
-
-
make_function - -
make_constructor -
- -
Example -
-
- -

Introduction

- -

make_function() and - make_constructor() are - the functions used internally by class_<>::def, class_<>::def, and - class_<>::def_init to produce Python - callable objects which wrap C++ functions and member functions. - -

Functions

-
-template <class F>
-objects::function* make_function(F f)
-
-template <class F, class Policies>
-objects::function* make_function(F f, Policies const& policies)
-
- -
-
Requires: F is a function pointer or member - function pointer type - -
Effects: Creates a Python callable object which, when called - from Python, converts its arguments to C++ and calls f. If - F is a pointer-to-member-function type, the target object of - the function call (*this) will be taken from the first - Python argument, and subsequent Python arguments will be used as the - arguments to f. If policies are supplied, it - must be a model of CallPolicies, and will - be applied to the function as described here. - -
Returns: A pointer convertible to PyObject* which - refers to the new Python callable object. -
-
-template <class T, class ArgList, class Generator>
-objects::function* make_constructor();
-
-template <class ArgList, class Generator, class Policies>
-objects::function* make_constructor(Policies const& policies)
-
- -
-
Requires: T is a class - type. Policies is a model of CallPolicies. ArgList - is an MPL sequence - of C++ argument types (A1, A2,... AN) such that if - a1, a2... aN are objects of type - A1, A2,... AN respectively, the expression new - Generator::apply<T>::type(a1, a2... aN) is - valid. Generator is a model of HolderGenerator. - -
Effects: Creates a Python callable object which, when called - from Python, expects its first argument to be a Boost.Python extension - class object. It converts its remaining its arguments to C++ and passes - them to the constructor of a dynamically-allocated - Generator::apply<T>::type object, which is - then installed in the extension class object. In the second - form, the policies are applied to the arguments and - result (None) - of the Python callable object - -
Returns: The new Python callable object -
- -

Example

- -

C++ function exposed below returns a callable object wrapping one of two - functions. -

-#include <boost/python/make_function.hpp>
-#include <boost/python/module.hpp>
-
-char const* foo() { return "foo"; }
-char const* bar() { return "bar"; }
-
-PyObject* choose_function(bool selector)
-{
-    if (selector)
-        return boost::python::make_function(foo);
-    else
-        return boost::python::make_function(bar);
-}
-
-BOOST_PYTHON_MODULE_INIT(make_function_test)
-{
-    module("make_function_test")
-        .def("choose_function", choose_function);
-}
-
- It can be used this way in Python: -
->>> from make_function_test import *
->>> f = choose_function(1)
->>> g = choose_function(0)
->>> f()
-'foo'
->>> g()
-'bar'
-
- -

- - 14 February 2002 - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/manage_new_object.html b/doc/v2/manage_new_object.html deleted file mode 100644 index 8630dfa5..00000000 --- a/doc/v2/manage_new_object.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - Boost.Python - <boost/python/manage_new_object.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header - <boost/python/manage_new_object.hpp>

-
-


- -

Contents

- -
-
Classes - -
-
-
Class - manage_new_object - -
-
-
Class - manage_new_object synopsis - -
Class - manage_new_object metafunctions -
-
- -
Example -
-
- -

Classes

- -

Class - manage_new_object

- -

manage_new_object is a model of ResultConverterGenerator which can be - used to wrap C++ functions which return a pointer to an object allocated - with a new-expression, and expect the caller to take responsibility - for deleting that object. - -

Class - manage_new_object synopsis

-
-namespace boost { namespace python
-{
-    struct manage_new_object
-    {
-        template <class T> struct apply;
-    };
-}}
-
- -

Class - manage_new_object metafunctions

-
-template <class T> struct apply
-
- -
-
Requires: T is U* for some - U. - -
Returns: typedef to_python_indirect<T> - type; -
- -

Example

- -

In C++: -

-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/manage_new_object.hpp>
-#include <boost/python/return_value_policy.hpp>
-
-
-struct Foo {
-   Foo(int x) : x(x){}
-   int get_x() { return x; }
-   int x;
-};
-
-Foo* make_foo(int x) { return new Foo(x); }
-
-// Wrapper code
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(my_module)
-{
-   module("my_module")
-      .def("make_foo", make_foo, return_value_policy<manage_new_object>)
-      .add(
-         class_<Foo>()
-            .def("get_x", &Foo::get_x)
-         )
-}
-
-In Python: -
->>> from my_module import *
->>> f = make_foo(3)     # create a Foo object
->>> f.get_x()
-3
-
- -

Revised - - 14 February 2002 - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/module.html b/doc/v2/module.html deleted file mode 100644 index 3685934c..00000000 --- a/doc/v2/module.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - Boost.Python - <boost/python/module.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/module.hpp>

-
-


- -

Contents

- -
-
Introduction - -
Macros - -
-
-
BOOST_PYTHON_MODULE_INIT -
- -
Classes - -
-
-
Class module - -
-
-
Class module - synopsis - -
Class module - constructor - -
Class module - modifier functions - -
Class module - observer functions -
-
- -
Example(s) -
-
- -

Introduction

- -

This header provides the basic facilities needed to create an - extension module. - -

Macros

- -

BOOST_PYTHON_MODULE_INIT(name) - is used to declare Python - module initialization functions. The name argument must - exactly match the name of the module to be initialized, and must conform to - Python's identifier naming - rules. Where you would normally write -

-void initname()
-{
-   ...
-
- Boost.Python modules should be initialized with -
-BOOST_PYTHON_MODULE_INIT(name)
-{
-   ...
-
- -

Classes

- -

Class module

- -

This class represents the Python extension module under construction. It - provides functions for adding attributes and for retrieving the underlying - Python module object. - -

Class module - synopsis

-
-namespace boost { namespace python
-{
-  class module : public module_base
-  {
-   public:
-      module(const char* name);
-
-      // modifier functions
-      module& setattr(const char* name, PyObject*);
-      module& setattr(const char* name, PyTypeObject*);
-      module& setattr(const char* name, ref const&);
-
-      module& add(PyTypeObject* x);
-      template <class T, class Bases, class HolderGenerator>
-      module& add(class_<T,Bases,HolderGenerator> const& c);
-
-      template <class Fn>
-      module& def(char const* name, Fn fn);
-      template <class Fn, class ResultHandler>
-      module& def(char const* name, Fn fn, ResultHandler handler);
-
-      // observer function
-      ref object() const;
-  };
-
-}}
-
- -

Class module - constructor

-
-module(const char* name);
-
- -
-
Requires: name is a ntbs whose value matches the - argument passed to BOOST_PYTHON_MODULE_INIT. - -
Effects: Creates a module object representing a - Python module named name. -
- -

Class module modifier - functions

-
-module& setattr(const char* name, PyObject* obj);
-module& setattr(const char* name, PyTypeObject* obj);
-module& setattr(const char* name, ref const& r);
-
- -
-
Requires: name is a ntbs which conforms to - Python's identifier - naming rules. In the first two forms, obj is non-null. - In the third form, r.get() is non-null. - -
Effects: Adds the given Python object to the module. If the - object is a product of make_function(), the - usual overloading procedure applies. - In the first two forms, ownership of a reference to obj is transferred - from caller to callee, even if an exception is thrown. - -
Returns: *this -
-
-module& add(PyTypeObject* x);
-
-template <class T, class Bases, class HolderGenerator>
-module& add(class_<T,Bases,HolderGenerator> const& c);
-
- -
-
Requires: In the first form, x is non-null - -
Effects: The first form adds the Python type object named by - x to the Python module under construction, with the name - given by the type's tp_name - field. The second form adds the extension class object being constructed - by c to the module, with the same name that was passed to - c's constructor. - -
Returns: *this - -
Rationale: Provides a way to set type attributes in the module - without having to explicitly specify the name. -
-
-template <class Fn>
-module& def(char const* name, Fn f);
-
-template <class Fn, class ResultHandler>
-module& def(char const* name, Fn f, ResultHandler handler);
-
- -
- -
Requires: f is a non-null pointer-to-function or - pointer-to-member-function. name is a ntbs which conforms to - Python's identifier - naming rules. In the first form, the return type of - f is not a reference and is not a pointer other - than char const* or PyObject*. In the - second form policy is a model of CallPolicy. - -
Effects: Adds the result of make_function(f) to - the extension module being defined, with the given name. If - the module already has an attribute named name, the - usual overloading procedure applies. - -
Returns: *this -
- -

Class module observer - functions

-
-ref object() const;
-
- -
-
Returns: A ref object which holds a reference to - the Python module object created by the module constructor. -
- -

Example(s)

- -

C++ module definition: -

-#include <boost/python/module.hpp>
-
-char const* greet()
-{
-    return "hello, Boost.Python!";
-}
-
-BOOST_PYTHON_MODULE_INIT(boost_greet)
-{
-    module("boost_greet")
-        .def("greet", greet);
-}
-
- -Interactive Python: -
->>> import boost_greet
->>> boost_greet.greet()
-'hello, Boost.Python!'
-
- -

Revised - - 14 February, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/operators.html b/doc/v2/operators.html deleted file mode 100755 index a43df858..00000000 --- a/doc/v2/operators.html +++ /dev/null @@ -1,531 +0,0 @@ - - - - - - Boost.Python - <boost/python/operators.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/operators.hpp>

-
-


- -

Contents

- -
-
Introduction - -
Classes -
-
- -
Class self_ns::self_t -
-
-
Class self_t synopsis - -
Class self_t inplace operators - -
Class self_t comparison functions - -
Class self_t non-member operations - -
Class self_t unary operations - -
Class self_t value operations -
- -
Class template other -
-
-
Class other synopsis -
- -
Class template operator_ -
-
-
Class operator_ synopsis -
- -
- -
Objects -
-
-
self -
- -
Examples -
-
- -

Introduction

- -

<boost/python/operators.hpp> provides types - and functions for automatically generating Python special - methods from the corresponding C++ constructs. Most of these - constructs are operator expressions, hence the name. To use the - facility, substitute the self object for an object of the - class type being wrapped in the expression to be exposed, and pass - the result to class_<>::def(). Much - of what is exposed in this header should be considered part of the - implementation, so is not documented in detail here. - -

Classes

- -

Class self_ns::self_t

- -

self_ns::self_t is the actual type of the self object. The library - isolates self_t in its own namespace, - self_ns, in order to prevent the generalized operator - templates which operate on it from being found by - argument-dependent lookup in other contexts. This should be - considered an implementation detail, since users should never have - to mention self_t directly. - -

Class self_ns::self_t synopsis

-
-namespace boost { namespace python { namespace self_ns {
-{
-   class self_t {};
-
-   // inplace operators
-   template <class T> operator_<unspecified> operator+=(self_t, T);
-   template <class T> operator_<unspecified> operator-=(self_t, T);
-   template <class T> operator_<unspecified> operator*=(self_t, T);
-   template <class T> operator_<unspecified> operator/=(self_t, T);
-   template <class T> operator_<unspecified> operator%=(self_t, T);
-   template <class T> operator_<unspecified> operator>>=(self_t, T);
-   template <class T> operator_<unspecified> operator<<=(self_t, T);
-   template <class T> operator_<unspecified> operator&=(self_t, T);
-   template <class T> operator_<unspecified> operator^=(self_t, T);
-   template <class T> operator_<unspecified> operator|=(self_t, T);
-
-   // comparisons
-   template <class L, class R> operator_<unspecified> operator==(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator!=(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator<(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator>(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator<=(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator>=(L const&, R const&);
-
-   // non-member operations
-   template <class L, class R> operator_<unspecified> operator+(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator-(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator*(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator/(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator%(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator>>(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator<<(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator&(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator^(L const&, R const&);
-   template <class L, class R> operator_<unspecified> operator|(L const&, R const&);
-   template <class L, class R> operator_<unspecified> pow(L const&, R const&);
-
-   // unary operations
-   operator_<unspecified> operator-(self_t);
-   operator_<unspecified> operator+(self_t);
-   operator_<unspecified> operator~(self_t);
-
-   // value operations
-   operator_<unspecified> int_(self_t);
-   operator_<unspecified> long_(self_t);
-   operator_<unspecified> float_(self_t);
-   operator_<unspecified> complex_(self_t);
-   operator_<unspecified> str(self_t);
-
-}}};
-
- -The tables below describe the methods generated when the results of -the expressions described are passed as arguments to class_<>::def(). -x is an object of the class type being wrapped. - - -

Class self_t inplace operators

- - - -In the table below, If r is an object of type -other<T>, -y is an object of type T; otherwise, -y is an object of the same type as -r. - - - -
C++ Expression - Python Method Name - C++ Implementation - -
self += r -__iadd__ -x += y - -
self -= r -__isub__ -x -= y - -
self *= r -__imul__ -x *= y - -
self /= r -__idiv__ -x /= y - -
self %= r -__imod__ -x %= y - -
self >>= r -__irshift__ -x >>= y - -
self <<= r -__ilshift__ -x <<= y - -
self &= r -__iand__ -x &= y - -
self ^= r -__ixor__ -x ^= y - -
self |= r -__ior__ -x |= y -
- -

Class self_t comparison - functions

- -In the tables below, if r is of type self_t, y is an object -of the same type as x; -
-if l or r is an object of type other<T>, -y is an object of type T; -
-otherwise, y is an object of the same type as -l or r.
-l -is never of type self_t. - -

-The column of Python Expressions illustrates the expressions -that will be supported in Python for objects convertible to the types -of x and y. The secondary operation arises -due to Python's reflection -rules for rich comparison operators, and are only used when the -corresponding operation is not defined as a method of the -y object. - - -
C++ Expression Python Method Name C++ Implementation -Python Expressions
(primary, secondary) - - -
self == r __eq__ x == y -x == y, y == x - -
l == self __eq__ y == x -y == x, x == y - -
self != r __ne__ x != y -x != y, y != x - -
l != self __ne__ y != x -y != x, x != y - -
self < r __lt__ x < y -x < y, y > x - -
l < self __gt__ y < x -y > x, x < y - -
self > r __gt__ x > y -x > y, y < x - -
l > self __lt__ y > x -y < x, x > y - -
self <= r __le__ x <= y -x <= y, y >= x - -
l <= self __ge__ y <= x -y >= x, x <= y - -
self >= r __ge__ x >= y -x >= y, y <= x - -
l >= self __le__ y >= x -y <= x, x >= y - - -
- - -

Class - self_t non-member operations

- -The operations whose names begin with "__r" -below will only be called if the left-hand operand does not already -support the given operation, as described here. - - -
C++ Expression Python Method Name C++ Implementation - - -
self + r __add__ x + y -
l + self __radd__ y + x - -
self - r __sub__ x - y -
l - self __rsub__ y - x - -
self * r __mul__ x * y -
l * self __rmul__ y * x - -
self / r __div__ x / y -
l / self __rdiv__ y / x - -
self % r __mod__ x % y -
l % self __rmod__ y % x - -
self >> r __rshift__ x >> y -
l >> self __rrshift__ y >> x - -
self << r __lshift__ x << y -
l << self __rlshift__ y << x - -
self & r __and__ x & y -
l & self __rand__ y & x - -
self ^ r __xor__ x ^ y -
l ^ self __rxor__ y ^ x - -
self | r __or__ x | y -
l | self __ror__ y | x - -
pow(self, r) __pow__ pow(x, y) -
pow(l, self) __rpow__ pow(y, x) - - -
- - -

Class - self_t unary operations

- - -
C++ Expression Python Method Name C++ Implementation - - -
-self __neg__ -x -
+self__pos__ +x -
~self__invert__ ~x - - -
- - -

Class - self_t value operations

- - -
C++ Expression Python Method Name C++ Implementation - - -
int_(self)__int__ long(x) -
long___long__ PyLong_FromLong(x) -
float___float__ double(x) -
complex___complex__ std::complex<double>(x) -
str__str__ lexical_cast<std::string>(x) - - -
- - - -

Class Template other

- -

Instances of other<T> can be used in - operator expressions with self; the - result is equivalent to the same expression with a T - object in place of other<T>. Use - other<T> to prevent construction of a - T object in case it is heavyweight, when no - constructor is available, or simply for clarity. - -

Class Template other synopsis

-
-namespace boost { namespace python
-{
-  template <class T>
-  struct other
-  {
-  };
-}}
-
- - - -

Class Template detail::operator_

- -

Instantiations of detail::operator_<> are - used as the return type of operator expressions involving self. This should be considered an - implementation detail and is only documented here as a way of - showing how the result of self-expressions match - calls to class_<>::def(). - -

Class Template - detail::operator_ synopsis

-
-namespace boost { namespace python { namespace detail
-{
-  template <unspecified>
-  struct operator_
-  {
-  };
-}}}
-
- -

Objects

- -

self - -

-namespace boost { namespace python
-{
-  extern self_ns self;
-}}
-
- -

Example

- -
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/operators.hpp>
-#include <boost/operators.hpp>
-
-struct number
-   : boost::integer_arithmetic<number>
-{
-   number(long x_) : x(x_) {}
-   operator long() const { return x; }
-
-   number& operator+=(number const& rhs)
-      { x += rhs }
-   number& operator-=(number const& rhs);
-      { x -= rhs }
-   number& operator*=(number const& rhs)
-      { x *= rhs }
-   number& operator/=(number const& rhs);
-      { x /= rhs }
-   number& operator%=(number const& rhs);
-      { x %= rhs }
-
-   long x;
-};
-
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(demo)
-{
-   module("demo")
-      .add(
-         class_<number>("number")
-            // interoperate with self
-            .def(self += self)
-            .def(self + self)
-            .def(self -= self)
-            .def(self - self)
-            .def(self *= self)
-            .def(self * self)
-            .def(self /= self)
-            .def(self / self)
-            .def(self %= self)
-            .def(self % self)
-            
-            // Convert to Python int
-            .def(int_(self))
-
-            // interoperate with long
-            .def(self += long())
-            .def(self + long())
-            .def(long() + self)
-            .def(self -= long())
-            .def(self - long())
-            .def(long() - self)
-            .def(self *= long())
-            .def(self * long())
-            .def(long() * self)
-            .def(self /= long())
-            .def(self / long())
-            .def(long() / self)
-            .def(self %= long())
-            .def(self % long())
-            .def(long() % self)
-
-         )
-      ;
-}
-
- -

Revised - - 3 June, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/overview.html b/doc/v2/overview.html deleted file mode 100644 index e6bf820a..00000000 --- a/doc/v2/overview.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - -Boost.Python - Overview - - - - - - - -
-

-

-
-

Boost.Python

-

Overview

-
-


-
-
Introduction
-
First topic
-
Second topic
-
Footnotes
-
-

Introduction

-

{{text}}

-

First Topic

-

{{text}}

-

Second Topic

-

{{text}}

-

Footnotes

-
-
(1) {{text}}
-
(2) {{text}}
-
-
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/pickle.html b/doc/v2/pickle.html deleted file mode 100644 index 13c7b306..00000000 --- a/doc/v2/pickle.html +++ /dev/null @@ -1,293 +0,0 @@ - - -Boost.Python Pickle Support - -
- -c++boost.gif (8819 bytes) - -
-

Boost.Python Pickle Support

- -Pickle is a Python module for object serialization, also known -as persistence, marshalling, or flattening. - -

-It is often necessary to save and restore the contents of an object to -a file. One approach to this problem is to write a pair of functions -that read and write data from a file in a special format. A powerful -alternative approach is to use Python's pickle module. Exploiting -Python's ability for introspection, the pickle module recursively -converts nearly arbitrary Python objects into a stream of bytes that -can be written to a file. - -

-The Boost Python Library supports the pickle module -through the interface as described in detail in the -Python Library Reference for pickle. This interface -involves the special methods __getinitargs__, -__getstate__ and __setstate__ as described -in the following. Note that Boost.Python is also fully compatible -with Python's cPickle module. - -


-

The Boost.Python Pickle Interface

- -At the user level, the Boost.Python pickle interface involves three special -methods: - -
-
-__getinitargs__ -
- When an instance of a Boost.Python extension class is pickled, the - pickler tests if the instance has a __getinitargs__ method. - This method must return a Python tuple (it is most convenient to use - a boost::python::tuple). When the instance is restored by the - unpickler, the contents of this tuple are used as the arguments for - the class constructor. - -

- If __getinitargs__ is not defined, pickle.load - will call the constructor (__init__) without arguments; - i.e., the object must be default-constructible. - -

-

-__getstate__ - -
- When an instance of a Boost.Python extension class is pickled, the - pickler tests if the instance has a __getstate__ method. - This method should return a Python object representing the state of - the instance. - -

-

-__setstate__ - -
- When an instance of a Boost.Python extension class is restored by the - unpickler (pickle.load), it is first constructed using the - result of __getinitargs__ as arguments (see above). Subsequently - the unpickler tests if the new instance has a __setstate__ - method. If so, this method is called with the result of - __getstate__ (a Python object) as the argument. - -
- -The three special methods described above may be .def()'ed -individually by the user. However, Boost.Python provides an easy to use -high-level interface via the -boost::python::pickle_suite class that also -enforces consistency: __getstate__ and __setstate__ -must be defined as pairs. Use of this interface is demonstrated by the -following examples. - -
-

Examples

- -There are three files in boost/libs/python/test that show how to -provide pickle support. - -
-

pickle1.cpp

- - The C++ class in this example can be fully restored by passing the - appropriate argument to the constructor. Therefore it is sufficient - to define the pickle interface method __getinitargs__. - This is done in the following way: - -
    -
  • 1. Definition of the C++ pickle function: -
    -  struct world_pickle_suite : boost::python::pickle_suite
    -  {
    -    static
    -    boost::python::tuple
    -    getinitargs(world const& w)
    -    {
    -        return boost::python::make_tuple(w.get_country());
    -    }
    -  };
    -
    -
  • 2. Establishing the Python binding: -
    -  class_<world>("world", args<const std::string&>())
    -      // ...
    -      .def_pickle(world_pickle_suite())
    -      // ...
    -
    -
- -
-

pickle2.cpp

- - The C++ class in this example contains member data that cannot be - restored by any of the constructors. Therefore it is necessary to - provide the __getstate__/__setstate__ pair of - pickle interface methods: - -
    -
  • 1. Definition of the C++ pickle functions: -
    -  struct world_pickle_suite : boost::python::pickle_suite
    -  {
    -    static
    -    boost::python::tuple
    -    getinitargs(const world& w)
    -    {
    -      // ...
    -    }
    -
    -    static
    -    boost::python::tuple
    -    getstate(const world& w)
    -    {
    -      // ...
    -    }
    -
    -    static
    -    void
    -    setstate(world& w, boost::python::tuple state)
    -    {
    -      // ...
    -    }
    -  };
    -
    -
  • 2. Establishing the Python bindings for the entire suite: -
    -  class_<world>("world", args<const std::string&>())
    -      // ...
    -      .def_pickle(world_pickle_suite())
    -      // ...
    -
    -
- -

- For simplicity, the __dict__ is not included in the result - of __getstate__. This is not generally recommended, but a - valid approach if it is anticipated that the object's - __dict__ will always be empty. Note that the safety guard - described below will catch the cases where this assumption is violated. - -


-

pickle3.cpp

- - This example is similar to pickle2.cpp. However, the - object's __dict__ is included in the result of - __getstate__. This requires a little more code but is - unavoidable if the object's __dict__ is not always empty. - -
-

Pitfall and Safety Guard

- -The pickle protocol described above has an important pitfall that the -end user of a Boost.Python extension module might not be aware of: -

- -__getstate__ is defined and the instance's __dict__ -is not empty. - -

- - The author of a Boost.Python extension class might provide a - __getstate__ method without considering the possibilities - that: - -

-

    -
  • - his class is used in Python as a base class. Most likely the - __dict__ of instances of the derived class needs to be - pickled in order to restore the instances correctly. - -

    -

  • - the user adds items to the instance's __dict__ directly. - Again, the __dict__ of the instance then needs to be - pickled. - -
-

- - To alert the user to this highly unobvious problem, a safety guard is - provided. If __getstate__ is defined and the instance's - __dict__ is not empty, Boost.Python tests if the class has - an attribute __getstate_manages_dict__. An exception is - raised if this attribute is not defined: - -

-    RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
-
- - To resolve this problem, it should first be established that the - __getstate__ and __setstate__ methods manage the - instances's __dict__ correctly. Note that this can be done - either at the C++ or the Python level. Finally, the safety guard - should intentionally be overridden. E.g. in C++ (from - pickle3.cpp): - -
-  struct world_pickle_suite : boost::python::pickle_suite
-  {
-    // ...
-
-    static bool getstate_manages_dict() { return true; }
-  };
-
- - Alternatively in Python: - -
-    import your_bpl_module
-    class your_class(your_bpl_module.your_class):
-      __getstate_manages_dict__ = 1
-      def __getstate__(self):
-        # your code here
-      def __setstate__(self, state):
-        # your code here
-
- -
-

Practical Advice

- -
    -
  • - In Boost.Python extension modules with many extension classes, - providing complete pickle support for all classes would be a - significant overhead. In general complete pickle support should - only be implemented for extension classes that will eventually - be pickled. - -

    -

  • - Avoid using __getstate__ if the instance can also be - reconstructed by way of __getinitargs__. This automatically - avoids the pitfall described above. - -

    -

  • - If __getstate__ is required, include the instance's - __dict__ in the Python object that is returned. - -
- -
- -© Copyright Ralf W. Grosse-Kunstleve 20012-2002. 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. - -

-Updated: Aug 2002. -

diff --git a/doc/v2/progress_reports.html b/doc/v2/progress_reports.html deleted file mode 100644 index 684fb254..00000000 --- a/doc/v2/progress_reports.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - -Boost.Python - Progress Reports - - - - - - - -
-

-

-
-

Boost.Python

-

Progress Reports

-
-
- -Monthly progress reports are required as part of Boost Consulting's -contract with LLNL for Boost.Python development. These reports contain -a useful record of the project history, including the rationale for -design decisions and links to relevant discussions. - -
-
February 2002
-
March 2002
-
April 2002
-
May 2002
-
June 2002
-
-
-

Revised - - 18 July, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/ptr.html b/doc/v2/ptr.html deleted file mode 100644 index 71cc6975..00000000 --- a/doc/v2/ptr.html +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - Boost.Python - <boost/python/ptr.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/ptr.hpp>

-
-
- -

Contents

- -
-
Introduction - -
Functions -
-
-
ptr -
- -
Classes -
-
-
Class template pointer_wrapper - -
-
-
Class template pointer_wrapper synopsis - -
Class - pointer_wrapper types - -
Class - pointer_wrapper constructors and destructor - -
Class - pointer_wrapper observer functions - -
-
- -
Metafunctions -
-
-
Class template is_pointer_wrapper - -
-
-
Class template is_pointer_wrapper synopsis -
- - -
Class template unwrap_pointer - -
-
-
Class template unwrap_pointer synopsis -
- -
- - -
Example(s) -
-
- -

Introduction

- -

<boost/python/ptr.hpp> defines the - ptr() function template, which allows users to - specify how to convert C++ pointer values to python in the context - of implementing overridable virtual functions, invoking Python - callable objects, or explicitly converting C++ objects to - Python. Normally, when passing pointers to Python callbacks, the - pointee is copied to ensure that the Python object - never holds a dangling reference. To specify that the new Python - object should merely contain a copy of a pointer p, - the user can pass ptr(p) instead of passing - p directly. This interface is meant to mirror the use - of boost::ref(), - which can be similarly used to prevent copying of referents. - -

ptr(p) returns an instance of pointer_wrapper<>, which - can be detected using the is_pointer_wrapper<> - metafunction; unwrap_pointer<> is a - metafunction which extracts the original pointer type from a - pointer_wrapper<>. These classes can be thought - of as implementation details. - -

Functions

-
-
-template <class T>
-pointer_wrapper<T> ptr(T x);
-
- -
-
Requires: T is a pointer type. - -
Returns: pointer_wrapper<T>(x) - -
Throws: nothing. -
- -

Classes

- -

Class template pointer_wrapper

- -

A "type envelope" which is returned by ptr(), used to indicate reference semantics - for pointers passed to Python callbacks. - -

Class - pointer_wrapper synopsis

-
-namespace boost { namespace python
-{
-    template<class Ptr> class pointer_wrapper
-    { 
-     public:
-        typedef Ptr type;
-
-        explicit pointer_wrapper(Ptr x);
-        operator Ptr() const;
-        Ptr get() const;
-    };
-}}
-
- -

Class template pointer_wrapper types

-
-typedef Ptr type;
-
-The type of the pointer being wrapped. - -

Class template pointer_wrapper constructors and - destructor

-
-explicit pointer_wrapper(Ptr x);
-
- -
-
Requires: Ptr is a pointer type. - -
Effects: Stores x in a the pointer_wrapper<>. -
Throws: nothing. -
- -

Class template pointer_wrapper observer - functions

-
-operator Ptr() const;
-Ptr get() const;
-
- -
-
Returns: a copy of the stored pointer. -
Rationale: pointer_wrapper is intended - to be a stand-in for the actual pointer type, but sometimes it's - better to have an explicit way to retrieve the pointer. -
- -

Class template is_pointer_wrapper

- -

A unary metafunction whose value is true iff its - argument is a pointer_wrapper<>. - -

Class template is_pointer_wrapper synopsis

-
-namespace boost { namespace python
-{
-    template<class T> class is_pointer_wrapper
-    { 
-        static unspecified value = ...;
-    };
-}}
-
- - -
-
Returns: true iff T is a - specialization of -pointer_wrapper<>. -
value is an integral constant convertible to bool of -unspecified type - -
- -

Class template unwrap_pointer

- -A unary metafunction which extracts the wrapped pointer type from a -specialization of pointer_wrapper<>. - -

Class template unwrap_pointer synopsis

-
-namespace boost { namespace python
-{
-    template<class T> class unwrap_pointer
-    { 
-        typedef unspecified type;
-    };
-}}
-
- -
-
Returns: T::type if T is a - specialization of -pointer_wrapper<>, T otherwise -
- - -

Example(s)

- -This example illustrates the use of ptr() to prevent an -object from being copied: -
-#include <boost/python/call.hpp>
-#include <boost/python/ptr.hpp>
-
-class expensive_to_copy
-{
-   ...
-};
-
-void pass_as_arg(expensive_to_copy* x, PyObject* f)
-{
-   // call the Python function f, passing a Python object built around
-   // which refers to *x by-pointer.
-   //
-   // *** Note: ensuring that *x outlives the argument to f() is    ***
-   // *** up to the user! Failure to do so could result in a crash! ***
-
-   boost::python::call<void>(f, ptr(x));
-}
-...
-
- -

Revised - - 29 May, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/rationale.html b/doc/v2/rationale.html deleted file mode 100644 index fb5304d8..00000000 --- a/doc/v2/rationale.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - -Boost.Python - Rationale - - - - - - - -
-

-

-
-

Boost.Python

-

Rationale

-
-


-
-
Introduction
-
First topic
-
Second topic
-
Footnotes
-
-

Introduction

-

{{text}}

-

First Topic

-

{{text}}

-

Second Topic

-

{{text}}

-

Footnotes

-
-
(1) {{text}}
-
(2) {{text}}
-
-
-

Revised - - 05 November, 2002 - -

-

© Copyright Dave Abrahams - 2002. All Rights Reserved.

- - diff --git a/doc/v2/reference.html b/doc/v2/reference.html deleted file mode 100644 index 9db8240b..00000000 --- a/doc/v2/reference.html +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - - Boost.Python - Reference - - - - -
-

C++ Boost

- -
-

Boost.Python

- -

Reference

-
-
- -

Contents

- -
-
Concepts - -
High Level Components - -
Function Invocation and Creation - -
-
-
Models of - CallPolicies - -
Models of - ResultConverter - -
Models of - ResultConverterGenerator -
- -
To/From Python Type Conversion - -
Utility and Infrastructure -
-
- - -

Concepts

- -
-
CallPolicies - -
Dereferenceable - -
Extractor - -
HolderGenerator - -
ResultConverter - -
ResultConverterGenerator -
- -

High Level Components

- -
-
class.hpp/class_fwd.hpp - -
-
-
Classes - -
-
-
class_ - -
bases - -
args -
-
- -
errors.hpp - -
-
-
Classes - -
-
-
error_already_set -
- -
Functions - -
-
-
handle_exception - -
expect_non_null -
-
- -
iterator.hpp - -
-
- -
Classes -
-
-
iterator - -
iterators -
- -
Functions - -
-
-
range -
-
- -
module.hpp -
-
-
Classes - -
-
-
module -
-
- -
objects.hpp -
-
-
Classes - -
-
-
not yet - documented -
-
- -
operators.hpp -
-
-
Classes -
-
-
self_t -
other -
operator_ -
- -
Objects -
-
-
self -
- -
- -
- -

Function Invocation and Creation

- -
-
call.hpp - -
-
-
Functions -
-
-
call -
-
- -
call_method.hpp - -
-
-
Functions - -
-
-
call_method -
-
- -
data_members.hpp - -
-
-
Functions - -
-
-
make_getter - -
make_setter -
-
- -
make_function.hpp - -
-
-
Functions - -
-
-
make_function - -
make_constructor -
-
- -
ptr.hpp - -
-
-
Functions - -
-
-
ptr -
- -
Classes - -
-
-
pointer_wrapper -
- -
MetaFunctions - -
-
-
is_pointer_wrapper - -
unwrap_pointer -
-
- - -

Models of CallPolicies

- -
-
default_call_policies.hpp - -
-
-
Classes - -
-
-
- default_call_policies - -
- default_result_converter -
-
- -
return_internal_reference.hpp - -
-
-
Classes - -
-
-
- return_internal_reference -
-
- -
return_value_policy.hpp - -
-
-
Classes - -
-
-
return_value_policy -
-
- -
with_custodian_and_ward.hpp - -
-
-
Classes - -
-
-
- with_custodian_and_ward - -
- with_custodian_and_ward_postcall -
-
-
- - -

Models of ResultConverter

- -
-
to_python_indirect.hpp - -
-
-
Classes - -
-
-
to_python_indirect -
-
- -
to_python_value.hpp - -
-
-
Classes - -
-
-
to_python_value -
-
-
- - -

Models of ResultConverterGenerator

- -
-
copy_const_reference.hpp - -
-
-
Classes - -
-
-
- copy_const_reference -
-
- -
copy_non_const_reference.hpp - -
-
-
Classes - -
-
-
- copy_non_const_reference -
-
- -
manage_new_object.hpp - -
-
-
Classes - -
-
-
manage_new_object -
-
- -
reference_existing_object.hpp - -
-
-
Classes - -
-
-
- reference_existing_object -
-
-
-
- -

To/From Python Type - Conversion

- -
-
from_python.hpp - -
-
-
Classes - -
-
-
from_python -
-
- -
implicit.hpp - -
-
-
Functions - -
-
-
implicitly_convertible -
-
- -
lvalue_from_pytype.hpp - -
-
-
Classes - -
-
-
lvalue_from_pytype - -
extract_identity - -
extract_member -
-
- -
to_python_converter.hpp - -
-
-
Classes - -
-
-
to_python_converter -
-
- -
- -

Utility and Infrastructure

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

Revised - - 3 June, 2002 - - - -

© Copyright Dave Abrahams 2002. All - Rights Reserved. - diff --git a/doc/v2/reference_existing_object.html b/doc/v2/reference_existing_object.html deleted file mode 100644 index dbb7a983..00000000 --- a/doc/v2/reference_existing_object.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - Boost.Python - - <boost/python/reference_existing_object.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header - <boost/python/reference_existing_object.hpp>

-
-


- -

Contents

- -
-
Classes - -
-
-
Class - reference_existing_object - -
-
-
Class - reference_existing_object synopsis - -
Class - reference_existing_object metafunctions -
-
- -
Example -
-
- -

Classes

- -

Class - reference_existing_object

- -

reference_existing_object is a model of ResultConverterGenerator which can be - used to wrap C++ functions which return a reference or pointer to a C++ - object. When the wrapped function is called, the value referenced by its - return value is not copied. A new Python object is created which contains a - pointer to the referent, and no attempt is made to ensure that the lifetime - of the referent is at least as long as that of the corresponding Python - object. Thus, it can be highly - dangerous to use reference_existing_object without - additional lifetime management from such models of CallPolicies as with_custodian_and_ward. - This class is used in the implementation of return_internal_reference. - -

Class - reference_existing_object synopsis

-
-namespace boost { namespace python
-{
-    struct reference_existing_object
-    {
-        template <class T> struct apply;
-    };
-}}
-
- -

Class - reference_existing_object metafunctions

-
-template <class T> struct apply
-
- -
-
Requires: T is U& or - U*for some U. - -
Returns: typedef to_python_indirect<T,V> - type, where V is a HolderObjectGenerator - which constructs an instance holder containing an unowned - U* pointing to the referent of the wrapped function's return - value. -
- -

Example

- -

In C++: -

-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/reference_existing_object.hpp>
-#include <boost/python/return_value_policy.hpp>
-#include <utility>
-
-// classes to wrap
-struct Singleton
-{
-   Singleton() : x(0) {}
-
-   int exchange(int n)  // set x and return the old value
-   {
-        std::swap(n, x);
-        return n;
-   }
-
-   int x;
-};
-
-Singleton& get_it()
-{
-   static Singleton just_one;
-   return just_one;
-}
-
-// Wrapper code
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(singleton)
-{
-   module("singleton")
-      .def("get_it", get_it)
-      .add(
-         class_<Singleton>()
-            .def("exchange", &Singleton::exchange)
-         );
-}
-
- In Python: -
->>> import singleton
->>> s1 = singleton.get_it()  
->>> s2 = singleton.get_it()
->>> id(s1) == id(s2)  # s1 and s2 are not the same object
-0
->>> s1.exchange(42)   # but they reference the same C++ Singleton
-0
->>> s2.exchange(99)
-42
-
- -

Revised - - 14 February 2002 - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/return_internal_reference.html b/doc/v2/return_internal_reference.html deleted file mode 100644 index 347db88c..00000000 --- a/doc/v2/return_internal_reference.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - Boost.Python - <boost/python/return_internal_reference.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/return_internal_reference.hpp>

-
-


- -

Contents

- -
-
Introduction - - -
Classes - -
-
-
Class Template return_internal_reference - -
-
- -
Class Template - return_internal_reference synopsis - -
Class - return_internal_reference static functions -
-
- - -
Example -
-
- -

Introduction

- - return_internal_reference instantiations are models of CallPolicies which allow pointers and - references to objects held internally by a free or member function - argument or from the target of a member function to be returned - safely without making a copy of the referent. The default for its - first template argument handles the common case where the - containing object is the target (*this) of a wrapped - member function. - -

Classes

- -

Class template return_internal_reference

- - - - - - - -
- return_internal_reference template parameters -
Parameter - - Requirements - - Description - - Default - -
owner_arg - - A positive compile-time constant of type - std::size_t. - - The index of the parameter which contains the object to - which the reference or pointer is being returned. If used to - wrap a member function, parameter 1 is the target object - (*this). Note that if the target Python object - type doesn't support weak references, a Python - TypeError exception will be raised when the - function being wrapped is called. - - 1 - -
Base - - A model of CallPolicies - - Used for policy composition. Any - result_converter it supplies will be overridden by - return_internal_reference, but its - precall and postcall policies are - composed as described here CallPolicies. - - default_call_policies - -
- -

Class template return_internal_reference synopsis

-
-namespace boost { namespace python
-{
-   template <std::size_t owner_arg = 1, class Base = default_call_policies>
-   struct return_internal_reference : Base
-   {
-      static PyObject* postcall(PyObject*, PyObject* result);
-      typedef reference_existing_object result_converter;
-   };
-}}
-
- -

Class - default_call_policies static functions

- -
-PyObject* postcall(PyObject* args, PyObject* result);
-
- -
-
Requires: PyTuple_Check(args) != 0 - -
Returns: with_custodian_and_ward_postcall::postcall(args, result) -
- - -

Example

- -

C++ module definition

- -
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/return_internal_reference.hpp>
-
-class Bar
-{
-   Bar(int x) : x(x) {}
-   int get_x() const { return x; }
-   void set_x(int x) { this->x = x; }
- private:
-   int x;
-}
-
-class Foo
-{
- public:
-   Foo(int x) : b(x) {}
-
-   // Returns an internal reference
-   Bar const& get_bar() const { return b; }
-
- private:
-   Bar b;
-};
-
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(internal_refs)
-{
-   module m("internal_refs")
-      .add(
-         class_<Bar>()
-            .def("get_x", &Bar::get_x)
-            .def("set_x", &Bar::set_x)
-         )
-      .add(
-         class_<Foo>()
-            .def_init(args<int>())
-            .def("get_bar", &Foo::get_bar
-                , return_internal_reference<>())
-         )
-      ;
-}
-
- -

Python code

- -
->>> from internal_refs import *
->>> f = Foo(3)
->>> b1 = f.get_bar()
->>> b2 = f.get_bar()
->>> b1.get_x()
-3
->>> b2.get_x()
-3
->>> b1.set_x(42)
->>> b2.get_x()
-42
-
- -

Revised - - 15 February, 2002 - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/return_value_policy.html b/doc/v2/return_value_policy.html deleted file mode 100644 index 88a72a0c..00000000 --- a/doc/v2/return_value_policy.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - Boost.Python - <boost/python/return_value_policy.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/return_value_policy.hpp>

-
-


- -

Contents

- -
-
Introduction - - -
Classes - -
-
-
Class Template return_value_policy - -
-
- -
Class Template - return_value_policy synopsis -
-
- - -
Example -
-
- -

Introduction

- - return_value_policy instantiations are simply models - of CallPolicies which are composed of a ResultConverterGenerator and optional Base CallPolicies. - -

Classes

- -

Class template return_value_policy

- - - - - - - -
- return_value_policy template parameters -
Parameter - - Requirements - - Default - -
ResultConverterGenerator - - A model of ResultConverterGenerator. - -
Base - - A model of CallPolicies - - default_call_policies - -
- -

Class template return_value_policy synopsis

-
-namespace boost { namespace python
-{
-  template <class ResultConverterGenerator, class Base = default_call_policies>
-  struct return_value_policy : Base
-  {
-      typedef ResultConverterGenerator result_converter;
-  };
-}}
-
- -

Example

- -

C++ Module Definition

-
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/copy_const_reference.hpp>
-#include <boost/python/return_value_policy.hpp>
-
-// classes to wrap
-struct Bar { int x; }
-
-struct Foo {
-   Foo(int x) : { b.x = x; }
-   Bar const& get_bar() const { return b; }
- private:
-   Bar b;
-};
-
-// Wrapper code
-using namespace boost::python;
-BOOST_PYTHON_MODULE_INIT(my_module)
-{
-   module("my_module")
-      .add(
-         class_<Bar>()
-         )
-      .add(
-         class_<Foo>()
-            .def_init(args<int>())
-            .def("get_bar", &Foo::get_bar
-                , return_value_policy<copy_const_reference>())
-         )
-       ;
-}
-
-

Python Code

-
->>> from my_module import *
->>> f = Foo(3)         # create a Foo object
->>> b = f.get_bar()    # make a copy of the internal Bar object
-
- -

Revised - - 15 February, 2002 - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/to_python_converter.html b/doc/v2/to_python_converter.html deleted file mode 100644 index a2a985d8..00000000 --- a/doc/v2/to_python_converter.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - Boost.Python - <boost/python/to_python_converter.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/to_python_converter.hpp>

-
-


- -

Contents

- -
-
Introduction - - -
Classes - -
-
-
Class Template to_python_converter - -
-
- -
Class Template - to_python_converter synopsis - -
Class Template - to_python_converter constructor -
-
- -
Example -
-
- -

Introduction

- - to_python_converter registers a conversion from - objects of a given C++ type into a Python object. - -

Classes

- -

Class template to_python_converter

- - to_python_converter adds a wrapper around a static - member function of its second template parameter, handling - low-level details such as insertion into the converter registry. - - - - - - - -
- to_python_converter template parameters
-In the table below, x denotes an object of type T -
Parameter - - Requirements - - Description - -
T - - - - The C++ type of the source object in the conversion - -
Conversion - - PyObject* p = Conversion::convert(x),
- if p == 0, PyErr_Occurred() != 0. - -
A class type whose static member function - convert does the real work of the conversion. - -
- -

Class template to_python_converter synopsis

-
-namespace boost { namespace python
-{
-  template <class T, class Conversion>
-  struct to_python_converter
-  {
-      to_python_converter();
-  };
-}}
-
- -

Class template to_python_converter constructor

-
-to_python_converter();
-
- -
- -
Effects: Registers a to_python converter which uses - Conversion::convert() to do its work. - -
- -

Example

- -This example presumes that someone has implemented the standard noddy example -module from the Python documentation, and placed the corresponding -declarations in "noddy.h". Because -noddy_NoddyObject is the ultimate trivial extension type, -the example is a bit contrived: it wraps a function for which all -information is contained in the type of its return value. - -

C++ module definition

- -
-#include <boost/python/reference.hpp>
-#include <boost/python/module.hpp>
-#include "noddy.h"
-
-struct tag {};
-tag make_tag() { return tag(); }
-
-using namespace boost::python;
-
-struct tag_to_noddy
-{
-    static PyObject* convert(tag const& x)
-    {
-        return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
-    }
-};
-
-BOOST_PYTHON_MODULE_INIT(to_python_converter)
-{
-    module("to_python_converter")
-        .def("make_tag", make_tag)
-        ;
-    to_python_converter<tag, tag_to_noddy>();
-}
-
- -

Python code

- -
->>> import to_python_converter
->>> def always_none():
-...     return None
-...
->>> def choose_function(x):
-...     if (x % 2 != 0):
-...         return to_python_converter.make_tag
-...     else:
-...         return always_none
-...
->>> a = [ choose_function(x) for x in range(5) ]
->>> b = [ f() for f in a ]
->>> type(b[0])
-<type 'NoneType'>
->>> type(b[1])
-<type 'Noddy'>
->>> type(b[2])
-<type 'NoneType'>
->>> type(b[3])
-<type 'Noddy'>
-
- -

Revised - - 05 November, 2001 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/to_python_indirect.html b/doc/v2/to_python_indirect.html deleted file mode 100644 index d0b82f70..00000000 --- a/doc/v2/to_python_indirect.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - Boost.Python - <boost/python/to_python_indirect.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/to_python_indirect.hpp>

-
-


- -

Contents

- -
-
Introduction - - -
Classes - -
-
-
Class Template to_python_indirect - -
-
- -
Class Template - to_python_indirect synopsis - -
Class Template - to_python_indirect observer functions - -
Class Template - to_python_indirect static functions -
-
- -
Example -
-
- -

Introduction

- - <boost/python/to_python_indirect.hpp> supplies - a way to construct new Python objects that hold wrapped C++ class - instances via a pointer or smart pointer. - -

Classes

- -

Class template to_python_indirect

-

Class template to_python_indirect converts objects -of its first argument type to python as extension class instances, using the ownership policy provided by its 2nd argument. - -

- - - - - - - -
- to_python_indirect Requirements
- - In the table below, x denotes an object of - type T, h denotes an - object of type - boost::python::objects::instance_holder*, and - p denotes an object of type - U*. - -
Parameter - - Requirements - - Description - -
T - - Either U cv& - (where cv is any optional cv-qualification) or a Dereferenceable type such that - *x is convertible to U const&, where - U is a class type. - - A type deferencing a C++ class exposed to Python using - class template class_. - -
MakeHolder - - h = MakeHolder::execute(p); - - A class whose static execute() creates an - instance_holder. - -
- - Instantiations of to_python_indirect are models of ResultConverter. - - -

Class template to_python_indirect synopsis

-
-namespace boost { namespace python
-{
-  template <class T, class MakeHolder>
-  struct to_python_indirect
-  {
-     static bool convertible();
-     PyObject* operator()(T ptr_or_reference) const;
-   private:
-     static PyTypeObject* type();
-  };
-}}
-
- -

Class template to_python_indirect observers

-
-PyObject* operator()(T x) const;
-
- -
- -
Requires: x refers to an object (if it - is a pointer type, it is non-null). convertible() == - true. - -
Effects: Creates an appropriately-typed Boost.Python - extension class instance, uses MakeHolder to create - an instance_holder from x, installs - the instance_holder in the new extension class - instance, and returns a pointer to it. - -
- - -

Class template to_python_indirect statics

-
-bool convertible();
-
- -
Effects: Returns true iff any module has - registered a Python type corresponding to U. - -

Example

- -This example replicates the functionality of reference_existing_object, -but without some of the compile-time error checking. - - -
-
-struct make_reference_holder
-{
-   typedef boost::python::objects::instance_holder* result_type;
-   template <class T>
-   static result_type execute(T* p)
-   {
-      return new boost::python::objects::pointer_holder<T*, T>(p);
-   }
-};
-
-struct reference_existing_object
-{
-   // metafunction returning the ResultConverter
-   template <class T>
-   struct apply
-   {
-      typedef boost::python::to_python_indirect<T,make_reference_holder> type;
-   };
-};
-
- -

Revised - - 16 February, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/to_python_value.html b/doc/v2/to_python_value.html deleted file mode 100644 index 990cea41..00000000 --- a/doc/v2/to_python_value.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - Boost.Python - <boost/python/to_python_value.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header - <boost/python/to_python_value.hpp>

-
-


- -

Contents

- -
-
Classes - -
-
-
Class - to_python_value - -
-
-
Class template - to_python_value synopsis - -
Class template - to_python_value observer functions -
-
- -
-
- -

Classes

- -

Class template - to_python_value

- -

to_python_value is a model of ResultConverter - which copies its argument into a new Python object. - -

Class - to_python_value synopsis

-
-namespace boost { namespace python
-{
-   template <class T>
-   struct to_python_value
-   {
-      typedef typename add_reference<
-         typename add_const<T>::type
-      >::type argument_type;
-
-      static bool convertible();
-      PyObject* operator()(argument_type) const;
-   };
-}}
-
- -

Class - to_python_value observers

-
-static bool convertible();
-
- -
-
Returns: true iff a converter has been registered which can convert T to python by-value. -
- -
-PyObject* operator()(argument_type x) const;
-
- -
-
Requires: convertible() == true -
Effects: converts x to python -
Returns: the resulting Python object iff a converter for T has been registered, 0 otherwise. -
- -

Revised - - 15 February, 2002 - - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/doc/v2/type_id.html b/doc/v2/type_id.html deleted file mode 100755 index 6407f913..00000000 --- a/doc/v2/type_id.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - Boost.Python - <boost/python/type_id.hpp> - - - - -
-

C++ Boost

- -
-

Boost.Python

- -

Header <boost/python/type_id.hpp>

-
-


- -

Contents

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

Introduction

- -

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

Classes

- -

Class type_info

- -

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

Class type_info - synopsis

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

Class type_info - constructor

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

Class - type_info comparisons

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

Class type_info - observers

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

Functions

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

Example

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

Revised - - 18 November, 2002 - - - -

© Copyright Dave Abrahams 2002. All - Rights Reserved. - diff --git a/doc/v2/with_custodian_and_ward.html b/doc/v2/with_custodian_and_ward.html deleted file mode 100644 index 6710d357..00000000 --- a/doc/v2/with_custodian_and_ward.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - - Boost.Python - <boost/python/with_custodian_and_ward.hpp> - - - -
-

-

- -
-

Boost.Python

- -

Header <boost/python/with_custodian_and_ward.hpp>

-
-


- -

Contents

- -
-
Introduction - - -
Classes -
- -
- -
Class Template with_custodian_and_ward -
-
- -
Class Template - with_custodian_and_ward synopsis - -
Class - with_custodian_and_ward static functions -
- -
Class Template with_custodian_and_ward_postcall -
-
- -
Class Template - with_custodian_and_ward_postcall synopsis - -
Class - with_custodian_and_ward_postcall static functions -
-
- - -
Example -
-
- -

Introduction

- - This header provides faciliites for establishing a lifetime - dependency between two of a function's Python argument or result - objects. The ward object will not be destroyed until after - the custodian as long as the custodian object supports weak - references (Boost.Python extension classes all support weak - references). If the custodian object does not support weak - references and is not None, an appropriate exception - will be thrown. The two class templates - with_custodian_and_ward and - with_custodian_and_ward_postcall differ in the point - at which they take effect. - -

In order to reduce the chance of inadvertently - creating dangling pointers, the default is to do lifetime binding - before the underlying C++ object is invoked. However, - before invocation the result object is not available, so - with_custodian_and_ward_postcall is provided to bind - lifetimes after invocation. Also, if a C++ exception is thrown - after with_custodian_and_ward<>::precall but - before the underlying C++ object actually stores a pointer, the - lifetime of the custodian and ward objects will be artificially - bound together, so one might choose - with_custodian_and_ward_postcall instead, depending - on the semantics of the function being wrapped. - -

Classes

- -

Class template with_custodian_and_ward

- - - - - - - - -
- with_custodian_and_ward template parameters -
Parameter - - Requirements - - Description - - Default - -
custodian - - A positive compile-time constant of type - std::size_t. - - The 1-based index of the parameter which is the dependency in the - lifetime relationship to be established. If used to - wrap a member function, parameter 1 is the target object - (*this). Note that if the target Python object - type doesn't support weak references, a Python - TypeError exception will be raised when the - C++ object being wrapped is called. - - -
ward - - A positive compile-time constant of type - std::size_t. - - The 1-based index of the parameter which is the dependent in the - lifetime relationship to be established. If used to - wrap a member function, parameter 1 is the target object - (*this). - - -
Base - - A model of CallPolicies - - Used for policy composition. - - default_call_policies - -
- -

Class template with_custodian_and_ward synopsis

-
-namespace boost { namespace python
-{
-   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
-   struct with_custodian_and_ward : Base
-   {
-      static bool precall(PyObject* args);
-   };
-}}
-
- -

Class - with_custodian_and_ward static functions

- -
-bool precall(PyObject* args);
-
- -
-
Requires: PyTuple_Check(args) != 0 -
Effects: Makes the lifetime of the argument indicated - by ward dependent on the lifetime of the argument - indicated by custodian. - -
Returns: false and PyErr_Occurred() != 0 - upon failure, true otherwise. -
- - - - -

Class template with_custodian_and_ward_postcall

- - - - - - - - -
- with_custodian_and_ward_postcall template parameters -
Parameter - - Requirements - - Description - - Default - -
custodian - - A compile-time constant of type - std::size_t. - - The index of the parameter which is the dependency in the - lifetime relationship to be established. Zero indicates the - result object; 1 indicates the first argument. If used to wrap - a member function, parameter 1 is the target object - (*this). Note that if the target Python object - type doesn't support weak references, a Python - TypeError exception will be raised when the - C++ object being wrapped is called. - - -
ward - - A compile-time constant of type std::size_t. - - The index of the parameter which is the dependent in the - lifetime relationship to be established. Zero indicates the - result object; 1 indicates the first argument. If used to wrap - a member function, parameter 1 is the target object - (*this). - -
Base - - A model of CallPolicies - - Used for policy - composition. - - default_call_policies - -
- -

Class template with_custodian_and_ward_postcall synopsis

-
-namespace boost { namespace python
-{
-   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
-   struct with_custodian_and_ward_postcall : Base
-   {
-      static PyObject* postcall(PyObject* args, PyObject* result);
-   };
-}}
-
- -

Class - with_custodian_and_ward_postcall static functions

- -
-PyObject* postcall(PyObject* args, PyObject* result);
-
- -
-
Requires: PyTuple_Check(args) - != 0, result != 0. - -
Effects: Makes the lifetime of the object indicated - by ward dependent on the lifetime of the object - indicated by custodian. - -
Returns: 0 and PyErr_Occurred() != 0 - upon failure, true otherwise. -
- - - -

Example

- -The following example shows how -with_custodian_and_ward_postcall is used by the library -to implement return_internal_reference - -
-template <std::size_t owner_arg = 1, class Base = default_call_policies>
-struct return_internal_reference
-    : with_custodian_and_ward_postcall<0, owner_arg, Base>
-{
-   typedef reference_existing_object result_converter;
-};
-
- -

Revised - - 29 May, 2002 - - -

© Copyright Dave - Abrahams 2002. All Rights Reserved. - diff --git a/example/Attic/project.zip b/example/Attic/project.zip deleted file mode 100644 index d863defd..00000000 Binary files a/example/Attic/project.zip and /dev/null differ diff --git a/example/Jamfile b/example/Jamfile deleted file mode 100644 index 05b97e14..00000000 --- a/example/Jamfile +++ /dev/null @@ -1,39 +0,0 @@ -# Specify our location in the boost project hierarchy -subproject libs/python/example ; - -# Declares the following targets: -# -# 1. an extension module called "getting_started1", which is -# built from "getting_started1.cpp". Built by default -# -# 2. A test target called my-test.test which runs -# test_getting_started1.py with the extension module above. Built -# when out-of date, but only if invoked by name or if the global -# "test" target is invoked. -# -# 3. A test target called my-test.run wihch runs the above test -# unconditionally. Built only when invoked by name. -# -# To see verbose test output, add "-sPYTHON_TEST_ARGS=-v" to the bjam -# command-line before the first target. -# - -# Include definitions needed for Python modules -SEARCH on python.jam = $(BOOST_BUILD_PATH) ; -include python.jam ; - -# Declare a Python extension called getting_started1 -extension getting_started1 -: # sources - getting_started1.cpp - - # dependencies - ../build/boost_python - ; - -# Declare a test for the extension module -boost-python-runtest my-test - : # Python test driver - test_getting_started1.py - # extension modules to use - getting_started1 ; \ No newline at end of file diff --git a/example/README b/example/README deleted file mode 100644 index ef7dc78f..00000000 --- a/example/README +++ /dev/null @@ -1,21 +0,0 @@ -To get started with the Boost Python Library, use the examples -getting_started1.cpp and getting_started2.cpp. - -Examples for providing pickle support can be found in: - pickle1.cpp - pickle2.cpp - pickle3.cpp -See also: libs/python/doc/pickle.html - -Other advanced concepts are introduced by: - abstract.cpp - simple_vector.cpp - do_it_yourself_convts.cpp - -Examples for the cross-module support are provided by: - noncopyable_export.cpp - noncopyable_import.cpp - dvect.cpp - ivect.cpp -See also: libs/python/doc/cross_module.html - diff --git a/example/abstract.cpp b/example/abstract.cpp deleted file mode 100644 index 97e38c2e..00000000 --- a/example/abstract.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Example by Ullrich Koethe -#include "boost/python/class_builder.hpp" -#include - -struct Abstract -{ - virtual std::string test() = 0; -}; - -struct Abstract_callback: Abstract -{ - Abstract_callback(PyObject * self) - : m_self(self) - {} - - std::string test() - { - return boost::python::callback::call_method(m_self, "test"); - } - - PyObject * m_self; -}; - -BOOST_PYTHON_MODULE_INIT(abstract) -{ - boost::python::module_builder a("abstract"); - - boost::python::class_builder - a_class(a, "Abstract"); - a_class.def(boost::python::constructor<>()); // wrap a constructor - a_class.def(&Abstract::test, "test"); -} diff --git a/example/do_it_yourself_convts.cpp b/example/do_it_yourself_convts.cpp deleted file mode 100644 index 427e7688..00000000 --- a/example/do_it_yourself_convts.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -/* - - This example shows how to convert a class from and to native - Python objects, such as tuples. - - We do not want to expose the helper class MillerIndex as an - Extension Class. However, in order to simplify the wrapper code, - we want to define from_python() and to_python() functions for - class MillerIndex. - - Consider the alternatives: - - - Expose MillerIndex as an Extension Class. - We need a constructor MillerIndex(python::tuple). - Python function calls become more complex: - foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) - We need a method such as MillerIndex().as_tuple(). - - - Define a wrapper function for each function that we - want to expose, e.g.: - void add(const IndexingSet& ixset, const python::tuple PyMIx) - - The first alternative introduces a new type that the user has to - deal with. Other modules using Miller indices might organize them in - different ways, for example to increase runtime efficiency for - important procedures. This means, the user has to know how to - convert between the different kinds of Miller index representations. - This can quickly become a nuisance. Relying on native Python data - structures minimizes the number of special types the user has to - learn and convert. Of course, this argument is only valid for - small and relatively simply classes. - - If there are many member functions with MillerIndex arguments, the - second alternative is impractical, and concentrating the conversion - mechanism in one central place is essential for code - maintainability. An added benefit is that more convenient (smarter) - conversion functions can be provided without cluttering the rest of - the wrapper code. - - */ - -#include -#include -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // The helper class. - // - class MillerIndex { - public: - int v[3]; - }; - - // The main class. Imagine that there are MANY member functions - // like add() and get(). - // - class IndexingSet { - private: - std::vector VMIx; - public: - void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } - MillerIndex get(std::size_t i) const { return VMIx[i]; } - }; -} - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - - // Convert a Python tuple to a MillerIndex object. - // - MillerIndex from_python(PyObject* p, python::type) - { - python::tuple tup - = python::tuple(python::ref(p, python::ref::increment_count)); - if (tup.size() != 3) { - PyErr_SetString(PyExc_ValueError, - "expecting exactly 3 values in tuple."); - python::throw_error_already_set(); - } - MillerIndex result; - for (int i = 0; i < 3; i++) - result.v[i] = from_python(tup[i].get(), python::type()); - return result; - } - - // Similar conversion for MillerIndex objects passed by value. - // Not actually used, but included to show the principle. - // - MillerIndex from_python(PyObject* p, python::type) - { - return from_python(p, python::type()); - } - - // Convert a MillerIndex object to a Python tuple. - // - PyObject* to_python(const MillerIndex& hkl) - { - python::tuple result(3); - for (int i = 0; i < 3; i++) - result.set_item(i, python::ref(to_python(hkl.v[i]))); - return result.reference().release(); - } - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -BOOST_PYTHON_MODULE_INIT(do_it_yourself_convts) -{ - // Create an object representing this extension module. - python::module_builder this_module("do_it_yourself_convts"); - - // Create the Python type object for our extension class. - python::class_builder ixset_class(this_module, "IndexingSet"); - - // Add the __init__ function. - ixset_class.def(python::constructor<>()); - // Add the member functions. - ixset_class.def(&IndexingSet::add, "add"); - ixset_class.def(&IndexingSet::get, "get"); -} diff --git a/example/dvect.cpp b/example/dvect.cpp deleted file mode 100644 index fa1506fe..00000000 --- a/example/dvect.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include "dvect.h" -#include "ivect.h" -#include -namespace python = boost::python; - -namespace { - -# include "dvect_conversions.cpp" -# include "ivect_conversions.cpp" - - vects::ivect dvect_as_ivect(const vects::dvect& dv) - { - vects::ivect iv(dv.size()); - vects::ivect::iterator iviter = iv.begin(); - for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); - return iv; - } -} - -# ifdef BOOST_MSVC // fixes for JIT debugging -# include -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) -{ - python::module_builder this_module("dvect"); - - python::class_builder dvect_class(this_module, "dvect"); - python::export_converters(dvect_class); - - python::import_converters ivect_converters("ivect", "ivect"); - - dvect_class.def(python::constructor()); - dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); - dvect_class.def(dvect_as_ivect, "as_ivect"); - -# include "dvect_defs.cpp" -# include "ivect_defs.cpp" -} diff --git a/example/dvect.h b/example/dvect.h deleted file mode 100644 index d059f04d..00000000 --- a/example/dvect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef DVECT_H -#define DVECT_H - -#include -#include - -namespace vects { - - struct dvect : public std::vector - { - dvect() : std::vector() {} - dvect(std::size_t n) : std::vector(n) {} - dvect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // DVECT_H diff --git a/example/dvect_conversions.cpp b/example/dvect_conversions.cpp deleted file mode 100644 index 21527243..00000000 --- a/example/dvect_conversions.cpp +++ /dev/null @@ -1,51 +0,0 @@ - // basics first: const reference converters - boost::python::tuple const_dvect_reference_as_tuple(const vects::dvect& dv) - { - return dv.as_tuple(); - } - - // to_python smart pointer conversions - std::auto_ptr dvect_as_auto_ptr(const vects::dvect& dv) - { - return std::auto_ptr(new vects::dvect(dv)); - } - boost::shared_ptr dvect_as_shared_ptr(const vects::dvect& dv) - { - return boost::shared_ptr(new vects::dvect(dv)); - } - - // smart pointers passed by value - boost::python::ref auto_ptr_value_dvect_as_tuple(std::auto_ptr dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - boost::python::ref shared_ptr_value_dvect_as_tuple(boost::shared_ptr dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - - // smart pointers passed by reference - boost::python::ref auto_ptr_reference_dvect_as_tuple(std::auto_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - boost::python::ref shared_ptr_reference_dvect_as_tuple(boost::shared_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - - // smart pointers passed by const reference - boost::python::ref auto_ptr_const_reference_dvect_as_tuple(const std::auto_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - boost::python::ref shared_ptr_const_reference_dvect_as_tuple(const boost::shared_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } diff --git a/example/dvect_defs.cpp b/example/dvect_defs.cpp deleted file mode 100644 index 2739b219..00000000 --- a/example/dvect_defs.cpp +++ /dev/null @@ -1,13 +0,0 @@ - this_module.def(dvect_as_auto_ptr, "dvect_as_auto_ptr"); - this_module.def(dvect_as_shared_ptr, "dvect_as_shared_ptr"); - - this_module.def(const_dvect_reference_as_tuple, "const_dvect_reference_as_tuple"); - - this_module.def(auto_ptr_value_dvect_as_tuple, "auto_ptr_value_dvect_as_tuple"); - this_module.def(shared_ptr_value_dvect_as_tuple, "shared_ptr_value_dvect_as_tuple"); - - this_module.def(auto_ptr_reference_dvect_as_tuple, "auto_ptr_reference_dvect_as_tuple"); - this_module.def(shared_ptr_reference_dvect_as_tuple, "shared_ptr_reference_dvect_as_tuple"); - - this_module.def(auto_ptr_const_reference_dvect_as_tuple, "auto_ptr_const_reference_dvect_as_tuple"); - this_module.def(shared_ptr_const_reference_dvect_as_tuple, "shared_ptr_const_reference_dvect_as_tuple"); diff --git a/example/getting_started1.cpp b/example/getting_started1.cpp deleted file mode 100644 index 91a1f551..00000000 --- a/example/getting_started1.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -#include - -namespace { // Avoid cluttering the global namespace. - - // A couple of simple C++ functions that we want to expose to Python. - std::string greet() { return "hello, world"; } - int square(int number) { return number * number; } -} - -#include -namespace python = boost::python; - -// Python requires an exported function called init in every -// extension module. This is where we build the module contents. -BOOST_PYTHON_MODULE_INIT(getting_started1) -{ - try { - // Create an object representing this extension module. - python::module_builder this_module("getting_started1"); - - // Add regular functions to the module. - this_module.def(greet, "greet"); - this_module.def(square, "square"); - } - catch(...) { - boost::python::handle_exception(); - } -} diff --git a/example/getting_started2.cpp b/example/getting_started2.cpp deleted file mode 100644 index 04fbcc29..00000000 --- a/example/getting_started2.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -#include -#include - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class hello - { - public: - hello(const std::string& country) { this->country = country; } - std::string greet() const { return "Hello from " + country; } - private: - std::string country; - }; - - // A function taking a hello object as an argument. - std::string invite(const hello& w) { - return w.greet() + "! Please come soon!"; - } -} - -#include -namespace python = boost::python; - -BOOST_PYTHON_MODULE_INIT(getting_started2) -{ - // Create an object representing this extension module. - python::module_builder this_module("getting_started2"); - - // Create the Python type object for our extension class. - python::class_builder hello_class(this_module, "hello"); - - // Add the __init__ function. - hello_class.def(python::constructor()); - // Add a regular member function. - hello_class.def(&hello::greet, "greet"); - - // Add invite() as a regular function to the module. - this_module.def(invite, "invite"); - - // Even better, invite() can also be made a member of hello_class!!! - hello_class.def(invite, "invite"); -} diff --git a/example/ivect.cpp b/example/ivect.cpp deleted file mode 100644 index 35662b10..00000000 --- a/example/ivect.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include "dvect.h" -#include "ivect.h" -#include -namespace python = boost::python; - -namespace { - -# include "dvect_conversions.cpp" -# include "ivect_conversions.cpp" - - vects::dvect ivect_as_dvect(const vects::ivect& iv) - { - vects::dvect dv(iv.size()); - vects::dvect::iterator dviter = dv.begin(); - for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); - return dv; - } -} - -# ifdef BOOST_MSVC // fixes for JIT debugging -# include -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) -{ - python::module_builder this_module("ivect"); - - python::class_builder ivect_class(this_module, "ivect"); - python::export_converters(ivect_class); - - python::import_converters dvect_converters("dvect", "dvect"); - - ivect_class.def(python::constructor()); - ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); - ivect_class.def(ivect_as_dvect, "as_dvect"); - -# include "dvect_defs.cpp" -# include "ivect_defs.cpp" -} - diff --git a/example/ivect.h b/example/ivect.h deleted file mode 100644 index b8d52246..00000000 --- a/example/ivect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef IVECT_H -#define IVECT_H - -#include -#include - -namespace vects { - - struct ivect : public std::vector - { - ivect() : std::vector() {} - ivect(std::size_t n) : std::vector(n) {} - ivect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // IVECT_H diff --git a/example/ivect_conversions.cpp b/example/ivect_conversions.cpp deleted file mode 100644 index 4f59573d..00000000 --- a/example/ivect_conversions.cpp +++ /dev/null @@ -1,51 +0,0 @@ - // basics first: const reference converters - boost::python::tuple const_ivect_reference_as_tuple(const vects::ivect& iv) - { - return iv.as_tuple(); - } - - // to_python smart pointer conversions - std::auto_ptr ivect_as_auto_ptr(const vects::ivect& iv) - { - return std::auto_ptr(new vects::ivect(iv)); - } - boost::shared_ptr ivect_as_shared_ptr(const vects::ivect& iv) - { - return boost::shared_ptr(new vects::ivect(iv)); - } - - // smart pointers passed by value - boost::python::ref auto_ptr_value_ivect_as_tuple(std::auto_ptr iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - boost::python::ref shared_ptr_value_ivect_as_tuple(boost::shared_ptr iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - - // smart pointers passed by reference - boost::python::ref auto_ptr_reference_ivect_as_tuple(std::auto_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - boost::python::ref shared_ptr_reference_ivect_as_tuple(boost::shared_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - - // smart pointers passed by const reference - boost::python::ref auto_ptr_const_reference_ivect_as_tuple(const std::auto_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - boost::python::ref shared_ptr_const_reference_ivect_as_tuple(const boost::shared_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } diff --git a/example/ivect_defs.cpp b/example/ivect_defs.cpp deleted file mode 100644 index 811c243d..00000000 --- a/example/ivect_defs.cpp +++ /dev/null @@ -1,13 +0,0 @@ - this_module.def(ivect_as_auto_ptr, "ivect_as_auto_ptr"); - this_module.def(ivect_as_shared_ptr, "ivect_as_shared_ptr"); - - this_module.def(const_ivect_reference_as_tuple, "const_ivect_reference_as_tuple"); - - this_module.def(auto_ptr_value_ivect_as_tuple, "auto_ptr_value_ivect_as_tuple"); - this_module.def(shared_ptr_value_ivect_as_tuple, "shared_ptr_value_ivect_as_tuple"); - - this_module.def(auto_ptr_reference_ivect_as_tuple, "auto_ptr_reference_ivect_as_tuple"); - this_module.def(shared_ptr_reference_ivect_as_tuple, "shared_ptr_reference_ivect_as_tuple"); - - this_module.def(auto_ptr_const_reference_ivect_as_tuple, "auto_ptr_const_reference_ivect_as_tuple"); - this_module.def(shared_ptr_const_reference_ivect_as_tuple, "shared_ptr_const_reference_ivect_as_tuple"); diff --git a/example/nested.cpp b/example/nested.cpp deleted file mode 100644 index a5632d16..00000000 --- a/example/nested.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -/* - This example shows how convert a nested Python tuple. - */ - -#include -#include - -namespace { - - boost::python::list - show_nested_tuples(boost::python::tuple outer) - { - boost::python::list result; - for (int i = 0; i < outer.size(); i++) { - boost::python::tuple inner( - BOOST_PYTHON_CONVERSION::from_python(outer[i].get(), - boost::python::type())); - for (int j = 0; j < inner.size(); j++) { - double x = BOOST_PYTHON_CONVERSION::from_python(inner[j].get(), - boost::python::type()); - char buf[128]; - sprintf(buf, "(%d,%d) %.6g", i, j, x); - result.append(BOOST_PYTHON_CONVERSION::to_python(std::string(buf))); - } - } - return result; - } - -} - -BOOST_PYTHON_MODULE_INIT(nested) -{ - boost::python::module_builder this_module("nested"); - this_module.def(show_nested_tuples, "show_nested_tuples"); -} diff --git a/example/noncopyable.h b/example/noncopyable.h deleted file mode 100644 index de7b3672..00000000 --- a/example/noncopyable.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NONCOPYABLE_H -#define NONCOPYABLE_H - -class store -{ - private: - store(const store&) { } // Disable the copy constructor. - int number; - public: - store(const int i) : number(i) { } - int recall() const { return number; } -}; - -#endif // NONCOPYABLE_H diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp deleted file mode 100644 index 3a81db75..00000000 --- a/example/noncopyable_export.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include -namespace python = boost::python; - -#include "noncopyable.h" - -# ifdef BOOST_MSVC // fixes for JIT debugging -# include -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) -{ - python::module_builder this_module("noncopyable_export"); - - python::class_builder store_class(this_module, "store"); - python::export_converters_noncopyable(store_class); - - store_class.def(python::constructor()); - store_class.def(&store::recall, "recall"); -} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp deleted file mode 100644 index d4227642..00000000 --- a/example/noncopyable_import.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include -namespace python = boost::python; - -#include "noncopyable.h" - -namespace { // Avoid cluttering the global namespace. - - // A function with store objects as both input and output parameters. - // Because the copy constructor is disabled, we cannot pass a store - // object by value. Instead, we pass a smart pointer. - std::auto_ptr add_stores(const store& s1, const store& s2) - { - int sum = s1.recall() + s2.recall(); - std::auto_ptr ss = std::auto_ptr(new store(sum)); - return ss; - } -} - -# ifdef BOOST_MSVC // fixes for JIT debugging -# include -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) -{ - python::module_builder this_module("noncopyable_import"); - - python::import_converters - dvect_converters("noncopyable_export", "store"); - - // Imagine all the additional classes with member functions - // that have store objects as input and output parameters. - // Lots and lots of them. - // However, to keep this example simple, we only define a - // module-level function. - this_module.def(add_stores, "add_stores"); -} diff --git a/example/pickle1.cpp b/example/pickle1.cpp deleted file mode 100644 index af041e72..00000000 --- a/example/pickle1.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -/* - This example shows how to make an Extension Class "pickleable". - - The world class below can be fully restored by passing the - appropriate argument to the constructor. Therefore it is sufficient - to define the pickle interface method __getinitargs__. - - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - private: - std::string country; - int secret_number; - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - }; - - // Support for pickle. - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); - } -} - -BOOST_PYTHON_MODULE_INIT(pickle1) -{ - // Create an object representing this extension module. - python::module_builder this_module("pickle1"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); -} diff --git a/example/pickle2.cpp b/example/pickle2.cpp deleted file mode 100644 index 781615cd..00000000 --- a/example/pickle2.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -/* - This example shows how to make an Extension Class "pickleable". - - The world class below contains member data (secret_number) that - cannot be restored by any of the constructors. Therefore it is - necessary to provide the __getstate__/__setstate__ pair of pickle - interface methods. - - For simplicity, the __dict__ is not included in the result of - __getstate__. This is not generally recommended, but a valid - approach if it is anticipated that the object's __dict__ will - always be empty. Note that safety guard are provided to catch the - cases where this assumption is not true. - - pickle3.cpp shows how to include the object's __dict__ in the - result of __getstate__. - - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - private: - std::string country; - int secret_number; - }; - - // Support for pickle. - - using BOOST_PYTHON_CONVERSION::from_python; - - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); // returning the reference avoids the copying. - } - - python::ref world_getstate(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_secret_number()); - return result.reference(); // returning the reference avoids the copying. - } - - void world_setstate(world& w, python::tuple state) { - if (state.size() != 1) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - python::throw_error_already_set(); - } - int number = from_python(state[0].get(), python::type()); - if (number != 42) - w.set_secret_number(number); - } -} - -BOOST_PYTHON_MODULE_INIT(pickle2) -{ - // Create an object representing this extension module. - python::module_builder this_module("pickle2"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def(world_getstate, "__getstate__"); - world_class.def(world_setstate, "__setstate__"); -} diff --git a/example/pickle3.cpp b/example/pickle3.cpp deleted file mode 100644 index 5f32b1f3..00000000 --- a/example/pickle3.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -/* - This example shows how to make an Extension Class "pickleable". - - The world class below contains member data (secret_number) that - cannot be restored by any of the constructors. Therefore it is - necessary to provide the __getstate__/__setstate__ pair of pickle - interface methods. - - The object's __dict__ is included in the result of __getstate__. - This requires more code (compare with pickle2.cpp), but is - unavoidable if the object's __dict__ is not always empty. - - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace boost { namespace python { - - ref getattr(PyObject* o, const std::string& attr_name) { - return ref(PyObject_GetAttrString(o, const_cast(attr_name.c_str()))); - } - ref getattr(const ref& r, const std::string& attr_name) { - return getattr(r.get(), attr_name); - } - -}} - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - private: - std::string country; - int secret_number; - }; - - // Support for pickle. - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); // returning the reference avoids the copying. - } - - python::ref world_getstate(python::tuple const & args, - python::dictionary const & keywords); - - PyObject* world_setstate(python::tuple const & args, - python::dictionary const & keywords); -} - -BOOST_PYTHON_MODULE_INIT(pickle3) -{ - // Create an object representing this extension module. - python::module_builder this_module("pickle3"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def_raw(world_getstate, "__getstate__"); - world_class.def_raw(world_setstate, "__setstate__"); - world_class.getstate_manages_dict(); -} - -namespace { - - using BOOST_PYTHON_CONVERSION::from_python; - using boost::python::type; - using boost::python::ref; - using boost::python::tuple; - using boost::python::list; - using boost::python::dictionary; - using boost::python::getattr; - - ref world_getstate(tuple const & args, dictionary const & keywords) - { - if(args.size() != 1 || keywords.size() != 0) { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - boost::python::throw_error_already_set(); - } - const world& w = from_python(args[0].get(), type()); - ref mydict = getattr(args[0], "__dict__"); - tuple result(2); - // store the object's __dict__ - result.set_item(0, mydict); - // store the internal state of the C++ object - result.set_item(1, w.get_secret_number()); - return result.reference(); // returning the reference avoids the copying. - } - - PyObject* world_setstate(tuple const & args, dictionary const & keywords) - { - if(args.size() != 2 || keywords.size() != 0) { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - boost::python::throw_error_already_set(); - } - world& w = from_python(args[0].get(), type()); - ref mydict = getattr(args[0], "__dict__"); - tuple state = from_python(args[1].get(), type()); - if (state.size() != 2) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - python::throw_error_already_set(); - } - // restore the object's __dict__ - dictionary odict = from_python(mydict.get(), type()); - const dictionary& pdict = from_python(state[0].get(), type()); - list pkeys(pdict.keys()); - for (int i = 0; i < pkeys.size(); i++) { - ref k(pkeys[i]); - //odict[k] = pdict[k]; // XXX memory leak! - odict[k] = pdict.get_item(k); // this does not leak. - } - // restore the internal state of the C++ object - int number = from_python(state[1].get(), type()); - if (number != 42) - w.set_secret_number(number); - return python::detail::none(); - } -} diff --git a/example/project.zip b/example/project.zip deleted file mode 100644 index d863defd..00000000 Binary files a/example/project.zip and /dev/null differ diff --git a/example/richcmp1.cpp b/example/richcmp1.cpp deleted file mode 100644 index 884fdfda..00000000 --- a/example/richcmp1.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include "vector_wrapper.h" - -namespace vects { - - struct dvect : public std::vector - { - dvect() : std::vector() {} - dvect(size_t n) : std::vector(n) {} - dvect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::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()); - } - - 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 \ - operator##oper(const dvect& lhs, const dvect& rhs) \ - { \ - if (lhs.size() != rhs.size()) { \ - PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \ - boost::python::throw_error_already_set(); \ - } \ - std::vector result(lhs.size()); \ - for (std::size_t i=0; i) - DVECT_BINARY_OPERATORS(>=) -# undef VECTOR_BINARY_OPERATORS - }; - -} // namespace - - -namespace { - - void init_module(boost::python::module_builder& this_module) - { - (void) example::wrap_vector(this_module, "vector_of_bool", bool()); - - boost::python::class_builder py_dvect(this_module, "dvect"); - - py_dvect.def(boost::python::constructor()); - 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()); - } - -} // namespace - -BOOST_PYTHON_MODULE_INIT(richcmp1) -{ - 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); -} diff --git a/example/richcmp2.cpp b/example/richcmp2.cpp deleted file mode 100644 index 993c6800..00000000 --- a/example/richcmp2.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// 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 - -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 py_code(this_module, "code"); - - py_code.def(boost::python::constructor<>()); - py_code.def(boost::python::constructor()); - 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 - -BOOST_PYTHON_MODULE_INIT(richcmp2) -{ - 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); -} diff --git a/example/richcmp3.cpp b/example/richcmp3.cpp deleted file mode 100644 index 02a2ebcb..00000000 --- a/example/richcmp3.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter. -// Comprehensive operator overloading for two vector types and scalars. - -#include -#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"); \ - boost::python::throw_error_already_set(); \ - } \ - result_type result(lhs.size()); \ - for (std::size_t i=0; i, vect_type1, <, vect_type2) \ - VECT_VECT_OPERATORS(std::vector, vect_type1, <=, vect_type2) \ - VECT_VECT_OPERATORS(std::vector, vect_type1, ==, vect_type2) \ - VECT_VECT_OPERATORS(std::vector, vect_type1, !=, vect_type2) \ - VECT_VECT_OPERATORS(std::vector, vect_type1, >, vect_type2) \ - VECT_VECT_OPERATORS(std::vector, 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, vect_type, <, scalar_type) \ - VECT_SCALAR_OPERATORS(std::vector, vect_type, <=, scalar_type) \ - VECT_SCALAR_OPERATORS(std::vector, vect_type, ==, scalar_type) \ - VECT_SCALAR_OPERATORS(std::vector, vect_type, !=, scalar_type) \ - VECT_SCALAR_OPERATORS(std::vector, vect_type, >, scalar_type) \ - VECT_SCALAR_OPERATORS(std::vector, 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 - dvect_class(this_module, "dvect"); - boost::python::class_builder - ivect_class(this_module, "ivect"); - - dvect_class.def(boost::python::constructor()); - dvect_class.def(&vects::dvect::as_tuple,"as_tuple"); - - dvect_class.def(boost::python::operators()); - dvect_class.def(boost::python::operators(), - boost::python::right_operand() ); - dvect_class.def(boost::python::operators(), - boost::python::left_operand() ); - dvect_class.def(boost::python::operators(), - boost::python::right_operand() ); - - dvect_class.def(boost::python::operators()); - dvect_class.def(boost::python::operators(), - boost::python::right_operand() ); - // left_operand not needed since Python uses reflection - dvect_class.def(boost::python::operators(), - boost::python::right_operand() ); - - ivect_class.def(boost::python::constructor()); - ivect_class.def(&vects::ivect::as_tuple,"as_tuple"); - - ivect_class.def(boost::python::operators()); - ivect_class.def(boost::python::operators(), - boost::python::right_operand() ); - ivect_class.def(boost::python::operators(), - boost::python::left_operand() ); - ivect_class.def(boost::python::operators(), - boost::python::right_operand() ); - - ivect_class.def(boost::python::operators()); - ivect_class.def(boost::python::operators(), - boost::python::right_operand() ); - // left_operand not needed since Python uses reflection - ivect_class.def(boost::python::operators(), - boost::python::right_operand() ); - } - -} // namespace - -BOOST_PYTHON_MODULE_INIT(richcmp3) -{ - 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); -} diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp deleted file mode 100644 index bc6e3408..00000000 --- a/example/simple_vector.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A wrapper is used to define additional constructors. - // - struct vector_double_wrapper: std::vector - { - // Tell the compiler how to convert a base class object to - // this wrapper object. - vector_double_wrapper(PyObject*, const std::vector& vd) - : std::vector(vd) {} - - vector_double_wrapper(PyObject* self) - : std::vector() {} - - vector_double_wrapper(PyObject* self, int n) - : std::vector(n) {} - - vector_double_wrapper(PyObject* self, python::tuple tuple) - : std::vector(tuple.size()) - { - std::vector::iterator vd = begin(); - for (int i = 0; i < tuple.size(); i++) - vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - python::type()); - } - }; - - void raise_vector_IndexError() { - PyErr_SetString(PyExc_IndexError, "vector index out of range"); - python::throw_error_already_set(); - } - - double getitem(const std::vector& vd, std::size_t key) { - if (key >= vd.size()) raise_vector_IndexError(); - return vd[key]; - } - - void setitem(std::vector& vd, std::size_t key, double d) { - if (key >= vd.size()) raise_vector_IndexError(); - std::vector::iterator vditer = vd.begin(); - vditer[key] = d; - } - - void delitem(std::vector& vd, std::size_t key) { - if (key >= vd.size()) raise_vector_IndexError(); - std::vector::iterator vditer = vd.begin(); - vd.erase(vditer + key); - } - - // Convert vector_double to a regular Python tuple. - // - python::tuple as_tuple(const std::vector& vd) - { - python::tuple t(vd.size()); - for (int i = 0; i < vd.size(); i++) t.set_item(i, - python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); - return t; - } - - // Function returning a vector_double object to Python. - // - std::vector foo(int n) - { - std::vector vd(n); - std::vector::iterator vditer = vd.begin(); - for (int i = 0; i < n; i++) vditer[i] = double(i); - return vd; - } - - // Same as foo(), but avoid copying on return. - // - std::auto_ptr > bar(int n) - { - std::auto_ptr > vdptr(new std::vector(n)); - std::vector::iterator vditer = vdptr->begin(); - for (int i = 0; i < n; i++) vditer[i] = double(10 * i); - return vdptr; - } -} - -BOOST_PYTHON_MODULE_INIT(simple_vector) -{ - python::module_builder this_module("simple_vector"); - - python::class_builder, vector_double_wrapper> - vector_double(this_module, "vector_double"); - - vector_double.def(python::constructor()); - vector_double.def(python::constructor<>()); - vector_double.def(python::constructor()); - vector_double.def(&std::vector::size, "__len__"); - vector_double.def(getitem, "__getitem__"); - vector_double.def(setitem, "__setitem__"); - vector_double.def(delitem, "__delitem__"); - vector_double.def(as_tuple, "as_tuple"); - - this_module.def(foo, "foo"); - this_module.def(bar, "bar"); -} diff --git a/example/test_abstract.py b/example/test_abstract.py deleted file mode 100644 index a48aff1b..00000000 --- a/example/test_abstract.py +++ /dev/null @@ -1,24 +0,0 @@ -# Example by Ullrich Koethe -r'''>>> from abstract import * - >>> class A(Abstract): - ... def __init__(self, text): - ... Abstract.__init__(self) # call the base class constructor - ... self.text = text - ... def test(self): # implement abstract function - ... return self.text - ... - >>> a = A("Hello") - >>> a.test() - 'Hello' -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_abstract - return doctest.testmod(test_abstract) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) diff --git a/example/test_cross_module.py b/example/test_cross_module.py deleted file mode 100644 index c5e2bef6..00000000 --- a/example/test_cross_module.py +++ /dev/null @@ -1,140 +0,0 @@ -r'''>>> import tst_noncopyable - >>> tst_noncopyable.f() - 1 - 2 - 3 - >>> import tst_dvect1 - >>> tst_dvect1.f() - (1.0, 2.0, 3.0, 4.0, 5.0) - (1, 2, 3, 4, 5) - (1, 2, 3, 4, 5) - (1, 2, 3, 4, 5) - (1, 2, 3, 4, 5) - (1, 2, 3, 4, 5) - (1, 2, 3, 4, 5) - >>> import tst_ivect1 - >>> tst_ivect1.f() - (1, 2, 3, 4, 5) - (1.0, 2.0, 3.0, 4.0, 5.0) - (1.0, 2.0, 3.0, 4.0, 5.0) - (1.0, 2.0, 3.0, 4.0, 5.0) - (1.0, 2.0, 3.0, 4.0, 5.0) - (1.0, 2.0, 3.0, 4.0, 5.0) - (1.0, 2.0, 3.0, 4.0, 5.0) - >>> import sys - >>> if ("--broken-auto-ptr" in sys.argv): - ... broken_auto_ptr = 1 - ... else: - ... broken_auto_ptr = 0 - >>> import tst_dvect2 - >>> tst_dvect2.f(broken_auto_ptr) - 1. auto_ptr_value_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. auto_ptr_value_ivect_as_tuple - None - 1. auto_ptr_value_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. auto_ptr_value_dvect_as_tuple - None - 1. shared_ptr_value_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. shared_ptr_value_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. shared_ptr_value_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. shared_ptr_value_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. auto_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. auto_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. auto_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. auto_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. shared_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. shared_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. shared_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. shared_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. auto_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. auto_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. auto_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. auto_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. shared_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. shared_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. shared_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. shared_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - >>> import tst_ivect2 - >>> tst_ivect2.f(broken_auto_ptr) - 1. auto_ptr_value_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. auto_ptr_value_dvect_as_tuple - None - 1. auto_ptr_value_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. auto_ptr_value_ivect_as_tuple - None - 1. shared_ptr_value_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. shared_ptr_value_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. shared_ptr_value_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. shared_ptr_value_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. auto_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. auto_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. auto_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. auto_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. shared_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. shared_ptr_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. shared_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. shared_ptr_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. auto_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. auto_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. auto_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. auto_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 1. shared_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 2. shared_ptr_const_reference_dvect_as_tuple - (1.0, 2.0, 3.0, 4.0, 5.0) - 1. shared_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) - 2. shared_ptr_const_reference_ivect_as_tuple - (1, 2, 3, 4, 5) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_cross_module - return doctest.testmod(test_cross_module) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) diff --git a/example/test_do_it_yourself_convts.py b/example/test_do_it_yourself_convts.py deleted file mode 100644 index 6f5fa5a0..00000000 --- a/example/test_do_it_yourself_convts.py +++ /dev/null @@ -1,23 +0,0 @@ -r'''>>> import do_it_yourself_convts - >>> ixset = do_it_yourself_convts.IndexingSet() - >>> ixset.add((1,2,3)) - >>> ixset.add((4,5,6)) - >>> ixset.add((7,8,9)) - >>> print ixset.get(0) - (1, 2, 3) - >>> print ixset.get(1) - (4, 5, 6) - >>> print ixset.get(2) - (7, 8, 9) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_do_it_yourself_convts - return doctest.testmod(test_do_it_yourself_convts) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) diff --git a/example/test_example1.py b/example/test_example1.py deleted file mode 100644 index 3a30cb5b..00000000 --- a/example/test_example1.py +++ /dev/null @@ -1,51 +0,0 @@ -r''' -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -That's it! If we build this shared library and put it on our PYTHONPATH we can -now access our C++ class and function from Python. - - >>> import hello - >>> hi_world = hello.world(3) - >>> hi_world.get() - 'hi, world' - >>> hello.length(hi_world) - 9 - -We can even make a subclass of hello.world: - - - >>> class my_subclass(hello.world): - ... def get(self): - ... return 'hello, world' - ... - >>> y = my_subclass(2) - >>> y.get() - 'hello, world' - -Pretty cool! You can't do that with an ordinary Python extension type! - - >>> hello.length(y) - 9 - -Of course, you may now have a slightly empty feeling in the pit of your little -pythonic stomach. Perhaps you feel your subclass deserves to have a length() of -12? If so, read on... -''' -from hello import * - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_example1 - return doctest.testmod(test_example1) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) diff --git a/example/test_getting_started1.py b/example/test_getting_started1.py deleted file mode 100644 index cd8fb59e..00000000 --- a/example/test_getting_started1.py +++ /dev/null @@ -1,18 +0,0 @@ -r'''>>> import getting_started1 - >>> print getting_started1.greet() - hello, world - >>> number = 11 - >>> print number, '*', number, '=', getting_started1.square(number) - 11 * 11 = 121 -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_getting_started1 - return doctest.testmod(test_getting_started1) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) diff --git a/example/test_getting_started2.py b/example/test_getting_started2.py deleted file mode 100644 index ccfaa4f1..00000000 --- a/example/test_getting_started2.py +++ /dev/null @@ -1,31 +0,0 @@ -r'''>>> from getting_started2 import * - >>> hi = hello('California') - >>> hi.greet() - 'Hello from California' - >>> invite(hi) - 'Hello from California! Please come soon!' - >>> hi.invite() - 'Hello from California! Please come soon!' - - >>> class wordy(hello): - ... def greet(self): - ... return hello.greet(self) + ', where the weather is fine' - ... - >>> hi2 = wordy('Florida') - >>> hi2.greet() - 'Hello from Florida, where the weather is fine' - >>> invite(hi2) - 'Hello from Florida! Please come soon!' -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_getting_started2 - return doctest.testmod(test_getting_started2) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) - diff --git a/example/test_nested.py b/example/test_nested.py deleted file mode 100644 index e9abbf0f..00000000 --- a/example/test_nested.py +++ /dev/null @@ -1,23 +0,0 @@ -r'''>>> import nested - >>> s = nested.show_nested_tuples(((1,2,3), (4,5,6,7))) - >>> for l in s: - ... print l - (0,0) 1 - (0,1) 2 - (0,2) 3 - (1,0) 4 - (1,1) 5 - (1,2) 6 - (1,3) 7 -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_nested - return doctest.testmod(test_nested) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) diff --git a/example/test_pickle1.py b/example/test_pickle1.py deleted file mode 100644 index 48c76a5f..00000000 --- a/example/test_pickle1.py +++ /dev/null @@ -1,33 +0,0 @@ -r'''>>> import pickle1 - >>> import re - >>> import pickle - >>> pickle1.world.__module__ - 'pickle1' - >>> pickle1.world.__safe_for_unpickling__ - 1 - >>> pickle1.world.__reduce__() - 'world' - >>> assert re.match( - ... "\(, \('Hello',\)\)", - ... repr(pickle1.world('Hello').__reduce__())) - >>> - >>> wd = pickle1.world('California') - >>> pstr = pickle.dumps(wd) - >>> wl = pickle.loads(pstr) - >>> print wd.greet() - Hello from California! - >>> print wl.greet() - Hello from California! -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_pickle1 - return doctest.testmod(test_pickle1) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) - diff --git a/example/test_pickle2.py b/example/test_pickle2.py deleted file mode 100644 index bafa9875..00000000 --- a/example/test_pickle2.py +++ /dev/null @@ -1,47 +0,0 @@ -r'''>>> import pickle2 - >>> import re - >>> import pickle - >>> pickle2.world.__module__ - 'pickle2' - >>> pickle2.world.__safe_for_unpickling__ - 1 - >>> pickle2.world.__reduce__() - 'world' - >>> assert re.match( - ... "\(, \('Hello',\), \(0,\)\)", - ... repr(pickle2.world('Hello').__reduce__())) - >>> - >>> for number in (24, 42): - ... wd = pickle2.world('California') - ... wd.set_secret_number(number) - ... pstr = pickle.dumps(wd) - ... wl = pickle.loads(pstr) - ... print wd.greet(), wd.get_secret_number() - ... print wl.greet(), wl.get_secret_number() - Hello from California! 24 - Hello from California! 24 - Hello from California! 42 - Hello from California! 0 - -# Now show that the __dict__ is not taken care of. - >>> wd = pickle2.world('California') - >>> wd.x = 1 - >>> wd.__dict__ - {'x': 1} - >>> try: pstr = pickle.dumps(wd) - ... except RuntimeError, err: print err[0] - ... - Incomplete pickle support (__getstate_manages_dict__ not set) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_pickle2 - return doctest.testmod(test_pickle2) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) - diff --git a/example/test_pickle3.py b/example/test_pickle3.py deleted file mode 100644 index 6ac83b18..00000000 --- a/example/test_pickle3.py +++ /dev/null @@ -1,39 +0,0 @@ -r'''>>> import pickle3 - >>> import re - >>> import pickle - >>> pickle3.world.__module__ - 'pickle3' - >>> pickle3.world.__safe_for_unpickling__ - 1 - >>> pickle3.world.__reduce__() - 'world' - >>> assert re.match( - ... "\(, \('Hello',\), \(\{\}, 0\)\)", - ... repr(pickle3.world('Hello').__reduce__())) - >>> - >>> for number in (24, 42): - ... wd = pickle3.world('California') - ... wd.set_secret_number(number) - ... wd.x = 2 * number - ... wd.y = 'y' * number - ... wd.z = 3. * number - ... pstr = pickle.dumps(wd) - ... wl = pickle.loads(pstr) - ... 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): - if args is not None: - import sys - sys.argv = args - import doctest, test_pickle3 - return doctest.testmod(test_pickle3) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) diff --git a/example/test_richcmp1.py b/example/test_richcmp1.py deleted file mode 100644 index d25fcc9c..00000000 --- a/example/test_richcmp1.py +++ /dev/null @@ -1,40 +0,0 @@ -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." diff --git a/example/test_richcmp2.py b/example/test_richcmp2.py deleted file mode 100644 index 859928c3..00000000 --- a/example/test_richcmp2.py +++ /dev/null @@ -1,41 +0,0 @@ -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." diff --git a/example/test_richcmp3.py b/example/test_richcmp3.py deleted file mode 100644 index a769af17..00000000 --- a/example/test_richcmp3.py +++ /dev/null @@ -1,77 +0,0 @@ -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." diff --git a/example/test_rwgk1.py b/example/test_rwgk1.py deleted file mode 100644 index 631eea3e..00000000 --- a/example/test_rwgk1.py +++ /dev/null @@ -1,19 +0,0 @@ -r'''>>> import rwgk1 - >>> print rwgk1.greet() - hello, world - >>> number = 11 - >>> print number, '*', number, '=', rwgk1.square(number) - 11 * 11 = 121 -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_rwgk1 - return doctest.testmod(test_rwgk1) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) - diff --git a/example/test_simple_vector.py b/example/test_simple_vector.py deleted file mode 100644 index c6a2cd59..00000000 --- a/example/test_simple_vector.py +++ /dev/null @@ -1,42 +0,0 @@ -r'''>>> import simple_vector - >>> v=simple_vector.vector_double() - >>> print v.as_tuple() - () - >>> v=simple_vector.vector_double(5) - >>> print v.as_tuple() - (0.0, 0.0, 0.0, 0.0, 0.0) - >>> print len(v) - 5 - >>> v=simple_vector.vector_double((3,4,5)) - >>> print v.as_tuple() - (3.0, 4.0, 5.0) - >>> print v[1] - 4.0 - >>> v[1] = 40 - >>> print v.as_tuple() - (3.0, 40.0, 5.0) - >>> for e in v: - ... print e - 3.0 - 40.0 - 5.0 - >>> del v[1] - >>> print v.as_tuple() - (3.0, 5.0) - >>> print simple_vector.foo(11).as_tuple() - (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) - >>> print simple_vector.bar(12).as_tuple() - (0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_simple_vector - return doctest.testmod(test_simple_vector) - -if __name__ == '__main__': - import sys - sys.exit(run()[0]) - diff --git a/example/tst_dvect1.py b/example/tst_dvect1.py deleted file mode 100644 index 22315528..00000000 --- a/example/tst_dvect1.py +++ /dev/null @@ -1,20 +0,0 @@ -def f(): - import dvect - dv = dvect.dvect((1,2,3,4,5)) - print dv.as_tuple() - iv = dv.as_ivect() - print iv.as_tuple() - print dvect.const_ivect_reference_as_tuple(iv) - aiv = dvect.ivect_as_auto_ptr(iv) - print dvect.const_ivect_reference_as_tuple(aiv) - siv = dvect.ivect_as_shared_ptr(iv) - print dvect.const_ivect_reference_as_tuple(siv) - print aiv.as_tuple() - print siv.as_tuple() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/tst_dvect2.py b/example/tst_dvect2.py deleted file mode 100644 index 90d381a7..00000000 --- a/example/tst_dvect2.py +++ /dev/null @@ -1,104 +0,0 @@ -def f(broken_auto_ptr): - import dvect - import ivect - # - dv = dvect.dvect((1,2,3,4,5)) - iv = dv.as_ivect() - # - aiv = dvect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_value_ivect_as_tuple' - print ivect.auto_ptr_value_ivect_as_tuple(aiv) - print '2. auto_ptr_value_ivect_as_tuple' - if (not broken_auto_ptr): - print ivect.auto_ptr_value_ivect_as_tuple(aiv) - else: - print None - # - adv = dvect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_value_dvect_as_tuple' - print ivect.auto_ptr_value_dvect_as_tuple(adv) - print '2. auto_ptr_value_dvect_as_tuple' - if (not broken_auto_ptr): - print ivect.auto_ptr_value_dvect_as_tuple(adv) - else: - print None - # - siv = dvect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_value_ivect_as_tuple' - print ivect.shared_ptr_value_ivect_as_tuple(siv) - print '2. shared_ptr_value_ivect_as_tuple' - print ivect.shared_ptr_value_ivect_as_tuple(siv) - # - sdv = dvect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_value_dvect_as_tuple' - print ivect.shared_ptr_value_dvect_as_tuple(sdv) - print '2. shared_ptr_value_dvect_as_tuple' - print ivect.shared_ptr_value_dvect_as_tuple(sdv) - # - aiv = dvect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_reference_ivect_as_tuple' - print ivect.auto_ptr_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_reference_ivect_as_tuple' - print ivect.auto_ptr_reference_ivect_as_tuple(aiv) - # - adv = dvect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_reference_dvect_as_tuple' - print ivect.auto_ptr_reference_dvect_as_tuple(adv) - print '2. auto_ptr_reference_dvect_as_tuple' - print ivect.auto_ptr_reference_dvect_as_tuple(adv) - # - siv = dvect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_reference_ivect_as_tuple' - print ivect.shared_ptr_reference_ivect_as_tuple(siv) - print '2. shared_ptr_reference_ivect_as_tuple' - print ivect.shared_ptr_reference_ivect_as_tuple(siv) - # - sdv = dvect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_reference_dvect_as_tuple' - print ivect.shared_ptr_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_reference_dvect_as_tuple' - print ivect.shared_ptr_reference_dvect_as_tuple(sdv) - # - aiv = dvect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_const_reference_ivect_as_tuple' - print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_const_reference_ivect_as_tuple' - print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) - # - adv = dvect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_const_reference_dvect_as_tuple' - print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) - print '2. auto_ptr_const_reference_dvect_as_tuple' - print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) - # - siv = dvect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_const_reference_ivect_as_tuple' - print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) - print '2. shared_ptr_const_reference_ivect_as_tuple' - print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) - # - sdv = dvect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_const_reference_dvect_as_tuple' - print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_const_reference_dvect_as_tuple' - print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) - -if (__name__ == "__main__"): - import sys, string - broken_auto_ptr = 0 - n = 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) diff --git a/example/tst_ivect1.py b/example/tst_ivect1.py deleted file mode 100644 index 7369fdbf..00000000 --- a/example/tst_ivect1.py +++ /dev/null @@ -1,20 +0,0 @@ -def f(): - import ivect - iv = ivect.ivect((1,2,3,4,5)) - print iv.as_tuple() - dv = iv.as_dvect() - print dv.as_tuple() - print ivect.const_dvect_reference_as_tuple(dv) - adv = ivect.dvect_as_auto_ptr(dv) - print ivect.const_dvect_reference_as_tuple(adv) - sdv = ivect.dvect_as_shared_ptr(dv) - print ivect.const_dvect_reference_as_tuple(sdv) - print adv.as_tuple() - print sdv.as_tuple() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/tst_ivect2.py b/example/tst_ivect2.py deleted file mode 100644 index a9e6aeef..00000000 --- a/example/tst_ivect2.py +++ /dev/null @@ -1,104 +0,0 @@ -def f(broken_auto_ptr): - import ivect - import dvect - # - iv = ivect.ivect((1,2,3,4,5)) - dv = iv.as_dvect() - # - adv = ivect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_value_dvect_as_tuple' - print dvect.auto_ptr_value_dvect_as_tuple(adv) - print '2. auto_ptr_value_dvect_as_tuple' - if (not broken_auto_ptr): - print dvect.auto_ptr_value_dvect_as_tuple(adv) - else: - print None - # - aiv = ivect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_value_ivect_as_tuple' - print dvect.auto_ptr_value_ivect_as_tuple(aiv) - print '2. auto_ptr_value_ivect_as_tuple' - if (not broken_auto_ptr): - print dvect.auto_ptr_value_ivect_as_tuple(aiv) - else: - print None - # - sdv = ivect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_value_dvect_as_tuple' - print dvect.shared_ptr_value_dvect_as_tuple(sdv) - print '2. shared_ptr_value_dvect_as_tuple' - print dvect.shared_ptr_value_dvect_as_tuple(sdv) - # - siv = ivect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_value_ivect_as_tuple' - print dvect.shared_ptr_value_ivect_as_tuple(siv) - print '2. shared_ptr_value_ivect_as_tuple' - print dvect.shared_ptr_value_ivect_as_tuple(siv) - # - adv = ivect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_reference_dvect_as_tuple' - print dvect.auto_ptr_reference_dvect_as_tuple(adv) - print '2. auto_ptr_reference_dvect_as_tuple' - print dvect.auto_ptr_reference_dvect_as_tuple(adv) - # - aiv = ivect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_reference_ivect_as_tuple' - print dvect.auto_ptr_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_reference_ivect_as_tuple' - print dvect.auto_ptr_reference_ivect_as_tuple(aiv) - # - sdv = ivect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_reference_dvect_as_tuple' - print dvect.shared_ptr_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_reference_dvect_as_tuple' - print dvect.shared_ptr_reference_dvect_as_tuple(sdv) - # - siv = ivect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_reference_ivect_as_tuple' - print dvect.shared_ptr_reference_ivect_as_tuple(siv) - print '2. shared_ptr_reference_ivect_as_tuple' - print dvect.shared_ptr_reference_ivect_as_tuple(siv) - # - adv = ivect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_const_reference_dvect_as_tuple' - print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) - print '2. auto_ptr_const_reference_dvect_as_tuple' - print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) - # - aiv = ivect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_const_reference_ivect_as_tuple' - print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_const_reference_ivect_as_tuple' - print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) - # - sdv = ivect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_const_reference_dvect_as_tuple' - print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_const_reference_dvect_as_tuple' - print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) - # - siv = ivect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_const_reference_ivect_as_tuple' - print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) - print '2. shared_ptr_const_reference_ivect_as_tuple' - print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) - -if (__name__ == "__main__"): - import sys, string - broken_auto_ptr = 0 - n = 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) diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py deleted file mode 100644 index 155910a5..00000000 --- a/example/tst_noncopyable.py +++ /dev/null @@ -1,16 +0,0 @@ -def f(): - import noncopyable_export - import noncopyable_import - s1 = noncopyable_export.store(1) - print s1.recall() - s2 = noncopyable_export.store(2) - print s2.recall() - s3 = noncopyable_import.add_stores(s1, s2) - print s3.recall() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/vector_wrapper.h b/example/vector_wrapper.h deleted file mode 100644 index 6a571343..00000000 --- a/example/vector_wrapper.h +++ /dev/null @@ -1,117 +0,0 @@ -// 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 - -namespace example { - - // A wrapper is used to define additional constructors. This wrapper - // is templated on the template parameter for its corresponding vector. - template - struct vector_wrapper: std::vector - { - // Tell the compiler how to convert a base class object to - // this wrapper object. - vector_wrapper(PyObject*, - const std::vector& vec): - std::vector(vec) {} - - vector_wrapper(PyObject* self): - std::vector() {} - - vector_wrapper(PyObject* self, - std::size_t n): - std::vector(n) {} - - vector_wrapper(PyObject* self, - boost::python::tuple tuple): - std::vector(tuple.size()) - { - std::vector::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()); - } - }; - - void raise_vector_IndexError() { - PyErr_SetString(PyExc_IndexError, "vector index out of range"); - boost::python::throw_error_already_set(); - } - - template - struct vector_access - { - static - T - getitem(const std::vector& vec, - std::size_t key) - { - if (key >= vec.size()) raise_vector_IndexError(); - return vec[key]; - } - - static - void - setitem(std::vector& vec, - std::size_t key, - const T &value) - { - if (key >= vec.size()) raise_vector_IndexError(); - vec[key] = value; - } - - static - void - delitem(std::vector& vec, - std::size_t key) - { - if (key >= vec.size()) raise_vector_IndexError(); - vec.erase(vec.begin() + key); - } - - // Convert vector to a regular Python tuple. - static - boost::python::tuple - as_tuple(const std::vector& 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 and add it to the given - // module with the given name. - template - boost::python::class_builder, vector_wrapper > - wrap_vector(boost::python::module_builder& module, - const std::string& vector_name, - const T&) - { - // Add the vector to the module. - boost::python::class_builder, vector_wrapper > - py_vector(module, vector_name.c_str()); - - // Define constructors and methods for the vector. - py_vector.def(boost::python::constructor<>()); - py_vector.def(boost::python::constructor()); - py_vector.def(boost::python::constructor()); - py_vector.def(&std::vector::size, "__len__"); - py_vector.def(&vector_access::getitem, "__getitem__"); - py_vector.def(&vector_access::setitem, "__setitem__"); - py_vector.def(&vector_access::delitem, "__delitem__"); - py_vector.def(&vector_access::as_tuple, "as_tuple"); - - return py_vector; - } -} - -#endif // BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H diff --git a/include/boost/python/args.hpp b/include/boost/python/args.hpp index dc00c96c..941529f0 100644 --- a/include/boost/python/args.hpp +++ b/include/boost/python/args.hpp @@ -1,5 +1,3 @@ -#if !defined(BOOST_PP_IS_ITERATING) - // Copyright David Abrahams 2002. Permission to copy, use, // modify, sell and distribute this software is granted provided this // copyright notice appears in all copies. This software is provided @@ -8,14 +6,8 @@ #ifndef ARGS_DWA2002323_HPP # define ARGS_DWA2002323_HPP # include - # include - -# include - -# include -# include -# include +# include namespace boost { namespace python { @@ -28,76 +20,15 @@ namespace detail } }} -# if !defined(__EDG_VERSION__) || __EDG_VERSION__ > 245 - namespace boost { namespace python { // A type list for specifying arguments -template < BOOST_PYTHON_ENUM_WITH_DEFAULT(BOOST_PYTHON_MAX_ARITY, typename A, boost::mpl::null_argument) > +template < BOOST_PYTHON_ENUM_WITH_DEFAULT(BOOST_PYTHON_MAX_ARITY, typename A, mpl::void_) > struct args : detail::args_base > - , boost::mpl::type_list< BOOST_PYTHON_UNARY_ENUM(BOOST_PYTHON_MAX_ARITY, A) >::type + , detail::type_list< BOOST_PYTHON_UNARY_ENUM(BOOST_PYTHON_MAX_ARITY, A) >::type {}; }} // namespace boost::python -# else // slow template instantiators need this other version with - // explicit specializations of mpl::size<> and - // mpl::at<>. Eventually, however, inheritance from mpl::list - // *should* be eliminated and the two versions unified, just in - // order to get true arity independence - -namespace boost { namespace python { - -template < BOOST_PYTHON_ENUM_WITH_DEFAULT(BOOST_PYTHON_MAX_ARITY, typename A, boost::mpl::null_argument) > -struct args : detail::args_base > -{}; - -}} // namespace boost::python - -namespace boost { namespace mpl { - -template struct size; -template struct at; - -# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, , 1)) -# include BOOST_PP_ITERATE() - -# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY - 1, , 2)) -# include BOOST_PP_ITERATE() - - -}} // namespace boost::mpl - -# endif // __EDG_VERSION__ # endif // ARGS_DWA2002323_HPP - -/* ---------- size ---------- */ -#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 -# line BOOST_PP_LINE(__LINE__, args.hpp(size)) - -# define N BOOST_PP_ITERATION() - -template -struct size > -{ - BOOST_STATIC_CONSTANT(long, value = N); -}; - -# undef N - -/* ---------- at ---------- */ -#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2 -# line BOOST_PP_LINE(__LINE__, args.hpp(at)) - -# define N BOOST_PP_ITERATION() - -template -struct at > -{ - typedef BOOST_PP_CAT(A, N) type; -}; - -# undef N - -#endif diff --git a/include/boost/python/bases.hpp b/include/boost/python/bases.hpp index 468c6744..ec03dfba 100644 --- a/include/boost/python/bases.hpp +++ b/include/boost/python/bases.hpp @@ -6,14 +6,16 @@ #ifndef BASES_DWA2002321_HPP # define BASES_DWA2002321_HPP # include -# include -# include -# include +# include +# include +# include +# include namespace boost { namespace python { + // A type list for specifying bases - template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename B, ::boost::mpl::null_argument) > - struct bases : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(B) >::type + template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_MAX_BASES, typename B, mpl::void_) > + struct bases : detail::type_list< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, B) >::type {}; namespace detail @@ -23,14 +25,14 @@ namespace boost { namespace python { { BOOST_STATIC_CONSTANT(bool, value = false); }; - template < BOOST_MPL_LIST_PARAMETERS(class B) > - struct specifies_bases< bases< BOOST_MPL_LIST_PARAMETERS(B) > > + template < BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, class B) > + struct specifies_bases< bases< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, B) > > { BOOST_STATIC_CONSTANT(bool, value = true); }; # else - template < BOOST_MPL_LIST_PARAMETERS(class B) > - static char is_bases_helper(bases< BOOST_MPL_LIST_PARAMETERS(B) > const&); + template < BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, class B) > + static char is_bases_helper(bases< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, B) > const&); static char (& is_bases_helper(...) )[256]; @@ -45,7 +47,7 @@ namespace boost { namespace python { # endif template > struct select_bases - : mpl::select_type< + : mpl::if_c< specifies_bases::value , T , Prev diff --git a/include/boost/python/call.hpp b/include/boost/python/call.hpp index 6ce027ef..4edceee3 100644 --- a/include/boost/python/call.hpp +++ b/include/boost/python/call.hpp @@ -54,8 +54,8 @@ call(PyObject* callable return converter( PyEval_CallFunction( callable - , const_cast("(" BOOST_PP_REPEAT(N, BOOST_PYTHON_FIXED, "O") ")") - BOOST_PP_REPEAT(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) + , const_cast("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) )); } diff --git a/include/boost/python/call_method.hpp b/include/boost/python/call_method.hpp index 7c8f0e90..e8917c22 100644 --- a/include/boost/python/call_method.hpp +++ b/include/boost/python/call_method.hpp @@ -54,8 +54,8 @@ call_method(PyObject* self, char const* name PyEval_CallMethod( self , const_cast(name) - , const_cast("(" BOOST_PP_REPEAT(N, BOOST_PYTHON_FIXED, "O") ")") - BOOST_PP_REPEAT(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) + , const_cast("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) )); } diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 918cf4d2..7f769739 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -20,7 +20,7 @@ # include # include # include -# include +# include # include # include # include @@ -40,7 +40,22 @@ namespace boost { namespace python { namespace detail { - struct write_type_id; + // This function object is used with mpl::for_each to write the id + // of the type a pointer to which is passed as its 2nd compile-time + // argument. into the iterator pointed to by its runtime argument + struct write_type_id + { + write_type_id(type_info**p) : p(p) {} + + // Here's the runtime behavior + template + void operator()(T*) const + { + *(*p)++ = type_id(); + }; + + type_info** p; + }; template struct select_held_type; @@ -56,7 +71,7 @@ namespace detail // to the type of holder that must be created. The 3rd argument is a // reference to the Python type object to be created. template - static inline void register_copy_constructor(mpl::bool_t const&, SelectHolder const& , T* = 0) + static inline void register_copy_constructor(mpl::bool_c const&, SelectHolder const& , T* = 0) { typedef typename SelectHolder::type holder; force_instantiate(objects::class_wrapper >()); @@ -65,12 +80,20 @@ namespace detail // Tag dispatched to have no effect. template - static inline void register_copy_constructor(mpl::bool_t const&, SelectHolder const&, T* = 0) + static inline void register_copy_constructor(mpl::bool_c const&, SelectHolder const&, T* = 0) { SelectHolder::register_(); } - template int assert_default_constructible(T const&); + template + struct assert_default_constructible + { + static int check2(T const&); + static int check() + { + return sizeof(check2(T())); + } + }; } // @@ -118,7 +141,7 @@ class class_ : public objects::class_base // Write the rest of the elements into succeeding positions. type_info* p = ids + 1; - mpl::for_each::execute(&p); + mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer*)0); } BOOST_STATIC_CONSTANT( @@ -265,7 +288,8 @@ class class_ : public objects::class_base // Define the default constructor. self& def_init() { - this->def_init(mpl::type_list<>::type()); + detail::assert_default_constructible::check(); + this->def_init(mpl::list0<>::type()); return *this; } @@ -392,7 +416,7 @@ inline void class_::register_() const objects::register_class_from_python(); detail::register_copy_constructor( - mpl::bool_t() + mpl::bool_c() , holder_selector::execute((held_type*)0) ); } @@ -404,7 +428,6 @@ inline class_::class_() : base(typeid(T).name(), id_vector::size, id_vector().ids) { this->register_(); - detail::force_instantiate(sizeof(detail::assert_default_constructible(T()))); this->def_init(); this->set_instance_size(holder_selector::additional_size()); } @@ -422,7 +445,6 @@ inline class_::class_(char const* name, char const* doc) : base(name, id_vector::size, id_vector().ids, doc) { this->register_(); - detail::force_instantiate(sizeof(detail::assert_default_constructible(T()))); this->def_init(); this->set_instance_size(holder_selector::additional_size()); } @@ -445,28 +467,6 @@ inline class_::class_(char const* name, char const* doc, no_init_t) namespace detail { - // This is an mpl BinaryMetaFunction object with a runtime behavior, - // which is to write the id of the type which is passed as its 2nd - // compile-time argument into the iterator pointed to by its runtime - // argument - struct write_type_id - { - // The first argument is Ignored because mpl::for_each is still - // currently an accumulate (reduce) implementation. - template struct apply - { - // also an artifact of accumulate-based for_each - typedef void type; - - // Here's the runtime behavior - static void execute(type_info** p) - { - *(*p)++ = type_id(); - } - }; - }; - - template struct has_noncopyable : type_traits::ice_or< @@ -478,7 +478,7 @@ namespace detail template struct select_held_type - : mpl::select_type< + : mpl::if_c< type_traits::ice_or< specifies_bases::value , is_same::value diff --git a/include/boost/python/converter/arg_from_python.hpp b/include/boost/python/converter/arg_from_python.hpp index 585a30eb..1e3dfa26 100755 --- a/include/boost/python/converter/arg_from_python.hpp +++ b/include/boost/python/converter/arg_from_python.hpp @@ -12,7 +12,7 @@ # include # include # include -# include +# include # include # include # include @@ -165,22 +165,22 @@ struct select_arg_from_python bool, back_ref = boost::python::is_back_reference::value); - typedef typename mpl::select_type< + typedef typename mpl::if_c< obj_mgr , object_manager_value_arg_from_python - , typename mpl::select_type< + , typename mpl::if_c< obj_mgr_ref , object_manager_ref_arg_from_python - , typename mpl::select_type< + , typename mpl::if_c< ptr , pointer_arg_from_python - , typename mpl::select_type< + , typename mpl::if_c< ptr_cref , pointer_cref_arg_from_python - , typename mpl::select_type< + , typename mpl::if_c< ref , reference_arg_from_python - , typename mpl::select_type< + , typename mpl::if_c< back_ref , back_reference_arg_from_python , arg_rvalue_from_python diff --git a/include/boost/python/converter/arg_to_python.hpp b/include/boost/python/converter/arg_to_python.hpp index 7abb274c..deab7964 100755 --- a/include/boost/python/converter/arg_to_python.hpp +++ b/include/boost/python/converter/arg_to_python.hpp @@ -109,22 +109,22 @@ namespace detail typedef typename unwrap_reference::type unwrapped_referent; typedef typename unwrap_pointer::type unwrapped_ptr; - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_string , arg_to_python - , typename mpl::select_type< + , typename mpl::if_c< function , function_arg_to_python - , typename mpl::select_type< + , typename mpl::if_c< manager , object_manager_arg_to_python - , typename mpl::select_type< + , typename mpl::if_c< ptr , pointer_deep_arg_to_python - , typename mpl::select_type< + , typename mpl::if_c< ptr_wrapper , pointer_shallow_arg_to_python - , typename mpl::select_type< + , typename mpl::if_c< ref_wrapper , reference_arg_to_python , value_arg_to_python diff --git a/include/boost/python/converter/callback.hpp b/include/boost/python/converter/callback.hpp new file mode 100644 index 00000000..d11dfcb1 --- /dev/null +++ b/include/boost/python/converter/callback.hpp @@ -0,0 +1,278 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef CALLBACK_DWA2002228_HPP +# define CALLBACK_DWA2002228_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + template + struct pointer_callback_from_python + { + pointer_callback_from_python(); + T operator()(PyObject*) const; + }; + + template + struct reference_callback_from_python + { + reference_callback_from_python(); + T operator()(PyObject*) const; + }; + + template + struct rvalue_callback_from_python + { + rvalue_callback_from_python(); + T const& operator()(PyObject*); + private: + rvalue_data m_data; + }; + + template + struct select_callback_from_python + { + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ref = is_reference::value); + + typedef typename mpl::select_if_c< + ptr + , pointer_callback_from_python + , typename mpl::select_if_c< + ref + , reference_callback_from_python + , rvalue_callback_from_python + >::type + >::type type; + }; + + + template + struct reference_callback_to_python : callback_to_python_holder + { + reference_callback_to_python(T& x); + private: + static PyObject* get_object(T& x); + }; + + template + struct value_callback_to_python : callback_to_python_base + { + // Throw an exception if the conversion can't succeed + value_callback_to_python(T const&); + }; + + template + struct pointer_deep_callback_to_python : callback_to_python_base + { + // Throw an exception if the conversion can't succeed + pointer_deep_callback_to_python(Ptr); + }; + + template + struct pointer_shallow_callback_to_python : callback_to_python_holder + { + // Throw an exception if the conversion can't succeed + pointer_shallow_callback_to_python(Ptr); + private: + static PyObject* get_object(Ptr p); + }; + + template + struct select_callback_to_python + { + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ref_wrapper = is_reference_wrapper::value); + + BOOST_STATIC_CONSTANT( + bool, ptr_wrapper = is_pointer_wrapper::value); + + typedef typename unwrap_reference::type unwrapped_referent; + typedef typename unwrap_pointer::type unwrapped_ptr; + + typedef typename mpl::select_if_c< + ptr + , pointer_deep_callback_to_python + , typename mpl::select_if_c< + ptr_wrapper + , pointer_shallow_callback_to_python + , typename mpl::select_if_c< + ref_wrapper + , reference_callback_to_python + , value_callback_to_python + >::type + >::type + >::type type; + }; +} + +template +struct callback_from_python + : detail::select_callback_from_python::type +{ + typedef T result_type; +}; + +struct void_result +{ + private: + void_result() {} + void operator=(void_result const&); + + // I would prefer to make this completely untouchable, but few + // compilers support template friends +# if 0 + void_result(void_result const&); +# endif + friend struct callback_from_python; +}; + +// Specialization as a convenience for call and call_method +template <> +struct callback_from_python +{ + typedef void_result result_type; + result_type operator()(PyObject* x) const + { + Py_DECREF(expect_non_null(x)); + return result_type(); + } +}; + +template +struct callback_to_python + : detail::select_callback_to_python::type +{ + typedef typename detail::select_callback_to_python::type base; + public: // member functions + // Throw an exception if the conversion can't succeed + callback_to_python(T const& x); +}; + +// Convenience macros for call<> and call_method<> code generation +# define BOOST_PYTHON_CALLBACK_TO_PYTHON_GET(index,ignored) \ + converter::callback_to_python( \ + BOOST_PP_CAT(a,index)).get() + +# define BOOST_PYTHON_ARG_STRING(nargs) \ + "(" BOOST_PP_REPEAT(nargs,BOOST_PYTHON_PROJECT_2ND,"O") ")" + +// +// Implementations +// +namespace detail +{ + template + inline rvalue_callback_from_python::rvalue_callback_from_python() + : m_data(rvalue_from_python_chain::value) + { + throw_if_not_registered(m_data.stage1); + } + + template + inline T const& rvalue_callback_from_python::operator()(PyObject* obj) + { + return *(T*)convert_rvalue(obj, m_data.stage1, m_data.storage.bytes); + } + + BOOST_PYTHON_DECL void throw_no_class_registered(); + + template + inline reference_callback_from_python::reference_callback_from_python() + { + detail::throw_if_not_registered(lvalue_from_python_chain::value); + } + + template + inline T reference_callback_from_python::operator()(PyObject* obj) const + { + return python::detail::void_ptr_to_reference( + callback_convert_reference(obj, lvalue_from_python_chain::value) + , (T(*)())0); + } + + template + inline pointer_callback_from_python::pointer_callback_from_python() + { + detail::throw_if_not_registered(lvalue_from_python_chain::value); + } + + template + inline T pointer_callback_from_python::operator()(PyObject* obj) const + { + return T(callback_convert_pointer(obj, lvalue_from_python_chain::value)); + } + + template + inline value_callback_to_python::value_callback_to_python(T const& x) + : callback_to_python_base(&x, to_python_function::value) + { + } + + template + inline pointer_deep_callback_to_python::pointer_deep_callback_to_python(Ptr x) + : callback_to_python_base(x, pointee_to_python_function::value) + { + } + + template + inline PyObject* reference_callback_to_python::get_object(T& x) + { + to_python_indirect convert; + if (!convert.convertible()) + throw_no_class_registered(); + return convert(x); + } + + template + inline reference_callback_to_python::reference_callback_to_python(T& x) + : callback_to_python_holder(get_object(x)) + { + } + + template + inline pointer_shallow_callback_to_python::pointer_shallow_callback_to_python(Ptr x) + : callback_to_python_holder(get_object(x)) + {} + + template + inline PyObject* pointer_shallow_callback_to_python::get_object(Ptr x) + { + to_python_indirect convert; + if (!convert.convertible()) + throw_no_class_registered(); + return x ? convert(x) : python::detail::none(); + } +} + +template +inline callback_to_python::callback_to_python(T const& x) + : base(x) +{} + +}}} // namespace boost::python::converter + +#endif // CALLBACK_DWA2002228_HPP diff --git a/include/boost/python/converter/callback_from_python_base.hpp b/include/boost/python/converter/callback_from_python_base.hpp new file mode 100644 index 00000000..117ba145 --- /dev/null +++ b/include/boost/python/converter/callback_from_python_base.hpp @@ -0,0 +1,25 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP +# define CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + + // Throw an exception + BOOST_PYTHON_DECL void throw_if_not_registered(rvalue_stage1_data const&); + BOOST_PYTHON_DECL void* convert_rvalue(PyObject*, rvalue_stage1_data& data, void* storage); + + BOOST_PYTHON_DECL void throw_if_not_registered(lvalue_from_python_registration*const&); + BOOST_PYTHON_DECL void* callback_convert_reference(PyObject*, lvalue_from_python_registration*const&); + BOOST_PYTHON_DECL void* callback_convert_pointer(PyObject*, lvalue_from_python_registration*const&); +} + +}}} // namespace boost::python::converter + +#endif // CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP diff --git a/include/boost/python/converter/callback_to_python_base.hpp b/include/boost/python/converter/callback_to_python_base.hpp new file mode 100644 index 00000000..c878850e --- /dev/null +++ b/include/boost/python/converter/callback_to_python_base.hpp @@ -0,0 +1,45 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef CALLBACK_TO_PYTHON_BASE_DWA200237_HPP +# define CALLBACK_TO_PYTHON_BASE_DWA200237_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + struct callback_to_python_holder + { + callback_to_python_holder(PyObject* obj); + inline PyObject* get() const; + private: + ref m_held; + }; + + struct BOOST_PYTHON_DECL callback_to_python_base : callback_to_python_holder + { + callback_to_python_base(void const volatile* source, to_python_function_t); + }; + + // + // implmentation + // + inline callback_to_python_holder::callback_to_python_holder(PyObject* obj) + : m_held(obj) + { + } + + inline PyObject* callback_to_python_holder::get() const + { + return m_held.get(); + } +} + +}}} // namespace boost::python::converter + +#endif // CALLBACK_TO_PYTHON_BASE_DWA200237_HPP diff --git a/include/boost/python/converter/find_from_python.hpp b/include/boost/python/converter/find_from_python.hpp new file mode 100644 index 00000000..709c5de0 --- /dev/null +++ b/include/boost/python/converter/find_from_python.hpp @@ -0,0 +1,29 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef FIND_FROM_PYTHON_DWA2002223_HPP +# define FIND_FROM_PYTHON_DWA2002223_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct lvalue_from_python_registration; +struct rvalue_from_python_registration; + +BOOST_PYTHON_DECL void* find( + PyObject* source, lvalue_from_python_registration const*); + +BOOST_PYTHON_DECL rvalue_stage1_data find( + PyObject* source, rvalue_from_python_registration const*); + +BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain( + PyObject* source, rvalue_from_python_registration const*); + +}}} // namespace boost::python::converter + +#endif // FIND_FROM_PYTHON_DWA2002223_HPP diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp new file mode 100644 index 00000000..a71c6548 --- /dev/null +++ b/include/boost/python/converter/from_python_data.hpp @@ -0,0 +1,129 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef FROM_PYTHON_AUX_DATA_DWA2002128_HPP +# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + template struct referent_size; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct referent_size + { + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(T)); + }; + +# else + + template struct referent_size + { + static T f(); + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(f())); + }; + +# endif + struct alignment_dummy; + typedef void (*function_ptr)(); + typedef int (alignment_dummy::*member_ptr); + typedef int (alignment_dummy::*member_function_ptr)(); + +# define BOOST_PYTHON_ALIGNMENT_TYPES BOOST_PP_TUPLE_TO_LIST( \ + 11, ( \ + char, short, int, long, float, double, long double \ + , void*, function_ptr, member_ptr, member_function_ptr)) + +# define BOOST_PYTHON_CHOOSE_LOWER_SIZE(R,P,I,T) \ + typename mpl::select_if_c< \ + sizeof(T) <= target, T, char>::type BOOST_PP_CAT(t,I); + +# define BOOST_PYTHON_CHOOSE_T(R,P,I,T) T BOOST_PP_CAT(t,I); + + template + union lower_size + { + BOOST_PP_LIST_FOR_EACH_I( + BOOST_PYTHON_CHOOSE_LOWER_SIZE + , ignored, BOOST_PYTHON_ALIGNMENT_TYPES) + }; + + template + union aligned_storage + { + Align align; + char bytes[size]; + }; + + template + struct referent_storage + { + typedef lower_size::value> align_t; + typedef aligned_storage::value> type; + }; +} + +template +struct rvalue_base_data +{ + rvalue_stage1_data stage1; + + typename detail::referent_storage< + typename add_reference::type + >::type storage; +}; + +template +struct rvalue_data : rvalue_base_data +{ + rvalue_data(rvalue_stage1_data const&); + rvalue_data(void*); + ~rvalue_data(); + private: + typedef typename add_reference::type>::type ref_type; +}; + +// +// Implementataions +// +template +inline rvalue_data::rvalue_data(rvalue_stage1_data const& stage1) +{ + this->stage1 = stage1; +} + +template +inline rvalue_data::rvalue_data(void* convertible) +{ + this->stage1.convertible = convertible; +} + +template +inline rvalue_data::~rvalue_data() +{ + if (this->stage1.convertible == this->storage.bytes) + python::detail::destroy_reference(this->storage.bytes); +} + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/include/boost/python/converter/from_python_function.hpp b/include/boost/python/converter/from_python_function.hpp new file mode 100644 index 00000000..eea96372 --- /dev/null +++ b/include/boost/python/converter/from_python_function.hpp @@ -0,0 +1,18 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef FROM_PYTHON_FUNCTION_DWA2002128_HPP +# define FROM_PYTHON_FUNCTION_DWA2002128_HPP + +# include + +namespace boost { namespace python { namespace converter { + +struct rvalue_stage1_data; +typedef void (*constructor_function)(PyObject* source, rvalue_stage1_data*); + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/include/boost/python/converter/from_python_stage1_data.hpp b/include/boost/python/converter/from_python_stage1_data.hpp new file mode 100644 index 00000000..50fd74ad --- /dev/null +++ b/include/boost/python/converter/from_python_stage1_data.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP +# define FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP + +# include + +namespace boost { namespace python { namespace converter { + +struct rvalue_stage1_data +{ + void* convertible; + constructor_function construct; +}; + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP diff --git a/include/boost/python/converter/lvalue_from_python_chain.hpp b/include/boost/python/converter/lvalue_from_python_chain.hpp new file mode 100644 index 00000000..a58b4309 --- /dev/null +++ b/include/boost/python/converter/lvalue_from_python_chain.hpp @@ -0,0 +1,70 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# define LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// Given T == U*cv&, T == U*, or T == U&, lvalue_from_python_chain +// declares a "templated global reference" to the lvalue from_python +// converter chain for U. The optional bool second argument callback, +// when true, removes special treatment for T == U*cv& so that the +// converter for U* is found. +namespace detail +{ + template + struct ptr_or_ptr_ref_lvalue_from_python_chain + { + static lvalue_from_python_registration*const& value; + }; + + template + lvalue_from_python_registration*const& + ptr_or_ptr_ref_lvalue_from_python_chain::value + = registry::lvalue_converters(pointer_type_id()); + + template + struct ref_lvalue_from_python_chain + { + static lvalue_from_python_registration*const& value; + }; + + template + lvalue_from_python_registration*const& + ref_lvalue_from_python_chain::value + = registry::lvalue_converters(undecorated_type_id()); + + template + struct select_lvalue_from_python_chain + { + BOOST_STATIC_CONSTANT( + bool, ptr + = !callback && boost::python::detail::is_reference_to_pointer::value + || is_pointer::value); + + typedef typename add_reference::type>::type normalized; + + typedef typename mpl::select_if_c< + ptr + , ptr_or_ptr_ref_lvalue_from_python_chain + , ref_lvalue_from_python_chain + >::type type; + }; +} + +template +struct lvalue_from_python_chain + : detail::select_lvalue_from_python_chain::type +{ +}; + +}}} // namespace boost::python::converter + +#endif // LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP diff --git a/include/boost/python/converter/object_manager.hpp b/include/boost/python/converter/object_manager.hpp index 431ef708..974c149b 100755 --- a/include/boost/python/converter/object_manager.hpp +++ b/include/boost/python/converter/object_manager.hpp @@ -10,7 +10,7 @@ # include # include # include -# include +# include # include // Facilities for dealing with types which always manage Python @@ -102,7 +102,7 @@ struct default_object_manager_traits template struct object_manager_traits - : mpl::select_type< + : mpl::if_c< is_handle::value , handle_object_manager_traits , default_object_manager_traits @@ -164,7 +164,7 @@ namespace detail template struct is_object_manager_help { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_object_manager::value , yes_reference_to_object_manager , no_reference_to_object_manager @@ -217,7 +217,7 @@ namespace detail template struct is_reference_to_object_manager { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_reference::value , detail::is_reference_to_object_manager_ref , detail::is_reference_to_object_manager_nonref diff --git a/include/boost/python/converter/pointee_to_python_function.hpp b/include/boost/python/converter/pointee_to_python_function.hpp new file mode 100644 index 00000000..0f1ae99e --- /dev/null +++ b/include/boost/python/converter/pointee_to_python_function.hpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP +# define POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// pointee_to_python_function -- +// +// essentially a "templated global reference" which holds the +// converter for converting a type to Python by-value. We "normalize" +// T by adding "const volatile&" so that fewer global variables and +// associated static initializations are generated. +namespace detail +{ + template + struct pointee_to_python_function_base + { + static to_python_function_t const& value; + }; + + template + to_python_function_t const& + pointee_to_python_function_base::value + = converter::registry::get_to_python_function(pointer_type_id()); +} + +template +struct pointee_to_python_function + : detail::pointee_to_python_function_base< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +}}} // namespace boost::python::converter + +#endif // POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/include/boost/python/converter/return_from_python.hpp b/include/boost/python/converter/return_from_python.hpp index f02f01d9..58d182f0 100755 --- a/include/boost/python/converter/return_from_python.hpp +++ b/include/boost/python/converter/return_from_python.hpp @@ -63,13 +63,13 @@ namespace detail BOOST_STATIC_CONSTANT( bool, ref = is_reference::value); - typedef typename mpl::select_type< + typedef typename mpl::if_c< obj_mgr , return_object_manager_from_python - , typename mpl::select_type< + , typename mpl::if_c< ptr , return_pointer_from_python - , typename mpl::select_type< + , typename mpl::if_c< ref , return_reference_from_python , return_rvalue_from_python diff --git a/include/boost/python/converter/rvalue_from_python_chain.hpp b/include/boost/python/converter/rvalue_from_python_chain.hpp new file mode 100644 index 00000000..c57ef564 --- /dev/null +++ b/include/boost/python/converter/rvalue_from_python_chain.hpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# define RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + template + struct rvalue_from_python_chain_impl + { + static rvalue_from_python_registration*const& value; + }; + + template + rvalue_from_python_registration*const& rvalue_from_python_chain_impl::value + = registry::rvalue_converters(undecorated_type_id()); +} + +template +struct rvalue_from_python_chain + : detail::rvalue_from_python_chain_impl< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +}}} // namespace boost::python::converter + +#endif // RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP diff --git a/include/boost/python/converter/rvalue_from_python_data.hpp b/include/boost/python/converter/rvalue_from_python_data.hpp index 72ea7bd7..16c9d44b 100644 --- a/include/boost/python/converter/rvalue_from_python_data.hpp +++ b/include/boost/python/converter/rvalue_from_python_data.hpp @@ -10,6 +10,8 @@ # include # include # include +# include +# include # include // Data management for potential rvalue conversions from Python to C++ diff --git a/include/boost/python/converter/smart_ptr.hpp b/include/boost/python/converter/smart_ptr.hpp new file mode 100644 index 00000000..bae4c2b8 --- /dev/null +++ b/include/boost/python/converter/smart_ptr.hpp @@ -0,0 +1,70 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef SMART_PTR_DWA2002123_HPP +# define SMART_PTR_DWA2002123_HPP + +# include +# include +namespace boost { namespace python { namespace converter { + +template +class smart_ptr_wrapper + : wrapper +{ + smart_ptr_wrapper(ref const& type_) + : m_class_object(type_) + { + assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); + } + + PyObject* convert(Pointer x) const; + + private: + ref m_class_object; + + smart_ptr_converters(); +} + + +// +// implementations +// + +template +PyObject* smart_ptr_wrapper::convert(Pointer x) const +{ + if (x.operator->() == 0) + return detail::none(); + + // Don't call the type to do the construction, since that + // would require the registration of an __init__ copy + // constructor. Instead, just construct the object in place. + PyObject* raw_result = (PyObject*)PyObject_New( + instance, (PyTypeObject*)m_class_object.get()); + + if (raw_result == 0) + return 0; + + // Everything's OK; Bypass NULL checks but guard against + // exceptions. + ref result(raw_result, ref::allow_null()); + + // Build a value_holder to contain the object using the copy + // constructor + objects::pointer_holder* + p = new objects::pointer_holder(x); + + // Install it in the instance + p->install(raw_result); + + // Return the new result + return result.release(); +} + + +}}} // namespace boost::python::converter + +#endif // SMART_PTR_DWA2002123_HPP diff --git a/include/boost/python/converter/to_python_function.hpp b/include/boost/python/converter/to_python_function.hpp new file mode 100644 index 00000000..ff3891e2 --- /dev/null +++ b/include/boost/python/converter/to_python_function.hpp @@ -0,0 +1,50 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef TO_PYTHON_FUNCTION_DWA2002128_HPP +# define TO_PYTHON_FUNCTION_DWA2002128_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// to_python_function -- +// +// essentially a "templated global reference" which holds the +// converter for converting a type to Python by-value. We "normalize" +// T by adding "const volatile&" so that fewer global variables and +// associated static initializations are generated. +namespace detail +{ + template + struct to_python_function_base + { + static to_python_function_t const& value; + }; + + template + to_python_function_t const& + to_python_function_base::value + = converter::registry::get_to_python_function(undecorated_type_id()); +} + +template +struct to_python_function + : detail::to_python_function_base< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp new file mode 100644 index 00000000..f1bfa8a3 --- /dev/null +++ b/include/boost/python/converter/type_id.hpp @@ -0,0 +1,176 @@ +// Copyright David Abrahams 2001. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef TYPE_ID_DWA20011127_HPP +# define TYPE_ID_DWA20011127_HPP +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + + +namespace boost { namespace python { namespace converter { + +// for this compiler at least, cross-shared-library type_info +// comparisons don't work, so use typeid(x).name() instead. It's not +// yet clear what the best default strategy is. +# if defined(__GNUC__) && __GNUC__ >= 3 +# define BOOST_PYTHON_TYPE_ID_NAME +# endif + +// type ids which represent the same information as std::type_info +// (i.e. the top-level reference and cv-qualifiers are stripped), but +// which works across shared libraries. +struct undecorated_type_id_t : totally_ordered +{ + undecorated_type_id_t(std::type_info const&); + + // default constructor needed to build arrays, etc. + undecorated_type_id_t(); + + bool operator<(undecorated_type_id_t const& rhs) const; + bool operator==(undecorated_type_id_t const& rhs) const; + + char const* name() const; + friend BOOST_PYTHON_DECL std::ostream& operator<<( + std::ostream&, undecorated_type_id_t const&); + + private: // data members +# ifdef BOOST_PYTHON_TYPE_ID_NAME + typedef char const* base_id_t; +# else + typedef std::type_info const* base_id_t; +# endif + + base_id_t m_base_type; +}; + +struct type_id_t : totally_ordered +{ + enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; + + type_id_t(undecorated_type_id_t, decoration = decoration()); + + bool operator<(type_id_t const& rhs) const; + bool operator==(type_id_t const& rhs) const; + + friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); + + operator undecorated_type_id_t const&() const; + private: // type + typedef undecorated_type_id_t base_id_t; + + private: // data members + decoration m_decoration; + base_id_t m_base_type; +}; + +template +inline undecorated_type_id_t undecorated_type_id(boost::type* = 0) +{ + return undecorated_type_id_t( +# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) + typeid(T) +# else // strip the decoration which msvc and Intel mistakenly leave in + python::detail::msvc_typeid() +# endif + ); +} + +template +inline type_id_t type_id(boost::type* = 0) +{ + return type_id_t( + undecorated_type_id() + , type_id_t::decoration( + (is_const::value || python::detail::is_reference_to_const::value + ? type_id_t::const_ : 0) + | (is_volatile::value || python::detail::is_reference_to_volatile::value + ? type_id_t::volatile_ : 0) + | (is_reference::value ? type_id_t::reference : 0) + ) + ); +} + +inline undecorated_type_id_t::undecorated_type_id_t(std::type_info const& id) + : m_base_type( +# ifdef BOOST_PYTHON_TYPE_ID_NAME + id.name() +# else + &id +# endif + ) +{ +} + +inline undecorated_type_id_t::undecorated_type_id_t() + : m_base_type() +{ +} + +inline type_id_t::type_id_t(undecorated_type_id_t base_t, decoration decoration) + : m_decoration(decoration) + , m_base_type(base_t) +{ +} + +inline bool undecorated_type_id_t::operator<(undecorated_type_id_t const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return std::strcmp(m_base_type, rhs.m_base_type) < 0; +# else + return m_base_type->before(*rhs.m_base_type); +# endif +} + +inline bool type_id_t::operator<(type_id_t const& rhs) const +{ + return m_decoration < rhs.m_decoration + || m_decoration == rhs.m_decoration + && m_base_type < rhs.m_base_type; +} + +inline bool undecorated_type_id_t::operator==(undecorated_type_id_t const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return !std::strcmp(m_base_type, rhs.m_base_type); +# else + return *m_base_type == *rhs.m_base_type; +# endif +} + +inline bool type_id_t::operator==(type_id_t const& rhs) const +{ + return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type; +} + +inline type_id_t::operator undecorated_type_id_t const&() const +{ + return m_base_type; +} + +inline char const* undecorated_type_id_t::name() const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return m_base_type; +# else + return m_base_type->name(); +# endif +} + + +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, undecorated_type_id_t const&); +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); + +}}} // namespace boost::python::converter + +#endif // TYPE_ID_DWA20011127_HPP diff --git a/include/boost/python/copy_const_reference.hpp b/include/boost/python/copy_const_reference.hpp index b2fdd61f..8eecd2ce 100644 --- a/include/boost/python/copy_const_reference.hpp +++ b/include/boost/python/copy_const_reference.hpp @@ -6,7 +6,7 @@ #ifndef COPY_CONST_REFERENCE_DWA2002131_HPP # define COPY_CONST_REFERENCE_DWA2002131_HPP # include -# include +# include # include namespace boost { namespace python { @@ -28,7 +28,7 @@ struct copy_const_reference template struct apply { - typedef typename mpl::select_type< + typedef typename mpl::if_c< detail::is_reference_to_const::value , to_python_value , detail::copy_const_reference_expects_a_const_reference_return_type diff --git a/include/boost/python/copy_mutable_reference.hpp b/include/boost/python/copy_mutable_reference.hpp new file mode 100644 index 00000000..acf170d0 --- /dev/null +++ b/include/boost/python/copy_mutable_reference.hpp @@ -0,0 +1,41 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef COPY_MUTABLE_REFERENCE_DWA2002131_HPP +# define COPY_MUTABLE_REFERENCE_DWA2002131_HPP +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct copy_mutable_reference_expects_a_reference_to_non_const_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template struct to_python_value; + +struct copy_mutable_reference +{ + template + struct apply + { + typedef typename mpl::select_if_c< + detail::is_reference_to_non_const::value + , to_python_value + , detail::copy_mutable_reference_expects_a_reference_to_non_const_return_type + >::type type; + }; +}; + +}} // namespace boost::python + +#endif // COPY_MUTABLE_REFERENCE_DWA2002131_HPP diff --git a/include/boost/python/copy_non_const_reference.hpp b/include/boost/python/copy_non_const_reference.hpp index 6f53fbdc..53c576e0 100644 --- a/include/boost/python/copy_non_const_reference.hpp +++ b/include/boost/python/copy_non_const_reference.hpp @@ -6,7 +6,7 @@ #ifndef COPY_NON_CONST_REFERENCE_DWA2002131_HPP # define COPY_NON_CONST_REFERENCE_DWA2002131_HPP # include -# include +# include # include namespace boost { namespace python { @@ -28,7 +28,7 @@ struct copy_non_const_reference template struct apply { - typedef typename mpl::select_type< + typedef typename mpl::if_c< boost::python::detail::is_reference_to_non_const::value , to_python_value , detail::copy_non_const_reference_expects_a_non_const_reference_return_type diff --git a/include/boost/python/default_call_policies.hpp b/include/boost/python/default_call_policies.hpp index f0b69255..f964990f 100644 --- a/include/boost/python/default_call_policies.hpp +++ b/include/boost/python/default_call_policies.hpp @@ -6,7 +6,7 @@ #ifndef DEFAULT_CALL_POLICIES_DWA2002131_HPP # define DEFAULT_CALL_POLICIES_DWA2002131_HPP # include -# include +# include # include # include @@ -50,7 +50,7 @@ struct default_result_converter { BOOST_STATIC_CONSTANT(bool, is_illegal = is_reference::value || is_pointer::value); - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_illegal , detail::specify_a_result_policy_to_wrap_functions_returning , boost::python::to_python_value< diff --git a/include/boost/python/detail/borrowed_ptr.hpp b/include/boost/python/detail/borrowed_ptr.hpp index dc50c634..6b35c862 100755 --- a/include/boost/python/detail/borrowed_ptr.hpp +++ b/include/boost/python/detail/borrowed_ptr.hpp @@ -8,7 +8,7 @@ # include # include -# include +# include # include # include # include @@ -77,7 +77,7 @@ typedef char (&no_borrowed_ptr_t)[2]; no_borrowed_ptr_t is_borrowed_ptr_test(...); template -typename mpl::select_type< +typename mpl::if_c< is_pointer::value , T , int diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index 322e1342..2ade2a11 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -21,8 +21,6 @@ # include # include -# // temp: include - # include # include # include diff --git a/include/boost/python/detail/convertible.hpp b/include/boost/python/detail/convertible.hpp index 4ab58d94..74440090 100755 --- a/include/boost/python/detail/convertible.hpp +++ b/include/boost/python/detail/convertible.hpp @@ -7,7 +7,7 @@ # define CONVERTIBLE_DWA2002614_HPP # if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 241 -# include +# include # include # endif @@ -26,7 +26,7 @@ struct convertible static inline yes_convertible check(Target) { return 0; } # else template - static inline typename mpl::select_type< + static inline typename mpl::if_c< is_convertible::value , yes_convertible , no_convertible diff --git a/include/boost/python/detail/defaults_def.hpp b/include/boost/python/detail/defaults_def.hpp index 7efbcb70..9c79d926 100644 --- a/include/boost/python/detail/defaults_def.hpp +++ b/include/boost/python/detail/defaults_def.hpp @@ -14,10 +14,10 @@ #include #include -#include +#include +#include #include #include -#include #include #include #include @@ -86,7 +86,7 @@ static void name_space_def( // template // inline void // define_stub_function( -// char const* name, StubsT s, NameSpaceT& name_space, boost::mpl::int_t) +// char const* name, StubsT s, NameSpaceT& name_space, mpl::int_c) // { // name_space.def(name, &StubsT::func_N); // } @@ -186,9 +186,9 @@ struct define_stub_function {}; // is a typelist that specifies the return type, the class (for member // functions, and the arguments. Here are some SigT examples: // -// int foo(int) mpl::type_list -// void bar(int, int) mpl::type_list -// void C::foo(int) mpl::type_list +// int foo(int) mpl::list +// void bar(int, int) mpl::list +// void C::foo(int) mpl::list // /////////////////////////////////////////////////////////////////////////////// template @@ -201,19 +201,18 @@ struct define_stub_function {}; SigT sig, char const* doc) { - typedef typename boost::python::detail::type_at<0, SigT>::type nth_type; + typedef typename mpl::front::type return_type; typedef typename StubsT::v_type v_type; typedef typename StubsT::nv_type nv_type; - typedef typename mpl::select_type< - boost::is_same::value + typedef typename mpl::if_c< + boost::is_same::value , v_type , nv_type >::type stubs_type; BOOST_STATIC_ASSERT( - (stubs_type::max_args) <= - boost::python::detail::type_list_size::value); + (stubs_type::max_args) <= mpl::size::value); typedef typename stubs_type::template gen gen_type; define_with_defaults_helper::def diff --git a/include/boost/python/detail/defaults_gen.hpp b/include/boost/python/detail/defaults_gen.hpp index b1ed0125..78808424 100644 --- a/include/boost/python/detail/defaults_gen.hpp +++ b/include/boost/python/detail/defaults_gen.hpp @@ -23,7 +23,8 @@ #include #include #include -#include +#include +#include namespace boost { namespace python { namespace detail { @@ -39,23 +40,23 @@ struct func_stubs_base {}; /////////////////////////////////////////////////////////////////////////////// #define BPL_IMPL_TYPEDEF_GEN(z, INDEX, DATA) \ - typedef typename boost::python::detail::type_at \ + typedef typename ::boost::mpl::at_c \ < \ - BOOST_PP_ADD(INDEX, DATA), \ + BOOST_PP_ADD_D(1, INDEX, DATA), \ SigT \ >::type BOOST_PP_CAT(T, INDEX); \ #define BPL_IMPL_FUNC_WRAPPER_GEN(z, index, DATA) \ static RT BOOST_PP_CAT(func_, index) ( \ BOOST_PYTHON_BINARY_ENUM( \ - BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), T, arg) \ + BOOST_PP_ADD_D(1, BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), T, arg) \ ) \ { \ BOOST_PP_TUPLE_ELEM(3, 2, DATA) \ BOOST_PP_TUPLE_ELEM(3, 0, DATA) \ ( \ BOOST_PP_ENUM_PARAMS( \ - BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), \ + BOOST_PP_ADD_D(1, BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), \ arg \ ) \ ); \ @@ -70,7 +71,7 @@ struct func_stubs_base {}; template \ struct gen { \ \ - typedef typename boost::python::detail::type_at<0, SigT>::type RT; \ + typedef typename ::boost::mpl::front::type RT; \ \ BOOST_PP_REPEAT_2ND \ ( \ @@ -83,7 +84,7 @@ struct func_stubs_base {}; ( \ BOOST_PP_INC(N_DFLTS), \ BPL_IMPL_FUNC_WRAPPER_GEN, \ - (FNAME, BOOST_PP_SUB(N_ARGS, N_DFLTS), RETURN) \ + (FNAME, BOOST_PP_SUB_D(1, N_ARGS, N_DFLTS), RETURN) \ ) \ }; \ }; \ @@ -92,14 +93,14 @@ struct func_stubs_base {}; #define BPL_IMPL_MEM_FUNC_WRAPPER_GEN(z, index, DATA) \ static RT BOOST_PP_CAT(func_, index) ( \ ClassT& obj BOOST_PP_COMMA_IF( \ - BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index)) \ + BOOST_PP_ADD_D(1, BOOST_PP_TUPLE_ELEM(3, 1, DATA), index)) \ BOOST_PYTHON_BINARY_ENUM( \ - BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), T, arg) \ + BOOST_PP_ADD_D(1, BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), T, arg) \ ) \ { \ BOOST_PP_TUPLE_ELEM(3, 2, DATA) obj.BOOST_PP_TUPLE_ELEM(3, 0, DATA)( \ BOOST_PP_ENUM_PARAMS( \ - BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), arg \ + BOOST_PP_ADD_D(1, BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), arg \ ) \ ); \ } @@ -113,8 +114,8 @@ struct func_stubs_base {}; template \ struct gen { \ \ - typedef typename boost::python::detail::type_at<0, SigT>::type RT; \ - typedef typename boost::python::detail::type_at<1, SigT>::type ClassT; \ + typedef typename ::boost::mpl::front::type RT; \ + typedef typename ::boost::mpl::at_c<1, SigT>::type ClassT; \ \ BOOST_PP_REPEAT_2ND \ ( \ @@ -127,7 +128,7 @@ struct func_stubs_base {}; ( \ BOOST_PP_INC(N_DFLTS), \ BPL_IMPL_MEM_FUNC_WRAPPER_GEN, \ - (FNAME, BOOST_PP_SUB(N_ARGS, N_DFLTS), RETURN) \ + (FNAME, BOOST_PP_SUB_D(1, N_ARGS, N_DFLTS), RETURN) \ ) \ }; \ }; @@ -224,11 +225,11 @@ struct func_stubs_base {}; // template // struct gen { // -// typedef typename mpl::at<0, SigT>::type RT; -// typedef typename mpl::at<1, SigT>::type T0; -// typedef typename mpl::at<2, SigT>::type T1; -// typedef typename mpl::at<3, SigT>::type T2; -// typedef typename mpl::at<4, SigT>::type T3; +// typedef typename ::boost::mpl::at_c<0, SigT>::type RT; +// typedef typename ::boost::mpl::at_c<1, SigT>::type T0; +// typedef typename ::boost::mpl::at_c<2, SigT>::type T1; +// typedef typename ::boost::mpl::at_c<3, SigT>::type T2; +// typedef typename ::boost::mpl::at_c<4, SigT>::type T3; // // static RT func_0(T0 arg0) // { return foo(arg0); } @@ -265,7 +266,7 @@ struct func_stubs_base {}; FNAME, \ GENERATOR_NAME, \ MAX_ARGS, \ - BOOST_PP_SUB(MAX_ARGS, MIN_ARGS) \ + BOOST_PP_SUB_D(1, MAX_ARGS, MIN_ARGS) \ ) #define BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(GENERATOR_NAME, FNAME, MIN_ARGS, MAX_ARGS) \ @@ -274,7 +275,7 @@ struct func_stubs_base {}; FNAME, \ GENERATOR_NAME, \ MAX_ARGS, \ - BOOST_PP_SUB(MAX_ARGS, MIN_ARGS) \ + BOOST_PP_SUB_D(1, MAX_ARGS, MIN_ARGS) \ ) // deprecated macro names (to be removed) diff --git a/include/boost/python/detail/destroy.hpp b/include/boost/python/detail/destroy.hpp index 89e82f73..7b107550 100644 --- a/include/boost/python/detail/destroy.hpp +++ b/include/boost/python/detail/destroy.hpp @@ -67,8 +67,8 @@ inline void destroy_referent_impl(void* p, T& (*)()) // note: cv-qualification needed for MSVC6 // must come *before* T for metrowerks value_destroyer< - (boost::is_array::value) - , (boost::has_trivial_destructor::value) + (boost::is_array::value) + ,(boost::has_trivial_destructor::value) >::execute((const volatile T*)p); } diff --git a/include/boost/python/detail/indirect_traits.hpp b/include/boost/python/detail/indirect_traits.hpp index faabecc2..c6f8bcc7 100644 --- a/include/boost/python/detail/indirect_traits.hpp +++ b/include/boost/python/detail/indirect_traits.hpp @@ -5,11 +5,17 @@ // to its suitability for any purpose. #ifndef INDIRECT_TRAITS_DWA2002131_HPP # define INDIRECT_TRAITS_DWA2002131_HPP -# include -# include -# include -# include -# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include namespace boost { namespace python { namespace detail { @@ -184,7 +190,7 @@ typedef char (&outer_no_type)[1]; template struct is_const_help { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_const::value , inner_yes_type , inner_no_type @@ -194,7 +200,7 @@ struct is_const_help template struct is_volatile_help { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_volatile::value , inner_yes_type , inner_no_type @@ -204,7 +210,7 @@ struct is_volatile_help template struct is_pointer_help { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_pointer::value , inner_yes_type , inner_no_type @@ -214,7 +220,7 @@ struct is_pointer_help template struct is_class_help { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_class::value , inner_yes_type , inner_no_type @@ -228,7 +234,7 @@ struct is_reference_to_function static T t; BOOST_STATIC_CONSTANT( bool, value - = sizeof(::boost::detail::is_function_tester(t)) == sizeof(::boost::type_traits::yes_type)); + = sizeof(::boost::type_traits::is_function_ptr_tester(t)) == sizeof(::boost::type_traits::yes_type)); # endif template @@ -237,7 +243,7 @@ struct is_pointer_to_function static T t; BOOST_STATIC_CONSTANT( bool, value - = sizeof(::boost::detail::is_function_tester(t)) == sizeof(::boost::type_traits::yes_type)); + = sizeof(::boost::type_traits::is_function_ptr_tester(t)) == sizeof(::boost::type_traits::yes_type)); }; struct false_helper1 diff --git a/include/boost/python/detail/make_tuple.hpp b/include/boost/python/detail/make_tuple.hpp index 41fcaa37..07cd9903 100644 --- a/include/boost/python/detail/make_tuple.hpp +++ b/include/boost/python/detail/make_tuple.hpp @@ -22,7 +22,7 @@ make_tuple(BOOST_PYTHON_BINARY_ENUM(N, A, const& a)) { tuple result((detail::new_reference)::PyTuple_New(N)); - BOOST_PP_REPEAT(N, BOOST_PYTHON_MAKE_TUPLE_ARG, _) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_MAKE_TUPLE_ARG, _) return result; } diff --git a/include/boost/python/detail/member_function_cast.hpp b/include/boost/python/detail/member_function_cast.hpp index 491e6711..f143abd0 100644 --- a/include/boost/python/detail/member_function_cast.hpp +++ b/include/boost/python/detail/member_function_cast.hpp @@ -11,7 +11,7 @@ # include -# include +# include # include # include @@ -71,7 +71,7 @@ struct member_function_cast # ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING : member_function_cast_impl # else - : mpl::select_type< + : mpl::if_c< is_member_function_pointer::value , member_function_cast_impl , non_member_function_cast_impl diff --git a/include/boost/python/detail/msvc_typeinfo.hpp b/include/boost/python/detail/msvc_typeinfo.hpp index 21e47389..b50922b7 100644 --- a/include/boost/python/detail/msvc_typeinfo.hpp +++ b/include/boost/python/detail/msvc_typeinfo.hpp @@ -8,8 +8,10 @@ #include #include -#include -#include +#include +#include +#include +#include // // Fix for MSVC's broken typeid() implementation which doesn't strip // decoration. This fix doesn't handle cv-qualified array types. It diff --git a/include/boost/python/detail/preprocessor.hpp b/include/boost/python/detail/preprocessor.hpp index 89d1d26d..45e307d4 100644 --- a/include/boost/python/detail/preprocessor.hpp +++ b/include/boost/python/detail/preprocessor.hpp @@ -30,6 +30,10 @@ # define BOOST_PYTHON_MAX_ARITY 15 # endif +# ifndef BOOST_PYTHON_MAX_BASES +# define BOOST_PYTHON_MAX_BASES 10 +# endif + # define BOOST_PYTHON_CV_QUALIFIER(i) \ BOOST_PYTHON_APPLY( \ BOOST_PP_TUPLE_ELEM(4, i, BOOST_PYTHON_CV_QUALIFIER_I) \ diff --git a/include/boost/python/detail/python_library_include.hpp b/include/boost/python/detail/python_library_include.hpp new file mode 100644 index 00000000..d2b78c6e --- /dev/null +++ b/include/boost/python/detail/python_library_include.hpp @@ -0,0 +1,183 @@ +#error obsolete +/* + * + * Copyright (c) 1998-2000 + * Dr John Maddock + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Dr John Maddock makes no representations + * about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_libary_include.hpp + * VERSION see + * DESCRIPTION: Automatic library inclusion for Borland/Microsoft compilers. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + + +#ifndef BOOST_REGEX_LIBRARY_INCLUDE_HPP +#define BOOST_REGEX_LIBRARY_INCLUDE_HPP +#ifndef BOOST_REGEX_NO_LIB + +#if defined(BOOST_MSVC) && !defined(BOOST_REGEX_BUILD_DLL) +#ifdef __SGI_STL_PORT + #ifdef _DLL + // All these are multithreaded: + #if defined(_DEBUG) && defined(__STL_DEBUG) + #pragma comment(lib, "vc6-stlport-re300ddl.lib") + #elif defined(_DEBUG) + #pragma comment(lib, "vc6-stlport-re300dl.lib") + #elif defined(BOOST_REGEX_STATIC_LINK) + // static regex lib, dll runtime + #pragma comment(lib, "vc6-stlport-re300ls.lib") + #else // DEBUG + #pragma comment(lib, "vc6-stlport-re300l.lib") + #endif // _DEBUG + #else // _DLL + #ifdef _MT + #if defined(_DEBUG) && defined(__STL_DEBUG) + #pragma comment(lib, "vc6-stlport-re300ddm.lib") + #elif defined(_DEBUG) + #pragma comment(lib, "vc6-stlport-re300dm.lib") + #else //_DEBUG + #pragma comment(lib, "vc6-stlport-re300m.lib") + #endif //_DEBUG + #else //_MT + // STLPort does not support single threaded builds: + #error STLPort does not support single threaded builds + #endif //_MT + #endif //_DLL +#elif _MSC_VER < 1300 + #ifdef _DLL + // All these are multithreaded: + #ifdef _DEBUG + #pragma comment(lib, "vc6-re300dl.lib") + #elif defined(BOOST_REGEX_STATIC_LINK) + // static regex lib, dll runtime + #pragma comment(lib, "vc6-re300ls.lib") + #else // DEBUG + #pragma comment(lib, "vc6-re300l.lib") + #endif // _DEBUG + #else // _DLL + #ifdef _MT + #ifdef _DEBUG + #pragma comment(lib, "vc6-re300dm.lib") + #else //_DEBUG + #pragma comment(lib, "vc6-re300m.lib") + #endif //_DEBUG + #else //_MT + #ifdef _DEBUG + #pragma comment(lib, "vc6-re300d.lib") + #else //_DEBUG + #pragma comment(lib, "vc6-re300.lib") + #endif //_DEBUG + #endif //_MT + #endif //_DLL +#else + #ifdef _DLL + // All these are multithreaded: + #ifdef _DEBUG + #pragma comment(lib, "vc7-re300dl.lib") + #elif defined(BOOST_REGEX_STATIC_LINK) + // static regex lib, dll runtime + #pragma comment(lib, "vc7-re300ls.lib") + #else // DEBUG + #pragma comment(lib, "vc7-re300l.lib") + #endif // _DEBUG + #else // _DLL + #ifdef _MT + #ifdef _DEBUG + #pragma comment(lib, "vc7-re300dm.lib") + #else //_DEBUG + #pragma comment(lib, "vc7-re300m.lib") + #endif //_DEBUG + #else //_MT + #ifdef _DEBUG + #pragma comment(lib, "vc7-re300d.lib") + #else //_DEBUG + #pragma comment(lib, "vc7-re300.lib") + #endif //_DEBUG + #endif //_MT + #endif //_DLL +#endif // __SGI_STL_PORT +#endif //BOOST_MSVC + + +#if defined(__BORLANDC__) && !defined(BOOST_REGEX_BUILD_DLL) + + #if __BORLANDC__ < 0x550 + + #ifdef BOOST_REGEX_USE_VCL + + #ifdef _RTLDLL + #pragma comment(lib, "bcb4re300lv.lib") + #else + #pragma comment(lib, "bcb4re300v.lib") + #endif + + #else // VCL + + #ifdef _RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb4re300lm.lib") + #else // __MT__ + #pragma comment(lib, "bcb4re300l.lib") + #endif // __MT__ + #else //_RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb4re300m.lib") + #else // __MT__ + #pragma comment(lib, "bcb4re300.lib") + #endif // __MT__ + #endif // _RTLDLL + + #endif // VCL + + #else // C++ Builder 5: + + #ifdef BOOST_REGEX_USE_VCL + + #ifdef _RTLDLL + #pragma comment(lib, "bcb5re300lv.lib") + #else + #pragma comment(lib, "bcb5re300v.lib") + #endif + + #else // VCL + + #ifdef _RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb5re300lm.lib") + #else // __MT__ + #pragma comment(lib, "bcb5re300l.lib") + #endif // __MT__ + #else //_RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb5re300m.lib") + #else // __MT__ + #pragma comment(lib, "bcb5re300.lib") + #endif // __MT__ + #endif // _RTLDLL + + #endif // VCL + + #endif + +#endif //__BORLANDC__ + +#endif //BOOST_REGEX_NO_LIB + +#endif // BOOST_REGEX_LIBRARY_INCLUDE_HPP + + + + diff --git a/include/boost/python/detail/referent_storage.hpp b/include/boost/python/detail/referent_storage.hpp index aebacf64..b93d888f 100644 --- a/include/boost/python/detail/referent_storage.hpp +++ b/include/boost/python/detail/referent_storage.hpp @@ -5,7 +5,7 @@ // to its suitability for any purpose. #ifndef REFERENT_STORAGE_DWA200278_HPP # define REFERENT_STORAGE_DWA200278_HPP -# include +# include # include namespace boost { namespace python { namespace detail { @@ -16,7 +16,7 @@ typedef int (alignment_dummy::*member_ptr); typedef int (alignment_dummy::*member_function_ptr)(); # define BOOST_PYTHON_ALIGNER(T, n) \ - typename mpl::select_type< \ + typename mpl::if_c< \ sizeof(T) <= size, T, char>::type t##n // Storage for size bytes, aligned to all fundamental types no larger than size diff --git a/include/boost/python/detail/result.hpp b/include/boost/python/detail/result.hpp index 84f6a554..6ec95fb7 100755 --- a/include/boost/python/detail/result.hpp +++ b/include/boost/python/detail/result.hpp @@ -14,7 +14,7 @@ # include # include -# include +# include # include # include @@ -60,7 +60,7 @@ struct void_type template struct result_result { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_class::value , get_result_type , void_type diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index 495a8564..9ab87c43 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -96,7 +96,7 @@ struct returning , PyObject*, P const* policies) { // check that each of the arguments is convertible - BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CHECK_CONVERSION, nil) // find the result converter typedef typename P::result_converter result_converter; @@ -104,7 +104,7 @@ struct returning if (!cr.convertible() || !policies->precall(args_)) return 0; PyObject* result = cr( - (*pf)(BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)) + (*pf)(BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CALL_ARGS, nil)) ); return policies->postcall(args_, result); } @@ -117,11 +117,11 @@ struct returning , PyObject*, P const* policies) { // check that each of the arguments is convertible - BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CHECK_CONVERSION, nil) if (!policies->precall(args_)) return 0; - (*pf)(BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)); + (*pf)(BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CALL_ARGS, nil)); return policies->postcall(args_, detail::none()); } # endif // returning void / non-void @@ -168,7 +168,7 @@ struct returning return 0; // unroll a loop for the rest of them - BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CHECK_CONVERSION, nil) // find the result converter typedef typename P::result_converter result_converter; @@ -177,7 +177,7 @@ struct returning return 0; PyObject* result = cr( ((ct(PyTuple_GET_ITEM(args_, 0))).*pmf)( - BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CALL_ARGS, nil)) ); return policies->postcall(args_, result); } @@ -196,13 +196,13 @@ struct returning return 0; // unroll a loop for the rest of them - BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CHECK_CONVERSION, nil) if (!policies->precall(args_)) return 0; ((ct(PyTuple_GET_ITEM(args_, 0))).*pmf)( - BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)); + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_CALL_ARGS, nil)); return policies->postcall(args_, detail::none()); } # endif diff --git a/include/boost/python/detail/type_list.hpp b/include/boost/python/detail/type_list.hpp index 66ac3857..4a09c0be 100644 --- a/include/boost/python/detail/type_list.hpp +++ b/include/boost/python/detail/type_list.hpp @@ -3,14 +3,38 @@ // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -#ifndef TYPE_LIST_DWA200222_HPP -# define TYPE_LIST_DWA200222_HPP -# include +#ifndef TYPE_LIST_DWA2002913_HPP +# define TYPE_LIST_DWA2002913_HPP -namespace boost { namespace python { namespace detail { +# include +# include +# include -struct empty_list : boost::mpl::type_list<>::type {}; +# if BOOST_PYTHON_MAX_ARITY + 2 > BOOST_PYTHON_MAX_BASES +# define BOOST_PYTHON_LIST_SIZE BOOST_PP_INC(BOOST_PP_INC(BOOST_PYTHON_MAX_ARITY)) +# else +# define BOOST_PYTHON_BASE_LIST_SIZE BOOST_PYTHON_MAX_BASES +# endif -}}} // namespace boost::python::detail +// Compute the MPL list header to use for lists up to BOOST_PYTHON_LIST_SIZE in length +# if BOOST_PYTHON_LIST_SIZE > 48 +# error Arities above 48 not supported by Boost.Python due to MPL internal limit +# elif BOOST_PYTHON_LIST_SIZE > 38 +# include +# elif BOOST_PYTHON_LIST_SIZE > 28 +# include +# elif BOOST_PYTHON_LIST_SIZE > 18 +# include +# elif BOOST_PYTHON_LIST_SIZE > 8 +# include +# else +# include +# endif -#endif // TYPE_LIST_DWA200222_HPP +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# include +# else +# include +# endif + +#endif // TYPE_LIST_DWA2002913_HPP diff --git a/include/boost/python/detail/type_list_impl.hpp b/include/boost/python/detail/type_list_impl.hpp new file mode 100644 index 00000000..2a02851f --- /dev/null +++ b/include/boost/python/detail/type_list_impl.hpp @@ -0,0 +1,55 @@ +#ifndef BOOST_PP_IS_ITERATING +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +# ifndef TYPE_LIST_IMPL_DWA2002913_HPP +# define TYPE_LIST_IMPL_DWA2002913_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +template +struct type_list + : BOOST_PP_CAT(mpl::list,BOOST_PYTHON_LIST_SIZE) +{ +}; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PP_DEC(BOOST_PYTHON_LIST_SIZE), )) +# include BOOST_PP_ITERATE() + + +}}} // namespace boost::python::detail + +# endif // TYPE_LIST_IMPL_DWA2002913_HPP + +#else // BOOST_PP_IS_ITERATING + +# define N BOOST_PP_ITERATION() +# define BOOST_PYTHON_VOID_ARGS BOOST_PP_SUB_D(1,BOOST_PYTHON_LIST_SIZE,N) + +template < + BOOST_PP_ENUM_PARAMS(N, class T) + > +struct type_list< + BOOST_PP_ENUM_PARAMS(N, T) + BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM( + BOOST_PYTHON_VOID_ARGS, BOOST_PYTHON_FIXED, mpl::void_) + > + : BOOST_PP_CAT(mpl::list,N) +{ +}; + +# undef BOOST_PYTHON_VOID_ARGS +# undef N + +#endif // BOOST_PP_IS_ITERATING diff --git a/include/boost/python/detail/type_list_impl_no_pts.hpp b/include/boost/python/detail/type_list_impl_no_pts.hpp new file mode 100644 index 00000000..1c4d392c --- /dev/null +++ b/include/boost/python/detail/type_list_impl_no_pts.hpp @@ -0,0 +1,101 @@ +#ifndef BOOST_PP_IS_ITERATING +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +# ifndef TYPE_LIST_IMPL_NO_PTS_DWA2002913_HPP +# define TYPE_LIST_IMPL_NO_PTS_DWA2002913_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +template< typename T > +struct is_list_arg +{ + enum { value = true }; +}; + +template<> +struct is_list_arg +{ + enum { value = false }; +}; + +template struct type_list_impl_chooser; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_LIST_SIZE, )) +# include BOOST_PP_ITERATE() + +# define BOOST_PYTHON_PLUS() + +# define BOOST_PYTHON_IS_LIST_ARG(z, n, data) \ + BOOST_PP_IF(n, BOOST_PYTHON_PLUS, BOOST_PP_EMPTY)() \ + is_list_arg< BOOST_PP_CAT(T,n) >::value + +template< + BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_LIST_SIZE, class T) + > +struct type_list_count_args +{ + enum { value = + BOOST_PP_REPEAT_1(BOOST_PYTHON_LIST_SIZE, BOOST_PYTHON_IS_LIST_ARG, _) + }; +}; + +# undef BOOST_PYTHON_IS_LIST_ARG +# undef BOOST_PYTHON_PLUS + +template< + BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_LIST_SIZE, class T) + > +struct type_list_impl +{ + typedef type_list_count_args< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_LIST_SIZE,T) > arg_num_; + typedef typename detail::type_list_impl_chooser< arg_num_::value > + ::template result_< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_LIST_SIZE,T) >::type type; +}; + +template< + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_LIST_SIZE, class T, mpl::void_) + > +struct type_list + : detail::type_list_impl< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_LIST_SIZE,T) >::type +{ + typedef typename detail::type_list_impl< + BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_LIST_SIZE,T) + >::type type; +}; + +}}} // namespace boost::python::detail + +# endif // TYPE_LIST_IMPL_NO_PTS_DWA2002913_HPP + +#else // BOOST_PP_IS_ITERATING + +# define N BOOST_PP_ITERATION() + +template<> +struct type_list_impl_chooser +{ + template< + BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_LIST_SIZE, class T) + > + struct result_ + { + typedef BOOST_PP_CAT(mpl::list,N)< + BOOST_PP_ENUM_PARAMS(N, T) + > type; + }; +}; + +# undef N + +#endif // BOOST_PP_IS_ITERATING diff --git a/include/boost/python/detail/type_list_utils.hpp b/include/boost/python/detail/type_list_utils.hpp index d03203b9..ebb5488b 100644 --- a/include/boost/python/detail/type_list_utils.hpp +++ b/include/boost/python/detail/type_list_utils.hpp @@ -1,116 +1,28 @@ -/////////////////////////////////////////////////////////////////////////////// -// +#error obsolete // Copyright David Abrahams 2002. Permission to copy, use, // modify, sell and distribute this software is granted provided this // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -// -/////////////////////////////////////////////////////////////////////////////// -#if !defined(BOOST_PP_IS_ITERATING) - #ifndef TYPE_LIST_UTILS_JDG20020826_HPP -#define TYPE_LIST_UTILS_JDG20020826_HPP +# define TYPE_LIST_UTILS_JDG20020826_HPP -# include -# include -//# include -//# include - -# include -# include -# include -# include -# include -# include - -# include +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION namespace boost { namespace python { namespace detail { -# if (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 245) \ - && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) +template< typename T > +struct is_list_arg +{ + enum { value = true }; +}; - template - struct type_at : public boost::mpl::at {}; - - template - struct type_list_size : public boost::mpl::size {}; - -// template -// struct pop_front : public boost::mpl::pop_front {}; -// -// template -// struct pop_back : public boost::mpl::pop_back {}; - -# else - - template - struct type_at {}; - - template - struct type_list_size {}; - -// template -// struct pop_front {}; -// -// template -// struct pop_back {}; - -// template -// struct push_back {}; - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3, (0, BOOST_PYTHON_MAX_ARITY, )) -# include BOOST_PP_ITERATE() - -# endif - -}}} // namespace boost::python::detail +template<> +struct is_list_arg +{ + enum { value = false }; +}; +}}} +# endif #endif // TYPE_LIST_UTILS_JDG20020826_HPP - -#else // defined(BOOST_PP_IS_ITERATING) - -# define N BOOST_PP_ITERATION() - -# if (N < BOOST_PYTHON_MAX_ARITY-1) - - template - struct type_at > - { - typedef BOOST_PP_CAT(A, N) type; - }; - -// template -// struct push_back, T> -// { -// typedef boost::mpl::type_list sequence; -// }; - -# if (N > 0) - -// template -// struct pop_front > -// { -// typedef boost::mpl::type_list sequence; -// }; -// -// template -// struct pop_back > -// { -// typedef boost::mpl::type_list sequence; -// }; - -# endif -# endif - - template - struct type_list_size > - { - BOOST_STATIC_CONSTANT(long, value = N); - }; - -# undef N - -#endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/include/boost/python/detail/wrap_function.hpp b/include/boost/python/detail/wrap_function.hpp new file mode 100644 index 00000000..488f939e --- /dev/null +++ b/include/boost/python/detail/wrap_function.hpp @@ -0,0 +1,40 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef WRAP_FUNCTION_DWA2002118_HPP +# define WRAP_FUNCTION_DWA2002118_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// A function which converts its argument into a Python callable +// object. Not very general yet! + +// This should eventually be replaced with a mechanism for specialized +// wrap/unwrap objects. In other words, to_python(f), where f is a +// function pointer or function type, should produce a callable Python +// object. + +template +inline PyObject* wrap_function_aux(F f, PyObject*) { return f; } + +template +inline PyObject* wrap_function_aux(F f, ...) { return make_function(f); } + +template +PyObject* wrap_function(F f) +{ + return wrap_function_aux(f, f); +} + +}}} // namespace boost::python::detail + +#endif // WRAP_FUNCTION_DWA2002118_HPP diff --git a/include/boost/python/enum.hpp b/include/boost/python/enum.hpp index f7d06075..072a0626 100644 --- a/include/boost/python/enum.hpp +++ b/include/boost/python/enum.hpp @@ -15,6 +15,8 @@ namespace boost { namespace python { template struct enum_ : public objects::enum_base { + typedef objects::enum_base base; + enum_(char const* name); inline enum_& value(char const* name, T); @@ -26,7 +28,7 @@ struct enum_ : public objects::enum_base template inline enum_::enum_(char const* name) - : enum_base( + : base( name , &enum_::to_python , &enum_::convertible @@ -39,7 +41,7 @@ inline enum_::enum_(char const* name) template PyObject* enum_::to_python(void const* x) { - return enum_base::to_python( + return base::to_python( converter::registered::converters.class_object , static_cast(*(T const*)x)); } diff --git a/include/boost/python/extract.hpp b/include/boost/python/extract.hpp index fdcaac28..598fe249 100644 --- a/include/boost/python/extract.hpp +++ b/include/boost/python/extract.hpp @@ -87,13 +87,13 @@ namespace converter BOOST_STATIC_CONSTANT( bool, ref = is_reference::value); - typedef typename mpl::select_type< + typedef typename mpl::if_c< obj_mgr , extract_object_manager - , typename mpl::select_type< + , typename mpl::if_c< ptr , extract_pointer - , typename mpl::select_type< + , typename mpl::if_c< ref , extract_reference , extract_rvalue diff --git a/include/boost/python/from_python.hpp b/include/boost/python/from_python.hpp new file mode 100644 index 00000000..726928ac --- /dev/null +++ b/include/boost/python/from_python.hpp @@ -0,0 +1,49 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef FROM_PYTHON_DWA2002128_HPP +# define FROM_PYTHON_DWA2002128_HPP + +# include + +namespace boost { namespace python { + +template +struct from_python + : converter::select_from_python::type +{ + typedef typename converter::select_from_python::type base; + from_python(PyObject*); +}; + +// specialization for PyObject* +template <> +struct from_python +{ + from_python(PyObject*) {} + bool convertible() const { return true; } + PyObject* operator()(PyObject* source) const { return source; } +}; + +template <> +struct from_python +{ + from_python(PyObject*) {} + bool convertible() const { return true; } + PyObject*const& operator()(PyObject*const& source) const { return source; } +}; + +// +// implementations +// +template +inline from_python::from_python(PyObject* source) + : base(source) +{ +} + +}} // namespace boost::python + +#endif // FROM_PYTHON_DWA2002128_HPP diff --git a/include/boost/python/init.hpp b/include/boost/python/init.hpp index 03625a1b..733973b1 100644 --- a/include/boost/python/init.hpp +++ b/include/boost/python/init.hpp @@ -10,21 +10,29 @@ #ifndef INIT_JDG20020820_HPP #define INIT_JDG20020820_HPP -#include -#include -#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include + +#include #include #include #include +#include #include -#include -#include -#include /////////////////////////////////////////////////////////////////////////////// #define BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT \ @@ -32,7 +40,7 @@ ( \ BOOST_PYTHON_MAX_ARITY, \ class T, \ - boost::mpl::null_argument \ + mpl::void_ \ ) \ #define BOOST_PYTHON_TEMPLATE_TYPES \ @@ -61,16 +69,6 @@ struct optional; // forward declaration namespace detail { - /////////////////////////////////////////////////////////////////////////// - // - // is_nil::value - // - // This metaprogram checks if T is nil - // - /////////////////////////////////////////////////////////////////////////// - template - struct is_nil : public boost::is_same {}; - /////////////////////////////////////////////////////////////////////////// // // is_optional::value @@ -95,291 +93,159 @@ namespace detail { BOOST_STATIC_CONSTANT( bool, value = sizeof(f(t())) == sizeof(::boost::type_traits::yes_type)); + typedef mpl::bool_c type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_optional,(T)) // needed for MSVC & Borland }; /////////////////////////////////////// #else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template - struct is_optional { + struct is_optional_impl { BOOST_STATIC_CONSTANT(bool, value = false); }; template - struct is_optional > { + struct is_optional_impl > { BOOST_STATIC_CONSTANT(bool, value = true); }; - #endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - - /////////////////////////////////////////////////////////////////////////// - // - // append_to_init [ and helpers ] - // - // A metaprogram appends T to the initializer type list - // - /////////////////////////////////////////////////////////////////////////// - struct append_to_init_helper1 { - - // Case 1: default case, just push T to the back of ListT - - template - struct apply { - - typedef typename boost::mpl::push_back::sequence sequence; - }; - }; - - struct append_to_init_helper2 { - - template - struct apply { - - // Case 2: optional case, T is an optional, append all - // the contents of the optional T into back of ListT - - typedef typename boost::mpl::for_each - < - typename T::sequence, - ListT, - boost::mpl::push_back - >::state sequence; - }; - }; - - struct append_to_init_helper3 { - - // Case 3: nil case, we found a nil, do nothing - - template - struct apply { - - typedef ListT sequence; - }; - }; - - template - struct append_to_init { - - typedef typename boost::mpl::select_type - < - is_optional::value, // if - append_to_init_helper2, // then - typename boost::mpl::select_type // else - < - is_nil::value, // if - append_to_init_helper3, // then - append_to_init_helper1 // else - >::type - >::type helper; - - typedef typename helper::template apply::sequence sequence; - }; - - /////////////////////////////////////////////////////////////////////////// - // - // check_init_params [ and helpers ] - // - // Check the init template parameters. Detect illegal - // arguments such as: - // - // init, int> // BAD trailing int - // init, optional > // BAD optional used twice - // - /////////////////////////////////////////////////////////////////////////// - template - struct check_init_params_helper { - - template - struct apply { - - // case where size of sequence is not zero - - typedef typename boost::mpl::pop_front::sequence rest; - - enum { - - // if first is optional then there must be no more - // elements to its right. if not then recurse and check - // the rest of the type list - - first_is_optional = - is_optional::type>::value, - size_of_rest = boost::mpl::size::value, - rest_is_nil = (size_of_rest == 0), - is_ok = first_is_optional ? rest_is_nil : - check_init_params_helper - ::template apply::is_ok - }; - }; - }; - - template <> - struct check_init_params_helper<0> { - - // case where size of sequence is zero - - template - struct apply { - - enum { is_ok = true }; - }; - }; - - struct init_base {}; - - template - struct check_init_params : init_base { - - typedef boost::mpl::type_list params; - - BOOST_STATIC_ASSERT - ( - check_init_params_helper::value> - ::template apply::is_ok - ); - }; - - /////////////////////////////////////////////////////////////////////////// - // - // count_optional_types [ and helpers ] - // - // count_optional_types::value computes the number of - // optional types (see init and optional below). For example: - // - // init >::value == 3 - // - /////////////////////////////////////////////////////////////////////////// template - struct count_optionals1 { - - BOOST_STATIC_CONSTANT(int, value = 0); - }; - - template - struct count_optionals2 { - - BOOST_STATIC_CONSTANT( - int, value = boost::mpl::size::value + 1); - }; - - template - struct count_optionals - : boost::mpl::select_type - < - is_optional::value, // if - count_optionals2, // then - count_optionals1 // else - >::type + struct is_optional : is_optional_impl { + typedef mpl::bool_c::value> type; + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_optional,(T)) // needed for MSVC & Borland }; - - template - struct count_optional_types { - - BOOST_STATIC_CONSTANT(int, value = - count_optionals::value + - count_optionals::value + - count_optionals::value - ); - }; + #endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) } // namespace detail -/////////////////////////////////////////////////////////////////////////////// -// -// init -// -// init::sequence returns a typelist. One of T0..TN -// mat be an optional<...> see below. There should be only one -// optional in the input types and an optional should be the -// last in the list. -// -/////////////////////////////////////////////////////////////////////////////// -#define BOOST_PYTHON_APPEND_TO_INIT(z, INDEX, D) \ - typedef typename detail::append_to_init \ - < \ - BOOST_PP_CAT(l, INDEX), \ - BOOST_PP_CAT(T, BOOST_PP_INC(INDEX)) \ - >::sequence BOOST_PP_CAT(l, BOOST_PP_INC(INDEX)); \ - template -struct init : detail::check_init_params +struct init //: detail::check_init_params { - typedef boost::mpl::type_list l0; - BOOST_PP_REPEAT - (BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BOOST_PYTHON_APPEND_TO_INIT, 0) + typedef detail::type_list signature_; + typedef typename mpl::end::type finish; - typedef BOOST_PP_CAT(l, BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY)) sequence; + // Find the optional<> element, if any + typedef typename mpl::find_if< + signature_, detail::is_optional + >::type opt; - BOOST_STATIC_CONSTANT(int, n_arguments = boost::mpl::size::value); - BOOST_STATIC_CONSTANT(int, n_defaults = - (detail::count_optional_types::value) - ); + // Check to make sure the optional<> element, if any, is the last one + typedef typename mpl::apply_if< + is_same + , mpl::identity + , mpl::next + >::type expected_finish; + BOOST_STATIC_ASSERT((is_same::value)); + + typedef typename mpl::apply_if< + is_same + , mpl::list0<> + , opt + >::type optional_args; + + // Count the number of default args + BOOST_STATIC_CONSTANT(int, n_defaults = mpl::size::value); + + typedef typename mpl::iterator_range< + typename mpl::begin::type + , opt + >::type required_args; + + // Build a reverse image of all the args, including optionals + typedef typename mpl::fold< + required_args + , mpl::list0<> + , mpl::push_front + >::type reversed_required; + + typedef typename mpl::fold< + optional_args + , reversed_required + , mpl::push_front + >::type reversed_args; + + // Count the maximum number of arguments + BOOST_STATIC_CONSTANT(int, n_arguments = mpl::size::value); }; /////////////////////////////////////////////////////////////////////////////// // // optional // -// optional::sequence returns a typelist. +// optional::type returns a typelist. // /////////////////////////////////////////////////////////////////////////////// template -struct optional { - - typedef boost::mpl::type_list sequence; +struct optional + : detail::type_list +{ }; -namespace detail { +namespace detail +{ + template + void def_init_reversed(ClassT& cl, ReversedArgs const&, CallPoliciesT const& policies, char const* doc) + { + typedef typename mpl::fold< + ReversedArgs + , mpl::list0<> + , mpl::push_front + >::type args; + + cl.def_init(args(), policies, doc); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper::apply + // + // General case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments and recursively calls + // define_class_init_helper::apply with one less arguments (the + // rightmost argument is shaved off) + // + /////////////////////////////////////////////////////////////////////////////// + template + struct define_class_init_helper { - /////////////////////////////////////////////////////////////////////////////// - // - // define_class_init_helper::apply - // - // General case - // - // Accepts a class_ and an arguments list. Defines a constructor - // for the class given the arguments and recursively calls - // define_class_init_helper::apply with one less arguments (the - // rightmost argument is shaved off) - // - /////////////////////////////////////////////////////////////////////////////// - template - struct define_class_init_helper { + template + static void apply(ClassT& cl, CallPoliciesT const& policies, ReversedArgs const& args, char const* doc) + { + def_init_reversed(cl, args, policies, doc); - template - static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc) - { - cl.def_init(args, policies, doc); - typename boost::mpl::pop_back::sequence next; - define_class_init_helper::apply(cl, policies, next, doc); - } - }; + typename mpl::pop_front::type next; + define_class_init_helper::apply(cl, policies, next, doc); + } + }; - /////////////////////////////////////////////////////////////////////////////// - // - // define_class_init_helper<0>::apply - // - // Terminal case - // - // Accepts a class_ and an arguments list. Defines a constructor - // for the class given the arguments. - // - /////////////////////////////////////////////////////////////////////////////// - template <> - struct define_class_init_helper<0> { + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper<0>::apply + // + // Terminal case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments. + // + /////////////////////////////////////////////////////////////////////////////// + template <> + struct define_class_init_helper<0> { - template - static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc) - { - cl.def_init(args, policies, doc); - } - }; + template + static void apply(ClassT& cl, CallPoliciesT const& policies, ReversedArgs const& args, char const* doc) + { + def_init_reversed(cl, args, policies, doc); + } + }; } /////////////////////////////////////////////////////////////////////////////// @@ -407,8 +273,8 @@ template void define_init(ClassT& cl, InitT const& i, CallPoliciesT const& policies, char const* doc) { - typedef typename InitT::sequence args_t; - detail::define_class_init_helper::apply(cl, policies, args_t(), doc); + typedef typename InitT::reversed_args reversed_args; + detail::define_class_init_helper::apply(cl, policies, reversed_args(), doc); } }} // namespace boost::python diff --git a/include/boost/python/manage_new_object.hpp b/include/boost/python/manage_new_object.hpp index e19035b7..0acbbec8 100644 --- a/include/boost/python/manage_new_object.hpp +++ b/include/boost/python/manage_new_object.hpp @@ -6,7 +6,7 @@ #ifndef MANAGE_NEW_OBJECT_DWA200222_HPP # define MANAGE_NEW_OBJECT_DWA200222_HPP # include -# include +# include # include # include @@ -27,7 +27,7 @@ struct manage_new_object template struct apply { - typedef typename mpl::select_type< + typedef typename mpl::if_c< boost::is_pointer::value , to_python_indirect , detail::manage_new_object_requires_a_pointer_return_type diff --git a/include/boost/python/object/auto_ptr_generator.hpp b/include/boost/python/object/auto_ptr_generator.hpp new file mode 100644 index 00000000..9c13e436 --- /dev/null +++ b/include/boost/python/object/auto_ptr_generator.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef AUTO_PTR_GENERATOR_DWA2002123_HPP +# define AUTO_PTR_GENERATOR_DWA2002123_HPP +# include + +namespace boost { namespace python { namespace object { + +struct auto_ptr_generator +{ + template + struct apply + { + typedef std::auto_ptr type; + }; +}; + +}}} // namespace boost::python::object + +#endif // AUTO_PTR_GENERATOR_DWA2002123_HPP diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp index 14e79a9d..79119ef7 100644 --- a/include/boost/python/object/class_converters.hpp +++ b/include/boost/python/object/class_converters.hpp @@ -13,6 +13,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -45,29 +46,22 @@ struct do_nothing template struct register_base_of { - // Ignored is needed because mpl::for_each is still actually - // accumulate. We're not using any state so it just sits there. - template - struct apply + // Here's the runtime part: + template + void operator()(Base*) const { - typedef void type; // 'type' needs to be defined for the same reasons + // Register the Base class + register_dynamic_id(); + // Register the up-cast + register_conversion(false); - // Here's the runtime part: - static void execute() - { - // Register the Base class - register_dynamic_id(); - // Register the up-cast - register_conversion(false); - - // Register the down-cast, if appropriate. - mpl::select_type< - is_polymorphic::value - , register_downcast - , do_nothing - >::type::execute(); - } - }; + // Register the down-cast, if appropriate. + mpl::if_c< + is_polymorphic::value + , register_downcast + , do_nothing + >::type::execute(); + } }; // Brings into existence all converters associated with a class Bases @@ -82,7 +76,7 @@ inline void register_class_from_python(Derived* = 0, Bases* = 0) register_dynamic_id(); // register each base in the sequence - mpl::for_each >::execute(); + mpl::for_each(register_base_of(), (Bases*)0, (add_pointer*)0); } }}} // namespace boost::python::object diff --git a/include/boost/python/object/class_object.hpp b/include/boost/python/object/class_object.hpp new file mode 100644 index 00000000..76960762 --- /dev/null +++ b/include/boost/python/object/class_object.hpp @@ -0,0 +1,26 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef CLASS_OBJECT_DWA200222_HPP +# define CLASS_OBJECT_DWA200222_HPP + +# include +# include + +namespace boost { namespace python { namespace objects { + +template +struct class_object +{ + static PyTypeObject*& reference; +}; + +template +PyTypeObject*& class_object::reference = converter::registry::class_object( + converter::undecorated_type_id()); + +}}} // namespace boost::python::objects + +#endif // CLASS_OBJECT_DWA200222_HPP diff --git a/include/boost/python/object/forward.hpp b/include/boost/python/object/forward.hpp index cc23e94c..93c1ed21 100644 --- a/include/boost/python/object/forward.hpp +++ b/include/boost/python/object/forward.hpp @@ -6,10 +6,11 @@ #ifndef FORWARD_DWA20011215_HPP # define FORWARD_DWA20011215_HPP -# include +# include # include # include # include +# include # include namespace boost { namespace python { namespace objects { @@ -30,7 +31,7 @@ struct reference_to_value // is T. template struct forward - : mpl::select_type< + : mpl::if_c< is_scalar::value , T , reference_to_value > diff --git a/include/boost/python/object/inheritance.hpp b/include/boost/python/object/inheritance.hpp index 5129e35e..88b556ff 100644 --- a/include/boost/python/object/inheritance.hpp +++ b/include/boost/python/object/inheritance.hpp @@ -8,7 +8,7 @@ # include # include -# include +# include # include namespace boost { namespace python { namespace objects { @@ -80,7 +80,7 @@ struct non_polymorphic_id_generator template struct dynamic_id_generator { - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_polymorphic::value , polymorphic_id_generator , non_polymorphic_id_generator >::type type; @@ -133,7 +133,7 @@ struct cast_generator is_base_and_derived::value )); - typedef typename mpl::select_type< + typedef typename mpl::if_c< is_upcast # if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // grab a few more implicit_cast cases for CodeWarrior diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 429704a3..2a9e4e58 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -15,7 +15,9 @@ # include # include -# include +# include +# include +# include # include # include @@ -29,8 +31,10 @@ namespace boost { namespace python { namespace objects { template struct make_holder; # define BOOST_PYTHON_FORWARD_ARG(z, index, _) \ - typedef typename mpl::at::type t##index; \ - typedef typename forward::type f##index; + typedef typename iter##index::type t##index; \ + typedef typename forward::type f##index; \ + typedef typename mpl::next::type \ + BOOST_PP_CAT(iter,BOOST_PP_INC(index)); # define BOOST_PYTHON_DO_FORWARD_ARG(z, index, _) , f##index(a##index) @@ -56,7 +60,8 @@ struct make_holder template struct apply { - BOOST_PP_REPEAT(N, BOOST_PYTHON_FORWARD_ARG, nil) + typedef typename mpl::begin::type iter0; + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FORWARD_ARG, nil) static void execute( PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, t, a)) @@ -66,7 +71,7 @@ struct make_holder void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder)); try { (new (memory) Holder( - p BOOST_PP_REPEAT(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p); + p BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p); } catch(...) { Holder::deallocate(p, memory); diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 9ead5d94..0dca4ae3 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -22,7 +22,7 @@ # include # include -# include +# include # include # include @@ -131,7 +131,7 @@ void* pointer_holder_back_reference::holds(type_info dst_t) # endif pointer_holder(PyObject* BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) : m_p(new Value( - BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) )) {} @@ -149,7 +149,7 @@ void* pointer_holder_back_reference::holds(type_info dst_t) pointer_holder_back_reference( PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) : m_p(new held_type( - p BOOST_PP_COMMA_IF(N) BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + p BOOST_PP_COMMA_IF(N) BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) )) {} diff --git a/include/boost/python/object/select_holder.hpp b/include/boost/python/object/select_holder.hpp index 6902f68d..3535fd29 100644 --- a/include/boost/python/object/select_holder.hpp +++ b/include/boost/python/object/select_holder.hpp @@ -15,10 +15,10 @@ # include # include # include -# include +# include # include # include -# include +# include # include namespace boost { namespace python { namespace objects { @@ -30,7 +30,7 @@ namespace detail { BOOST_STATIC_CONSTANT(bool, selector = (!is_same::value) | has_back_reference::value); - typedef typename mpl::select_type< + typedef typename mpl::if_c< selector , value_holder_back_reference , value_holder @@ -38,18 +38,18 @@ namespace detail static inline void register_() { - select_value_holder::register_(mpl::bool_t()); + select_value_holder::register_(mpl::bool_c()); } static type* get() { return 0; } private: - static inline void register_(mpl::bool_t) + static inline void register_(mpl::bool_c) { python::detail::force_instantiate(instance_finder::registration); } - static inline void register_(mpl::bool_t) + static inline void register_(mpl::bool_c) { } }; @@ -60,7 +60,7 @@ namespace detail typedef typename python::pointee::type pointee; BOOST_STATIC_CONSTANT(bool, selector = (!is_same::value) | has_back_reference::value); - typedef typename mpl::select_type< + typedef typename mpl::if_c< selector , pointer_holder_back_reference , pointer_holder @@ -68,13 +68,13 @@ namespace detail static inline void register_() { - select_pointer_holder::register_(mpl::bool_t()); + select_pointer_holder::register_(mpl::bool_c()); } static type* get() { return 0; } private: - static inline void register_(mpl::bool_t) + static inline void register_(mpl::bool_c) { // not implemented at least until we solve the back // reference issue mentioned in pointer_holder.hpp. @@ -94,7 +94,7 @@ namespace detail } }; - static inline void register_(mpl::bool_t) + static inline void register_(mpl::bool_c) { python::detail::force_instantiate( objects::class_wrapper< diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index ea751edc..d40d058d 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -101,7 +101,7 @@ void* value_holder_back_reference::holds( value_holder( PyObject* BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) : m_held( - BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) ) {} @@ -121,7 +121,7 @@ void* value_holder_back_reference::holds( PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) : m_held( p BOOST_PP_COMMA_IF(N) - BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) ) { } diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp index a0119503..ebdfeac1 100755 --- a/include/boost/python/object_core.hpp +++ b/include/boost/python/object_core.hpp @@ -180,7 +180,7 @@ namespace api // there is a confirmed CWPro8 codegen bug here. We prevent the // early destruction of a temporary by binding a named object // instead. -# if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3001 +# if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3002 typedef object const& object_cref2; # else typedef object const object_cref2; diff --git a/include/boost/python/operators2.hpp b/include/boost/python/operators2.hpp index 8c56abf7..3f06eb46 100755 --- a/include/boost/python/operators2.hpp +++ b/include/boost/python/operators2.hpp @@ -11,7 +11,7 @@ # include # include # include -# include +# include # include # include # include @@ -120,15 +120,15 @@ namespace detail // self_t template struct operator_ - : mpl::select_type< - (is_same::value) - , typename mpl::select_type< - (is_same::value) + : mpl::if_< + is_same + , typename mpl::if_< + is_same , binary_op , binary_op_l::type> >::type - , typename mpl::select_type< - (is_same::value) + , typename mpl::if_< + is_same , unary_op , binary_op_r::type> >::type diff --git a/include/boost/python/pointee.hpp b/include/boost/python/pointee.hpp index 52d65d67..d62bab54 100644 --- a/include/boost/python/pointee.hpp +++ b/include/boost/python/pointee.hpp @@ -7,6 +7,7 @@ # define POINTEE_DWA2002323_HPP # include +# include namespace boost { namespace python { diff --git a/include/boost/python/reference_existing_object.hpp b/include/boost/python/reference_existing_object.hpp index 1f8a43d8..e16dcf18 100644 --- a/include/boost/python/reference_existing_object.hpp +++ b/include/boost/python/reference_existing_object.hpp @@ -6,7 +6,7 @@ #ifndef REFERENCE_EXISTING_OBJECT_DWA200222_HPP # define REFERENCE_EXISTING_OBJECT_DWA200222_HPP # include -# include +# include # include # include @@ -32,7 +32,7 @@ struct reference_existing_object BOOST_STATIC_CONSTANT( bool, ok = is_pointer::value || is_reference::value); - typedef typename mpl::select_type< + typedef typename mpl::if_c< ok , to_python_indirect , detail::reference_existing_object_requires_a_pointer_or_reference_return_type diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp index 3a968f45..7e350d77 100644 --- a/include/boost/python/return_internal_reference.hpp +++ b/include/boost/python/return_internal_reference.hpp @@ -9,7 +9,7 @@ # include # include # include -# include +# include namespace boost { namespace python { @@ -30,7 +30,7 @@ struct return_internal_reference private: BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0); public: - typedef typename mpl::select_type< + typedef typename mpl::if_c< legal , reference_existing_object , detail::return_internal_reference_owner_arg_must_be_greater_than_zero diff --git a/include/boost/python/signature.hpp b/include/boost/python/signature.hpp index 3bef081e..bd4b26df 100644 --- a/include/boost/python/signature.hpp +++ b/include/boost/python/signature.hpp @@ -19,8 +19,19 @@ # include # include # include -# include +# include + # include +# include +# include +# include + +# define BOOST_PYTHON_FUNCTION_SIGNATURE_LIST(n) \ + BOOST_PP_CAT(mpl::list, BOOST_PP_INC(n)) + +# define BOOST_PYTHON_MEMBER_FUNCTION_SIGNATURE_LIST(n) \ + BOOST_PP_CAT(mpl::list, BOOST_PP_INC(BOOST_PP_INC(n))) + /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace python { namespace detail { @@ -30,28 +41,28 @@ namespace boost { namespace python { namespace detail { // The following macros generate expansions for: // // template -// inline boost::mpl::type_list +// inline mpl::list // get_signature(RT(*)(T0...TN)) // { -// return boost::mpl::type_list(); +// return mpl::list(); // } // // template -// inline boost::mpl::type_list +// inline mpl::list // get_signature(RT(ClassT::*)(T0...TN))) // { -// return boost::mpl::type_list(); +// return mpl::list(); // } // // template -// inline boost::mpl::type_list +// inline mpl::list // get_signature(RT(ClassT::*)(T0...TN) const)) // { -// return boost::mpl::type_list(); +// return mpl::list(); // } // // These functions extract the return type, class (for member functions) -// and arguments of the input signature and stuffs them in an mpl::type_list. +// and arguments of the input signature and stuffs them in an mpl::list. // /////////////////////////////////////////////////////////////////////////////// @@ -65,6 +76,10 @@ namespace boost { namespace python { namespace detail { }} // namespace boost::python + +# undef BOOST_PYTHON_FUNCTION_SIGNATURE_LIST +# undef BOOST_PYTHON_MEMBER_FUNCTION_SIGNATURE_LIST + /////////////////////////////////////////////////////////////////////////////// # endif // SIGNATURE_JDG20020813_HPP @@ -73,47 +88,38 @@ namespace boost { namespace python { namespace detail { # define N BOOST_PP_ITERATION() template < - class RT BOOST_PP_COMMA_IF(N) - BOOST_PYTHON_UNARY_ENUM(N, class T)> -inline boost::mpl::type_list< - RT BOOST_PP_COMMA_IF(N) - BOOST_PP_ENUM_PARAMS(N, T)> + class RT BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> +inline BOOST_PYTHON_FUNCTION_SIGNATURE_LIST(N)< + RT BOOST_PP_ENUM_TRAILING_PARAMS(N, T)> get_signature(RT(*)(BOOST_PP_ENUM_PARAMS(N, T))) { - return boost::mpl::type_list< - RT BOOST_PP_COMMA_IF(N) - BOOST_PP_ENUM_PARAMS(N, T)>(); + return BOOST_PYTHON_FUNCTION_SIGNATURE_LIST(N)< + RT BOOST_PP_ENUM_TRAILING_PARAMS(N, T) + >(); } /////////////////////////////////////////////////////////////////////////////// #if N <= (BOOST_PYTHON_MAX_ARITY - 2) template < - class RT, class ClassT BOOST_PP_COMMA_IF(N) - BOOST_PYTHON_UNARY_ENUM(N, class T)> -inline boost::mpl::type_list< - RT, ClassT BOOST_PP_COMMA_IF(N) - BOOST_PP_ENUM_PARAMS(N, T)> + class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> +inline BOOST_PYTHON_MEMBER_FUNCTION_SIGNATURE_LIST(N)< + RT, ClassT BOOST_PP_ENUM_TRAILING_PARAMS(N, T)> get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS(N, T))) { - return boost::mpl::type_list< - RT, ClassT BOOST_PP_COMMA_IF(N) - BOOST_PP_ENUM_PARAMS(N, T)>(); + return BOOST_PYTHON_MEMBER_FUNCTION_SIGNATURE_LIST(N)< + RT, ClassT BOOST_PP_ENUM_TRAILING_PARAMS(N, T)>(); } /////////////////////////////////////// template < - class RT, class ClassT BOOST_PP_COMMA_IF(N) - BOOST_PYTHON_UNARY_ENUM(N, class T)> -inline boost::mpl::type_list< - RT, ClassT const BOOST_PP_COMMA_IF(N) - BOOST_PP_ENUM_PARAMS(N, T)> + class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> +inline BOOST_PYTHON_MEMBER_FUNCTION_SIGNATURE_LIST(N)< + RT, ClassT const BOOST_PP_ENUM_TRAILING_PARAMS(N, T)> get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS(N, T)) const) { - return boost::mpl::type_list< - RT, ClassT const - BOOST_PP_COMMA_IF(N) - BOOST_PP_ENUM_PARAMS(N, T)>(); + return BOOST_PYTHON_MEMBER_FUNCTION_SIGNATURE_LIST(N)< + RT, ClassT const BOOST_PP_ENUM_TRAILING_PARAMS(N, T)>(); } #endif // N < (BOOST_PYTHON_MAX_ARITY - 2) diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index b85eaf68..3b9cd76c 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -11,7 +11,7 @@ # include # include # include -# include +# include # include # include # include @@ -46,7 +46,7 @@ namespace detail template struct to_python_value - : mpl::select_type< + : mpl::if_c< boost::type_traits::ice_or< converter::is_object_manager::value , converter::is_reference_to_object_manager::value diff --git a/include/boost/python/type_from_python.hpp b/include/boost/python/type_from_python.hpp new file mode 100644 index 00000000..38d2ceea --- /dev/null +++ b/include/boost/python/type_from_python.hpp @@ -0,0 +1,103 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef TYPE_FROM_PYTHON_DWA2002130_HPP +# define TYPE_FROM_PYTHON_DWA2002130_HPP + +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + // Given a pointer-to-function of 1 parameter returning a reference + // type, return the type_id of the function's return type. + template + inline converter::undecorated_type_id_t extractor_type_id(T&(*)(U)) + { + return converter::undecorated_type_id(); + } + + // A function generator whose static execute() function is an lvalue + // from_python converter using the given Extractor. U is expected to + // be the actual type of the PyObject instance from which the result + // is being extracted. + template + struct normalized_extractor + { + static inline void* execute(PyObject* op) + { + typedef typename boost::add_reference::type param; + return &Extractor::execute( + boost::python::detail::void_ptr_to_reference( + op, (param(*)())0 ) + ); + } + }; + + // Given an Extractor type and a pointer to its execute function, + // return a new object whose static execute function does the same + // job but is a conforming lvalue from_python conversion function. + // + // usage: normalize(&Extractor::execute) + template + inline normalized_extractor + normalize(T(*)(U), Extractor* = 0) + { + return normalized_extractor(); + } +} + +// An Extractor which extracts the given member from a Python object +// whose instances are stored as InstanceType. +template +struct member_extractor +{ + static MemberType& execute(InstanceType& c) + { + (void)c.ob_type; // static assertion + return c.*member; + } +}; + +// An Extractor which simply extracts the entire python object +// instance of InstanceType. +template +struct identity_extractor +{ + static InstanceType& execute(InstanceType& c) + { + (void)c.ob_type; // static assertion + return c; + } +}; + +// Registers a from_python conversion which extracts lvalues using +// Extractor's static execute function from Python objects whose type +// object is python_type. +template +struct type_from_python +{ + type_from_python() + { + converter::registry::insert( + &extract, detail::extractor_type_id(&Extractor::execute)); + } + + static void* extract(PyObject* op) + { + return PyObject_TypeCheck(op, const_cast(python_type)) + ? const_cast( + static_cast( + detail::normalize(&Extractor::execute).execute(op))) + : 0 + ; + } +}; + +}} // namespace boost::python + +#endif // TYPE_FROM_PYTHON_DWA2002130_HPP diff --git a/index.html b/index.html deleted file mode 100644 index dff3b20f..00000000 --- a/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - -Automatic redirection failed, please go to -doc/index.html. - - \ No newline at end of file diff --git a/release_notes.txt b/release_notes.txt deleted file mode 100644 index 8932a0aa..00000000 --- a/release_notes.txt +++ /dev/null @@ -1,217 +0,0 @@ -2000-11-22 10:00 - Ullrich fixed bug in operator_dispatcher. - -2000-11-21 10:00 - Changed all class and function names into lower_case. - - Ullrich updated documentation for operator wrapping. - -2000-11-20 10:00 - Ullrich renamed ExtensionClass:register_coerce() into - ExtensionClass:def_standard_coerce() and made it public - - Ullrich improved shared_pod_manager. - -2000-11-17 15:04 - Changed allocation strategy of shared_pod_manager to make it portable. - - Added pickling support + tests thanks to "Ralf W. Grosse-Kunstleve" - - - Added a specialization of Callback to prevent unsafe usage. - - Fixed Ullrich's operator_dispatcher refcount bug - - Removed const char* return values from virtual functions in tests; that - usage was unsafe. - - Ullrich changed Module::add() so that it steals a reference (fix of refcount bug) - - Ullrich added operator_dispatcher::create() optimization - - Ullrich changed design and implementation of TypeObjectBase::enable() (to eliminate low-level - code) and added shared_pod_manager optimization. - - -2000-11-15 12:01 - Fixed refcount bugs in operator calls. - - Added callback_adjust_refcount(PyObject*, Type) to account for different ownership - semantics of Callback's return types and Caller's arguments (which both use from_python()) - This bug caused refcount errors during operator calls. - - Moved operator_dispatcher into extclass.cpp - Gave it shared ownership of the objects it wraps - - Introduced sequence points in extension_class_coerce for exception-safety - - UPPER_CASE_MACRO_NAMES - - MixedCase template type argument names - - Changed internal error reporting to use Python exceptions so we don't force the - user to link in iostreams code - - Changed error return value of call_cmp to -1 - - Moved unwrap_* functions out of operator_dispatcher. This was transitional: when - I realized they didn't need to be declared in extclass.h I moved them out, but - now that operator_dispatcher itself is in extclass.cpp they could go back in. - - Numerous formatting tweaks - - Updated the BoundFunction::create() optimization and enabled it so it could actually be used! - -2000-11-15 00:26 - - Made Ullrich's operators support work with MSVC - - Cleaned up operators.h such that invalid define_operator<0> is no longer needed. - - Ullrich created operators.h to support wrapping of C++ operators (including the "__r*__" forms). - He added several auxiliary classes to extclass.h and extclass.cpp (most importantly, - py::detail::operator_dispatcher and py::operators) - -2000-11-13 22:29 - - removed obsolete ExtensionClassFromPython for good. - - removed unused class ExtensionType forward declaration - -2000-11-12 13:08 - - Added enum_as_int_converters for easier enum wrapping - - Introduced new conversion namespace macros: - PY_BEGIN_CONVERSION_NAMESPACE, - PY_END_CONVERSION_NAMESPACE, - PY_CONVERSION - - callback.h, gen_callback.py: - Added call() function so that a regular python function (as opposed to - method or other function-as-attribute) can be called. - - Added newlines for readability. - - class_wrapper.h: - Fixed a bug in add(), which allows non-method class attributes - - Ullrich has added def_raw for simple varargs and keyword support. - - Fixed version number check for __MWERKS__ - - Added tests for enums and non-method class attributes - - objects.h/objects.cpp: - Added py::String operator*= and operator* for repetition - - Change Dict::items(), keys(), and values() to return a List - - Added template versions of set_item, etc., methods so that users can optionally - use C++ types that have to_python() functions as parameters. - - Changed various Ptr by-value parameters to const Ptr& - - -======= Release ======= -2000-11-06 0:22 - Lots of documentation updates - - added 4-argument template constructor to py::Tuple - - added "add" member function to ClassWrapper<> to allow arbitrary Python - objects to be added to an extension class. - - gen_all.py now generates support for n argument member functions and n+1 - argument member functions at the suggestion of "Ralf W. Grosse-Kunstleve" - - - Added regression tests and re-ordered declare_base calls to verify that the - phantom base class issue is resolved. - -2000-11-04 17:35 - - Integrated Ullrich Koethe's brilliant from_python_experiment for better - error-reporting in many cases. - - extclass.h, gen_extclass.py: - removed special-case MSVC code - added much commentary - removed unused py_copy_to_new_value_holder - - init_function.h, gen_init_function.py: - added missing 'template' keyword on type-dependent template member usage - removed special-case MSVC code - added much commentary - -2000-11-04 0:36 - - Removed the need for the phantom base class that screwed up inheritance - hierarchies, introduced error-prone ordering dependencies, and complexified - logic in many places! - - extclass.h: Added some explanatory comments, removed wasteful m_self member - of HeldInstance - - extclass_demo.cpp: Added #pragmas which allow compilation in ansi strict - mode under Metrowerks - - functions.h: Added virtual_function as part of phantom base class removal; - expanded commentary - - pyptr.h: Added some missing 'typename's and a GCC workaround fix - - subclass.cpp: Added missing string literal const_cast<>s. - -2000-11-03 10:58 - - Fix friend function instantiation bug caught by Metrowerks (thanks - Metrowerks!) - - Add proof-of-concept for one technique of wrapping function that return a - pointer - - Worked around MSVC optimizer bug by writing to_python(double) and - to_python(float) out-of-line - -2000-11-02 23:25 - - Add /Zm200 option to vc6_prj to deal with MSVC resource limitations - - Remove conflicting /Ot option from vc6_prj release build - -======= Release ======= -2000-11-02 17:42 - - Added a fix for interactions between default virtual function - implementations and declare_base(). You still need to write your - declare_base() /after/ all member functions have been def()d for the two - classes concerned. Many, many thanks to Ullrich Koethe - for all his work on this. - - Added missing conversions: - to_python(float) - from_python(const char* const&) - from_python(const double&) - from_python(const float&) - - Added a Regression test for a reference-counting bug thanks to Mark Evans - () - - const-ify ClassBase::getattr() - - Add repr() function to Class - - Add to_python/from_python conversions for PyPtr - - Standardize set_item/get_item interfaces (instead of proxies) for Dict and List - - Add Reprable<> template to newtypes.h - - Fix a bug wherein the __module__ attribute would be lost for classes that have a - default virtual function implementation. - - Remove extra ';' in module.cpp thanks to "Ralf W. Grosse-Kunstleve" - - - Fix a bug in the code of example1.html diff --git a/src/aix_init_module.cpp b/src/aix_init_module.cpp deleted file mode 100644 index 3d74596e..00000000 --- a/src/aix_init_module.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#ifdef _AIX -#include -#include - -extern "C" -{ -#include -#include -} - -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace detail { - -namespace -{ - extern "C" void initlibbpl() - { - static PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; - Py_InitModule("libbpl", initial_methods); - } - - struct find_and_open_file - { - FILE* fp; - std::string libpath; // -- search path - std::string filename; // -- filename to look for - std::string fullpath; // -- full path to file - - find_and_open_file( - const std::string& libpath_env - , const std::string& file); - }; - - find_and_open_file::find_and_open_file( - const std::string& libpath_env - , const std::string& file) - : fp(0) - { - char* value = std::getenv(libpath_env.c_str()); - - if(value == 0) - return; - - libpath = value; - - if (libpath == "") - return; - - std::string::size_type pos = 0, prev_pos = 0; - - // -- loop through all search paths looking for file - while((pos = libpath.find_first_of(":",pos)) != std::string::npos) - { - fullpath = libpath.substr(prev_pos,pos - prev_pos) + "/" + file; - if (::access(fullpath.c_str(), R_OK) == 0) - { - struct stat filestat; - ::stat(fullpath.c_str(), &filestat); - if (!S_ISDIR(filestat.st_mode)) - { - fp = std::fopen(fullpath.c_str(), "r"); - if (fp) - { - filename = file; - } - return; - } - } - prev_pos = ++pos; - } - - // -- mop up odd path - if (libpath.find_first_of(":", prev_pos) == std::string::npos) - { - fullpath = libpath.substr(prev_pos, libpath.size() - prev_pos) + "/" + file; - if (::access(fullpath.c_str(), R_OK) == 0) - { - struct stat filestat; - ::stat(fullpath.c_str(),&filestat); - if (!S_ISDIR(filestat.st_mode)) - { - fp = std::fopen(fullpath.c_str(), "r"); - filename = file; - } - } - } - } -} - -void aix_init_module( - so_load_function load_dynamic_module - , char const* module_name - , void (*init_module)()) -{ - static bool initialized; - if (!initialized) - { - char const* const name = "libbpl.so"; - find_and_open_file dynlib("LIBPATH", name); - if (dynlib.fp == 0) - { - fprintf(stderr, " Error: could not find %s\n", name); - return; - } - - std::string::size_type pos = pos = dynlib.filename.find_first_of(".so",0); - if (pos == std::string::npos) - { - fprintf(stderr, "dynamic library %s must end with .so\n", dynlib.filename.c_str()); - return; - } - - PyObject* m = - load_dynamic_module( - const_cast(dynlib.filename.substr(0,pos).c_str()), - const_cast(dynlib.fullpath.c_str()), - dynlib.fp); - - if (m == 0) - { - fprintf(stderr, "failed to load library %s\n", name); - return; - } - Py_DECREF(m); - - initialized = true; - } - python::detail::init_module(module_name, init_module); -} - -}}} // namespace boost::python -#endif diff --git a/src/classes.cpp b/src/classes.cpp deleted file mode 100644 index 440fe6a7..00000000 --- a/src/classes.cpp +++ /dev/null @@ -1,1047 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// Revision History: -// 04 Mar 01 Rolled in const_cast from Dragon fork (Dave Abrahams) -// 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) -// 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function) - -#define BOOST_PYTHON_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { - -namespace detail { - void enable_named_method(boost::python::detail::class_base* type_obj, const char* name); -} - -namespace { - // Add the name of the module currently being loaded to the name_space with the - // key "__module__". If no module is being loaded, or if name_space already has - // a key "__module", has no effect. This is not really a useful public - // interface; it's just used for class_t<>::class_t() below. - void add_current_module_name(dictionary&); - - bool is_prefix(const char* s1, const char* s2); - bool is_special_name(const char* name); - void enable_special_methods(boost::python::detail::class_base* derived, const tuple& bases, const dictionary& name_space); - - void report_ignored_exception(PyObject* source) - { - // This bit of code copied wholesale from classobject.c in the Python source. - PyObject *f, *t, *v, *tb; - PyErr_Fetch(&t, &v, &tb); - f = PySys_GetObject(const_cast("stderr")); - if (f != NULL) - { - PyFile_WriteString(const_cast("Exception "), f); - if (t) { - PyFile_WriteObject(t, f, Py_PRINT_RAW); - if (v && v != Py_None) { - PyFile_WriteString(const_cast(": "), f); - PyFile_WriteObject(v, f, 0); - } - } - PyFile_WriteString(const_cast(" in "), f); - PyFile_WriteObject(source, f, 0); - PyFile_WriteString(const_cast(" ignored\n"), f); - PyErr_Clear(); /* Just in case */ - } - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); - } - - // - // pickle support courtesy of "Ralf W. Grosse-Kunstleve" - // - PyObject* class_reduce(PyObject* klass) - { - return PyObject_GetAttrString(klass, const_cast("__name__")); - } - - ref global_class_reduce() - { - return ref(detail::new_wrapped_function(class_reduce)); - } - - - tuple instance_reduce(PyObject* obj) - { - ref instance_class(PyObject_GetAttrString(obj, const_cast("__class__"))); - - ref getinitargs(PyObject_GetAttrString(obj, const_cast("__getinitargs__")), - ref::null_ok); - PyErr_Clear(); - ref initargs; - if (getinitargs.get() != 0) - { - initargs = ref(PyEval_CallObject(getinitargs.get(), NULL)); - initargs = ref(PySequence_Tuple(initargs.get())); - } - else - { - initargs = ref(PyTuple_New(0)); - } - - ref getstate(PyObject_GetAttrString(obj, const_cast("__getstate__")), - ref::null_ok); - PyErr_Clear(); - - ref dict(PyObject_GetAttrString(obj, const_cast("__dict__")), ref::null_ok); - PyErr_Clear(); - - if (getstate.get() != 0) - { - if (dict.get() != 0 && dictionary(dict).size() > 0) - { - ref getstate_manages_dict(PyObject_GetAttrString(instance_class.get(), const_cast("__getstate_manages_dict__")), ref::null_ok); - PyErr_Clear(); - if (getstate_manages_dict.get() == 0) - { - PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__getstate_manages_dict__ not set)"); - throw_error_already_set(); - } - } - - ref state = ref(PyEval_CallObject(getstate.get(), NULL)); - return tuple(instance_class, initargs, state); - } - - if (getinitargs.get() == 0) - { - ref dict_defines_state(PyObject_GetAttrString(instance_class.get(), const_cast("__dict_defines_state__")), ref::null_ok); - PyErr_Clear(); - if (dict_defines_state.get() == 0) - { - PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__dict_defines_state__ not set)"); - throw_error_already_set(); - } - } - - if (dict.get() != 0 && dictionary(dict).size() > 0) - { - return tuple(instance_class, initargs, dict); - } - - return tuple(instance_class, initargs); - } - - ref global_instance_reduce() - { - return ref(detail::new_wrapped_function(instance_reduce)); - } -} - - -namespace detail { - - class_base::class_base(PyTypeObject* meta_class_obj, string name, tuple bases, const dictionary& name_space) - : type_object_base(meta_class_obj), - m_name(name), - m_bases(bases), - m_name_space(name_space) - { - this->tp_name = const_cast(name.c_str()); - enable(type_object_base::getattr); - enable(type_object_base::setattr); - add_current_module_name(m_name_space); - static const boost::python::string docstr("__doc__", boost::python::string::interned); - if (PyDict_GetItem(m_name_space.get(), docstr.get())== 0) - { - PyDict_SetItem(m_name_space.get(), docstr.get(), Py_None); - } - enable_special_methods(this, bases, name_space); - } - - void class_base::add_base(ref base) - { - tuple new_bases(m_bases.size() + 1); - for (std::size_t i = 0; i < m_bases.size(); ++i) - new_bases.set_item(i, m_bases[i]); - new_bases.set_item(m_bases.size(), base); - m_bases = new_bases; - } - - PyObject* class_base::getattr(const char* name) - { - if (!BOOST_CSTD_::strcmp(name, "__dict__")) - { - PyObject* result = m_name_space.get(); - Py_INCREF(result); - return result; - } - - if (!BOOST_CSTD_::strcmp(name, "__bases__")) - { - PyObject* result = m_bases.get(); - Py_INCREF(result); - return result; - } - - if (!BOOST_CSTD_::strcmp(name, "__name__")) - { - PyObject* result = m_name.get(); - Py_INCREF(result); - return result; - } - - // pickle support courtesy of "Ralf W. Grosse-Kunstleve" - if (!BOOST_CSTD_::strcmp(name, "__safe_for_unpickling__")) - { - return PyInt_FromLong(1); - } - if (!BOOST_CSTD_::strcmp(name, "__reduce__")) - { - PyObject* self = as_object(this); - ref target(self, ref::increment_count); - return bound_function::create(target, global_class_reduce()); - } - - ref local_attribute = m_name_space.get_item(string(name).reference()); - - if (local_attribute.get()) - return local_attribute.release(); - - // In case there are no bases... - PyErr_SetString(PyExc_AttributeError, name); - - // Check bases - for (std::size_t i = 0; i < m_bases.size(); ++i) - { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) - PyErr_Clear(); // we're going to try a base class - else if (PyErr_Occurred()) - break; // Other errors count, though! - - PyObject* base_attribute = PyObject_GetAttrString(m_bases[i].get(), const_cast(name)); - - if (base_attribute != 0) - { - // Unwind the actual underlying function from unbound Python class - // methods in case of multiple inheritance from real Python - // classes. Python stubbornly insists that the first argument to a - // method must be a true Python instance object otherwise. Do not - // unwrap bound methods; that would interfere with intended semantics. - if (PyMethod_Check(base_attribute) - && reinterpret_cast(base_attribute)->im_self == 0) - { - PyObject* function - = reinterpret_cast(base_attribute)->im_func; - Py_INCREF(function); - Py_DECREF(base_attribute); - return function; - } - else - { - return base_attribute; - } - } - } - return 0; - } - - // Mostly copied wholesale from Python's classobject.c - PyObject* class_base::repr() const - { - PyObject *mod = PyDict_GetItemString( - m_name_space.get(), const_cast("__module__")); - unsigned long address = reinterpret_cast(this); - string result = (mod == NULL || !PyString_Check(mod)) - ? string("") % tuple(m_name, address) - : string("") % tuple(ref(mod, ref::increment_count), m_name, address); - return result.reference().release(); - } - - - int class_base::setattr(const char* name, PyObject* value) - { - if (is_special_name(name) - && BOOST_CSTD_::strcmp(name, "__doc__") != 0 - && BOOST_CSTD_::strcmp(name, "__name__") != 0) - { - boost::python::string message("Special attribute names other than '__doc__' and '__name__' are read-only, in particular: "); - PyErr_SetObject(PyExc_TypeError, (message + name).get()); - throw_error_already_set(); - } - - if (PyCallable_Check(value)) - detail::enable_named_method(this, name); - - return PyDict_SetItemString( - m_name_space.reference().get(), const_cast(name), value); - } - - bool class_base::initialize_instance(instance* obj, PyObject* args, PyObject* keywords) - { - // Getting the init function off the obj should result in a - // bound method. - PyObject* const init_function = obj->getattr("__init__", false); - - if (init_function == 0) - { - if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); // no __init__? That's legal. - } - else { - return false; // Something else? Keep the error - } - } - else - { - // Manage the reference to the bound function - ref init_function_holder(init_function); - - // Declare a ref to manage the result of calling __init__ (which should be None). - ref init_result( - PyEval_CallObjectWithKeywords(init_function, args, keywords)); - } - return true; - } - - void class_base::instance_dealloc(PyObject* obj) const - { - Py_INCREF(obj); // This allows a __del__ function to revive the obj - - PyObject* exc_type; - PyObject* exc_value; - PyObject* exc_traceback; - PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); - - // This scope ensures that the reference held by del_function doesn't release - // the last reference and delete the object recursively (infinitely). - { - ref del_function; - try { - instance* const target = boost::python::downcast(obj); - del_function = ref(target->getattr("__del__", false), ref::null_ok); - } - catch(...) { - } - - if (del_function.get() != 0) - { - ref result(PyEval_CallObject(del_function.get(), (PyObject *)NULL), ref::null_ok); - - if (result.get() == NULL) - report_ignored_exception(del_function.get()); - } - } - PyErr_Restore(exc_type, exc_value, exc_traceback); - - if (--obj->ob_refcnt <= 0) - delete_instance(obj); - } - - -} - -instance::instance(PyTypeObject* class_) - : boost::python::detail::base_object(class_) -{ -} - -instance::~instance() -{ -} - -PyObject* instance::getattr(const char* name, bool use_special_function) -{ - if (!BOOST_CSTD_::strcmp(name, "__dict__")) - { - if (PyEval_GetRestricted()) { - PyErr_SetString(PyExc_RuntimeError, - "instance.__dict__ not accessible in restricted mode"); - return 0; - } - Py_INCREF(m_name_space.get()); - return m_name_space.get(); - } - - if (!BOOST_CSTD_::strcmp(name, "__class__")) - { - Py_INCREF(this->ob_type); - return as_object(this->ob_type); - } - - if (!BOOST_CSTD_::strcmp(name, "__reduce__")) - { - return detail::bound_function::create(ref(this, ref::increment_count), global_instance_reduce()); - } - - ref local_attribute = m_name_space.get_item(string(name).reference()); - - if (local_attribute.get()) - return local_attribute.release(); - - // Check its class. - PyObject* function = - PyObject_GetAttrString(as_object(this->ob_type), const_cast(name)); - - if (function == 0 && !use_special_function) - { - return 0; - } - - ref class_attribute; - if (function != 0) - { - // This will throw if the attribute wasn't found - class_attribute = ref(function); - } - else - { - // Clear the error while we try special methods method (if any). - PyErr_Clear(); - - // First we try the special method that comes from concatenating - // "__getattr__" and and 2 trailing underscores. This is an - // extension to regular Python class functionality. - const string specific_getattr_name(detail::getattr_string() + name + "__"); - PyObject* getattr_method = PyObject_GetAttr( - as_object(this->ob_type), specific_getattr_name.get()); - - // Use just the first arg to PyEval_CallFunction if found - char* arg_format = const_cast("(O)"); - - // Try for the regular __getattr__ method if not found - if (getattr_method == 0) - { - PyErr_Clear(); - getattr_method = PyObject_GetAttrString( - as_object(this->ob_type), const_cast("__getattr__")); - - // Use both args to PyEval_CallFunction - arg_format = const_cast("(Os)"); - } - - // If there is no such method, throw now. - if (PyErr_Occurred()) - { - PyErr_SetString(PyExc_AttributeError, name); - return 0; - } - - // Take ownership of the method - ref owner(getattr_method); - - // Call it to get the attribute. - return PyEval_CallFunction(getattr_method, arg_format, this, name); - } - - if (!PyCallable_Check(class_attribute.get())) - { - PyErr_Clear(); - return class_attribute.release(); - } - else - { - return detail::bound_function::create(ref(this, ref::increment_count), class_attribute); - } -} - -// instance::setattr_dict -// -// Implements setattr() functionality for the "__dict__" attribute -// -int instance::setattr_dict(PyObject* value) -{ - if (PyEval_GetRestricted()) - { - PyErr_SetString(PyExc_RuntimeError, - "__dict__ not accessible in restricted mode"); - return -1; - } - - if (value == 0 || !PyDict_Check(value)) - { - PyErr_SetString(PyExc_TypeError, - "__dict__ must be set to a dictionary"); - return -1; - } - m_name_space = dictionary(ref(value, ref::increment_count)); - return 0; -} - -// instance::setattr - -// -// Implements the setattr() and delattr() functionality for our own instance -// objects, using the standard Python interface: if value == 0, we are deleting -// the attribute, and returns 0 unless an error occurred. -int instance::setattr(const char* name, PyObject* value) -{ - if (BOOST_CSTD_::strcmp(name, "__class__") == 0) - { - PyErr_SetString(PyExc_TypeError, "__class__ attribute is read-only"); - throw_error_already_set(); - } - - if (BOOST_CSTD_::strcmp(name, "__dict__") == 0) - return setattr_dict(value); - - // Try to find an appropriate "specific" setter or getter method, either - // __setattr____(value) or __delattr____(). This is an extension - // to regular Python class functionality. - const string& base_name = value ? detail::setattr_string() : detail::delattr_string(); - const string specific_method_name(base_name + name + "__"); - - ref special_method( - PyObject_GetAttr(as_object(this->ob_type), specific_method_name.get()), - ref::null_ok); - - PyObject* result_object = 0; - if (special_method.get() != 0) - { - // The specific function was found; call it now. Note that if value is - // not included in the format string, it is ignored. - char* format_string = const_cast(value ? "(OO)" : "(O)"); - result_object = PyEval_CallFunction(special_method.get(), format_string, this, value); - } - else - { - // If not found, try the usual __setattr__(name, value) or - // __delattr__(name) functions. - PyErr_Clear(); - special_method.reset( - PyObject_GetAttr(as_object(this->ob_type), base_name.get()), - ref::null_ok); - - if (special_method.get() != 0) - { - // The special function was found; call it now. Note that if value - // is not included in the format string, it is ignored. - char* format_string = const_cast(value ? "(OsO)" : "(Os)"); - result_object = PyEval_CallFunction( - special_method.get(), format_string, this, name, value); - } - } - - // If we found an appropriate special method, handle the return value. - if (special_method.get() != 0) - { - ref manage_result(result_object); - return 0; - } - - PyErr_Clear(); // Nothing was found; clear the python error state - - if (value == 0) // Try to remove the attribute from our name space - { - const int result = PyDict_DelItemString(m_name_space.reference().get(), - const_cast(name)); - if (result < 0) - { - PyErr_Clear(); - PyErr_SetString(PyExc_AttributeError, "delete non-existing instance attribute"); - } - return result; - } - else // Change the specified item in our name space - { - return PyDict_SetItemString(m_name_space.reference().get(), - const_cast(name), value); - } -} - -PyObject* instance::call(PyObject* args, PyObject* keywords) -{ - return PyEval_CallObjectWithKeywords( - ref(getattr("__call__")).get(), // take possession of the result from getattr() - args, keywords); -} - -PyObject* instance::repr() -{ - return callback::call_method(this, "__repr__"); -} - -int instance::compare(PyObject* other) -{ - return callback::call_method(this, "__cmp__", other); -} - -PyObject* instance::str() -{ - return callback::call_method(this, "__str__"); -} - -long instance::hash() -{ - return callback::call_method(this, "__hash__"); -} - -int instance::length() -{ - return callback::call_method(this, "__len__"); -} - -PyObject* instance::get_subscript(PyObject* key) -{ - return callback::call_method(this, "__getitem__", key); -} - -void instance::set_subscript(PyObject* key, PyObject* value) -{ - if (value == 0) - callback::call_method(this, "__delitem__", key); - else - callback::call_method(this, "__setitem__", key, value); -} - -PyObject* instance::get_slice(int start, int finish) -{ - return callback::call_method(this, "__getslice__", start, finish); -} - -void instance::set_slice(int start, int finish, PyObject* value) -{ - if (value == 0) - callback::call_method(this, "__delslice__", start, finish); - else - callback::call_method(this, "__setslice__", start, finish, value); -} - -PyObject* instance::add(PyObject* other) -{ - return callback::call_method(this, "__add__", other); -} - -PyObject* instance::subtract(PyObject* other) -{ - return callback::call_method(this, "__sub__", other); -} - -PyObject* instance::multiply(PyObject* other) -{ - return callback::call_method(this, "__mul__", other); -} - -PyObject* instance::divide(PyObject* other) -{ - return callback::call_method(this, "__div__", other); -} - -PyObject* instance::remainder(PyObject* other) -{ - return callback::call_method(this, "__mod__", other); -} - -PyObject* instance::divmod(PyObject* other) -{ - return callback::call_method(this, "__divmod__", other); -} - -PyObject* instance::power(PyObject* exponent, PyObject* modulus) -{ - if (as_object(modulus) == Py_None) - return callback::call_method(this, "__pow__", exponent); - else - return callback::call_method(this, "__pow__", exponent, modulus); -} - -PyObject* instance::negative() -{ - return callback::call_method(this, "__neg__"); -} - -PyObject* instance::positive() -{ - return callback::call_method(this, "__pos__"); -} - -PyObject* instance::absolute() -{ - return callback::call_method(this, "__abs__"); -} - -int instance::nonzero() -{ - return callback::call_method(this, "__nonzero__"); -} - -PyObject* instance::invert() -{ - return callback::call_method(this, "__invert__"); -} - -PyObject* instance::lshift(PyObject* other) -{ - return callback::call_method(this, "__lshift__", other); -} - -PyObject* instance::rshift(PyObject* other) -{ - return callback::call_method(this, "__rshift__", other); -} - -PyObject* instance::do_and(PyObject* other) -{ - return callback::call_method(this, "__and__", other); -} - -PyObject* instance::do_xor(PyObject* other) -{ - return callback::call_method(this, "__xor__", other); -} - -PyObject* instance::do_or(PyObject* other) -{ - return callback::call_method(this, "__or__", other); -} - -int instance::coerce(PyObject** x, PyObject** y) -{ - assert(this == *x); - - // Coerce must return a tuple - tuple result(callback::call_method(this, "__coerce__", *y)); - - *x = result[0].release(); - *y = result[1].release(); - return 0; -} - -PyObject* instance::as_int() -{ - return callback::call_method(this, "__int__"); -} - -PyObject* instance::as_long() -{ - return callback::call_method(this, "__long__"); -} - -PyObject* instance::as_float() -{ - return callback::call_method(this, "__float__"); -} - -PyObject* instance::oct() -{ - return callback::call_method(this, "__oct__"); -} - -PyObject* instance::hex() -{ - return callback::call_method(this, "__hex__"); -} - -PyObject* instance::lt(PyObject* other) -{ - return callback::call_method(this, "__lt__", other); -} - -PyObject* instance::le(PyObject* other) -{ - return callback::call_method(this, "__le__", other); -} - -PyObject* instance::eq(PyObject* other) -{ - return callback::call_method(this, "__eq__", other); -} - -PyObject* instance::ne(PyObject* other) -{ - return callback::call_method(this, "__ne__", other); -} - -PyObject* instance::gt(PyObject* other) -{ - return callback::call_method(this, "__gt__", other); -} - -PyObject* instance::ge(PyObject* other) -{ - return callback::call_method(this, "__ge__", other); -} - -PyObject* instance::inplace_add(PyObject* other) -{ - return callback::call_method(this, "__iadd__", other); -} - -PyObject* instance::inplace_subtract(PyObject* other) -{ - return callback::call_method(this, "__isub__", other); -} - -PyObject* instance::inplace_multiply(PyObject* other) -{ - return callback::call_method(this, "__imul__", other); -} - -PyObject* instance::inplace_divide(PyObject* other) -{ - return callback::call_method(this, "__idiv__", other); -} - -PyObject* instance::inplace_remainder(PyObject* other) -{ - return callback::call_method(this, "__imod__", other); -} - -PyObject* instance::inplace_power(PyObject* exponent, PyObject* modulus) -{ - if (modulus == Py_None) - return callback::call_method(this, "__ipow__", exponent); - else - return callback::call_method(this, "__ipow__", exponent, modulus); -} - -PyObject* instance::inplace_lshift(PyObject* other) -{ - return callback::call_method(this, "__ilshift__", other); -} - -PyObject* instance::inplace_rshift(PyObject* other) -{ - return callback::call_method(this, "__irshift__", other); -} - -PyObject* instance::inplace_and(PyObject* other) -{ - return callback::call_method(this, "__iand__", other); -} - -PyObject* instance::inplace_or(PyObject* other) -{ - return callback::call_method(this, "__ior__", other); -} - -PyObject* instance::inplace_xor(PyObject* other) -{ - return callback::call_method(this, "__ixor__", other); -} - -namespace { - struct named_capability - { - const char* name; - detail::type_object_base::capability capability; - }; - - const named_capability enablers[] = - { - { "__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 }, - { "__iadd__", detail::type_object_base::number_inplace_add }, - { "__isub__", detail::type_object_base::number_inplace_subtract }, - { "__imul__", detail::type_object_base::number_inplace_multiply }, - { "__idiv__", detail::type_object_base::number_inplace_divide }, - { "__imod__", detail::type_object_base::number_inplace_remainder }, - { "__ipow__", detail::type_object_base::number_inplace_power }, - { "__ilshift__", detail::type_object_base::number_inplace_lshift }, - { "__irshift__", detail::type_object_base::number_inplace_rshift }, - { "__iand__", detail::type_object_base::number_inplace_and }, - { "__ixor__", detail::type_object_base::number_inplace_xor }, - { "__ior__", detail::type_object_base::number_inplace_or }, - { "__repr__", detail::type_object_base::repr }, - { "__str__", detail::type_object_base::str }, - { "__call__", detail::type_object_base::call }, - { "__getattr__", detail::type_object_base::getattr }, - { "__setattr__", detail::type_object_base::setattr }, - { "__len__", detail::type_object_base::mapping_length }, - { "__len__", detail::type_object_base::sequence_length }, - { "__getitem__", detail::type_object_base::mapping_subscript }, - { "__getitem__", detail::type_object_base::sequence_item }, - { "__setitem__", detail::type_object_base::mapping_ass_subscript }, - { "__setitem__", detail::type_object_base::sequence_ass_item }, - { "__delitem__", detail::type_object_base::mapping_ass_subscript }, - { "__delitem__", detail::type_object_base::sequence_ass_item }, - { "__getslice__", detail::type_object_base::sequence_slice }, - { "__setslice__", detail::type_object_base::sequence_ass_slice }, - { "__delslice__", detail::type_object_base::sequence_ass_slice }, - { "__add__", detail::type_object_base::number_add }, - { "__sub__", detail::type_object_base::number_subtract }, - { "__mul__", detail::type_object_base::number_multiply }, - { "__div__", detail::type_object_base::number_divide }, - { "__mod__", detail::type_object_base::number_remainder }, - { "__divmod__", detail::type_object_base::number_divmod }, - { "__pow__", detail::type_object_base::number_power }, - { "__neg__", detail::type_object_base::number_negative }, - { "__pos__", detail::type_object_base::number_positive }, - { "__abs__", detail::type_object_base::number_absolute }, - { "__nonzero__", detail::type_object_base::number_nonzero }, - { "__invert__", detail::type_object_base::number_invert }, - { "__lshift__", detail::type_object_base::number_lshift }, - { "__rshift__", detail::type_object_base::number_rshift }, - { "__and__", detail::type_object_base::number_and }, - { "__xor__", detail::type_object_base::number_xor }, - { "__or__", detail::type_object_base::number_or }, - { "__coerce__", detail::type_object_base::number_coerce }, - { "__int__", detail::type_object_base::number_int }, - { "__long__", detail::type_object_base::number_long }, - { "__float__", detail::type_object_base::number_float }, - { "__oct__", detail::type_object_base::number_oct }, - { "__hex__", detail::type_object_base::number_hex } - }; - - bool is_prefix(const char* s1, const char* s2) - { - while (*s1 != 0 && *s2 != 0 && *s1 == *s2) - ++s1, ++s2; - return *s1 == 0; - } - - bool is_special_name(const char* name) - { - if (name[0] != '_' || name[1] != '_' || name[2] == 0 || name[3] == 0) - return false; - - std::size_t name_length = BOOST_CSTD_::strlen(name); - return name[name_length - 1] == '_' && name[name_length - 2] == '_'; - } -} - -namespace detail { - // Enable the special handler for methods of the given name, if any. - void enable_named_method(boost::python::detail::class_base* type_obj, const char* name) - { - const std::size_t num_enablers = PY_ARRAY_LENGTH(enablers); - - // Make sure this ends with "__" since we'll only compare the head of the - // string. This is done to make the __getattr____/__setattr____ - // extension work. - if (!is_special_name(name)) - return; - - for (std::size_t i = 0; i < num_enablers; ++i) - { - if (is_prefix(enablers[i].name + 2, name + 2)) - { - type_obj->enable(enablers[i].capability); - } - } - } -} - -namespace { - // Enable any special methods which are enabled in the base class. - void enable_special_methods(boost::python::detail::class_base* derived, const tuple& bases, const dictionary& name_space) - { - for (std::size_t i = 0; i < bases.size(); ++i) - { - PyObject* base = bases[i].get(); - - for (std::size_t n = 0; n < PY_ARRAY_LENGTH(enablers); ++n) - { - ref attribute( - PyObject_GetAttrString(base, const_cast(enablers[n].name)), - ref::null_ok); - PyErr_Clear(); - if (attribute.get() != 0 && PyCallable_Check(attribute.get())) - detail::add_capability(enablers[n].capability, derived); - } - } - - list keys(name_space.keys()); - for (std::size_t j = 0, len = keys.size(); j < len; ++j) - { - string name_obj(keys.get_item(j)); - const char* name = name_obj.c_str(); - - if (!is_special_name(name)) - continue; - - for (std::size_t i = 0; i < PY_ARRAY_LENGTH(enablers); ++i) - { - if (is_prefix(enablers[i].name + 2, name + 2)) - { - detail::add_capability(enablers[i].capability, derived); - } - } - } - } - - void add_current_module_name(dictionary& name_space) - { - static string module_key("__module__", string::interned); - - // If the user didn't specify a __module__ attribute already - if (name_space.get_item(module_key).get() == 0) - { - if (module_builder::initializing()) - { - // The global __name__ is not properly set in this case - name_space.set_item(module_key, module_builder::name()); - } - else - { - // Get the module name from the global __name__ - PyObject *globals = PyEval_GetGlobals(); - if (globals != NULL) - { - PyObject *module_name = PyDict_GetItemString(globals, const_cast("__name__")); - if (module_name != NULL) - name_space.set_item(module_key, module_name); - } - } - } - } -} - -BOOST_PYTHON_DECL bool adjust_slice_indices(PyObject* obj, int& start, int& finish) -{ - ref len(PyEval_CallMethod(obj, "__len__", "()") - , ref::null_ok); - - if (len.get() == 0) - return false; - - int length = PyInt_AsLong(len.get()); - - // This is standard Python class behavior. - if (start < 0) - start += length; - if (finish < 0) - finish += length; - - // This is not - if (start < 0) - start = 0; - if (finish < 0) - finish = 0; - - return true; -} - -namespace detail { -const string& setattr_string() -{ - static string x("__setattr__", string::interned); - return x; -} - -const string& getattr_string() -{ - static string x("__getattr__", string::interned); - return x; -} - -const string& delattr_string() -{ - static string x("__delattr__", string::interned); - return x; -} -} - -}} // namespace boost::python diff --git a/src/conversions.cpp b/src/conversions.cpp deleted file mode 100644 index 3c5edad5..00000000 --- a/src/conversions.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// Revision History: -// 05 Apr 01 added: from_python std::string type checking (rwgk) -// 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve) -// 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) -// 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) -// 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) - -#define BOOST_PYTHON_SOURCE - -#include -#include -#include -#include -#include - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -BOOST_PYTHON_DECL long from_python(PyObject* p, boost::python::type) -{ - // Why am I clearing the error here before trying to convert? I know there's a reason... - long result; - { - result = PyInt_AsLong(p); - if (PyErr_Occurred()) - boost::python::throw_argument_error(); - } - return result; -} - -BOOST_PYTHON_DECL double from_python(PyObject* p, boost::python::type) -{ - double result; - { - result = PyFloat_AsDouble(p); - if (PyErr_Occurred()) - boost::python::throw_argument_error(); - } - return result; -} - -template -T integer_from_python(PyObject* p, boost::python::type) -{ - const long long_result = from_python(p, boost::python::type()); - - try - { - return boost::numeric_cast(long_result); - } - catch(const boost::bad_numeric_cast&) - { - char buffer[256]; - const char message[] = "%ld out of range for %s"; - sprintf(buffer, message, long_result, typeid(T).name()); - PyErr_SetString(PyExc_ValueError, buffer); - boost::python::throw_argument_error(); - } - return 0; // Not smart enough to know that the catch clause always rethrows -} - -template -PyObject* integer_to_python(T value) -{ - long value_as_long; - - try - { - value_as_long = boost::numeric_cast(value); - } - catch(const boost::bad_numeric_cast&) - { - const char message[] = "value out of range for Python int"; - PyErr_SetString(PyExc_ValueError, message); - boost::python::throw_error_already_set(); - } - - return to_python(value_as_long); -} - -BOOST_PYTHON_DECL int from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -BOOST_PYTHON_DECL PyObject* to_python(unsigned int i) -{ - return integer_to_python(i); -} - -BOOST_PYTHON_DECL unsigned int from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -BOOST_PYTHON_DECL short from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -BOOST_PYTHON_DECL float from_python(PyObject* p, boost::python::type) -{ - return static_cast(from_python(p, boost::python::type())); -} - -BOOST_PYTHON_DECL PyObject* to_python(unsigned short i) -{ - return integer_to_python(i); -} - -BOOST_PYTHON_DECL unsigned short from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -BOOST_PYTHON_DECL PyObject* to_python(char c) -{ - if (c == '\0') return PyString_FromString(""); - return PyString_FromStringAndSize(&c, 1); -} - -BOOST_PYTHON_DECL char from_python(PyObject* p, boost::python::type) -{ - int l = -1; - if (PyString_Check(p)) l = PyString_Size(p); - if (l < 0 || l > 1) { - PyErr_SetString(PyExc_TypeError, "expected string of length 0 or 1"); - boost::python::throw_argument_error(); - } - if (l == 0) return '\0'; - return PyString_AsString(p)[0]; -} - -BOOST_PYTHON_DECL PyObject* to_python(unsigned char i) -{ - return integer_to_python(i); -} - -BOOST_PYTHON_DECL unsigned char from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -BOOST_PYTHON_DECL PyObject* to_python(signed char i) -{ - return integer_to_python(i); -} - -BOOST_PYTHON_DECL signed char from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -BOOST_PYTHON_DECL PyObject* to_python(unsigned long x) -{ - return integer_to_python(x); -} - -BOOST_PYTHON_DECL unsigned long from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -BOOST_PYTHON_DECL void from_python(PyObject* p, boost::python::type) -{ - if (p != Py_None) { - PyErr_SetString(PyExc_TypeError, "expected argument of type None"); - boost::python::throw_argument_error(); - } -} - -BOOST_PYTHON_DECL const char* from_python(PyObject* p, boost::python::type) -{ - const char* s = PyString_AsString(p); - if (!s) - boost::python::throw_argument_error(); - return s; -} - -BOOST_PYTHON_DECL PyObject* to_python(const std::string& s) -{ - return PyString_FromStringAndSize(s.data(), s.size()); -} - -BOOST_PYTHON_DECL std::string from_python(PyObject* p, boost::python::type) -{ - if (! PyString_Check(p)) { - PyErr_SetString(PyExc_TypeError, "expected a string"); - boost::python::throw_argument_error(); - } - return std::string(PyString_AsString(p), PyString_Size(p)); -} - -BOOST_PYTHON_DECL bool from_python(PyObject* p, boost::python::type) -{ - int value = from_python(p, boost::python::type()); - if (value == 0) - return false; - return true; -} - -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 -// An optimizer bug prevents these from being inlined. -BOOST_PYTHON_DECL PyObject* to_python(double d) -{ - return PyFloat_FromDouble(d); -} - -BOOST_PYTHON_DECL PyObject* to_python(float f) -{ - return PyFloat_FromDouble(f); -} -#endif - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - diff --git a/src/converter/arg_to_python_base.cpp b/src/converter/arg_to_python_base.cpp deleted file mode 100644 index 1740f6ee..00000000 --- a/src/converter/arg_to_python_base.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace converter { - -namespace -{ - inline PyObject* convert_to_python(void const volatile* source, registration const& converters) - { - if (converters.to_python == 0) - { - handle<> msg( - ::PyString_FromFormat( - "No to_python (by-value) converter found for C++ type: %s" - , converters.target_type.name())); - - PyErr_SetObject(PyExc_TypeError, msg.get()); - - throw_error_already_set(); - } - - return source == 0 - ? incref(Py_None) - : converters.to_python(const_cast(source)); - } -} - -namespace detail -{ - arg_to_python_base::arg_to_python_base( - void const volatile* source, registration const& converters) -# if !defined(BOOST_MSVC) || BOOST_MSVC <= 1300 || _MSC_FULL_VER > 13102179 - : handle<>(converter::convert_to_python(source, converters)) -# else - : m_ptr(converter::convert_to_python(source, converters)) -# endif - { - } - - BOOST_PYTHON_DECL void throw_no_class_registered() - { - PyErr_SetString( - PyExc_TypeError - , const_cast("class not registered for to_python type")); - throw_error_already_set(); - } -} - -}}} // namespace boost::python::converter diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp deleted file mode 100644 index b5916dde..00000000 --- a/src/converter/builtin_converters.cpp +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace converter { - -namespace -{ - // An lvalue conversion function which extracts a char const* from a - // Python String. - void* convert_to_cstring(PyObject* obj) - { - return PyString_Check(obj) ? PyString_AsString(obj) : 0; - } - - // Given a target type and a SlotPolicy describing how to perform a - // given conversion, registers from_python converters which use the - // SlotPolicy to extract the type. - template - struct slot_rvalue_from_python - { - public: - slot_rvalue_from_python() - { - registry::insert( - &slot_rvalue_from_python::convertible - , &slot_rvalue_from_python::construct - , type_id() - ); - } - - private: - static void* convertible(PyObject* obj) - { - unaryfunc* slot = SlotPolicy::get_slot(obj); - return slot && *slot ? slot : 0; - } - - static void construct(PyObject* obj, rvalue_from_python_stage1_data* data) - { - // Get the (intermediate) source object - unaryfunc creator = *static_cast(data->convertible); - handle<> intermediate(creator(obj)); - - // Get the location in which to construct - void* storage = ((rvalue_from_python_storage*)data)->storage.bytes; - new (storage) T(SlotPolicy::extract(intermediate.get())); - - // record successful construction - data->convertible = storage; - } - }; - - // A SlotPolicy for extracting integer types from Python objects - struct int_rvalue_from_python_base - { - static unaryfunc* get_slot(PyObject* obj) - { - PyNumberMethods* number_methods = obj->ob_type->tp_as_number; - if (number_methods == 0) - return 0; - - return (PyInt_Check(obj) || PyLong_Check(obj)) - ? &number_methods->nb_int : 0; - } - }; - - template - struct int_rvalue_from_python : int_rvalue_from_python_base - { - static T extract(PyObject* intermediate) - { - return numeric_cast(PyInt_AS_LONG(intermediate)); - } - }; - -// Checking Python's macro instead of Boost's - we don't seem to get -// the config right all the time. Furthermore, Python's is defined -// when long long is absent but __int64 is present. - -#ifdef HAVE_LONG_LONG - // A SlotPolicy for extracting long long types from Python objects - - struct long_long_rvalue_from_python_base - { - static unaryfunc* get_slot(PyObject* obj) - { - PyNumberMethods* number_methods = obj->ob_type->tp_as_number; - if (number_methods == 0) - return 0; - - // Return the identity conversion slot to avoid creating a - // new object. We'll handle that in the extract function - if (PyInt_Check(obj)) - return &number_methods->nb_int; - else if (PyLong_Check(obj)) - return &number_methods->nb_long; - else - return 0; - } - }; - - struct long_long_rvalue_from_python : long_long_rvalue_from_python_base - { - static LONG_LONG extract(PyObject* intermediate) - { - if (PyInt_Check(intermediate)) - { - return PyInt_AS_LONG(intermediate); - } - else - { - LONG_LONG result = PyLong_AsLongLong(intermediate); - - if (PyErr_Occurred()) - throw_error_already_set(); - - return result; - } - } - }; - - struct unsigned_long_long_rvalue_from_python : long_long_rvalue_from_python_base - { - static unsigned LONG_LONG extract(PyObject* intermediate) - { - if (PyInt_Check(intermediate)) - { - return numeric_cast(PyInt_AS_LONG(intermediate)); - } - else - { - unsigned LONG_LONG result = PyLong_AsUnsignedLongLong(intermediate); - - if (PyErr_Occurred()) - throw_error_already_set(); - - return result; - } - } - }; -#endif - - // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc - // "slot" which just returns its argument. Used for bool - // conversions, since all Python objects are directly convertible to - // bool - extern "C" PyObject* identity_unaryfunc(PyObject* x) - { - Py_INCREF(x); - return x; - } - unaryfunc py_object_identity = identity_unaryfunc; - - // A SlotPolicy for extracting bool from a Python object - struct bool_rvalue_from_python - { - static unaryfunc* get_slot(PyObject* obj) - { - return obj == Py_None || PyInt_Check(obj) ? &py_object_identity : 0; - } - - static bool extract(PyObject* intermediate) - { - return PyObject_IsTrue(intermediate); - } - }; - - // A SlotPolicy for extracting floating types from Python objects. - struct float_rvalue_from_python - { - static unaryfunc* get_slot(PyObject* obj) - { - PyNumberMethods* number_methods = obj->ob_type->tp_as_number; - if (number_methods == 0) - return 0; - - // For integer types, return the tp_int conversion slot to avoid - // creating a new object. We'll handle that below - if (PyInt_Check(obj)) - return &number_methods->nb_int; - - return (PyLong_Check(obj) || PyFloat_Check(obj)) - ? &number_methods->nb_float : 0; - } - - static double extract(PyObject* intermediate) - { - if (PyInt_Check(intermediate)) - { - return PyInt_AS_LONG(intermediate); - } - else - { - return PyFloat_AS_DOUBLE(intermediate); - } - } - }; - - // A SlotPolicy for extracting C++ strings from Python objects. - struct string_rvalue_from_python - { - // If the underlying object is "string-able" this will succeed - static unaryfunc* get_slot(PyObject* obj) - { - return (PyString_Check(obj)) - ? &obj->ob_type->tp_str : 0; - }; - - // Remember that this will be used to construct the result object - static char const* extract(PyObject* intermediate) - { - return PyString_AsString(intermediate); - } - }; - - struct complex_rvalue_from_python - { - static unaryfunc* get_slot(PyObject* obj) - { - if (PyComplex_Check(obj)) - return &py_object_identity; - else - return float_rvalue_from_python::get_slot(obj); - } - - static std::complex extract(PyObject* intermediate) - { - if (PyComplex_Check(intermediate)) - { - return std::complex( - PyComplex_RealAsDouble(intermediate) - , PyComplex_ImagAsDouble(intermediate)); - } - else if (PyInt_Check(intermediate)) - { - return PyInt_AS_LONG(intermediate); - } - else - { - return PyFloat_AS_DOUBLE(intermediate); - } - } - }; -} - -BOOST_PYTHON_DECL PyObject* do_return_to_python(char x) -{ - return PyString_FromStringAndSize(&x, 1); -} - -BOOST_PYTHON_DECL PyObject* do_return_to_python(char const* x) -{ - return x ? PyString_FromString(x) : boost::python::detail::none(); -} - -BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject* x) -{ - return x ? x : boost::python::detail::none(); -} - -BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject* x) -{ - if (x == 0) - return boost::python::detail::none(); - - Py_INCREF(x); - return x; -} - -#define REGISTER_INT_CONVERTERS(U) slot_rvalue_from_python >() -#define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U) - -void initialize_builtin_converters() -{ - // booleans - slot_rvalue_from_python(); - - // integer types - REGISTER_INT_CONVERTERS2(char); - REGISTER_INT_CONVERTERS2(short); - REGISTER_INT_CONVERTERS2(int); - REGISTER_INT_CONVERTERS2(long); - -// using Python's macro instead of Boost's - we don't seem to get the -// config right all the time. -# ifdef HAVE_LONG_LONG - slot_rvalue_from_python(); - slot_rvalue_from_python(); -# endif - - // floating types - slot_rvalue_from_python(); - slot_rvalue_from_python(); - slot_rvalue_from_python(); - - slot_rvalue_from_python,complex_rvalue_from_python>(); - slot_rvalue_from_python,complex_rvalue_from_python>(); - slot_rvalue_from_python,complex_rvalue_from_python>(); - - // Add an lvalue converter for char which gets us char const* - registry::insert(convert_to_cstring,type_id()); - - // Register by-value converters to std::string - slot_rvalue_from_python(); -} - -}}} // namespace boost::python::converter diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp deleted file mode 100644 index ade39a21..00000000 --- a/src/converter/from_python.cpp +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace converter { - -// rvalue_from_python_stage1 -- do the first stage of a conversion -// from a Python object to a C++ rvalue. -// -// source - the Python object to be converted -// converters - the registry entry for the target type T -// -// Postcondition: where x is the result, one of: -// -// 1. x.convertible == 0, indicating failure -// -// 2. x.construct == 0, x.convertible is the address of an object of -// type T. Indicates a successful lvalue conversion -// -// 3. where y is of type rvalue_from_python_data, -// x.construct(source, y) constructs an object of type T -// in y.storage.bytes and then sets y.convertible == y.storage.bytes, -// or else throws an exception and has no effect. -BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( - PyObject* source - , registration const& converters) -{ - rvalue_from_python_chain const* chain = converters.rvalue_chain; - - rvalue_from_python_stage1_data data; - data.convertible = 0; - for (;chain != 0; chain = chain->next) - { - void* r = chain->convertible(source); - if (r != 0) - { - data.convertible = r; - data.construct = chain->construct; - break; - } - } - return data; -} - -// rvalue_result_from_python -- return the address of a C++ object which -// can be used as the result of calling a Python function. -// -// src - the Python object to be converted -// -// data - a reference to the base part of a -// rvalue_from_python_data object, where T is the -// target type of the conversion. -// -// Requires: data.convertible == ®istered::converters -// -BOOST_PYTHON_DECL void* rvalue_result_from_python( - PyObject* src, rvalue_from_python_stage1_data& data) -{ - // Take possession of the source object. - handle<> holder(src); - - // Retrieve the registration - // Cast in two steps for less-capable compilers - void const* converters_ = data.convertible; - registration const& converters = *static_cast(converters_); - - // Look for an eligible converter - data = rvalue_from_python_stage1(src, converters); - return rvalue_from_python_stage2(src, data, converters); -} - -BOOST_PYTHON_DECL void* rvalue_from_python_stage2( - PyObject* source, rvalue_from_python_stage1_data& data, registration const& converters) -{ - if (!data.convertible) - { - handle<> msg( - ::PyString_FromFormat( - "No registered converter was able to produce a C++ rvalue of type %s from this Python object of type %s" - , converters.target_type.name() - , source->ob_type->tp_name - )); - - PyErr_SetObject(PyExc_TypeError, msg.get()); - throw_error_already_set(); - } - - // If a construct function was registered (i.e. we found an - // rvalue conversion), call it now. - if (data.construct != 0) - data.construct(source, &data); - - // Return the address of the resulting C++ object - return data.convertible; -} - -BOOST_PYTHON_DECL void* get_lvalue_from_python( - PyObject* source - , registration const& converters) -{ - lvalue_from_python_chain const* chain = converters.lvalue_chain; - - for (;chain != 0; chain = chain->next) - { - void* r = chain->convert(source); - if (r != 0) - return r; - } - return 0; -} - -namespace -{ - // Prevent looping in implicit conversions. This could/should be - // much more efficient, but will work for now. - typedef std::vector visited_t; - static visited_t visited; - - inline bool visit(rvalue_from_python_chain const* chain) - { - visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain); - if (p != visited.end() && *p == chain) - return false; - visited.insert(p, chain); - return true; - } - - void unvisit(rvalue_from_python_chain const* chain) - { - visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain); - assert(p != visited.end()); - visited.erase(p); - } -} - -BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain( - PyObject* source - , registration const& converters) -{ - rvalue_from_python_chain const* chain = converters.rvalue_chain; - - if (!visit(chain)) - return 0; - - try - { - for (;chain != 0; chain = chain->next) - { - if (chain->convertible(source)) - break; - } - } - catch(...) - { - unvisit(chain); - throw; - } - unvisit(chain); - return chain; -} - -namespace -{ - void throw_no_lvalue_from_python(PyObject* source, registration const& converters, char const* ref_type) - { - handle<> msg( - ::PyString_FromFormat( - "No registered converter was able to extract a C++ %s to type %s" - " from this Python object of type %s" - , ref_type - , converters.target_type.name() - , source->ob_type->tp_name - )); - - PyErr_SetObject(PyExc_TypeError, msg.get()); - - throw_error_already_set(); - } - - void* lvalue_result_from_python( - PyObject* source - , registration const& converters - , char const* ref_type) - { - handle<> holder(source); - if (source->ob_refcnt <= 2) - { - handle<> msg( - ::PyString_FromFormat( - "Attempt to return dangling %s to object of type: %s" - , ref_type - , converters.target_type.name())); - - PyErr_SetObject(PyExc_ReferenceError, msg.get()); - - throw_error_already_set(); - } - - void* result = get_lvalue_from_python(source, converters); - if (!result) - (throw_no_lvalue_from_python)(source, converters, ref_type); - return result; - } - -} - -BOOST_PYTHON_DECL void throw_no_pointer_from_python(PyObject* source, registration const& converters) -{ - (throw_no_lvalue_from_python)(source, converters, "pointer"); -} - -BOOST_PYTHON_DECL void throw_no_reference_from_python(PyObject* source, registration const& converters) -{ - (throw_no_lvalue_from_python)(source, converters, "reference"); -} - -BOOST_PYTHON_DECL void* reference_result_from_python( - PyObject* source - , registration const& converters) -{ - return (lvalue_result_from_python)(source, converters, "reference"); -} - -BOOST_PYTHON_DECL void* pointer_result_from_python( - PyObject* source - , registration const& converters) -{ - if (source == Py_None) - { - Py_DECREF(source); - return 0; - } - return (lvalue_result_from_python)(source, converters, "pointer"); -} - -BOOST_PYTHON_DECL void throw_no_class_registered() -{ - PyErr_SetString( - PyExc_TypeError - , const_cast("class not registered for to_python type")); - throw_error_already_set(); -} - -BOOST_PYTHON_DECL void void_result_from_python(PyObject* o) -{ - Py_DECREF(expect_non_null(o)); -} - -} - -BOOST_PYTHON_DECL PyObject* -pytype_check(PyTypeObject* type_, PyObject* source) -{ - if (!PyObject_IsInstance(source, python::upcast(type_))) - { - handle<> keeper(source); - handle<> msg( - ::PyString_FromFormat( - "Expecting an object of type %s; got an object of type %s instead" - , type_->tp_name - , source->ob_type->tp_name - )); - PyErr_SetObject(PyExc_TypeError, msg.get()); - throw_error_already_set(); - } - return source; -} - -}} // namespace boost::python::converter diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp deleted file mode 100644 index 60db3bb8..00000000 --- a/src/converter/registry.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright David Abrahams 2001. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#include -#include -#include -#include -#include - -#ifdef BOOST_PYTHON_TRACE_REGISTRY -# include -#endif - -namespace boost { namespace python { namespace converter { - -namespace // -{ - typedef registration entry; - - typedef std::set registry_t; - - registry_t& entries() - { - static registry_t registry; - -# ifdef BOOST_PYTHON_DYNAMIC_LIB // this conditional should go away eventually. - static bool builtin_converters_initialized = false; - if (!builtin_converters_initialized) - { - // Make this true early because registering the builtin - // converters will cause recursion. - builtin_converters_initialized = true; - - initialize_builtin_converters(); - } -# ifdef BOOST_PYTHON_TRACE_REGISTRY - std::cout << "registry: "; - for (registry_t::iterator p = registry.begin(); p != registry.end(); ++p) - { - std::cout << p->target_type << "; "; - } - std::cout << '\n'; -# endif -# endif - return registry; - } - - entry* get(type_info type) - { -# ifdef BOOST_PYTHON_TRACE_REGISTRY - registry_t::iterator p = entries().find(entry(type)); - - std::cout << "looking up " << type - << (p == entries().end() || p->target_type != type - ? "...NOT found\n" : "...found\n"); -# endif - return const_cast( - &*entries().insert(entry(type)).first - ); - } -} // namespace - -namespace registry -{ - void insert(to_python_function_t f, type_info source_t) - { -# ifdef BOOST_PYTHON_TRACE_REGISTRY - std::cout << "inserting to_python " << source_t << "\n"; -# endif - to_python_function_t& slot = get(source_t)->to_python; - - assert(slot == 0); // we have a problem otherwise - if (slot != 0) - { - throw std::runtime_error( - "trying to register to_python_converter for a type which already has a registered to_python_converter"); - } - slot = f; - } - - // Insert an lvalue from_python converter - void insert(convertible_function convert, type_info key) - { -# ifdef BOOST_PYTHON_TRACE_REGISTRY - std::cout << "inserting lvalue from_python " << key << "\n"; -# endif - entry* found = get(key); - lvalue_from_python_chain *registration = new lvalue_from_python_chain; - registration->convert = convert; - registration->next = found->lvalue_chain; - found->lvalue_chain = registration; - - insert(convert, 0, key); - } - - // Insert an rvalue from_python converter - void insert(void* (*convertible)(PyObject*) - , constructor_function construct - , type_info key) - { -# ifdef BOOST_PYTHON_TRACE_REGISTRY - std::cout << "inserting rvalue from_python " << key << "\n"; -# endif - entry* found = get(key); - rvalue_from_python_chain *registration = new rvalue_from_python_chain; - registration->convertible = convertible; - registration->construct = construct; - registration->next = found->rvalue_chain; - found->rvalue_chain = registration; - } - - // Insert an rvalue from_python converter - void push_back(void* (*convertible)(PyObject*) - , constructor_function construct - , type_info key) - { -# ifdef BOOST_PYTHON_TRACE_REGISTRY - std::cout << "push_back rvalue from_python " << key << "\n"; -# endif - rvalue_from_python_chain** found = &get(key)->rvalue_chain; - while (*found != 0) - found = &(*found)->next; - - rvalue_from_python_chain *registration = new rvalue_from_python_chain; - registration->convertible = convertible; - registration->construct = construct; - registration->next = 0; - *found = registration; - } - - registration const& lookup(type_info key) - { - return *get(key); - } - - registration const* query(type_info type) - { - registry_t::iterator p = entries().find(entry(type)); -# ifdef BOOST_PYTHON_TRACE_REGISTRY - std::cout << "querying " << type - << (p == entries().end() || p->target_type != type - ? "...NOT found\n" : "...found\n"); -# endif - return (p == entries().end() || p->target_type != type) ? 0 : &*p; - } -} // namespace registry - -}}} // namespace boost::python::converter diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp deleted file mode 100644 index 74bcd39b..00000000 --- a/src/converter/type_id.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright David Abrahams 2001. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT -# include -#else -# include -#endif - -namespace boost { namespace python { - -BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_info const& x) -{ - return os << x.name(); -} - -namespace detail -{ - BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, detail::decorated_type_info const& x) - { - os << x.m_base_type; - if (x.m_decoration & decorated_type_info::const_) - os << " const"; - if (x.m_decoration & decorated_type_info::volatile_) - os << " volatile"; - if (x.m_decoration & decorated_type_info::reference) - os << "&"; - return os; - } -} -}} // namespace boost::python::converter diff --git a/src/cross_module.cpp b/src/cross_module.cpp deleted file mode 100644 index d339c4a7..00000000 --- a/src/cross_module.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* (C) Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy, use, - modify, sell and distribute this software is granted provided this - copyright notice appears in all copies. This software is provided - "as is" without express or implied warranty, and with no claim as to - its suitability for any purpose. - - Revision History: - 17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve) -*/ - -#define BOOST_PYTHON_SOURCE - -# include -namespace python = boost::python; -# include // MSVC6.0SP4 does not know std::fprintf -# include // MSVC6.0SP4 does not know std::strcmp - -namespace -{ - - PyObject* get_module_dict(const char* module_name) - { - python::ref module_obj(PyImport_ImportModule((char*) module_name)); - PyObject* module_dict = PyModule_GetDict(module_obj.get()); - if (module_dict == 0) python::throw_import_error(); - return module_dict; - } -} - -namespace boost { namespace python { - -void BOOST_PYTHON_DECL throw_import_error() -{ - throw import_error(); -} - -void BOOST_PYTHON_DECL throw_export_error() -{ - throw export_error(); -} - -namespace detail -{ - BOOST_PYTHON_DECL const char* converters_attribute_name = "__converters__"; - - BOOST_PYTHON_DECL void* import_converter_object(const std::string& module_name, - const std::string& py_class_name, - const std::string& attribute_name) - { - static std::string err; - PyObject* module_dict = get_module_dict(const_cast(module_name.c_str())); - PyObject* py_class = PyDict_GetItemString(module_dict, const_cast(py_class_name.c_str())); - if (py_class == 0) { - err = std::string("module ") + module_name + " has no attribute " + py_class_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - python::throw_import_error(); - } - python::ref c_obj(PyObject_GetAttrString(py_class, const_cast(attribute_name.c_str())), ref::null_ok); - if (c_obj.get() == 0) { - err = std::string("object ") + module_name + "." + py_class_name - + " has no attribute " + attribute_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - python::throw_import_error(); - } - if (! PyCObject_Check(c_obj.get())) { - err = std::string("object ") + module_name + "." + py_class_name + "." - + attribute_name + " is not a PyCObject"; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - python::throw_import_error(); - } - return PyCObject_AsVoidPtr(c_obj.get()); - } - - BOOST_PYTHON_DECL void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor) - { - if (importing_major != imported_major) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Fatal: export_converters_api mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - PyErr_SetString(PyExc_RuntimeError, - "Fatal: export_converters_api mismatch"); - throw_import_error(); - } - if (importing_minor != imported_minor) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Warning: export_converters_api mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - } - } - -} - -}} // namespace boost::python::detail diff --git a/src/dict.cpp b/src/dict.cpp deleted file mode 100644 index 6cd72c27..00000000 --- a/src/dict.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include - -namespace boost { namespace python { - -namespace -{ - // When returning list objects from methods, it may turn out that the - // derived class is returning something else, perhaps something not - // even derived from list. Since it is generally harmless for a - // Boost.Python wrapper object to hold an object of a different - // type, and because calling list() with an object may in fact - // perform a conversion, the least-bad alternative is to assume that - // we have a Python list object and stuff it into the list result. - list assume_list(object const& o) - { - return list(detail::borrowed_reference(o.ptr())); - } - - // No PyDict_CheckExact; roll our own. - inline bool check_exact(dict const* p) - { - return p->ptr()->ob_type == &PyDict_Type; - } -} - -BOOST_PYTHON_DECL detail::new_reference dict::call(object const& arg_) -{ - return (detail::new_reference)PyObject_CallFunction( - (PyObject*)&PyDict_Type, "(O)", - arg_.ptr()); -} - -BOOST_PYTHON_DECL dict::dict() - : object(detail::new_reference(PyDict_New())) -{} - -BOOST_PYTHON_DECL dict::dict(object_cref data) - : object(dict::call(data)) -{} - -BOOST_PYTHON_DECL void dict::clear() -{ - if (check_exact(this)) - PyDict_Clear(this->ptr()); - else - this->attr("clear")(); -} - -BOOST_PYTHON_DECL dict dict::copy() -{ - if (check_exact(this)) - { - return dict(detail::new_reference( - PyDict_Copy(this->ptr()))); - } - else - { - return dict(detail::borrowed_reference( - this->attr("copy")().ptr() - )); - } -} - -BOOST_PYTHON_DECL object dict::get(object_cref k) const -{ - if (check_exact(this)) - { - return object(detail::borrowed_reference( - PyDict_GetItem(this->ptr(),k.ptr()))); - } - else - { - return this->attr("get")(k); - } -} - -BOOST_PYTHON_DECL object dict::get(object_cref k, object_cref d) const -{ - return this->attr("get")(k,d); -} - -BOOST_PYTHON_DECL bool dict::has_key(object_cref k) const -{ - return extract(this->attr("has_key")(k)); -} - -BOOST_PYTHON_DECL list dict::items() const -{ - if (check_exact(this)) - { - return list(detail::new_reference( - PyDict_Items(this->ptr()))); - } - else - { - return assume_list(this->attr("items")()); - } -} - -BOOST_PYTHON_DECL object dict::iteritems() const -{ - return this->attr("iteritems")(); -} - -BOOST_PYTHON_DECL object dict::iterkeys() const -{ - return this->attr("iterkeys")(); -} - -BOOST_PYTHON_DECL object dict::itervalues() const -{ - return this->attr("itervalues")(); -} - -BOOST_PYTHON_DECL list dict::keys() const -{ - if (check_exact(this)) - { - return list(detail::new_reference( - PyDict_Keys(this->ptr()))); - } - else - { - return assume_list(this->attr("keys")()); - } -} - -BOOST_PYTHON_DECL tuple dict::popitem() -{ - return tuple(detail::borrowed_reference( - this->attr("popitem")().ptr() - )); -} - -BOOST_PYTHON_DECL object dict::setdefault(object_cref k) -{ - return this->attr("setdefault")(k); -} - -BOOST_PYTHON_DECL object dict::setdefault(object_cref k, object_cref d) -{ - return this->attr("setdefault")(k,d); -} - -BOOST_PYTHON_DECL void dict::update(object_cref other) -{ - if (check_exact(this)) - { - if (PyDict_Update(this->ptr(),other.ptr()) == -1) - throw_error_already_set(); - } - else - { - this->attr("update")(other); - } -} - -BOOST_PYTHON_DECL list dict::values() const -{ - if (check_exact(this)) - { - return list(detail::new_reference( - PyDict_Values(this->ptr()))); - } - else - { - return assume_list(this->attr("values")()); - } -} - -}} // namespace boost::python diff --git a/src/errors.cpp b/src/errors.cpp deleted file mode 100644 index 05e40658..00000000 --- a/src/errors.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright David Abrahams 2001. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#ifndef BOOST_PYTHON_SOURCE -# define BOOST_PYTHON_SOURCE -#endif - -#include -#include -#ifdef BOOST_PYTHON_V2 -# include -#endif - -namespace boost { namespace python { - -// IMPORTANT: this function may only be called from within a catch block! -BOOST_PYTHON_DECL bool handle_exception_impl(function0 f) -{ - try - { -#ifdef BOOST_PYTHON_V2 - if (detail::exception_handler::chain) - return detail::exception_handler::chain->handle(f); -#endif - f(); - return false; - } - catch(const boost::python::error_already_set&) - { - // The python error reporting has already been handled. - } - catch(const std::bad_alloc&) - { - PyErr_NoMemory(); - } - catch(const bad_numeric_cast& x) - { - PyErr_SetString(PyExc_OverflowError, x.what()); - } - catch(const std::exception& x) - { - PyErr_SetString(PyExc_RuntimeError, x.what()); - } - catch(...) - { - PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception"); - } - return true; -} - -void BOOST_PYTHON_DECL throw_argument_error() -{ - throw argument_error(); -} - -void BOOST_PYTHON_DECL throw_error_already_set() -{ - throw error_already_set(); -} - -namespace detail { - - BOOST_PYTHON_DECL void expect_complex(PyObject* p) - { - if (!PyComplex_Check(p)) - { - PyErr_SetString(PyExc_TypeError, "expected a complex number"); - boost::python::throw_argument_error(); - } - } - -// needed by void_adaptor (see void_adaptor.hpp) -BOOST_PYTHON_DECL PyObject arbitrary_object = { 0 }; - -#ifdef BOOST_PYTHON_V2 -bool exception_handler::operator()(function0 const& f) const -{ - if (m_next) - { - return m_next->handle(f); - } - else - { - f(); - return false; - } -} - -exception_handler::exception_handler(handler_function const& impl) - : m_impl(impl) - , m_next(0) -{ - if (chain != 0) - tail->m_next = this; - else - chain = this; - tail = this; -} - -exception_handler* exception_handler::chain; -exception_handler* exception_handler::tail; - -BOOST_PYTHON_DECL void register_exception_handler(handler_function const& f) -{ - // the constructor links the new object into a handler chain, so - // this object isn't actaully leaked (until, of course, the - // interpreter exits). - new exception_handler(f); -} -#endif - -} // namespace boost::python::detail - -}} // namespace boost::python - - diff --git a/src/extension_class.cpp b/src/extension_class.cpp deleted file mode 100644 index 5dc6ec23..00000000 --- a/src/extension_class.cpp +++ /dev/null @@ -1,685 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// Revision History: -// 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) - -#define BOOST_PYTHON_SOURCE -#define BOOST_PYTHON_EXPORT - -#include -#include -#include -#include -#include - -namespace boost { namespace python { -namespace detail { - - struct operator_dispatcher - : public PyObject - { - static PyTypeObject type_obj; - static PyNumberMethods number_methods; - - static operator_dispatcher* create(const ref& o, const ref& s); - - ref m_object; - ref m_self; - - // data members for allocation/deallocation optimization - operator_dispatcher* m_free_list_link; - static operator_dispatcher* free_list; - - private: - // only accessible through create() - operator_dispatcher(const ref& o, const ref& s); - }; - - operator_dispatcher* operator_dispatcher::free_list = 0; - -}}} // namespace boost::python::detail - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -inline PyObject* to_python(boost::python::detail::operator_dispatcher* n) { return n; } - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - - -namespace boost { namespace python { - -BOOST_PYTHON_DECL tuple standard_coerce(ref l, ref r) -{ - // Introduced sequence points for exception-safety. - ref first(detail::operator_dispatcher::create(l, l)); - - ref second(r->ob_type == &detail::operator_dispatcher::type_obj - ? r - : ref(detail::operator_dispatcher::create(r, ref()))); - - return tuple(first, second); -} - -namespace detail { - - enum { unwrap_exception_code = -1000 }; - - int unwrap_args(PyObject* left, PyObject* right, PyObject*& self, PyObject*& other) - { - if (left->ob_type != &operator_dispatcher::type_obj || - right->ob_type != &operator_dispatcher::type_obj) - { - PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_args(): expecting operator_dispatcher arguments only!"); - return unwrap_exception_code; - } - - typedef reference DPtr; - DPtr lwrapper(static_cast(left), DPtr::increment_count); - DPtr rwrapper(static_cast(right), DPtr::increment_count); - - if (lwrapper->m_self.get() != 0) - { - self = lwrapper->m_self.get(); - other = rwrapper->m_object.get(); - return 0; - } - else - { - self = rwrapper->m_self.get(); - other = lwrapper->m_object.get(); - return 1; - } - } - - int unwrap_pow_args(PyObject* left, PyObject* right, PyObject* m, - PyObject*& self, PyObject*& first, PyObject*& second) - { - if (left->ob_type != &operator_dispatcher::type_obj || - right->ob_type != &operator_dispatcher::type_obj || - m->ob_type != &operator_dispatcher::type_obj) - { - PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_pow_args(): expecting operator_dispatcher arguments only!"); - return unwrap_exception_code; - } - - typedef reference DPtr; - DPtr lwrapper(static_cast(left), DPtr::increment_count); - DPtr rwrapper(static_cast(right), DPtr::increment_count); - DPtr mwrapper(static_cast(m), DPtr::increment_count); - - if (lwrapper->m_self.get() != 0) - { - self = lwrapper->m_self.get(); - first = rwrapper->m_object.get(); - second = mwrapper->m_object.get(); - return 0; - } - else if (rwrapper->m_self.get() != 0) - { - self = rwrapper->m_self.get(); - first = lwrapper->m_object.get(); - second = mwrapper->m_object.get(); - return 1; - } - else - { - self = mwrapper->m_self.get(); - first = lwrapper->m_object.get(); - second = rwrapper->m_object.get(); - return 2; - } - } - -extension_instance* get_extension_instance(PyObject* p) -{ - // The object's type will just be some class_t object, - // but if its meta-type is right, then it is an extension_instance. - if (p->ob_type->ob_type != extension_meta_class()) - { - PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); - boost::python::throw_argument_error(); - } - return static_cast(p); -} - -void -extension_instance::add_implementation(std::auto_ptr holder) -{ - for (held_objects::const_iterator p = m_wrapped_objects.begin(); - p != m_wrapped_objects.end(); ++p) - { - if (typeid(*holder) == typeid(**p)) - { - PyErr_SetString(PyExc_RuntimeError, "Base class already initialized"); - throw_error_already_set(); - } - } - m_wrapped_objects.push_back(holder.release()); -} - -extension_instance::extension_instance(PyTypeObject* class_) - : instance(class_) -{ -} - -extension_instance::~extension_instance() -{ - for (held_objects::const_iterator p = m_wrapped_objects.begin(), - finish = m_wrapped_objects.end(); - p != finish; ++p) - { - delete *p; - } -} - -BOOST_PYTHON_DECL meta_class* extension_meta_class() -{ - static meta_class result; - return &result; -} - -typedef class_t extension_class_t; - -bool is_subclass(const extension_class_t* derived, - const PyObject* possible_base) -{ - - tuple bases = derived->bases(); - - for (std::size_t i = 0, size = bases.size(); i < size; ++i) - { - const PyObject* base = bases[i].get(); - - if (base == possible_base) - return true; - - if (base->ob_type == extension_meta_class()) - { - const extension_class_t* base_class = downcast(base); - if (is_subclass(base_class, possible_base)) - return true; - } - } - return false; -} - -// Return true iff obj is an obj of target_class -bool is_instance(extension_instance* obj, - class_t* target_class) -{ - if (obj->ob_type == target_class) - return true; - else - { - return is_subclass( - downcast >(obj->ob_type).get(), - as_object(target_class)); - } -} - -void two_string_error(PyObject* exception_object, const char* format, const char* s1, const char* s2) -{ - char buffer[256]; - std::size_t format_length = BOOST_CSTD_::strlen(format); - std::size_t length1 = BOOST_CSTD_::strlen(s1); - std::size_t length2 = BOOST_CSTD_::strlen(s2); - - std::size_t additional_length = length1 + length2; - if (additional_length + format_length > format_length - 1) - { - std::size_t difference = sizeof(buffer) - 1 - additional_length; - length1 -= difference / 2; - additional_length -= difference / 2; - } - - sprintf(buffer, format, length1, s1, length2, s2); - - PyErr_SetString(exception_object, buffer); - if (exception_object == PyExc_TypeError) - throw_argument_error(); - else - throw_error_already_set(); -} - -// This is called when an attempt has been made to convert the given obj to -// a C++ type for which it doesn't have any obj data. In that case, either -// the obj was not derived from the target_class, or the appropriate -// __init__ function wasn't called to initialize the obj data of the target class. -void report_missing_instance_data( - extension_instance* obj, // The object being converted - class_t* target_class, // the extension class of the C++ type - const std::type_info& target_typeid, // The typeid of the C++ type - bool target_is_ptr) -{ - char buffer[256]; - if (is_instance(obj, target_class)) - { - if (target_is_ptr) - { - two_string_error(PyExc_RuntimeError, - "Object of extension class '%.*s' does not wrap <%.*s>.", - obj->ob_type->tp_name, target_typeid.name()); - } - else - { - const char message[] = "__init__ function for extension class '%.*s' was never called."; - sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, - target_class->tp_name); - } - PyErr_SetString(PyExc_RuntimeError, buffer); - } - else if (target_class == 0) - { - const char message[] = "Cannot convert to <%.*s>; its Python class was never created or has been deleted."; - sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, target_typeid.name()); - PyErr_SetString(PyExc_RuntimeError, buffer); - } - else - { - two_string_error(PyExc_TypeError, "extension class '%.*s' is not convertible into '%.*s'.", - obj->ob_type->tp_name, target_class->tp_name); - } -} - -void report_missing_instance_data( - extension_instance* obj, // The object being converted - class_t* target_class, // the extension class of the C++ type - const std::type_info& target_typeid) // The typeid of the C++ type -{ - report_missing_instance_data(obj, target_class, target_typeid, false); -} - -void report_missing_ptr_data( - extension_instance* obj, // The object being converted - class_t* target_class, // the extension class of the C++ type - const std::type_info& target_typeid) // The typeid of the C++ type -{ - report_missing_instance_data(obj, target_class, target_typeid, true); -} - -void report_missing_class_object(const std::type_info& info) -{ - char buffer[256]; - const char message[] = "Cannot convert <%.*s> to python; its Python class was never created or has been deleted."; - sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name()); - PyErr_SetString(PyExc_RuntimeError, buffer); - throw_error_already_set(); -} - -void report_released_smart_pointer(const std::type_info& info) -{ - char buffer[256]; - const char message[] = "Converting from python, pointer or smart pointer to <%.*s> is NULL."; - sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name()); - PyErr_SetString(PyExc_RuntimeError, buffer); - throw_argument_error(); -} - -read_only_setattr_function::read_only_setattr_function(const char* name) - : m_name(name) -{ -} - -PyObject* read_only_setattr_function::do_call(PyObject* /*args*/, PyObject* /*keywords*/) const -{ - PyErr_SetObject(PyExc_AttributeError, ("'" + m_name + "' attribute is read-only").get()); - return 0; -} - -const char* read_only_setattr_function::description() const -{ - return "uncallable"; -} - -extension_class_base::extension_class_base(const char* name) - : class_t( - extension_meta_class(), string(name), tuple(), dictionary()) -{ -} - -// This function is used in from_python() to convert wrapped classes that are -// related by inheritance. The problem is this: although C++ provides all necessary -// conversion operators, source and target of a conversion must be known at compile -// time. However, in Python we want to convert classes at runtime. The solution is to -// generate conversion functions at compile time, register them within the appropriate -// class objects and call them when a particular runtime conversion is required. - -// If functions for any possible conversion have to be stored, their number will grow -// qudratically. To reduce this number, we actually store only conversion functions -// between adjacent levels in the inheritance tree. By traversing the tree recursively, -// we can build any allowed conversion as a concatenation of simple conversions. This -// traversal is done in the functions try_base_class_conversions() and -// try_derived_class_conversions(). If a particular conversion is impossible, all -// conversion functions will return a NULL pointer. - -// The function extract_object_from_holder() attempts to actually extract the pointer -// to the contained object from an instance_holder_base (a wrapper class). A conversion -// of the held object to 'T *' is allowed when the conversion -// 'dynamic_cast *>(an_instance_holder_base)' succeeds. -void* extension_class_base::try_class_conversions(instance_holder_base* object) const -{ - void* result = try_derived_class_conversions(object); - if (result) - return result; - - if (!object->held_by_value()) - return try_base_class_conversions(object); - else - return 0; -} - -void* extension_class_base::try_base_class_conversions(instance_holder_base* object) const -{ - for (std::size_t i = 0; i < base_classes().size(); ++i) - { - if (base_classes()[i].convert == 0) - continue; - void* result1 = base_classes()[i].class_object->extract_object_from_holder(object); - if (result1) - return (*base_classes()[i].convert)(result1); - - void* result2 = base_classes()[i].class_object->try_base_class_conversions(object); - if (result2) - return (*base_classes()[i].convert)(result2); - } - return 0; -} - -void* extension_class_base::try_derived_class_conversions(instance_holder_base* object) const -{ - for (std::size_t i = 0; i < derived_classes().size(); ++i) - { - void* result1 = derived_classes()[i].class_object->extract_object_from_holder(object); - if (result1) - return (*derived_classes()[i].convert)(result1); - - void* result2 = derived_classes()[i].class_object->try_derived_class_conversions(object); - if (result2) - return (*derived_classes()[i].convert)(result2); - } - return 0; -} - -void extension_class_base::add_method(function* method, const char* name) -{ - add_method(reference(method), name); -} - -void extension_class_base::add_method(reference method, const char* name) -{ - // Add the attribute to the computed target - function::add_to_namespace(method, name, this->dict().get()); - - // If it is a special member function it should be enabled both here and there. - detail::enable_named_method(this, name); -} - -void extension_class_base::add_constructor_object(function* init_fn) -{ - add_method(init_fn, "__init__"); -} - -void extension_class_base::add_setter_method(function* setter_, const char* name) -{ - reference setter(setter_); - add_method(setter, (detail::setattr_string() + name + "__").c_str()); -} - -void extension_class_base::add_getter_method(function* getter_, const char* name) -{ - reference getter(getter_); - add_method(getter, (detail::getattr_string() + name + "__").c_str()); -} - -void extension_class_base::set_attribute(const char* name, PyObject* x_) -{ - ref x(x_); - set_attribute(name, x); -} - -void extension_class_base::set_attribute(const char* name, ref x) -{ - dict().set_item(string(name), x); - if (PyCallable_Check(x.get())) - detail::enable_named_method(this, name); -} - -operator_dispatcher::operator_dispatcher(const ref& o, const ref& s) - : m_object(o), m_self(s), m_free_list_link(0) - -{ - PyObject* self = this; - PyObject_INIT(self, &type_obj); -} - -operator_dispatcher* -operator_dispatcher::create(const ref& object, const ref& self) -{ - operator_dispatcher* const result = free_list; - if (result == 0) - return new operator_dispatcher(object, self); - - free_list = result->m_free_list_link; - result->m_object = object; - result->m_self = self; - - PyObject* result_as_pyobject = result; - PyObject_INIT(result_as_pyobject, &type_obj); - return result; -} - -extern "C" -{ - -void operator_dispatcher_dealloc(PyObject* self) -{ - operator_dispatcher* obj = static_cast(self); - obj->m_free_list_link = operator_dispatcher::free_list; - operator_dispatcher::free_list = obj; - obj->m_object.reset(); - obj->m_self.reset(); -} - -int operator_dispatcher_coerce(PyObject** l, PyObject** r) -{ - Py_INCREF(*l); - - return handle_exception( - bind_return( - *r - , bind(operator_dispatcher::create, - ref(*r, ref::increment_count), - ref()))) - ? -1 : 0; -} - -#define PY_DEFINE_OPERATOR(id, symbol) \ - PyObject* operator_dispatcher_call_##id(PyObject* left, PyObject* right) \ - { \ - /* unwrap the arguments from their OperatorDispatcher */ \ - PyObject* self; \ - PyObject* other; \ - int reverse = unwrap_args(left, right, self, other); \ - if (reverse == unwrap_exception_code) \ - return 0; \ - \ - /* call the function */ \ - PyObject* result = \ - PyEval_CallMethod(self, \ - const_cast(reverse ? "__r" #id "__" : "__" #id "__"), \ - const_cast("(O)"), \ - other); \ - if (result == 0 && PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)) \ - { \ - PyErr_Clear(); \ - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for " #symbol); \ - } \ - return result; \ - } - -PY_DEFINE_OPERATOR(add, +) -PY_DEFINE_OPERATOR(sub, -) -PY_DEFINE_OPERATOR(mul, *) -PY_DEFINE_OPERATOR(div, /) -PY_DEFINE_OPERATOR(mod, %) -PY_DEFINE_OPERATOR(divmod, divmod) -PY_DEFINE_OPERATOR(lshift, <<) -PY_DEFINE_OPERATOR(rshift, >>) -PY_DEFINE_OPERATOR(and, &) -PY_DEFINE_OPERATOR(xor, ^) -PY_DEFINE_OPERATOR(or, |) - -/* coercion rules for heterogeneous pow(): - pow(Foo, int): left, right coerced; m: None => reverse = 0 - pow(int, Foo): left, right coerced; m: None => reverse = 1 - pow(Foo, int, int): left, right, m coerced => reverse = 0 - pow(int, Foo, int): left, right, m coerced => reverse = 1 - pow(int, int, Foo): left, right, m coerced => reverse = 2 - pow(Foo, Foo, int): left, right coerced; m coerced twice => reverse = 0 - pow(Foo, int, Foo): left, right, m coerced => reverse = 0 - pow(int, Foo, Foo): left, right, m coerced => reverse = 1 -*/ -PyObject* operator_dispatcher_call_pow(PyObject* left, PyObject* right, PyObject* m) -{ - int reverse; - PyObject* self; - PyObject* first; - PyObject* second; - - if (m->ob_type == Py_None->ob_type) - { - reverse = unwrap_args(left, right, self, first); - second = m; - } - else - { - reverse = unwrap_pow_args(left, right, m, self, first, second); - } - - if (reverse == unwrap_exception_code) - return 0; - - // call the function - PyObject* result = - PyEval_CallMethod(self, - const_cast((reverse == 0) - ? "__pow__" - : (reverse == 1) - ? "__rpow__" - : "__rrpow__"), - const_cast("(OO)"), - first, second); - if (result == 0 && - (PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_TypeError) || - PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError))) - { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()"); - } - return result; -} - -int operator_dispatcher_call_cmp(PyObject* left, PyObject* right) -{ - // unwrap the arguments from their OperatorDispatcher - PyObject* self; - PyObject* other; - int reverse = unwrap_args(left, right, self, other); - if (reverse == unwrap_exception_code) - return -1; - - // call the function - PyObject* result = - PyEval_CallMethod(self, - const_cast(reverse ? "__rcmp__" : "__cmp__"), - const_cast("(O)"), - other); - if (result == 0) - { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for cmp() or <"); - return -1; - } - else - { - try - { - return BOOST_PYTHON_CONVERSION::from_python(result, type()); - } - catch(...) - { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "cmp() didn't return int"); - return -1; - } - } -} - -} // extern "C" - -PyTypeObject operator_dispatcher::type_obj = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, - const_cast("operator_dispatcher"), - sizeof(operator_dispatcher), - 0, - &operator_dispatcher_dealloc, - 0, - 0, - 0, - &operator_dispatcher_call_cmp, - 0, - &operator_dispatcher::number_methods, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 -}; - -PyNumberMethods operator_dispatcher::number_methods = -{ - &operator_dispatcher_call_add, - &operator_dispatcher_call_sub, - &operator_dispatcher_call_mul, - &operator_dispatcher_call_div, - &operator_dispatcher_call_mod, - &operator_dispatcher_call_divmod, - &operator_dispatcher_call_pow, - 0, - 0, - 0, - 0, - 0, - &operator_dispatcher_call_lshift, - &operator_dispatcher_call_rshift, - &operator_dispatcher_call_and, - &operator_dispatcher_call_xor, - &operator_dispatcher_call_or, - &operator_dispatcher_coerce, - 0, - 0, - 0, - 0, - 0 -}; - -} // namespace detail - -}} // namespace boost::python diff --git a/src/functions.cpp b/src/functions.cpp deleted file mode 100644 index cb9b067d..00000000 --- a/src/functions.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// Revision History: -// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) - -#define BOOST_PYTHON_SOURCE - -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace detail { - -struct function::type_object : - singleton > > -{ - type_object() : singleton_base(&PyType_Type) {} -}; - - -void function::add_to_namespace(reference new_function, const char* name, PyObject* dict) -{ - dictionary d(ref(dict, ref::increment_count)); - string key(name); - - ref existing_object = d.get_item(key.reference()); - if (existing_object.get() == 0) - { - d[key] = ref(new_function.get(), ref::increment_count); - } - else - { - if (existing_object->ob_type == type_object::instance()) - { - function* f = static_cast(existing_object.get()); - while (f->m_overloads.get() != 0) - f = f->m_overloads.get(); - f->m_overloads = new_function; - } - else - { - PyErr_SetObject(PyExc_RuntimeError, - (string("Attempt to overload ") + name - + " failed. The existing attribute has type " - + existing_object->ob_type->tp_name).get()); - throw_error_already_set(); - } - } -} - -function::function() - : python_object(type_object::instance()) -{ -} - -PyObject* function::call(PyObject* args, PyObject* keywords) const -{ - // Traverse the linked list of function overloads until we find one that - // matches. - for (const function* f = this; f != 0; f = f->m_overloads.get()) - { - PyErr_Clear(); - try - { - PyObject* const result = f->do_call(args, keywords); - if (result != 0) - return result; - } - catch(const argument_error&) - { - } - } - - // If we get here, no overloads matched the arguments - - // Allow the single-function error-reporting to take effect unless there was - // an overload - if (m_overloads.get() == 0) - return 0; - - // Synthesize a more-explicit error message - PyErr_Clear(); - string message("No overloaded functions match ("); - tuple arguments(ref(args, ref::increment_count)); - for (std::size_t i = 0; i < arguments.size(); ++i) - { - if (i != 0) - message += ", "; - message += arguments[i]->ob_type->tp_name; - } - - message += "). Candidates are:\n"; - for (const function* f1 = this; f1 != 0; f1 = f1->m_overloads.get()) - { - if (f1 != this) - message += "\n"; - message += f1->description(); - } - - PyErr_SetObject(PyExc_TypeError, message.get()); - return 0; -} - -// The instance class whose obj represents the type of bound_function -// objects in Python. bound_functions must be GetAttrable so the __doc__ -// attribute of built-in Python functions can be accessed when bound. -struct bound_function::type_object : - singleton > > > -{ - type_object() : singleton_base(&PyType_Type) {} - -private: // type_object hook override - void dealloc(bound_function*) const; -}; - -bound_function* bound_function::create(const ref& target, const ref& fn) -{ - bound_function* const result = free_list; - if (result == 0) - return new bound_function(target, fn); - - free_list = result->m_free_list_link; - result->m_target = target; - result->m_unbound_function = fn; - - PyObject* self = result; - PyObject_INIT(self, type_object::instance()); - return result; -} - -bound_function::bound_function(const ref& target, const ref& fn) - : python_object(type_object::instance()), - m_target(target), - m_unbound_function(fn), - m_free_list_link(0) -{ -} - -PyObject* -bound_function::call(PyObject* args, PyObject* keywords) const -{ - // Build a new tuple which prepends the target to the arguments - tuple tail_arguments(ref(args, ref::increment_count)); - ref all_arguments(PyTuple_New(tail_arguments.size() + 1)); - - PyTuple_SET_ITEM(all_arguments.get(), 0, m_target.get()); - Py_INCREF(m_target.get()); - for (std::size_t i = 0; i < tail_arguments.size(); ++i) - { - PyTuple_SET_ITEM(all_arguments.get(), i + 1, tail_arguments[i].get()); - Py_INCREF(tail_arguments[i].get()); - } - - return PyEval_CallObjectWithKeywords(m_unbound_function.get(), all_arguments.get(), keywords); -} - -PyObject* bound_function::getattr(const char* name) const -{ - return PyObject_GetAttrString(m_unbound_function.get(), const_cast(name)); -} - -void bound_function::type_object::dealloc(bound_function* obj) const -{ - obj->m_free_list_link = free_list; - free_list = obj; - obj->m_target.reset(); - obj->m_unbound_function.reset(); -} - -bound_function* bound_function::free_list; - -}}} // namespace boost::python::detail diff --git a/src/gen_all.py b/src/gen_all.py deleted file mode 100644 index 3877d181..00000000 --- a/src/gen_all.py +++ /dev/null @@ -1,26 +0,0 @@ -from gen_callback import * -from gen_caller import * -from gen_init_function import * -from gen_signatures import * -from gen_singleton import * -from gen_extclass import * - -def gen_all(args): - open('callback.hpp', 'w').write(gen_callback(args)) - open('caller.hpp', 'w').write(gen_caller(args)) - open('init_function.hpp', 'w').write(gen_init_function(args)) - open('signatures.hpp', 'w').write(gen_signatures(args)) - open('singleton.hpp', 'w').write(gen_singleton(args)) - open('extension_class.hpp', 'w').write(gen_extclass(args)) - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 10 - else: - args = int(sys.argv[1]) - - print gen_all(args) - - diff --git a/src/gen_arg_tuple_size.py b/src/gen_arg_tuple_size.py deleted file mode 100644 index 9de332ab..00000000 --- a/src/gen_arg_tuple_size.py +++ /dev/null @@ -1,139 +0,0 @@ -# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -# distribute this software is granted provided this copyright notice appears -# in all copies. This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. -# -# This work was funded in part by Lawrence Berkeley National Labs - -from gen_function import * -import string - -header = '''// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// This work was funded in part by Lawrence Berkeley National Labs -// -// This file generated for %d-argument member functions and %d-argument free -// functions by gen_arg_tuple_size.python -''' - -_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') - -_suffix = { - '': ''' -// Metrowerks thinks this creates ambiguities -# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 -''', ' const volatile': ''' -# endif // __MWERKS__ -''' - }; - -def gen_arg_tuple_size(member_function_args, free_function_args = None): - if free_function_args is None: - free_function_args = member_function_args + 1 - - return_none = '''; - return detail::none();''' - - return (header % (member_function_args, free_function_args) - + ''' -#ifndef ARG_TUPLE_SIZE_DWA20011201_HPP -# define ARG_TUPLE_SIZE_DWA20011201_HPP - -# include - -namespace boost { namespace python { namespace detail { - -// Computes (at compile-time) the number of elements that a Python -// argument tuple must have in order to be passed to a wrapped C++ -// (member) function of the given type. -template struct arg_tuple_size; - -# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__BORLANDC__) - -''' - + gen_functions( -'''template -struct arg_tuple_size -{ - BOOST_STATIC_CONSTANT(std::size_t, value = %n); -}; - -''', free_function_args) - - + '\n' - - + reduce(lambda x,y: x+'\n'+y - , map( - lambda cv: gen_functions( -'''template -struct arg_tuple_size -{ - BOOST_STATIC_CONSTANT(std::size_t, value = %+); -}; - -''' - , member_function_args, cv) + _suffix.get(cv, '') - , _cv_qualifiers)) - - + -'''# else - -// We will use the "sizeof() trick" to work around the lack of -// partial specialization in MSVC6 and its broken-ness in borland. -// See http://opensource.adobe.com or -// http://groups.yahoo.com/group/boost/message/5441 for -// more examples - -// The following helper functions are never actually called, since -// they are only used within a sizeof() expression, but the type of -// their return value is used to discriminate between various free -// and member function pointers at compile-time. - -''' - + gen_functions( -'''template -char_array<%n> arg_tuple_size_helper(R (*)(%(A%+%:, %))); - -''', free_function_args) - - + reduce(lambda x,y: x+'\n'+y - , map( - lambda cv: gen_functions( -'''template -char_array<%+> arg_tuple_size_helper(R (A0::*)(%(A%+%:, %))%1); - -''', member_function_args, cv) - , _cv_qualifiers)) - + ''' -template -struct arg_tuple_size -{ - // The sizeof() magic happens here - BOOST_STATIC_CONSTANT(std::size_t, value - = sizeof(arg_tuple_size_helper(F(0)).elements) - 1); -}; -# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -}}} // namespace boost::python::detail - -#endif // ARG_TUPLE_SIZE_DWA20011201_HPP -''') - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - member_function_args = 5 - free_function_args = 6 - else: - member_function_args = int(sys.argv[1]) - if len(sys.argv) > 2: - free_function_args = int(sys.argv[2]) - else: - free_function_args = member_function_args - - print gen_arg_tuple_size(member_function_args, free_function_args) - - diff --git a/src/gen_call.py b/src/gen_call.py deleted file mode 100644 index f609c0ae..00000000 --- a/src/gen_call.py +++ /dev/null @@ -1,82 +0,0 @@ -# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -# distribute this software is granted provided this copyright notice appears -# in all copies. This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. -# -# This work was funded in part by Lawrence Berkeley National Labs - -from gen_function import * -import string - -header = '''// Copyright David Abrahams 2001. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -// -// This work was funded in part by Lawrence Berkeley National Labs -// -// This file generated for %d-argument member functions and %d-argument free -// functions by gen_call.py - -#ifndef CALL_DWA20011214_HPP -# define CALL_DWA20011214_HPP - -# include - -namespace boost { namespace python { - -''' -_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') - -def gen_call(member_function_args, free_function_args = None): - if free_function_args is None: - free_function_args = member_function_args + 1 - - return (header % (member_function_args, free_function_args) - + gen_functions( -'''template -inline PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -''', free_function_args) - + -'''// Member functions -''' - + reduce(lambda x,y: x+y - , map(lambda cv: - gen_functions( -'''template -inline PyObject* call(R (A0::*f)(%(A%+%:, %))%1, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -''' - , member_function_args, cv) - , _cv_qualifiers)) - + -''' -}} // namespace boost::python - -#endif // CALL_DWA20011214_HPP -''') - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - member_function_args = 5 - free_function_args = 6 - else: - member_function_args = int(sys.argv[1]) - if len(sys.argv) > 2: - free_function_args = int(sys.argv[2]) - else: - free_function_args = member_function_args - - print gen_call(member_function_args, free_function_args) - - diff --git a/src/gen_callback.py b/src/gen_callback.py deleted file mode 100644 index f178212b..00000000 --- a/src/gen_callback.py +++ /dev/null @@ -1,124 +0,0 @@ -from gen_function import * -import string - -def gen_callback(args): - return ( -"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// This file was generated for %d-argument python callbacks by gen_callback.python - -#ifndef CALLBACK_DWA_052100_H_ -# define CALLBACK_DWA_052100_H_ - -# include -# include - -namespace boost { namespace python { - -namespace detail { - template - inline void callback_adjust_refcount(PyObject*, type) {} - - inline void callback_adjust_refcount(PyObject* p, type) - { Py_INCREF(p); } -} - -// Calling Python from C++ -template -struct callback -{""" % args - - + gen_functions(''' -%{ template <%(class A%n%:, %)> -%} static R call_method(PyObject* self, const char* name%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(%(O%))")%(, - p%n.get()%))); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - -%{ template <%(class A%n%:, %)> -%} static R call(PyObject* self%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallFunction(self, const_cast("(%(O%))")%(, - p%n.get()%))); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } -''', args) - + -"""}; - -// This specialization wouldn't be needed, but MSVC6 doesn't correctly allow the following: -// void g(); -// void f() { return g(); } -template <> -struct callback -{ -""" - + gen_functions(''' -%{ template <%(class A%n%:, %)> -%} static void call_method(PyObject* self, const char* name%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(%(O%))")%(, - p%n.get()%))); - } - -%{ template <%(class A%n%:, %)> -%} static void call(PyObject* self%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallFunction(self, const_cast("(%(O%))")%(, - p%n.get()%))); - } -''', args) - + -"""}; - -// Make it a compile-time error to try to return a const char* from a virtual -// function. The standard conversion -// -// from_python(PyObject* string, boost::python::type) -// -// returns a pointer to the character array which is internal to string. The -// problem with trying to do this in a standard callback function is that the -// Python string would likely be destroyed upon return from the calling function -// (boost::python::callback::call[_method]) when its reference count is -// decremented. If you absolutely need to do this and you're sure it's safe (it -// usually isn't), you can use -// -// boost::python::string result(boost::python::callback::call[_method](...args...)); -// ...result.c_str()... // access the char* array -template <> -struct callback -{ - // Try hard to generate a readable error message - typedef struct unsafe_since_python_string_may_be_destroyed {} call, call_method; -}; - -}} // namespace boost::python - -#endif // CALLBACK_DWA_052100_H_ -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_callback(args) diff --git a/src/gen_caller.py b/src/gen_caller.py deleted file mode 100644 index 26bd88c6..00000000 --- a/src/gen_caller.py +++ /dev/null @@ -1,138 +0,0 @@ -# (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -# distribute this software is granted provided this copyright notice appears -# in all copies. This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. -# -# The author gratefully acknowleges the support of Dragon Systems, Inc., in -# producing this work. - -from gen_function import * -import string - -header = '''// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// This file generated for %d-argument member functions and %d-argument free -// functions by gen_caller.python -''' - -body_sections = ( -''' -#ifndef CALLER_DWA05090_H_ -# define CALLER_DWA05090_H_ - -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -// Calling C++ from Python -template -struct caller -{ -''', -''' -''', -''' // Free functions -''', -'''}; - -template <> -struct caller -{ -''', -''' -''', -''' - // Free functions -''', -'''}; - -}} // namespace boost::python - -#endif -''') - -#' - -member_function = ''' template - static PyObject* call(%1 (T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; -%( PyObject* a%n; -%) if (!PyArg_ParseTuple(args, const_cast("O%(O%)"), &self%(, &a%n%))) - return 0; - T& target = from_python(self, type()); - %3(target.*pmf)(%(from_python(a%n, type())%:, - %))%4 - } - -''' - -free_function = '''%{ template <%(class A%n%:, %)> -%} static PyObject* call(%1 (*f)(%(A%n%:, %)), PyObject* args, PyObject* /* keywords */ ) { -%( PyObject* a%n; -%) if (!PyArg_ParseTuple(args, const_cast("%(O%)")%(, &a%n%))) - return 0; - %2f(%(from_python(a%n, type())%:, - %))%3 - } - -''' - -def gen_caller(member_function_args, free_function_args = None): - if free_function_args is None: - free_function_args = member_function_args + 1 - - return_none = '''; - return detail::none();''' - - return (header % (member_function_args, free_function_args) - + body_sections[0] - + gen_functions(member_function, member_function_args, - 'R', '', 'return to_python(', ');') - + body_sections[1] - + gen_functions(member_function, member_function_args, - 'R', ' const', 'return to_python(', ');') - + body_sections[2] - - + gen_functions(free_function, free_function_args, - 'R', 'return to_python(', ');') - + body_sections[3] - - # specialized part for void return values begins here - + gen_functions(member_function, member_function_args, - 'void', '', '', return_none) - + body_sections[4] - + gen_functions(member_function, member_function_args, - 'void', ' const', '', return_none) - + body_sections[5] - - + gen_functions(free_function, free_function_args, - 'void', '', return_none) - + body_sections[6] - ) - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - member_function_args = 5 - free_function_args = 6 - else: - member_function_args = int(sys.argv[1]) - if len(sys.argv) > 2: - free_function_args = int(sys.argv[2]) - else: - free_function_args = member_function_args - - print gen_caller(member_function_args, free_function_args) - - diff --git a/src/gen_extclass.py b/src/gen_extclass.py deleted file mode 100644 index 787e262e..00000000 --- a/src/gen_extclass.py +++ /dev/null @@ -1,948 +0,0 @@ -from gen_function import * -import string - -def gen_extclass(args): - return ( -"""// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// This file automatically generated for %d-argument constructors by -// 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) - -#ifndef EXTENSION_CLASS_DWA052000_H_ -# define EXTENSION_CLASS_DWA052000_H_ - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -// forward declarations -template struct operators; -template struct left_operand; -template struct right_operand; - -enum without_downcast_t { without_downcast }; - -namespace detail -{ - -// forward declarations - class extension_instance; - class extension_class_base; - template class instance_holder; - template class instance_value_holder; - template class instance_ptr_holder; - template struct operand_select; - template struct choose_op; - template struct choose_rop; - template struct choose_unary_op; - template struct define_operator; - - class BOOST_PYTHON_DECL extension_instance : public instance - { - public: - extension_instance(PyTypeObject* class_); - ~extension_instance(); - - void add_implementation(std::auto_ptr holder); - - typedef std::vector held_objects; - const held_objects& wrapped_objects() const - { return m_wrapped_objects; } - private: - held_objects m_wrapped_objects; - }; - -} // namespace detail - -# ifndef BOOST_PYTHON_NO_TEMPLATE_EXPORT -BOOST_PYTHON_EXPORT_TEMPLATE_CLASS class_t; -BOOST_PYTHON_EXPORT_TEMPLATE_CLASS meta_class; -# endif - -namespace detail { - -BOOST_PYTHON_DECL meta_class* extension_meta_class(); -BOOST_PYTHON_DECL extension_instance* get_extension_instance(PyObject* p); -BOOST_PYTHON_DECL void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); -BOOST_PYTHON_DECL void report_missing_ptr_data(extension_instance*, class_t*, const std::type_info&); -BOOST_PYTHON_DECL void report_missing_class_object(const std::type_info&); -BOOST_PYTHON_DECL void report_released_smart_pointer(const std::type_info&); - -template -T* check_non_null(T* p) -{ - if (p == 0) - report_released_smart_pointer(typeid(T)); - return p; -} - -template class held_instance; - -typedef void* (*conversion_function_ptr)(void*); - -struct BOOST_PYTHON_DECL base_class_info -{ - base_class_info(extension_class_base* t, conversion_function_ptr f) - :class_object(t), convert(f) - {} - - extension_class_base* class_object; - conversion_function_ptr convert; -}; - -typedef base_class_info derived_class_info; - -struct add_operator_base; - -class BOOST_PYTHON_DECL extension_class_base : public class_t -{ - public: - extension_class_base(const char* name); - - public: - // the purpose of try_class_conversions() and its related functions - // is explained in extclass.cpp - void* try_class_conversions(instance_holder_base*) const; - void* try_base_class_conversions(instance_holder_base*) const; - void* try_derived_class_conversions(instance_holder_base*) const; - - void set_attribute(const char* name, PyObject* x); - void set_attribute(const char* name, ref x); - - private: - virtual void* extract_object_from_holder(instance_holder_base* v) const = 0; - virtual std::vector const& base_classes() const = 0; - virtual std::vector const& derived_classes() const = 0; - - protected: - friend struct add_operator_base; - void add_method(reference method, const char* name); - void add_method(function* method, const char* name); - - void add_constructor_object(function*); - void add_setter_method(function*, const char* name); - void add_getter_method(function*, const char* name); -}; - -template -class class_registry -{ - public: - static extension_class_base* class_object() - { return static_class_object; } - - // Register/unregister the Python class object corresponding to T - static void register_class(extension_class_base*); - static void unregister_class(extension_class_base*); - - // Establish C++ inheritance relationships - static void register_base_class(base_class_info const&); - static void register_derived_class(derived_class_info const&); - - // Query the C++ inheritance relationships - static std::vector const& base_classes(); - static std::vector const& derived_classes(); - private: - static extension_class_base* static_class_object; - static std::vector static_base_class_info; - static std::vector static_derived_class_info; -}; - -template -struct is_null_helper -{ - template - static bool test(Ptr x) { return x == 0; } -}; - -template <> -struct is_null_helper -{ - template - static bool test(const Ptr& x) { return x.get() == 0; } -}; - -template -bool is_null(const Ptr& x) -{ - return is_null_helper<(is_pointer::value)>::test(x); -} - -}}} // namespace boost::python::detail - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -// This class' only job is to define from_python and to_python converters for T -// 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. -// -// 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 python_extension_class_converters -{ - public: - // Get an object which can be used to convert T to/from python. This is used - // as a kind of concept check by the global template - // - // PyObject* to_python(const T& x) - // - // below this class, to prevent the confusing messages that would otherwise - // pop up. Now, if T hasn't been wrapped as an extension class, the user - // will see an error message about the lack of an eligible - // py_extension_class_converters() function. - friend python_extension_class_converters py_extension_class_converters(boost::python::type) - { - return python_extension_class_converters(); - } - - // This is a member function because in a conforming implementation, friend - // funcitons defined inline in the class body are all instantiated as soon - // as the enclosing class is instantiated. If T is not copyable, that causes - // a compiler error. Instead, we access this function through the global - // template - // - // PyObject* to_python(const T& x) - // - // defined below this class. Since template functions are instantiated only - // on demand, errors will be avoided unless T is noncopyable and the user - // writes code which causes us to try to copy a T. - PyObject* to_python(const T& x) const - { - boost::python::reference result(create_instance()); - result->add_implementation( - std::auto_ptr( - new boost::python::detail::instance_value_holder(result.get(), x))); - return result.release(); - } - - friend - T* non_null_from_python(PyObject* obj, boost::python::type) - { - // downcast to an extension_instance, then find the actual T - boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj); - typedef std::vector::const_iterator iterator; - for (iterator p = self->wrapped_objects().begin(); - p != self->wrapped_objects().end(); ++p) - { - boost::python::detail::instance_holder* held = dynamic_cast*>(*p); - if (held != 0) - return held->target(); - - // see extclass.cpp for an explanation of try_class_conversions() - void* target = boost::python::detail::class_registry::class_object()->try_class_conversions(*p); - if(target) - return static_cast(target); - } - boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); - boost::python::throw_argument_error(); -#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 - return 0; -#endif - } - - // Convert to T* - friend T* from_python(PyObject* obj, boost::python::type) - { - if (obj == Py_None) - return 0; - else - return non_null_from_python(obj, boost::python::type()); - } - - // Extract from obj a mutable reference to the PtrType object which is holding a T. - template - static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type) - { - // downcast to an extension_instance, then find the actual T - boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj); - typedef std::vector::const_iterator iterator; - for (iterator p = self->wrapped_objects().begin(); - p != self->wrapped_objects().end(); ++p) - { - boost::python::detail::instance_ptr_holder* held = - dynamic_cast*>(*p); - if (held != 0) - return held->ptr(); - } - boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); - boost::python::throw_argument_error(); -#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 - return *(PtrType*)0; -#endif - } - - // Extract from obj a reference to the PtrType object which is holding a - // T. If it weren't for auto_ptr, it would be a constant reference. Do not - // modify the referent except by copying an auto_ptr! If obj is None, the - // reference denotes a default-constructed PtrType - template - static PtrType& smart_ptr_value(PyObject* obj, boost::python::type) - { - if (obj == Py_None) - { - static PtrType null_ptr; - return null_ptr; - } - return smart_ptr_reference(obj, boost::python::type()); - } - - template - static PyObject* smart_ptr_to_python(PtrType x) - { - if (boost::python::detail::is_null(x)) - { - return boost::python::detail::none(); - } - - boost::python::reference result(create_instance()); - result->add_implementation( - std::auto_ptr( - new boost::python::detail::instance_ptr_holder(x))); - return result.release(); - } - - static boost::python::reference create_instance() - { - PyTypeObject* class_object = boost::python::detail::class_registry::class_object(); - if (class_object == 0) - boost::python::detail::report_missing_class_object(typeid(T)); - - return boost::python::reference( - new boost::python::detail::extension_instance(class_object)); - } - - // Convert to const T* - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to const T* const& - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T* const& - friend T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T& - friend T& from_python(PyObject* p, boost::python::type) - { return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type())); } - - // Convert to const T& - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return smart_ptr_reference(p, boost::python::type >()); } - - friend std::auto_ptr from_python(PyObject* p, boost::python::type >) - { return smart_ptr_value(p, boost::python::type >()); } - - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return smart_ptr_value(p, boost::python::type >()); } - - friend PyObject* to_python(std::auto_ptr x) - { return smart_ptr_to_python(x); } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return smart_ptr_reference(p, boost::python::type >()); } - - friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type >) - { return smart_ptr_value(p, boost::python::type >()); } - - friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return smart_ptr_value(p, boost::python::type >()); } - - friend PyObject* to_python(boost::shared_ptr x) - { return smart_ptr_to_python(x); } -}; - -// Convert T to_python, instantiated on demand and only if there isn't a -// non-template overload for this function. This version is the one invoked when -// T is a wrapped class. See the first 2 functions declared in -// python_extension_class_converters above for more info. -template -PyObject* to_python(const T& x) -{ - return py_extension_class_converters(boost::python::type()).to_python(x); -} - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters); - -namespace detail { - -template class instance_holder; - -class BOOST_PYTHON_DECL read_only_setattr_function : public function -{ - public: - read_only_setattr_function(const char* name); - PyObject* do_call(PyObject* args, PyObject* keywords) const; - const char* description() const; - private: - string m_name; -}; - - template - struct define_conversion - { - static void* upcast_ptr(void* v) - { - return static_cast(static_cast(v)); - } - - static void* downcast_ptr(void* v) - { - return dynamic_cast(static_cast(v)); - } - }; - -// An easy way to make an extension base class which wraps T. Note that Python -// subclasses of this class will simply be class_t objects. -// -// U should be a class derived from T which overrides virtual functions with -// boilerplate code to call back into Python. See extclass_demo.h for examples. -// -// U is optional, but you won't be able to override any member functions in -// Python which are called from C++ if you don't supply it. If you just want to -// be able to use T in python without overriding member functions, you can omit -// U. -template > -class extension_class - : public python_extension_class_converters, // This generates the to_python/from_python functions - public extension_class_base -{ - public: - typedef T wrapped_type; - typedef U callback_type; - - // Construct with a name that comes from typeid(T).name(). The name only - // affects the objects of this class are represented through repr() - extension_class(); - - // Construct with the given name. The name only affects the objects of this - // class are represented through repr() - extension_class(const char* name); - - ~extension_class(); - - // define constructors -""" % args - + gen_function( -""" template <%(class A%n%:, %)> - inline void def(constructor<%(A%n%:, %)>) - // The following incantation builds a signature1, signature2,... object. It - // should _all_ get optimized away. - { add_constructor( - %(prepend(type::id(), - %) signature0()%()%)); - } -""", args) - + -""" - - // export homogeneous operators (type of both lhs and rhs is 'operator') - // usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>()); - - // export homogeneous operators (type of both lhs and rhs is 'T const&') - // usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>()); - template - inline void def(operators) - { - typedef typename operand_select::template wrapped::type true_operand; - def_operators(operators()); - } - - // export heterogeneous operators (type of lhs: 'left', of rhs: 'right') - // usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(), - // boost::python::right_operand()); - - // export heterogeneous operators (type of lhs: 'T const&', of rhs: 'right') - // usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(), - // boost::python::right_operand()); - template - inline void def(operators, right_operand r) - { - typedef typename operand_select::template wrapped::type true_left; - def_operators(operators(), r); - } - - // export heterogeneous reverse-argument operators - // (type of lhs: 'left', of rhs: 'right') - // usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(), - // boost::python::left_operand()); - - // export heterogeneous reverse-argument operators - // (type of lhs: 'left', of rhs: 'T const&') - // usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(), - // boost::python::left_operand()); - template - inline void def(operators, left_operand l) - { - typedef typename operand_select::template wrapped::type true_right; - def_operators(operators(), l); - } - - // define a function that passes Python arguments and keywords - // to C++ verbatim (as a 'tuple const&' and 'dictionary const&' - // respectively). This is useful for manual argument passing. - // It's also the only possibility to pass keyword arguments to C++. - // Fn must have a signatur that is compatible to - // PyObject* (*)(PyObject* aTuple, PyObject* aDictionary) - template - inline void def_raw(Fn fn, const char* name) - { - this->add_method(new_raw_arguments_function(fn), name); - } - - // define member functions. In fact this works for free functions, too - - // they act like static member functions, or if they start with the - // appropriate self argument (as a pointer), they can be used just like - // ordinary member functions -- just like Python! - template - inline void def(Fn fn, const char* name) - { - this->add_method(new_wrapped_function(fn), name); - } - - // Define a virtual member function with a default implementation. - // default_fn should be a function which provides the default implementation. - // Be careful that default_fn does not in fact call fn virtually! - template - inline void def(Fn fn, const char* name, DefaultFn default_fn) - { - this->add_method(new_virtual_function(type(), fn, default_fn), name); - } - - // Provide a function which implements x., reading from the given - // member (pm) of the T obj - template - inline void def_getter(MemberType T::*pm, const char* name) - { - this->add_getter_method(new getter_function(pm), name); - } - - // Provide a function which implements assignment to x., writing to - // the given member (pm) of the T obj - template - inline void def_setter(MemberType T::*pm, const char* name) - { - this->add_setter_method(new setter_function(pm), name); - } - - // Expose the given member (pm) of the T obj as a read-only attribute - template - inline void def_readonly(MemberType T::*pm, const char* name) - { - this->add_setter_method(new read_only_setattr_function(name), name); - this->def_getter(pm, name); - } - - // Expose the given member (pm) of the T obj as a read/write attribute - template - inline void def_read_write(MemberType T::*pm, const char* name) - { - this->def_getter(pm, name); - this->def_setter(pm, name); - } - - // define the standard coercion needed for operator overloading - void def_standard_coerce(); - - // declare the given class a base class of this one and register - // up and down conversion functions - template - void declare_base(extension_class* base) - { - // see extclass.cpp for an explanation of why we need to register - // conversion functions - base_class_info baseInfo(base, - &define_conversion::downcast_ptr); - class_registry::register_base_class(baseInfo); - add_base(ref(as_object(base), ref::increment_count)); - - derived_class_info derivedInfo(this, - &define_conversion::upcast_ptr); - class_registry::register_derived_class(derivedInfo); - } - - // declare the given class a base class of this one and register - // only up conversion function - template - void declare_base(extension_class* base, without_downcast_t) - { - // see extclass.cpp for an explanation of why we need to register - // conversion functions - base_class_info baseInfo(base, 0); - class_registry::register_base_class(baseInfo); - add_base(ref(as_object(base), ref::increment_count)); - - derived_class_info derivedInfo(this, - &define_conversion::upcast_ptr); - class_registry::register_derived_class(derivedInfo); - } - - private: // types - typedef instance_value_holder holder; - - private: // extension_class_base virtual function implementations - std::vector const& base_classes() const; - std::vector const& derived_classes() const; - void* extract_object_from_holder(instance_holder_base* v) const; - - private: // Utility functions - template - inline void def_operators(operators) - { - def_standard_coerce(); - - // for some strange reason, this prevents MSVC from having an - // "unrecoverable block scoping error"! - typedef choose_op<(which & op_add)> choose_add; - - choose_op<(which & op_add)>::template args::add(this); - choose_op<(which & op_sub)>::template args::add(this); - choose_op<(which & op_mul)>::template args::add(this); - choose_op<(which & op_div)>::template args::add(this); - choose_op<(which & op_mod)>::template args::add(this); - choose_op<(which & op_divmod)>::template args::add(this); - choose_op<(which & op_pow)>::template args::add(this); - choose_op<(which & op_lshift)>::template args::add(this); - choose_op<(which & op_rshift)>::template args::add(this); - choose_op<(which & op_and)>::template args::add(this); - choose_op<(which & op_xor)>::template args::add(this); - choose_op<(which & op_or)>::template args::add(this); - choose_op<(which & op_gt)>::template args::add(this); - choose_op<(which & op_ge)>::template args::add(this); - choose_op<(which & op_lt)>::template args::add(this); - choose_op<(which & op_le)>::template args::add(this); - choose_op<(which & op_eq)>::template args::add(this); - choose_op<(which & op_ne)>::template args::add(this); - choose_unary_op<(which & op_neg)>::template args::add(this); - choose_unary_op<(which & op_pos)>::template args::add(this); - choose_unary_op<(which & op_abs)>::template args::add(this); - choose_unary_op<(which & op_invert)>::template args::add(this); - choose_unary_op<(which & op_int)>::template args::add(this); - choose_unary_op<(which & op_long)>::template args::add(this); - choose_unary_op<(which & op_float)>::template args::add(this); - choose_op<(which & op_cmp)>::template args::add(this); - choose_unary_op<(which & op_str)>::template args::add(this); - } - - template - inline void def_operators(operators, right_operand) - { - def_standard_coerce(); - - choose_op<(which & op_add)>::template args::add(this); - choose_op<(which & op_sub)>::template args::add(this); - choose_op<(which & op_mul)>::template args::add(this); - choose_op<(which & op_div)>::template args::add(this); - choose_op<(which & op_mod)>::template args::add(this); - choose_op<(which & op_divmod)>::template args::add(this); - choose_op<(which & op_pow)>::template args::add(this); - choose_op<(which & op_lshift)>::template args::add(this); - choose_op<(which & op_rshift)>::template args::add(this); - choose_op<(which & op_and)>::template args::add(this); - choose_op<(which & op_xor)>::template args::add(this); - choose_op<(which & op_or)>::template args::add(this); - choose_op<(which & op_cmp)>::template args::add(this); - choose_op<(which & op_gt)>::template args::add(this); - choose_op<(which & op_ge)>::template args::add(this); - choose_op<(which & op_lt)>::template args::add(this); - choose_op<(which & op_le)>::template args::add(this); - choose_op<(which & op_eq)>::template args::add(this); - choose_op<(which & op_ne)>::template args::add(this); - } - - template - inline void def_operators(operators, left_operand) - { - def_standard_coerce(); - - choose_rop<(which & op_add)>::template args::add(this); - choose_rop<(which & op_sub)>::template args::add(this); - choose_rop<(which & op_mul)>::template args::add(this); - choose_rop<(which & op_div)>::template args::add(this); - choose_rop<(which & op_mod)>::template args::add(this); - choose_rop<(which & op_divmod)>::template args::add(this); - choose_rop<(which & op_pow)>::template args::add(this); - choose_rop<(which & op_lshift)>::template args::add(this); - choose_rop<(which & op_rshift)>::template args::add(this); - choose_rop<(which & op_and)>::template args::add(this); - choose_rop<(which & op_xor)>::template args::add(this); - choose_rop<(which & op_or)>::template args::add(this); - choose_rop<(which & op_cmp)>::template args::add(this); - } - - template - void add_constructor(signature sig) - { - this->add_constructor_object(init_function::create(sig)); - } -}; - -// A simple wrapper over a T which allows us to use extension_class with a -// single template parameter only. See extension_class, above. -template -class held_instance : public Held -{ - // There are no member functions: we want to avoid inadvertently overriding - // any virtual functions in Held. -public:""" - + gen_functions("""%{ - template <%(class A%n%:, %)>%} - held_instance(PyObject*%(, A%n% a%n%)) : Held( - %(typename unwrap_parameter::type(a%n)%: - , %)) {}""", args) - + """ -}; - -// Abstract base class for all obj holders. Base for template class -// instance_holder<>, below. -class BOOST_PYTHON_DECL instance_holder_base -{ -public: - virtual ~instance_holder_base() {} - virtual bool held_by_value() = 0; -}; - -// Abstract base class which holds a Held, somehow. Provides a uniform way to -// get a pointer to the held object -template -class instance_holder : public instance_holder_base -{ -public: - virtual Held*target() = 0; -}; - -// Concrete class which holds a Held by way of a wrapper class Wrapper. If Held -// can be constructed with arguments (A1...An), Wrapper must have a -// corresponding constructor for arguments (PyObject*, A1...An). Wrapper is -// neccessary to implement virtual function callbacks (there must be a -// back-pointer to the actual Python object so that we can call any -// overrides). held_instance (above) is used as a default Wrapper class when -// there are no virtual functions. -template -class instance_value_holder : public instance_holder -{ -public: - Held* target() { return &m_held; } - Wrapper* value_target() { return &m_held; } - - instance_value_holder(extension_instance* p) : - m_held(p) {} - template - instance_value_holder(extension_instance* p, A1 a1) : - m_held(p, a1) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2) : - m_held(p, a1, a2) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3) : - m_held(p, a1, a2, a3) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4) : - m_held(p, a1, a2, a3, a4) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : - m_held(p, a1, a2, a3, a4, a5) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : - m_held(p, a1, a2, a3, a4, a5, a6) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : - m_held(p, a1, a2, a3, a4, a5, a6, a7) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : - m_held(p, a1, a2, a3, a4, a5, a6, a7, a8) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : - m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : - m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {} - - public: // implementation of instance_holder_base required interface - bool held_by_value() { return true; } - - private: - Wrapper m_held; -}; - -// Concrete class which holds a HeldType by way of a (possibly smart) pointer -// PtrType. By default, these are only generated for PtrType == -// std::auto_ptr and PtrType == boost::shared_ptr. -template -class instance_ptr_holder : public instance_holder -{ - public: - HeldType* target() { return &*m_ptr; } - PtrType& ptr() { return m_ptr; } - - instance_ptr_holder(PtrType ptr) : m_ptr(ptr) {} - - public: // implementation of instance_holder_base required interface - bool held_by_value() { return false; } - private: - PtrType m_ptr; -}; - -// -// Template function implementations -// - -template -extension_class::extension_class() - : extension_class_base(typeid(T).name()) -{ - class_registry::register_class(this); -} - -template -extension_class::extension_class(const char* name) - : extension_class_base(name) -{ - class_registry::register_class(this); -} - -template -void extension_class::def_standard_coerce() -{ - ref coerce_fct = dict().get_item(string("__coerce__")); - - if(coerce_fct.get() == 0) // not yet defined - this->def(&standard_coerce, "__coerce__"); -} - -template -inline -std::vector const& -extension_class::base_classes() const -{ - return class_registry::base_classes(); -} - -template -inline -std::vector const& -extension_class::derived_classes() const -{ - return class_registry::derived_classes(); -} - -template -void* extension_class::extract_object_from_holder(instance_holder_base* v) const -{ - instance_holder* held = dynamic_cast*>(v); - if(held) - return held->target(); - return 0; -} - -template -extension_class::~extension_class() -{ - class_registry::unregister_class(this); -} - -template -inline void class_registry::register_class(extension_class_base* p) -{ - // You're not expected to create more than one of these! - assert(static_class_object == 0); - static_class_object = p; -} - -template -inline void class_registry::unregister_class(extension_class_base* p) -{ - // The user should be destroying the same object they created. - assert(static_class_object == p); - (void)p; // unused in shipping version - static_class_object = 0; -} - -template -void class_registry::register_base_class(base_class_info const& i) -{ - static_base_class_info.push_back(i); -} - -template -void class_registry::register_derived_class(derived_class_info const& i) -{ - static_derived_class_info.push_back(i); -} - -template -std::vector const& class_registry::base_classes() -{ - return static_base_class_info; -} - -template -std::vector const& class_registry::derived_classes() -{ - return static_derived_class_info; -} - -// -// Static data member declaration. -// -template -extension_class_base* class_registry::static_class_object; -template -std::vector class_registry::static_base_class_info; -template -std::vector class_registry::static_derived_class_info; - -}}} // namespace boost::python::detail - -#endif // EXTENSION_CLASS_DWA052000_H_ -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_extclass(args) diff --git a/src/gen_function.py b/src/gen_function.py deleted file mode 100644 index dba53c3b..00000000 --- a/src/gen_function.py +++ /dev/null @@ -1,243 +0,0 @@ -r""" ->>> template = ''' template -... static PyObject* call( %1(T::*pmf)(%(A%+%:, %))%2, PyObject* args, PyObject* ) { -... PyObject* self; -... %( PyObject* a%+; -... %) if (!PyArg_ParseTuple(args, const_cast("O%(O%)"), &self%(, &a%+%))) -... return 0; -... T& target = from_python(self, type()); -... %3to_python((target.*pmf)(%( -... from_python(a%+, type())%:,%) -... ));%4 -... }''' - ->>> print gen_function(template, 0, 'R ', '', 'return ', '') - template - static PyObject* call( R (T::*pmf)(), PyObject* args, PyObject* ) { - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)( - )); - } - ->>> print gen_function(template, 2, 'R ', '', 'return ', '') - template - static PyObject* call( R (T::*pmf)(A1, A2), PyObject* args, PyObject* ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)( - from_python(a1, type()), - from_python(a2, type()) - )); - } - ->>> print gen_function(template, 3, 'void ', ' const', '', '\n'+8*' ' + 'return none();') - template - static PyObject* call( void (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) - return 0; - T& target = from_python(self, type()); - to_python((target.*pmf)( - from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()) - )); - return none(); - } -""" -import string - -def _find(s, sub, start=0, end=None): - """Just like string.find, except it returns end or len(s) when not found. - """ - if end == None: - end = len(s) - - pos = string.find(s, sub, start, end) - if pos < 0: - return end - else: - return pos - -def _raise_no_argument(key, n, args): - raise IndexError(str(key) + " extra arg(s) not passed to gen_function") - -def _gen_common_key(key, n, args, fill = _raise_no_argument): - # import sys - # print >> sys.stderr, "_gen_common_key(", repr(key), ",", repr(n), ',', repr(args), ',', fill, ')' - # sys.stderr.flush() - if len(key) > 0 and key in '123456789': - index = int(key) - 1; - - if index >= len(args): - return fill(key, n, args) - - arg = args[index] - if callable(arg): - return str(arg(key, n, args)) - else: - return str(arg) - elif key in ('x','n','-','+'): - return str(n + {'-':-1,'+':+1,'x':0,'n':0}[key]) - else: - return key - -def _gen_arg(template, n, args, fill = _raise_no_argument): - - result = '' - i = 0 - while i < len(template): # until the template is consumed - # consume everything up to the first '%' - delimiter_pos = _find(template, '%', i) - result = result + template[i:delimiter_pos] - - # The start position of whatever comes after the '%'+key - start = delimiter_pos + 2 - key = template[start - 1 : start] # the key character. If there were no - # '%'s left, key will be empty - - if 0 and key == 'n': - result = result + `n` - else: - result = result + _gen_common_key(key, n, args, fill) - - i = start - - return result - -def gen_function(template, n, *args, **keywords): - r"""gen_function(template, n, [args...] ) -> string - - Generate a function declaration based on the given template. - - Sections of the template between '%(', '%)' pairs are repeated n times. If '%:' - appears in the middle, it denotes the beginning of a '%'. - - Sections of the template between '%{', '%}' pairs are ommitted if n == 0. - - %n is transformed into the string representation of 1..n for each - repetition within %(...%). Elsewhere, %n is transformed into the - string representation of n - - %- is transformed into the string representation of 0..n-1 for - each repetition within %(...%). Elsewhere, %- is transformed into the - string representation of n-1. - - %+ is transformed into the string representation of 2..n+1 for - each repetition within %(...%). Elsewhere, %- is transformed into the - string representation of n+1. - - %x is always transformed into the string representation of n - - %z, where z is a digit, selects the corresponding additional - argument. If that argument is callable, it is called with three - arguments: - key - the string representation of 'z' - n - the iteration number - args - a tuple consisting of all the additional arguments to - this function - otherwise, the selected argument is converted to a string representation - - - for example, - - >>> gen_function('%1 abc%x(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void') - 'void abc2(int a0, int a1); // all args are ints' - - >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x') - 'x abc();' - - >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, lambda key, n, args: 'abcd'[n]) - 'a abc();' - - >>> gen_function('%2 %1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x', fill = lambda key, n, args: 'const') - 'const x abc();' - - >>> gen_function('abc%[k%:v%]', 0, fill = lambda key, n, args, value = None: '<' + key + ',' + value + '>') - 'abc' - -""" - expand = (lambda s, n = n: - apply(gen_function, (s, n) + args, keywords)) - - fill = keywords.get('fill', _raise_no_argument); - result = '' - i = 0 - while i < len(template): # until the template is consumed - # consume everything up to the first '%' - delimiter_pos = _find(template, '%', i) - result = result + template[i:delimiter_pos] - - # The start position of whatever comes after the '%'+key - start = delimiter_pos + 2 - key = template[start - 1 : start] # the key character. If there were no - # '%'s left, key will be empty - - pairs = { '(':')', '{':'}', '[':']' } - - if key in pairs.keys(): - end = string.find(template, '%' + pairs[key], start) - assert end >= 0, "Matching '" + '%' + pairs[key] +"' not found!" - delimiter_pos = end - - if key == '{': - if n > 0: - result = result + expand(template[start:end]) - else: - separator_pos = _find(template, '%:', start, end) - remainder = template[separator_pos+2 : end] - - if key == '(': - for x in range(n): - - iteration = expand( - template[start:separator_pos], x) - - result = result + expand(iteration, x) - - if x != n - 1: - result = result + expand(remainder, x) - else: - function_result = fill( - template[start:separator_pos], n, args, value = remainder) - result = result + expand(function_result) - - else: - result = result + expand(_gen_common_key(key, n, args, fill)) - - i = delimiter_pos + 2 - - return result - -def gen_functions(template, n, *args, **keywords): - r"""gen_functions(template, n, [args...]) -> string - - Call gen_function repeatedly with from 0..n and the given optional - arguments. - - >>> print gen_functions('%1 abc(%(int a%n%:, %));%{ // all args are ints%}\n', 2, 'void'), - void abc(); - void abc(int a0); // all args are ints - void abc(int a0, int a1); // all args are ints - - """ - fill = keywords.get('fill', _raise_no_argument); - result = '' - for x in range(n + 1): - result = result + apply(gen_function, (template, x) + args, keywords) - return result - -if __name__ == '__main__': - import doctest - import sys - doctest.testmod(sys.modules.get(__name__)) diff --git a/src/gen_init_function.py b/src/gen_init_function.py deleted file mode 100644 index 69c772c5..00000000 --- a/src/gen_init_function.py +++ /dev/null @@ -1,215 +0,0 @@ -from gen_function import * -import string - -def gen_init_function(args): - - return ( -"""// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// This file was generated for %d-argument constructors by gen_init_function.python - -#ifndef INIT_FUNCTION_DWA052000_H_ -# define INIT_FUNCTION_DWA052000_H_ - -# include -# include -# include -# include - -namespace boost { namespace python { - -namespace detail { - - // parameter_traits - so far, this is a way to pass a const T& when we can be - // sure T is not a reference type, and a raw T otherwise. This should be - // rolled into boost::call_traits. Ordinarily, parameter_traits would be - // written: - // - // template struct parameter_traits - // { - // typedef const T& const_reference; - // }; - // - // template struct parameter_traits - // { - // typedef T& const_reference; - // }; - // - // template <> struct parameter_traits - // { - // typedef void const_reference; - // }; - // - // ...but since we can't partially specialize on reference types, we need this - // long-winded but equivalent incantation. - - // const_ref_selector -- an implementation detail of parameter_traits (below). This uses - // the usual "poor man's partial specialization" hack for MSVC. - template - struct const_ref_selector - { - template - struct const_ref - { - typedef const T& type; - }; - }; - - template <> - struct const_ref_selector - { - template - struct const_ref - { - typedef T type; - }; - }; - -# ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4181) -# endif // BOOST_MSVC - template - struct parameter_traits - { - private: - enum { is_ref = boost::is_reference::value }; - typedef const_ref_selector selector; - public: - typedef typename selector::template const_ref::type const_reference; - }; -# ifdef BOOST_MSVC -# pragma warning(pop) -# endif // BOOST_MSVC - - // Full spcialization for void - template <> - struct parameter_traits - { - typedef void const_reference; - }; - - struct reference_parameter_base {}; - - template - class reference_parameter - : public reference_parameter_base - { - public: - typedef typename parameter_traits::const_reference const_reference; - reference_parameter(const_reference value) - : value(value) {} - operator const_reference() { return value; } - private: - const_reference value; - }; - -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct unwrap_parameter - { - typedef typename boost::add_reference::type type; - }; - - template - struct unwrap_parameter > - { - typedef typename reference_parameter::const_reference type; - }; -# else - template - struct unwrap_parameter_helper - { - template - struct apply - { - typedef typename T::const_reference type; - }; - }; - - template <> - struct unwrap_parameter_helper - { - template - struct apply - { - typedef typename add_reference::type type; - }; - }; - - template - struct unwrap_parameter - { - BOOST_STATIC_CONSTANT( - bool, is_wrapped = (is_base_and_derived::value)); - - typedef typename unwrap_parameter_helper< - is_wrapped - >::template apply::type type; - }; -# endif - -class extension_instance; -class instance_holder_base; - -class init; -""" - + gen_functions('template struct init%x;\n', args) - + """ -template -struct init_function -{ -""" + gen_functions("""%{ - template <%(class A%n%:, %)> -%} static init* create(signature%x%{<%(A%n%:, %)>%}) { - return new init%x::const_reference%)>; - } -""", args)+"""}; - -class init : public function -{ -private: // override function hook - PyObject* do_call(PyObject* args, PyObject* keywords) const; -private: - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0; -}; -""" + gen_functions(""" - -template -struct init%x : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - %(PyObject* a%n; - %)if (!PyArg_ParseTuple(args, const_cast("%(O%)")%(, &a%n%))) - throw_argument_error(); - return new T(self%(, - boost::python::detail::reference_parameter(from_python(a%n, type()))%) - ); - } - const char* description() const - { return typeid(void (*)(T&%(, A%n%%))).name(); } -};""", args) + """ - -}}} // namespace boost::python::detail - -#endif // INIT_FUNCTION_DWA052000_H_ -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_init_function(args) - diff --git a/src/gen_py_api.py b/src/gen_py_api.py deleted file mode 100644 index bc965d8f..00000000 --- a/src/gen_py_api.py +++ /dev/null @@ -1,776 +0,0 @@ -# Copyright David Hawkes 2002. -# Permission is hereby granted to copy, use and modify this software -# for any purpose, including commercial distribution, provided this -# copyright notice is not removed. No warranty WHATSOEVER is provided with this -# software. Any user(s) accepts this software "as is" and as such they will not -# bind the author(s) to any claim of suitabilty for any purpose. - -# Build python API wrappers for boost python - -import re - -API_List = [ -'PyObject*{new} abs{direct}(int{template})', -'PyObject*{new} abs{direct}(PyObject*)', -'PyObject*{new} abs{direct}(short)', -'PyObject*{new} abs{direct}(int)', -'PyObject*{new} abs{direct}(long)', -'PyObject*{new} abs{direct}(double const &)', -'PyObject*{new,err=NULL} PyObject_CallObject{decl=apply}(PyObject*,PyObject*)', -'PyObject*{new,err=NULL} PyObject_Call{decl=apply}(PyObject*,PyObject*,PyObject*)', -'bool PyCallable_Check{decl=callable}(PyObject*)', -'PyObject*{new} chr{direct}(int{template})', -'PyObject*{new} chr{direct}(PyObject*)', -'PyObject*{new} chr{direct}(short)', -'PyObject*{new} chr{direct}(int)', -'PyObject*{new} chr{direct}(long)', -'int{err=-1} PyObject_Cmp{decl=cmp}(PyObject*{template},PyObject*{template},int{result})', -'int{err=-1} PyObject_Cmp{decl=cmp}(PyObject*,PyObject*,int{result})', -'PyObject*{new} coerce{direct}(PyObject*,PyObject*)', -'PyObject*{new} compile{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} compile{direct}(const char*,const char*,const char*)', -'PyObject*{new} compile{direct}(PyObject*,PyObject*,PyObject*,PyObject*)', -'PyObject*{new} compile{direct}(const char*,const char*,const char*,int)', -'PyObject*{new} compile{direct}(PyObject*,PyObject*,PyObject*,PyObject*,PyObject*)', -'PyObject*{new} compile{direct}(const char*,const char*,const char*,int,int)', -'PyObject*{new} complex{direct}(int{template})', -'PyObject*{new} complex{direct}(PyObject*)', -'PyObject*{new} complex{direct}(double const&)', -'PyObject*{new} complex{direct}(int{template},int{template})', -'PyObject*{new} complex{direct}(PyObject*,PyObject*)', -'PyObject*{new} complex{direct}(double const&,double const&)', -'PyObject*{new} dict{direct}()', -'PyObject*{new} dict{direct}(PyObject*)', -'PyObject*{new} PyObject_Dir{decl=dir}(PyObject*{value=NULL})', -'PyObject*{new} PyObject_Dir{decl=dir}(PyObject*)', -'PyObject*{new} divmod{direct}(int{template},int{template})', -'PyObject*{new} divmod{direct}(PyObject*,PyObject*)', -'PyObject*{new} divmod{direct}(int,int)', -'PyObject*{new} divmod{direct}(long,long)', -'PyObject*{new} divmod{direct}(double const&,double const&)', -'PyObject*{new} PyRun_String{decl=eval}(char*{const},int{value=Py_eval_input},PyObject*{value=globals().ptr()},PyObject*{value=globals().ptr()})', -'PyObject*{new} PyRun_String{decl=eval}(char*{const},int{value=Py_eval_input},PyObject*,PyObject*{value=globals().ptr()})', -'PyObject*{new} PyRun_String{decl=eval}(char*{const},int{value=Py_eval_input},PyObject*,PyObject*)', -'PyObject*{new} PyRun_String{decl=exec}(char*{const},int{value=Py_file_input},PyObject*{value=globals().ptr()},PyObject*{value=globals().ptr()})', -'PyObject*{new} PyRun_String{decl=exec}(char*{const},int{value=Py_file_input},PyObject*,PyObject*{value=globals().ptr()})', -'PyObject*{new} PyRun_String{decl=exec}(char*{const},int{value=Py_file_input},PyObject*,PyObject*)', -'PyObject*{new} execfile{direct}(PyObject*)', -'PyObject*{new} execfile{direct}(PyObject*,PyObject*)', -'PyObject*{new} execfile{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} file{direct}(PyObject*)', -'PyObject*{new} file{direct}(const char*)', -'PyObject*{new} file{direct}(PyObject*,PyObject*)', -'PyObject*{new} file{direct}(const char*,const char*)', -'PyObject*{new} file{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} file{direct}(const char*,const char*,int)', -'PyObject*{new} filter{direct}(PyObject*,PyObject*)', -'PyObject*{new} float{direct,decl=float_}(PyObject*)', -'PyObject*{new} float{direct,decl=float_}(const char*)', -'PyObject*{new} float{direct,decl=float_}(double const&)', -'PyObject*{new} getattr{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} getattr{direct}(PyObject*,const char *,PyObject*)', -'PyObject*{borrowed,err=NULL} PyModule_GetDict{decl=globals}(PyObject*{value=PyImport_AddModule("__main__")})', -'bool PyObject_HasAttr{decl=hasattr}(PyObject*,PyObject*)', -'bool PyObject_HasAttrString{decl=hasattr}(PyObject*,char*{const})', -'long{err=-1} PyObject_Hash{decl=hash}(PyObject*)', -'PyObject*{new} hex{direct}(int{template})', -'PyObject*{new} hex{direct}(PyObject*)', -'PyObject*{new} hex{direct}(char)', -'PyObject*{new} hex{direct}(short)', -'PyObject*{new} hex{direct}(int)', -'PyObject*{new} hex{direct}(long)', -'long id{direct}(PyObject*)', -'PyObject*{new} input{direct}()', -'PyObject*{new} input{direct}(PyObject*)', -'PyObject*{new} input{direct}(const char*)', -'PyObject*{new} int{direct,decl=int_}(PyObject*)', -'PyObject*{new} int{direct,decl=int_}(long)', -'PyObject*{new} int{direct,decl=int_}(const char*)', -'PyObject*{new} intern{direct}(PyObject*)', -'PyObject*{new} intern{direct}(const char*)', -'bool PyObject_IsInstance{decl=isinstance}(PyObject*,PyObject*)', -'bool PyObject_IsSubclass{decl=issubclass}(PyObject*,PyObject*)', -'PyObject*{new} PyObject_GetIter{decl=iter}(PyObject*)', -'PyObject*{new} iter{direct}(PyObject*,PyObject*)', -'long{err=-1} PyObject_Length{decl=len}(PyObject*)', -'PyObject*{new} list{direct}()', -'PyObject*{new} list{direct}(PyObject*)', -'PyObject*{new} long{direct,decl=long_}(PyObject*)', -'PyObject*{new} long{direct,decl=long_}(long)', -'PyObject*{new} long{direct,decl=long_}(const char*)', -'PyObject*{new} map{direct,argrepeat}(PyObject*)', -'PyObject*{new} max{direct,argrepeat}(PyObject*{template})', -'PyObject*{new} max{direct,argrepeat}(PyObject*)', -'PyObject*{new} min{direct,argrepeat}(PyObject*{template})', -'PyObject*{new} min{direct,argrepeat}(PyObject*)', -'PyObject*{new} oct{direct}(int{template})', -'PyObject*{new} oct{direct}(PyObject*)', -'PyObject*{new} oct{direct}(char)', -'PyObject*{new} oct{direct}(short)', -'PyObject*{new} oct{direct}(int)', -'PyObject*{new} oct{direct}(long)', -'PyObject*{new} open{direct}(PyObject*)', -'PyObject*{new} open{direct}(const char*)', -'PyObject*{new} open{direct}(PyObject*,PyObject*)', -'PyObject*{new} open{direct}(const char*,const char*)', -'PyObject*{new} open{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} open{direct}(const char*,const char*,int)', -'long ord{direct}(PyObject*)', -'long ord{direct}(const char*)', -'PyObject*{new} pow{direct}(int{template},int{template})', -'PyObject*{new} pow{direct}(PyObject*,PyObject*)', -'PyObject*{new} pow{direct}(double const&,double const&)', -'PyObject*{new} pow{direct}(double const&,double const&,double const&)', -'PyObject*{new} print{direct,statement=print _1,argrepeat}(int{template})', -'PyObject*{new} print{direct,statement=print _1,argrepeat}(PyObject*)', -'PyObject*{new} print{decl=print_file,direct,statement="print >>_1, _2",argrepeat}(PyObject*,int{template})', -'PyObject*{new} print{decl=print_file,direct,statement="print >>_1, _2",argrepeat}(PyObject*,PyObject*)', -'PyObject*{new} range{direct}(int{template})', -'PyObject*{new} range{direct}(PyObject*)', -'PyObject*{new} range{direct}(int)', -'PyObject*{new} range{direct}(int{template},int{template})', -'PyObject*{new} range{direct}(PyObject*,PyObject*)', -'PyObject*{new} range{direct}(int,int)', -'PyObject*{new} range{direct}(int{template},int{template},int{template})', -'PyObject*{new} range{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} range{direct}(int,int,int)', -'PyObject*{new} raw_input{direct}()', -'PyObject*{new} raw_input{direct}(PyObject*)', -'PyObject*{new} raw_input{direct}(const char*)', -'PyObject*{new} reduce{direct}(PyObject*,PyObject*)', -'PyObject*{new} reduce{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new,err=NULL} PyImport_ReloadModule{decl=reload}(PyObject*)', -'PyObject*{new} PyObject_Repr{decl=repr}(PyObject*)', -'PyObject*{new} round{direct}(int{template})', -'PyObject*{new} round{direct}(PyObject*)', -'PyObject*{new} round{direct}(double const&)', -'PyObject*{new} round{direct}(int{template},int{template})', -'PyObject*{new} round{direct}(PyObject*,PyObject*)', -'PyObject*{new} round{direct}(double const&,double const&)', -'PyObject*{new} slice{direct}(int{template})', -'PyObject*{new} slice{direct}(PyObject*)', -'PyObject*{new} slice{direct}(int)', -'PyObject*{new} slice{direct}(int{template},int{template})', -'PyObject*{new} slice{direct}(PyObject*,PyObject*)', -'PyObject*{new} slice{direct}(int,int)', -'PyObject*{new} slice{direct}(int{template},int{template},int{template})', -'PyObject*{new} slice{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} slice{direct}(int,int,int)', -'PyObject*{new} PyObject_Str{decl=str}(PyObject*)', -'PyObject*{new} tuple{direct}()', -'PyObject*{new} tuple{direct}(PyObject*)', -'PyObject*{new,err=NULL} PyObject_Type{decl=type_}(PyObject*)', -'PyObject*{new} unichr{direct}(int{template})', -'PyObject*{new} unichr{direct}(PyObject*)', -'PyObject*{new} unichr{direct}(short)', -'PyObject*{new} unichr{direct}(int)', -'PyObject*{new} unichr{direct}(long)', -'PyObject*{new} PyObject_Unicode{decl=unicode}(PyObject*)', -'PyObject*{new} unicode{direct}(PyObject*,PyObject*)', -'PyObject*{new} unicode{direct}(PyObject*,const char*)', -'PyObject*{new} unicode{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} unicode{direct}(PyObject*,const char*,const char*)', -'PyObject*{new} vars{direct}()', -'PyObject*{new} vars{direct}(PyObject*)', -'PyObject*{new} xrange{direct}(int{template})', -'PyObject*{new} xrange{direct}(PyObject*)', -'PyObject*{new} xrange{direct}(int)', -'PyObject*{new} xrange{direct}(int{template},int{template})', -'PyObject*{new} xrange{direct}(PyObject*,PyObject*)', -'PyObject*{new} xrange{direct}(int,int)', -'PyObject*{new} xrange{direct}(int{template},int{template},int{template})', -'PyObject*{new} xrange{direct}(PyObject*,PyObject*,PyObject*)', -'PyObject*{new} xrange{direct}(int,int,int)', -'PyObject*{new} zip{direct,argrepeat}(PyObject*)', -'PyObject*{new,err=NULL} Py_CompileString{decl=compile_string}(char*{const},char*{const},int)', -'int{err=-1} PyImport_AppendInittab{decl=import_append_inittab}(char*{const},void(*arg)(void))', -'PyObject*{borrowed,err=NULL} PyImport_AddModule{decl=import_add_module}(char*{const})', -'PyObject*{borrowed,err=NULL} PyImport_GetModuleDict{decl=import_get_module_dict}()', -'PyObject*{new,err=NULL} PyImport_Import{decl=import_import}(PyObject*)', -'PyObject*{new,err=NULL} PyImport_Import{decl=import_import}(const char*{object})', -'PyObject*{new,err=NULL} PyImport_ImportModule{decl=import_import_module}(char*{const})', -'PyObject*{new,err=NULL} PyImport_ImportModuleEx{decl=import_import_module_ex}(char*{const},PyObject*,PyObject*,PyObject*)', -'PyObject*{borrowed,err=NULL} PyModule_GetDict{decl=module_get_dict}(PyObject*)', -'int{err=-1} PyObject_Print{decl=object_print}(PyObject*,FILE*,int)', -'PyObject*{new,err=NULL} PyRun_File{decl=run_file}(FILE*,char*{const},int,PyObject*,PyObject*)', -'int{err=-1} PyRun_SimpleFile{decl=run_simple_file}(FILE*,char*{const})', -'int{err=-1} PyRun_SimpleString{decl=run_simple_string}(char*{const})', -'PyObject*{new,err=NULL} PyRun_String{decl=run_string}(char*{const},int,PyObject*,PyObject*)', -'PyObject*{new} call_statement{statement,direct}(const char*{statement})', -'PyObject*{new} call_statement{statement,direct}(const char*{statement},call_dict_usage{use_gd})', -'PyObject*{new} call_statement{argrepeat,statement,direct}(const char*{statement},int{template})', -'PyObject*{new} call_statement{argrepeat,statement,direct}(const char*{statement},PyObject*)', -'PyObject*{new} call_statement{argrepeat,statement,direct}(const char*{statement},call_dict_usage{use_gd},int{template})', -'PyObject*{new} call_statement{argrepeat,statement,direct}(const char*{statement},call_dict_usage{use_gd},PyObject*)', -] - -DeclFile = '../../../boost/python/py_interface.hpp' -ImplFile = 'py_interface.cpp' - -DeclFileHeader = '''\ -// Automatically generated from py_api_gen.py -#ifndef PY_INTERFACE_HPP -#define PY_INTERFACE_HPP - -#include -#include - -namespace boost { namespace python { namespace api { - -enum call_dict_usage { use_new_dict, use_local_dict, use_global_dict }; - -namespace api_detail { - -BOOST_PYTHON_DECL object get_func(const char* name); -BOOST_PYTHON_DECL object call_statement(const char *stmt, int n, ...); -BOOST_PYTHON_DECL object call_statement_du(const char *stmt, call_dict_usage cdu, int n, ...); - -template -struct get_arg -{ - get_arg(A const &a) : h(a) {} - object h; - operator object const& () { return h; } - operator object const* () { return &h; } -}; - -template<> -struct get_arg -{ - get_arg(object const &a) : h(a) {} - object const &h; - operator object const& () { return h; } - operator object const* () { return &h; } -}; - -template<> -struct get_arg -{ - get_arg(PyObject* a) : h((python::detail::borrowed_reference)a) {} - object h; - operator object const& () { return h; } - operator object const* () { return &h; } -}; - -} - -BOOST_PYTHON_DECL object locals(); - -''' - -DeclFileTrailer = '''\ -}}} - -#endif // PY_INTERFACE_HPP -''' - -ImplFileHeader = '''\ -// Automatically generated from py_api_gen.py - -#include - -namespace boost { namespace python { namespace api { - -namespace api_detail { - -BOOST_PYTHON_DECL object get_func(const char* name) { - object __builtin__((python::detail::borrowed_reference)::PyImport_AddModule(const_cast("__builtin__"))); - return object(__builtin__.attr(name)); -} - -inline handle<> get_current_frame() -{ - return handle<>(allow_null(borrowed((PyObject*)(PyThreadState_Get()->frame)))); -} - -inline object get_global_dict(call_dict_usage cdu, handle<> const& frame) -{ - if(frame.get()) - return object(object(frame).attr("f_globals")); - else - return api::globals(); -} - -object get_local_dict(call_dict_usage cdu, handle<> const& frame, object const& global_dict) -{ - switch(cdu) { - case use_new_dict: - return api::dict(); - case use_global_dict: - return global_dict; - default: - if(frame.get()) - return object(object(frame).attr("f_locals")); - else - return api::dict(); - } -} - -inline object call_statement(const char *stmt, object const& global_dict, object& local_dict) -{ - local_dict["_0"] = object((python::detail::borrowed_reference)Py_None); - api::run_string(stmt, Py_file_input, global_dict, local_dict); - return object(local_dict["_0"]); -} - -object call_statement(const char *stmt) -{ - handle<> frame(get_current_frame()); - if(frame.get()) { - object f(frame); - object gd(f.attr("f_globals")); - object ld(f.attr("f_locals")); - return call_statement(stmt, gd, ld); - } else { - object gd(api::globals()); - object ld(api::dict()); - return call_statement(stmt, gd, ld); - } -} - -object call_statement_du(const char *stmt, call_dict_usage cdu) -{ - handle<> frame(get_current_frame()); - object gd(get_global_dict(cdu, frame)); - return call_statement(stmt, gd, get_local_dict(cdu, frame, gd)); -} - -inline object call_statement(const char *stmt, object const& global_dict, object& local_dict, int n, va_list mk) -{ - static const char *(idx[]) = { "_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8", "_9", "_10" }; - local_dict["_0"] = object((python::detail::borrowed_reference)Py_None); - for(int i = 0; i < n; ++i) - { - object const* p_arg = va_arg(mk, object const*); - object const& arg = *p_arg; - if(i < (int) (sizeof(idx) / sizeof(idx[0]))) - local_dict[idx[i]] = arg; - else { - local_dict[object("_") + object((python::detail::new_reference)PyObject_Str(object(i + 1).ptr()))] = arg; - } - } - va_end(mk); - api::run_string(stmt, Py_file_input, global_dict, local_dict); - return object(local_dict["_0"]); -} - -BOOST_PYTHON_DECL object call_statement(const char *stmt, int n, ...) -{ - va_list mk; - va_start(mk, n); - handle<> frame(get_current_frame()); - if(frame.get()) { - object f(frame); - object gd(f.attr("f_globals")); - object ld(f.attr("f_locals")); - return call_statement(stmt, gd, ld, n, mk); - } else { - object gd(api::globals()); - object ld(api::dict()); - return call_statement(stmt, gd, ld, n, mk); - } -} - -BOOST_PYTHON_DECL object call_statement_du(const char *stmt, call_dict_usage cdu, int n, ...) -{ - handle<> frame(get_current_frame()); - object gd(get_global_dict(cdu, frame)); - va_list mk; - va_start(mk, n); - return call_statement(stmt, gd, get_local_dict(cdu, frame, gd), n, mk); -} - -} - -BOOST_PYTHON_DECL object locals() -{ - handle<> frame(api_detail::get_current_frame()); - if(frame.get()) - return object(object(frame).attr("f_locals")); - else - return api::dict(); -} - -''' - -ImplFileTrailer = '''\ -}}} -''' - -def SplitOutList(l): - vals_list = [] - if l == None: - return vals_list - vals_list = re.findall(r'((?:[^,{}]|(?:{[^{}]*}))+),?\s*', l) - return vals_list - -def SplitOutListDict(l): - vals_dict = {} - if l == None: - return vals_dict - vals = re.findall(r'((?:"[^"]+"|[^,"]+)+)\s*,?', l) - for val in vals: - m = re.match(r'(?P[^\s=]+)\s*(=\s*(?P"?)(?P.+)(?P=qt))?', val).groupdict() - vals_dict[m['aname']] = m['aval'] - return vals_dict - -def SplitOutAttrs(a): - soa = {} - m = re.match(r'(?P[^{]+)({(?P[^}]+)})?', a).groupdict() - soa['name'] = m['name'] - soa.update(SplitOutListDict(m['attrs'])) - return soa - -def is_object(name): - if re.match(r'PyObject\s*\*', name['name']): - return 1 - return 0 - -def is_arg_really_const(arg): - return arg.has_key('const') - -def get_actual_rtn_type(rtn, args): - i = 0 - for a in args: - if a.has_key('result'): - true_rtn = dict(rtn) - true_rtn['name'] = a['name'] - true_rtn['arg_number'] = i - return true_rtn - i += 1 - return rtn - -def is_template(name): - return name.has_key('template') - -def decl_func_arg(arg, p): - if arg.has_key('value'): - return '' - elif arg.has_key('result'): - return '' - elif is_object(arg): - if is_template(arg): - sn = str(p) - return 'A' + sn +' const& a' + sn - else: - return 'object const& a' + str(p) - elif is_arg_really_const(arg): - return 'const ' + arg['name'] + ' a' + str(p) - elif re.search(r'arg', arg['name']): - return re.sub(r'arg', 'a' + str(p), arg['name']) - else: - if is_template(arg): - sn = str(p) - return 'A' + sn +' const& a' + sn - else: - return arg['name'] + ' a' + str(p) - -def decl_func_args(name, args): - if not len(args): - return '' - d_args = reduce(lambda x,y : x + (y and (', ' + y) or ''), map(decl_func_arg, args, xrange(len(args)))) - return d_args - -def call_func_arg(arg, p): - if arg.has_key('value'): - return arg['value'] - elif arg.has_key('result'): - return '&rslt' - elif arg.has_key('template'): - sn = str(p) - return 'api_detail::get_arg(a%s)' % (sn, sn) - elif arg.has_key('object'): - return 'object(a%s).ptr()' % str(p) - elif is_object(arg): - return 'a' + str(p) + '.ptr()' - elif is_arg_really_const(arg): - return 'const_cast<%s>(%s)' % (arg['name'], 'a' + str(p)) - else: - return 'a' + str(p) - -def call_func_args(args): - if not len(args): - return '' - d_args = reduce(lambda x,y : x + (y and ((x and ', ' or '') + y) or ''), map(call_func_arg, args, xrange(len(args)))) - return d_args - -def call_func(name, args): - return '::%s(%s)' % (name['name'], call_func_args(args)) - -def call_func_direct_arg(arg, p): - if arg.has_key('use_gd'): - return '' - elif arg.has_key('statement'): - return '' - elif arg.has_key('value'): - return arg['value'] - elif arg.has_key('template'): - sn = str(p) - if arg.has_key('addr'): - return '(object const*)api_detail::get_arg(a%s)' % (sn, sn) - else: - return 'api_detail::get_arg(a%s)' % (sn, sn) - elif is_object(arg): - if arg.has_key('addr'): - return '&a' + str(p) - else: - return 'a' + str(p) - else: - if arg.has_key('addr'): - return '&object(a%s)' % str(p) - else: - return 'object(a%s)' % str(p) - -def call_func_direct_args(args): - if not len(args): - return '' - d_args = reduce(lambda x,y : x + (y and ((x and ', ' or '') + y) or ''), map(call_func_direct_arg, args, xrange(len(args)))) - return d_args - -def get_statement_arg(args): - i = 0 - for arg in args: - if arg.has_key('statement'): - return i - i = i + 1 - return -1 - -def get_use_gd_arg(args): - i = 0 - for arg in args: - if arg.has_key('use_gd'): - return i - i = i + 1 - return -1 - -def call_func_direct(name, args): - if name.has_key('statement'): - na = len(args) - ugd = get_use_gd_arg(args) - sa = get_statement_arg(args) - if ugd >= 0: - ugd = 'a' + str(ugd) - na = na - 1 - else: - if (sa < 0) and (na > 0): - ugd = 'use_new_dict' - else: - ugd = None - if sa >= 0: - na = na - 1 - if na > 0: - if ugd: - return 'api_detail::call_statement_du(%s, %s, %s, %s)' % ('a' + str(sa), ugd, na, call_func_direct_args(args)) - else: - return 'api_detail::call_statement(%s, %s, %s)' % ('a' + str(sa), na, call_func_direct_args(args)) - else: - if ugd: - return 'api_detail::call_statement_du(%s, %s)' % ('a' + str(sa), ugd) - else: - return 'api_detail::call_statement(%s)' % ('a' + str(sa)) - else: - if na > 0: - if ugd: - return 'api_detail::call_statement_du("%s", %s, %s, %s)' % (name['statement'], ugd, na, call_func_direct_args(args)) - else: - return 'api_detail::call_statement("%s", %s, %s)' % (name['statement'], na, call_func_direct_args(args)) - else: - if ugd: - return 'api_detail::call_statement_du("%s", %s)' % (name['statement'], ugd) - else: - return 'api_detail::call_statement("%s")' % (name['statement']) - else: - return 'api_detail::get_func("%s")(%s)' % (name['name'], call_func_direct_args(args)) - -def decl_template_arg(arg, p): - if arg.has_key('value'): - return '' - elif arg.has_key('result'): - return '' - elif is_template(arg): - return 'class A' + str(p) - else: - return '' - -def decl_template_args(args): - if not len(args): - return '' - d_args = reduce(lambda x,y : x + (y and ((x and ', ' or '') + y) or ''), map(decl_template_arg, args, xrange(len(args)))) - return d_args - -def is_rtn_borrowed_object(rtn): - if is_object(rtn): - return rtn.has_key('borrowed') - else: - return 0 - -def is_rtn_new_object(rtn): - if is_object(rtn): - return not rtn.has_key('borrowed') - else: - return 0 - -def is_func_direct(name): - return name.has_key('direct') - -def rtn_call_func_direct(rtn, name, args): - if rtn['name'] == 'void': - direct_code = ' %s;' % call_func_direct(name, args) - elif is_object(rtn): - direct_code = ' return %s;' % call_func_direct(name, args) - else: - r = '''\ - object r(%s); - return boost::python::arg_from_python<%s>(r.ptr())(r.ptr());''' - direct_code = r % (call_func_direct(name, args), rtn['name']) - return direct_code - -def rtn_call_func(rtn, name, args): - if is_func_direct(name): - return rtn_call_func_direct(rtn, name, args) - true_rtn = get_actual_rtn_type(rtn, args) - err = true_rtn.get('err') - arg_number = true_rtn.get('arg_number') - if rtn['name'] == 'void': - return ' %s;' % call_func(name, args) - elif is_rtn_new_object(rtn): - if err and (err != 'NULL'): - r = '''\ - PyObject* r = %s; - if(r == %s) - throw_error_already_set(); - return object((python::detail::new_reference)r);''' - return r % (call_func(name, args), err) - else: - return ' return object((python::detail::new_reference)%s);' % call_func(name, args) - elif is_rtn_borrowed_object(rtn): - if err and (err != 'NULL'): - r = '''\ - PyObject* r = %s; - if(r == %s) - throw_error_already_set(); - return object((python::detail::borrowed_reference)r);''' - return r % (call_func(name, args), err) - else: - return ' return object((python::detail::borrowed_reference)%s);' % call_func(name, args) - else: - if err: - if arg_number == None: - r = '''\ - %s r = %s; - if(r == %s) - throw_error_already_set(); - return r;''' - return r % (rtn['name'], call_func(name, args), err) - else: - r = '''\ - %s rslt; - %s r = %s; - if(r == %s) - throw_error_already_set(); - return rslt;''' - return r % (true_rtn['name'], rtn['name'], call_func(name, args), err) - else: - return ' return %s;' % call_func(name, args) - -def decl_func(name, args): - return '%s(%s)' % (name.get('decl', name['name']), decl_func_args(name, args)) - -def rtn_decl_func(rtn, name, args): - true_rtn = get_actual_rtn_type(rtn, args) - ta = decl_template_args(args) - if ta: - decl = 'template<%s>\n' % ta - else: - decl = 'BOOST_PYTHON_DECL ' - if is_object(true_rtn): - return decl + 'object %s' % decl_func(name, args) - else: - return decl + '%s %s' % (true_rtn['name'], decl_func(name, args)) - -def is_info_template(fn_info): - for arg in fn_info['args']: - if is_template(arg): - return 1 - return 0 - -def parse_func(func): - fn_info = {} - fnm = re.match(r'(?P\S+)\s+(?P[^\s\(\){}]+({[^{}]*})?)\s*\((?P(({[^{}]*})+|(\([^\(\)]*\))+|[^\(\)]+)*)\)', func).groupdict() - fn_info['fname'] = SplitOutAttrs(fnm['fname']) - fn_info['rtn'] = SplitOutAttrs(fnm['rtn']) - fn_info['args'] = map(SplitOutAttrs, SplitOutList(fnm['args'])) - if fn_info['fname'].has_key('statement'): - if is_info_template(fn_info): - for arg in fn_info['args']: - if is_template(arg): - arg['addr'] = None - else: - for arg in fn_info['args']: - if is_object(arg): - arg['addr'] = None - return fn_info - -def get_argrepeat(fn_info): - if fn_info['fname'].has_key('argrepeat'): - argrepeat = fn_info['fname']['argrepeat'] - if argrepeat == None: - argrepeat = 10 - else: - argrepeat = 1 - return argrepeat - -def do_arg_repeat(fn_info): - fn_info['args'] = fn_info['args'] + [fn_info['args'][len(fn_info['args']) - 1],] - if fn_info['fname'].has_key('statement'): - stmt = fn_info['fname']['statement'] - if stmt: - s_args = re.findall(r'[\s,\(](?:_([0-9]+))(?=$|[\s,\)])', stmt) - if s_args: - mx = reduce(max, map(int, s_args), 0) - mx_arg = '_' + str(mx) - next_arg = '_' + str(mx + 1) - stmt = re.sub(r'(?<=[\s,\(])' + mx_arg + '(?=$|[\s,\)])', mx_arg + ', ' + next_arg, stmt, 1) - fn_info['fname']['statement'] = stmt - -def decl_funcs(fn_list): - fn_defs = '' - for fn in fn_list: - fn_info = parse_func(fn) - argrepeat = get_argrepeat(fn_info) - for ar in xrange(argrepeat): - fn_defs += rtn_decl_func(fn_info['rtn'], fn_info['fname'], fn_info['args']) - if is_info_template(fn_info): - fn_defs += '\n{\n' + rtn_call_func(fn_info['rtn'], fn_info['fname'], fn_info['args']) + '\n}\n' - else: - fn_defs += ';\n' - if ar != (argrepeat - 1): - do_arg_repeat(fn_info) - return fn_defs - -def impl_funcs(fn_list): - fn_defs = '' - for fn in fn_list: - fn_info = parse_func(fn) - if is_info_template(fn_info): - continue - argrepeat = get_argrepeat(fn_info) - for ar in xrange(argrepeat): - fn_defs += rtn_decl_func(fn_info['rtn'], fn_info['fname'], fn_info['args']) + ' {\n' - fn_defs += rtn_call_func(fn_info['rtn'], fn_info['fname'], fn_info['args']) + '\n}\n\n' - if ar != (argrepeat - 1): - do_arg_repeat(fn_info) - return fn_defs - -if __name__ == '__main__': - f = file(DeclFile, 'w') - print >>f, DeclFileHeader - print >>f, decl_funcs(API_List) - print >>f, DeclFileTrailer - f.close() - - f = file(ImplFile, 'w') - print >>f, ImplFileHeader - print >>f, impl_funcs(API_List) - print >>f, ImplFileTrailer - f.close() diff --git a/src/gen_returning.py b/src/gen_returning.py deleted file mode 100644 index 8f7c866c..00000000 --- a/src/gen_returning.py +++ /dev/null @@ -1,201 +0,0 @@ -# (C) Copyright David Abrahams 2001,2002. Permission to copy, use, modify, sell and -# distribute this software is granted provided this copyright notice appears -# in all copies. This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. -# -# This work was funded in part by Lawrence Berkeley National Labs - -from gen_function import * -import string - -header = '''// (C) Copyright David Abrahams 2001,2002. Permission to copy, use, modify, sell -// and distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// This work was funded in part by Lawrence Berkeley National Labs -// -// This file generated for %d-argument member functions and %d-argument free -// functions by gen_returning.py -''' - -body_sections = ( -''' -#ifndef RETURNING_DWA20011201_HPP -# define RETURNING_DWA20011201_HPP - -# include -# include -# include -# include - -namespace boost { namespace python { namespace detail { - -// Calling C++ from Python -template -struct returning -{ -''', -''' -''', -''' // Free functions -''', -'''}; - -template <> -struct returning -{ - typedef void R; -''', -''' -''', -''' - // Free functions -''', -'''}; - -}}} // namespace boost::python::detail - -#endif // RETURNING_DWA20011201_HPP -''') - -#' - -member_function = ''' template - static PyObject* call(R (A0::*pmf)(%(A%+%:, %))%1, PyObject* args_, PyObject*, P const& policies) - { - // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args_, 0)); - if (!c0.convertible()) return 0; -%( from_python c%+(PyTuple_GET_ITEM(args_, %+)); - if (!c%+.convertible()) return 0; -%) -%[r%: // find the result converter - typedef typename P::result_converter result_converter; - typename eval::type cr; - if (!cr.convertible()) return 0; - -%] if (!policies.precall(args_)) return 0; - - %[r%:PyObject* result = cr( %]((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( - %(c%+(PyTuple_GET_ITEM(args_, %+))%: - , %))%[r%: )%]; - - return policies.postcall(args_, %[r%:result%]%[v%:detail::none()%]); - } -''' - -free_function = ''' template - static PyObject* call(R (*pf)(%(A%n%:, %)), PyObject* args_, PyObject*, P const& policies) - {%{ - // check that each of the arguments is convertible -%}%( from_python c%n(PyTuple_GET_ITEM(args_, %n)); - if (!c%n.convertible()) return 0; -%) -%[r%: // find the result converter - typedef typename P::result_converter result_converter; - typename eval::type cr; - if (!cr.convertible()) return 0; - -%]%[not-void-and-0-arg%: if (!policies.precall(args_)) return 0; - -%] %[r%:PyObject* result = cr( %](*pf)( - %(c%n(PyTuple_GET_ITEM(args_, %n))%: - , %))%[r%: )%]; - - return policies.postcall(args_, %[r%:result%]%[v%:detail::none()%]); - } -''' - -def _returns_value(key, n, args, value): - if key != 'v': - return value - else: - return '' - -def _returns_void(key, n, args, value): - if key == 'v' or key == 'not-void-and-0-arg' and n != 0: - return value - else: - return '' - -_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') - -_prefix = { -# ' const': ''' - -# // missing cv-qualified -> cv-unqualified member pointer conversions -# # if defined(__MWERKS__) && __MWERKS__ <=0x2406 || defined(BOOST_MSVC) && BOOST_MSVC <= 1200 || defined(__BORLANDC__) -# ''', - ' const volatile': ''' -// missing const volatile type traits -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -'''}; - -def gen_returning(member_function_args, free_function_args = None): - if free_function_args is None: - free_function_args = member_function_args + 1 - - return_none = '''; - return detail::none();''' - - return (header % (member_function_args, free_function_args) - + body_sections[0] - # - # functions returning results - # - - + reduce(lambda x,y: x+y - , map(lambda cv: - _prefix.get(cv,'') - + gen_functions(member_function, - member_function_args, cv, - fill = _returns_value) + '\n' - , _cv_qualifiers)) - + '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -''' -## endif // missing cv-qualified -> cv-unqualified member pointer conversions -#''' - # free functions - + gen_functions(free_function, free_function_args, fill = _returns_value) - + body_sections[3] - - # - # functions returning void - # - - + reduce(lambda x,y: x+y - , map(lambda cv: - _prefix.get(cv,'') - + gen_functions(member_function, - member_function_args, cv, fill = - _returns_void) + '\n' - , _cv_qualifiers)) - - + '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -''' -## endif // missing cv-qualified -> cv-unqualified member pointer conversions -#''' - # free functions - + gen_functions(free_function, free_function_args, fill = _returns_void) - + body_sections[6] - ) - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - member_function_args = 5 - free_function_args = 6 - else: - member_function_args = int(sys.argv[1]) - if len(sys.argv) > 2: - free_function_args = int(sys.argv[2]) - else: - free_function_args = member_function_args - - print gen_returning(member_function_args, free_function_args) - - diff --git a/src/gen_signature.py b/src/gen_signature.py deleted file mode 100644 index 1af3437d..00000000 --- a/src/gen_signature.py +++ /dev/null @@ -1,90 +0,0 @@ -# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -# distribute this software is granted provided this copyright notice appears -# in all copies. This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. -# -# This work was funded in part by Lawrence Berkeley National Labs - -from gen_function import * -import string - -header = '''// (C) Copyright David Abrahams 2002. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// This work was funded in part by Lawrence Berkeley and Lawrence -// Livermore National Labs -// -// This file generated for %d-argument member functions and %d-argument free -// functions by gen_signature.py -''' - -_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') - -_suffix = { - '': ''' -// Metrowerks thinks this creates ambiguities -# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 -''', ' const volatile': ''' -# endif // __MWERKS__ -''' - }; - -def gen_arg_tuple_size(member_function_args, free_function_args = None): - if free_function_args is None: - free_function_args = member_function_args + 1 - - return_none = '''; - return detail::none();''' - - return (header % (member_function_args, free_function_args) - + ''' -#ifndef SIGNATURE_DWA2002128_HPP -# define SIGNATURE_DWA2002128_HPP - -# include - -namespace boost { namespace python { namespace detail { -''' - - + gen_functions(''' -template -mpl::type_list -signature(R (*)(%(A%n%:, %))) -{ - return mpl::type_list() -} -''', free_function_args) - - + reduce(lambda x,y: x+'\n'+y - , map( - lambda cv: gen_functions( -'''template -mpl::type_list signature(R (A0::*)(%(A%+%:, %))%1) -{ - return mpl::type_list(); -} - -''', member_function_args, cv) - , _cv_qualifiers)) + '''}}} // namespace boost::python::detail - -#endif // SIGNATURE_DWA2002128_HPP -''') - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - member_function_args = 5 - free_function_args = 6 - else: - member_function_args = int(sys.argv[1]) - if len(sys.argv) > 2: - free_function_args = int(sys.argv[2]) - else: - free_function_args = member_function_args - - print gen_arg_tuple_size(member_function_args, free_function_args) - - diff --git a/src/gen_signatures.py b/src/gen_signatures.py deleted file mode 100644 index f5a97b17..00000000 --- a/src/gen_signatures.py +++ /dev/null @@ -1,158 +0,0 @@ -from gen_function import * -import string - -def gen_struct_signatures(args): - result = '' - for n in range(args, -1, -1): - result = ( - result + gen_function("""%{template <%(class T%n%:, %)> -%}struct signature%x {}; - -""", n) -# + ((n == args) and [""] or -# [gen_function(""" -# template -# static inline signature%1 prepend(type) -# { return signature%1(); }""", -# n, (str(n+1),)) -# ] -# )[0] -# -# + ((n != 0) and [""] or -# [""" -# // This one terminates the chain. Prepending void_t to the head of a void_t -# // signature results in a void_t signature again. -# static inline signature0 prepend(void_t) { return signature0(); }"""] -# )[0] -# + """ -#}; -# -#""" - + ((n == args) and [""] or - [gen_function( -"""template <%(class T%n%, %)class X> -inline signature%1 prepend(type, signature%x%{<%(T%n%:, %)>%}) - { return signature%1(); } - -""", n, str(n+1)) - ] - )[0] - ) - return result - -def gen_signatures(args): - return ( -"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. -// -// This file automatically generated by gen_signatures.python for %d arguments. -#ifndef SIGNATURES_DWA050900_H_ -# define SIGNATURES_DWA050900_H_ - -# include - -namespace boost { namespace python { - -namespace detail { -// A stand-in for the built-in void. This one can be passed to functions and -// (under MSVC, which has a bug, be used as a default template type parameter). -struct void_t {}; -} - -// An envelope in which type information can be delivered for the purposes -// of selecting an overloaded from_python() function. This is needed to work -// around MSVC's lack of partial specialiation/ordering. Where normally we'd -// want to form a function call like void f(), We instead pass -// type as one of the function parameters to select a particular -// overload. -// -// The id typedef helps us deal with the lack of partial ordering by generating -// unique types for constructor signatures. In general, type::id is type, -// but type::id is just void_t. -template -struct type -{ - typedef type id; -}; - -template <> -struct type -{ - typedef boost::python::detail::void_t id; -}; - -namespace detail { -// These basically encapsulate a chain of types, , used to make the syntax of -// add(constructor()) work. We need to produce a unique type for each number -// of non-default parameters to constructor<>. Q: why not use a recursive -// formulation for infinite extensibility? A: MSVC6 seems to choke on constructs -// that involve recursive template nesting. -// -// signature chaining -""" % args - + gen_struct_signatures(args) - + """ -// This one terminates the chain. Prepending void_t to the head of a void_t -// signature results in a void_t signature again. -inline signature0 prepend(void_t, signature0) { return signature0(); } - -} // namespace detail -""" - + gen_function(""" -template <%(class A%n% = detail::void_t%:, %)> -struct constructor -{ -}; -""", args) - + """ -namespace detail { -// Return value extraction: - -// This is just another little envelope for carrying a typedef (see type, -// above). I could have re-used type, but that has a very specific purpose. I -// thought this would be clearer. -template -struct return_value_select { typedef T type; }; - -// free functions""" - + gen_functions(""" -template -return_value_select return_value(R (*)(%(A%n%:, %))) { return return_value_select(); } -""", args) - - + -""" -// TODO(?): handle 'const void' - -// member functions""" - + gen_functions(""" -template -return_value_select return_value(R (T::*)(%(A%n%:, %))) { return return_value_select(); } -""", args) - - + gen_functions(""" -template -return_value_select return_value(R (T::*)(%(A%n%:, %)) const) { return return_value_select(); } -""", args) - - + """ -}}} // namespace boost::python::detail - -#endif -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_signatures(args) - diff --git a/src/gen_singleton.py b/src/gen_singleton.py deleted file mode 100644 index 3a5ca7e3..00000000 --- a/src/gen_singleton.py +++ /dev/null @@ -1,58 +0,0 @@ -from gen_function import * -import string - -def gen_singleton(args): - return ( -"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -#ifndef SINGLETON_DWA051900_H_ -# define SINGLETON_DWA051900_H_ - -# include - -namespace boost { namespace python { namespace detail { - -struct empty {}; -template -struct singleton : Base -{ - typedef singleton singleton_base; // Convenience type for derived class constructors - - static Derived* instance(); - - // Pass-through constructors -""" - + gen_functions("""%{ - template <%(class A%n%:, %)> -%} singleton(%(const A%n& a%n%:, %)) : Base(%(a%n%:, %)) {} -""", args) - + """ -}; - -template -Derived* singleton::instance() -{ - static Derived x; - return &x; -} - -}}} // namespace boost::python::detail - -#endif -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_singleton(args) diff --git a/src/gen_value_holder.py b/src/gen_value_holder.py deleted file mode 100644 index b01e2c0e..00000000 --- a/src/gen_value_holder.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright David Abrahams 2002. Permission to copy, use, modify, -# sell and distribute this software is granted provided this -# copyright notice appears in all copies. This software is provided -# "as is" without express or implied warranty, and with no claim as -# to its suitability for any purpose. -# -# This work was funded in part by Lawrence Livermore National Labs - -from gen_function import * -import string - -def _generate(member_function_args, free_function_args = None): - return ('''// Copyright David Abrahams 2001. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#ifndef VALUE_HOLDER_DWA20011215_HPP -# define VALUE_HOLDER_DWA20011215_HPP - -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace objects { - -template -struct value_holder : instance_holder -{ - // Forward construction to the held object -''' - + - gen_functions( diff --git a/src/init_function.cpp b/src/init_function.cpp deleted file mode 100644 index 1ebfa501..00000000 --- a/src/init_function.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -#define BOOST_PYTHON_SOURCE - -#include -#include -#include -#include - -namespace boost { namespace python { namespace detail { - - PyObject* init::do_call(PyObject* args_, PyObject* keywords) const - { - tuple args(ref(args_, ref::increment_count)); - if (args[0]->ob_type->ob_type != extension_meta_class()) - { - PyErr_SetString(PyExc_TypeError, "argument 1 to __init__ must be an ExtensionInstance"); - return 0; - } - - extension_instance *self = static_cast(args[0].get()); - - tuple ctor_args = args.slice(1, args.size()); - - std::auto_ptr result( - create_holder(self, ctor_args.get(), keywords)); - - self->add_implementation(result); - return none(); - } - -}}} // namespace boost::python::detail diff --git a/src/list.cpp b/src/list.cpp deleted file mode 100644 index ee8bceb3..00000000 --- a/src/list.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#include - -namespace boost { namespace python { - -BOOST_PYTHON_DECL detail::new_non_null_reference list::call(object const& arg_) -{ - return (detail::new_non_null_reference) - (expect_non_null)( - PyObject_CallFunction( - (PyObject*)&PyList_Type, "(O)", - arg_.ptr())); -} - -BOOST_PYTHON_DECL list::list() - : object(detail::new_reference(PyList_New(0))) -{} - -BOOST_PYTHON_DECL list::list(object_cref sequence) - : object(list::call(sequence)) -{} - -BOOST_PYTHON_DECL void list::append(object_cref x) -{ - if (PyList_CheckExact(this->ptr())) - { - if (PyList_Append(this->ptr(), x.ptr()) == -1) - throw_error_already_set(); - } - else - { - this->attr("append")(x); - } -} - -BOOST_PYTHON_DECL long list::count(object_cref value) const -{ - object result_obj(this->attr("count")(value)); - long result = PyInt_AsLong(result_obj.ptr()); - if (result == -1) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL void list::extend(object_cref sequence) -{ - this->attr("extend")(sequence); -} - -BOOST_PYTHON_DECL long list::index(object_cref value) const -{ - object result_obj(this->attr("index")(value)); - long result = PyInt_AsLong(result_obj.ptr()); - if (result == -1) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL void list::insert(int index, object_cref item) -{ - if (PyList_CheckExact(this->ptr())) - { - if (PyList_Insert(this->ptr(), index, item.ptr()) == -1) - throw_error_already_set(); - } - else - { - this->attr("insert")(index, item); - } -} - -BOOST_PYTHON_DECL void list::insert(object const& index, object_cref x) -{ - long index_ = PyInt_AsLong(index.ptr()); - if (index_ == -1 && PyErr_Occurred()) - throw_error_already_set(); - this->insert(index_, x); -} - -BOOST_PYTHON_DECL object list::pop() -{ - return this->attr("pop")(); -} - -BOOST_PYTHON_DECL object list::pop(long index) -{ - return this->pop(object(index)); -} - -BOOST_PYTHON_DECL object list::pop(object const& index) -{ - return this->attr("pop")(index); -} - -BOOST_PYTHON_DECL void list::remove(object_cref value) -{ - this->attr("remove")(value); -} - -BOOST_PYTHON_DECL void list::reverse() -{ - if (PyList_CheckExact(this->ptr())) - { - if (PyList_Reverse(this->ptr()) == -1) - throw_error_already_set(); - } - else - { - this->attr("reverse")(); - } -} - -BOOST_PYTHON_DECL void list::sort() -{ - if (PyList_CheckExact(this->ptr())) - { - if (PyList_Sort(this->ptr()) == -1) - throw_error_already_set(); - } - else - { - this->attr("sort")(); - } -} - -BOOST_PYTHON_DECL void list::sort(object_cref cmpfunc) -{ - this->attr("sort")(cmpfunc); -} - -}} // namespace boost::python diff --git a/src/long.cpp b/src/long.cpp deleted file mode 100644 index 2cf98610..00000000 --- a/src/long.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#include - -namespace boost { namespace python { - -BOOST_PYTHON_DECL detail::new_non_null_reference long_::call(object const& arg_) -{ - return (detail::new_non_null_reference)PyObject_CallFunction( - (PyObject*)&PyLong_Type, "(O)", - arg_.ptr()); -} - -BOOST_PYTHON_DECL detail::new_non_null_reference long_::call(object const& arg_, object const& base) -{ - return (detail::new_non_null_reference)PyObject_CallFunction( - (PyObject*)&PyLong_Type, "(OO)", - arg_.ptr(), base.ptr()); -} - -BOOST_PYTHON_DECL long_::long_() - : object( - detail::new_reference( - PyObject_CallFunction((PyObject*)&PyLong_Type, "()")) - ) -{} - -BOOST_PYTHON_DECL long_::long_(object_cref arg) - : object(long_::call(arg)) -{} - -BOOST_PYTHON_DECL long_::long_(object_cref arg, object_cref base) - : object(long_::call(arg, base)) -{} - - -}} // namespace boost::python diff --git a/src/module.cpp b/src/module.cpp deleted file mode 100644 index 2dd476d1..00000000 --- a/src/module.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace detail { - -module_base::module_base(char const* name, char const* doc) - : m_module( - allow_null(python::borrowed( - scope().ptr() - ))) -{ - if (doc != 0) - scope().attr("__doc__") = doc; -} - -module_base::~module_base() -{ -} - -void module_base::setattr_doc(const char* name, python::object const& x, char const* doc) -{ - // Use function::add_to_namespace to achieve overloading if - // appropriate. - objects::function::add_to_namespace(python::object(m_module), name, x, doc); -} - -void BOOST_PYTHON_DECL scope_setattr_doc(char const* name, object const& x, char const* doc) -{ - // Use function::add_to_namespace to achieve overloading if - // appropriate. - scope current; - objects::function::add_to_namespace(current, name, x, doc); -} - -void module_base::add(type_handle const& x) -{ - this->setattr_doc(x->tp_name, python::object(x), 0); -} - -PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } }; - -namespace -{ - PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; -} - -BOOST_PYTHON_DECL void init_module(char const* name, void(*init_function)()) -{ - - PyObject* m - = Py_InitModule(const_cast(name), initial_methods); - - if (m != 0) - { - ; - - // Create the current module scope - scope current_module( - (object( - ((borrowed_reference_t*)m) - )) - ); - - handle_exception(init_function); - } -} - -}}} // namespace boost::python::detail - -namespace boost { namespace python { - -BOOST_PYTHON_DECL PyObject* scope::current_scope = 0; - -}} diff --git a/src/module_builder.cpp b/src/module_builder.cpp deleted file mode 100644 index 1e47badb..00000000 --- a/src/module_builder.cpp +++ /dev/null @@ -1,64 +0,0 @@ - // (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -#define BOOST_PYTHON_SOURCE - -#include - -namespace boost { namespace python { - -namespace { - ref name_holder; -} - -bool module_builder_base::initializing() -{ - return name_holder.get() != 0; -} - -string module_builder_base::name() -{ - // If this fails, you haven't created a module_builder object - assert(initializing()); - return string(name_holder); -} - -module_builder_base::module_builder_base(const char* name) - : m_module(Py_InitModule(const_cast(name), initial_methods)) -{ - // If this fails, you've created more than 1 module_builder object in your module - assert(name_holder.get() == 0); - name_holder = ref(PyObject_GetAttrString(m_module, const_cast("__name__"))); -} - -module_builder_base::~module_builder_base() -{ - name_holder.reset(); -} - -void -module_builder_base::add(detail::function* x, const char* name) -{ - reference f(x); // First take possession of the object. - detail::function::add_to_namespace(f, name, PyModule_GetDict(m_module)); -} - -void module_builder_base::add(ref x, const char* name) -{ - PyObject* dictionary = PyModule_GetDict(m_module); - PyDict_SetItemString(dictionary, const_cast(name), x.get()); -} - -void module_builder_base::add(PyTypeObject* x, const char* name /*= 0*/) -{ - this->add(ref(as_object(x)), name ? name : x->tp_name); -} - -PyMethodDef module_builder_base::initial_methods[] = { { 0, 0, 0, 0 } }; - -}} // namespace boost::python diff --git a/src/object/class.cpp b/src/object/class.cpp deleted file mode 100644 index 3cd62a37..00000000 --- a/src/object/class.cpp +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright David Abrahams 2001. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { - -# ifdef BOOST_PYTHON_SELF_IS_CLASS -namespace self_ns -{ - self_t self; -} -# endif - -instance_holder::instance_holder() - : m_next(0) -{ -} - -instance_holder::~instance_holder() -{ -} - -// This is copied from typeobject.c in the Python sources. Even though -// class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets -// filled in by the base class initialization process in -// PyType_Ready(). However, tp_is_gc is *not* copied from the base -// type, making it assume that classes are GC-able even if (like -// class_type_object) they're statically allocated. -static int -type_is_gc(PyTypeObject *python_type) -{ - return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE; -} - -static PyTypeObject class_metatype_object = { - PyObject_HEAD_INIT(0)//&PyType_Type) - 0, - "Boost.Python.class", - PyType_Type.tp_basicsize, - 0, - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, //&PyType_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, // filled in with type_new /* tp_new */ - 0, // filled in with __PyObject_GC_Del /* tp_free */ - (inquiry)type_is_gc, /* tp_is_gc */ -}; - -// Install the instance data for a C++ object into a Python instance -// object. -void instance_holder::install(PyObject* self) throw() -{ - assert(self->ob_type->ob_type == &class_metatype_object); - m_next = ((objects::instance<>*)self)->objects; - ((objects::instance<>*)self)->objects = this; -} - - -namespace objects -{ -// Get the metatype object for all extension classes. - BOOST_PYTHON_DECL type_handle class_metatype() - { - if (class_metatype_object.tp_dict == 0) - { - class_metatype_object.ob_type = &PyType_Type; - class_metatype_object.tp_base = &PyType_Type; - if (PyType_Ready(&class_metatype_object)) - return type_handle(); - } - return type_handle(borrowed(&class_metatype_object)); - } - extern "C" - { - static void instance_dealloc(PyObject* inst) - { - instance<>* kill_me = (instance<>*)inst; - - for (instance_holder* p = kill_me->objects, *next; p != 0; p = next) - { - next = p->next(); - p->~instance_holder(); - instance_holder::deallocate(inst, dynamic_cast(p)); - } - - // Python 2.2.1 won't add weak references automatically when - // tp_itemsize > 0, so we need to manage that - // ourselves. Accordingly, we also have to clean up the - // weakrefs ourselves. - if (kill_me->weakrefs != NULL) - PyObject_ClearWeakRefs(inst); - - Py_XDECREF(kill_me->dict); - - inst->ob_type->tp_free(inst); - } - - static PyObject * - instance_new(PyTypeObject* type_, PyObject* args, PyObject *kw) - { - // Attempt to find the __instance_size__ attribute. If not present, no problem. - PyObject* d = type_->tp_dict; - PyObject* instance_size_obj = PyObject_GetAttrString(d, "__instance_size__"); - - long instance_size = 0; - if (instance_size != 0) - instance_size = PyInt_AsLong(instance_size_obj); - - if (instance_size < 0) - instance_size = 0; - PyErr_Clear(); // Clear any errors that may have occurred. - - instance<>* result = (instance<>*)type_->tp_alloc(type_, instance_size); - if (result) - { - // Guido says we can use ob_size for any purpose we - // like, so we'll store the total size of the object - // there. A negative number indicates that the extra - // instance memory is not yet allocated to any holders. - result->ob_size = -(offsetof(instance<>,storage) + instance_size); - } - return (PyObject*)result; - } - - static PyObject* instance_get_dict(PyObject* op, void*) - { - instance<>* inst = downcast >(op); - if (inst->dict == 0) - inst->dict = PyDict_New(); - return python::xincref(inst->dict); - } - - static int instance_set_dict(PyObject* op, PyObject* dict, void*) - { - instance<>* inst = downcast >(op); - python::xdecref(inst->dict); - inst->dict = python::incref(dict); - return 0; - } - } - - - static PyGetSetDef instance_getsets[] = { - {"__dict__", instance_get_dict, instance_set_dict, NULL}, - {0} - }; - - - static PyMemberDef instance_members[] = { - {"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0}, - {0} - }; - - static PyTypeObject class_type_object = { - PyObject_HEAD_INIT(0) //&class_metatype_object) - 0, - "Boost.Python.instance", - offsetof(instance<>,storage), /* tp_basicsize */ - 1, /* tp_itemsize */ - instance_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(instance<>,weakrefs), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - instance_members, /* tp_members */ - instance_getsets, /* tp_getset */ - 0, //&PyBaseObject_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(instance<>,dict), /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - instance_new /* tp_new */ - }; - - BOOST_PYTHON_DECL type_handle class_type() - { - if (class_type_object.tp_dict == 0) - { - class_type_object.ob_type = incref(class_metatype().get()); - class_type_object.tp_base = &PyBaseObject_Type; - if (PyType_Ready(&class_type_object)) - return type_handle(); - } - return type_handle(borrowed(&class_type_object)); - } - - BOOST_PYTHON_DECL void* - find_instance_impl(PyObject* inst, type_info type) - { - if (inst->ob_type->ob_type != &class_metatype_object) - return 0; - - instance<>* self = reinterpret_cast*>(inst); - - for (instance_holder* match = self->objects; match != 0; match = match->next()) - { - void* const found = match->holds(type); - if (found) - return found; - } - return 0; - } - - object module_prefix() - { - object result( - PyObject_IsInstance(scope().ptr(), upcast(&PyModule_Type)) - ? object(scope().attr("__name__")) - : api::getattr(scope(), "__module__", str()) - ); - - if (result) - result += '.'; - - return result; - } - - namespace - { - // Find a registered class object corresponding to id. Return a - // null handle if no such class is registered. - inline type_handle query_class(class_id id) - { - converter::registration const* p = converter::registry::query(id); - return type_handle( - python::borrowed( - python::allow_null(p ? p->class_object : 0)) - ); - } - - // Find a registered class corresponding to id. If not found, - // throw an appropriate exception. - type_handle get_class(class_id id) - { - type_handle result(query_class(id)); - - if (result.get() == 0) - { - object report("extension class wrapper for base class "); - report = report + id.name() + " has not been created yet"; - PyErr_SetObject(PyExc_RuntimeError, report.ptr()); - throw_error_already_set(); - } - return result; - } - - // class_base constructor - // - // name - the name of the new Python class - // - // num_types - one more than the number of declared bases - // - // types - array of python::type_info, the first item - // corresponding to the class being created, and the - // rest corresponding to its declared bases. - // - inline object - new_class(char const* name, std::size_t num_types, class_id const* const types) - { - assert(num_types >= 1); - - // Build a tuple of the base Python type objects. If no bases - // were declared, we'll use our class_type() as the single base - // class. - std::size_t const num_bases = std::max(num_types - 1, static_cast(1)); - handle<> bases(PyTuple_New(num_bases)); - - for (std::size_t i = 1; i <= num_bases; ++i) - { - type_handle c = (i >= num_types) ? class_type() : get_class(types[i]); - // PyTuple_SET_ITEM steals this reference - PyTuple_SET_ITEM(bases.get(), i - 1, upcast(c.release())); - } - - // Call the class metatype to create a new class - object result = object(class_metatype())(module_prefix() + name, bases, dict()); - assert(PyType_IsSubtype(result.ptr()->ob_type, &PyType_Type)); - - if (scope().ptr() != Py_None) - scope().attr(name) = result; - - return result; - } - } - - class_base::class_base( - char const* name, std::size_t num_types, class_id const* const types, char const* doc) - : object(new_class(name, num_types, types)) - { - // Insert the new class object in the registry - converter::registration& converters = const_cast( - converter::registry::lookup(types[0])); - - // Class object is leaked, for now - converters.class_object = (PyTypeObject*)incref(this->ptr()); - - if (doc) - this->attr("__doc__") = doc; - } - - void class_base::set_instance_size(std::size_t instance_size) - { - this->attr("__instance_size__") = instance_size; - } - - extern "C" - { - // This declaration needed due to broken Python 2.2 headers - extern DL_IMPORT(PyTypeObject) PyProperty_Type; - } - - void class_base::add_property(char const* name, object const& fget) - { - object property( - (python::detail::new_reference) - PyObject_CallFunction((PyObject*)&PyProperty_Type, "O", fget.ptr())); - - this->setattr(name, property); - } - - void class_base::add_property(char const* name, object const& fget, object const& fset) - { - object property( - (python::detail::new_reference) - PyObject_CallFunction((PyObject*)&PyProperty_Type, "OO", fget.ptr(), fset.ptr())); - - this->setattr(name, property); - } - - void class_base::setattr(char const* name, object const& x) - { - if (PyObject_SetAttrString(this->ptr(), const_cast(name), x.ptr()) < 0) - throw_error_already_set(); - } - - namespace - { - extern "C" PyObject* no_init(PyObject*, PyObject*) - { - ::PyErr_SetString(::PyExc_RuntimeError, "This class cannot be instantiated from Python"); - return NULL; - } - static ::PyMethodDef no_init_def = { - "__init__", no_init, METH_VARARGS, - "Raises an exception\n" - "This class cannot be instantiated from Python\n" - }; - } - - void class_base::def_no_init() - { - handle<> f(::PyCFunction_New(&no_init_def, 0)); - this->setattr("__init__", object(f)); - } - - void class_base::enable_pickling(bool getstate_manages_dict) - { - setattr("__reduce__", object(make_instance_reduce_function())); - setattr("__safe_for_unpickling__", object(true)); - - if (getstate_manages_dict) - { - setattr("__getstate_manages_dict__", object(true)); - } - } - - BOOST_PYTHON_DECL type_handle registered_class_object(class_id id) - { - return query_class(id); - } -} // namespace objects - - -void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size) -{ - assert(self_->ob_type->ob_type == &class_metatype_object); - objects::instance<>* self = (objects::instance<>*)self_; - - int total_size_needed = holder_offset + holder_size; - - if (-self->ob_size >= total_size_needed) - { - // holder_offset should at least point into the variable-sized part - assert(holder_offset >= offsetof(objects::instance<>,storage)); - - // Record the fact that the storage is occupied, noting where it starts - self->ob_size = holder_offset; - return (char*)self + holder_offset; - } - else - { - void* const result = PyMem_Malloc(holder_size); - if (result == 0) - throw std::bad_alloc(); - return result; - } -} - -void instance_holder::deallocate(PyObject* self_, void* storage) throw() -{ - assert(self_->ob_type->ob_type == &class_metatype_object); - objects::instance<>* self = (objects::instance<>*)self_; - if (storage != (char*)self + self->ob_size) - { - PyMem_Free(storage); - } -} - -}} // namespace boost::python diff --git a/src/object/enum.cpp b/src/object/enum.cpp deleted file mode 100644 index b09a70a8..00000000 --- a/src/object/enum.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace objects { - -struct enum_object -{ - PyIntObject base_object; - PyObject* name; -}; - -static PyMemberDef enum_members[] = { - {"name", T_OBJECT_EX, offsetof(enum_object,name),READONLY}, - {0} -}; - - -extern "C" -{ - static int - enum_print(PyObject *v, BOOST_CSTD_::FILE *fp, int flags) - { - PyObject* s - = (flags & Py_PRINT_RAW) ? v->ob_type->tp_str(v) : v->ob_type->tp_repr(v); - if (s == 0) - return -1; - - char const* text = PyString_AsString(s); - if (text == 0) - return -1; - - BOOST_CSTD_::fprintf(fp, text); - return 0; - } - - /* flags -- not used but required by interface */ - static PyObject* enum_repr(PyObject* self_) - { - enum_object* self = downcast(self_); - if (!self->name) - { - return PyString_FromFormat("%s(%ld)", self_->ob_type->tp_name, PyInt_AS_LONG(self_)); - } - else - { - char* name = PyString_AsString(self->name); - if (name == 0) - return 0; - - return PyString_FromFormat("%s.%s", self_->ob_type->tp_name, name); - } - } - - static PyObject* enum_str(PyObject* self_) - { - enum_object* self = downcast(self_); - if (!self->name) - { - return PyInt_Type.tp_str(self_); - } - else - { - return incref(self->name); - } - } -} - -static PyTypeObject enum_type_object = { - PyObject_HEAD_INIT(0) // &PyType_Type - 0, - "Boost.Python.enum", - sizeof(enum_object), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - enum_print, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - enum_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - enum_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT - | Py_TPFLAGS_CHECKTYPES - | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - enum_members, /* tp_members */ - 0, /* tp_getset */ - 0, //&PyInt_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0 /* tp_new */ -}; - -object module_prefix(); - -namespace -{ - object new_enum_type(char const* name) - { - if (enum_type_object.tp_dict == 0) - { - enum_type_object.ob_type = incref(&PyType_Type); - enum_type_object.tp_base = &PyInt_Type; - if (PyType_Ready(&enum_type_object)) - throw_error_already_set(); - } - - type_handle metatype(borrowed(&PyType_Type)); - type_handle base(borrowed(&enum_type_object)); - - // suppress the instance __dict__ in these enum objects. There - // may be a slicker way, but this'll do for now. - dict d; - d["__slots__"] = tuple(); - d["values"] = dict(); - - object result = (object(metatype))( - module_prefix() + name, make_tuple(base), d); - - scope().attr(name) = result; - - return result; - } -} - -enum_base::enum_base( - char const* name - , converter::to_python_function_t to_python - , converter::convertible_function convertible - , converter::constructor_function construct - , type_info id - ) - : object(new_enum_type(name)) -{ - converter::registration& converters - = const_cast( - converter::registry::lookup(id)); - - converters.class_object = downcast(this->ptr()); - converter::registry::insert(to_python, id); - converter::registry::insert(convertible, construct, id); -} - -void enum_base::add_value(char const* name_, long value) -{ - // Convert name to Python string - object name(name_); - - // Create a new enum instance by calling the class with a value - object x = (*this)(value); - - // Store the object in the enum class - (*this).attr(name_) = x; - - dict d = extract(this->attr("values"))(); - d[value] = x; - - // Set the name field in the new enum instanec - enum_object* p = downcast(x.ptr()); - Py_XDECREF(p->name); - p->name = incref(name.ptr()); -} - -PyObject* enum_base::to_python(PyTypeObject* type_, long x) -{ - object type((type_handle(borrowed(type_)))); - - dict d = extract(type.attr("values"))(); - object v = d.get(x, object()); - return incref( - (v == object() ? type(x) : v).ptr()); -} - -}}} // namespace boost::python::object diff --git a/src/object/function.cpp b/src/object/function.cpp deleted file mode 100644 index 6d013b3a..00000000 --- a/src/object/function.cpp +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright David Abrahams 2001. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace objects { - -extern PyTypeObject function_type; - -function::function(py_function const& implementation, unsigned min_args, unsigned max_args) - : m_fn(implementation) - , m_min_args(min_args) - , m_max_args(std::max(max_args,min_args)) -{ - PyObject* p = this; - if (function_type.ob_type == 0) - { - function_type.ob_type = &PyType_Type; - ::PyType_Ready(&function_type); - } - PyObject_INIT(p, &function_type); -} - -function::~function() -{ -} - -PyObject* function::call(PyObject* args, PyObject* keywords) const -{ - std::size_t nargs = PyTuple_GET_SIZE(args); - function const* f = this; - do - { - // Check for a plausible number of arguments - if (nargs >= f->m_min_args && nargs <= f->m_max_args) - { - // Call the function - PyObject* result = f->m_fn(args, keywords); - - // If the result is NULL but no error was set, m_fn failed - // the argument-matching test. - - // This assumes that all other error-reporters are - // well-behaved and never return NULL to python without - // setting an error. - if (result != 0 || PyErr_Occurred()) - return result; - } - f = f->m_overloads.get(); - } - while (f); - // None of the overloads matched; time to generate the error message - argument_error(args, keywords); - return 0; -} - -void function::argument_error(PyObject* args, PyObject* keywords) const -{ - // This function needs to be improved to do better error reporting. - PyErr_BadArgument(); -} - -void function::add_overload(handle const& overload_) -{ - function* parent = this; - - while (parent->m_overloads) - parent = parent->m_overloads.get(); - - parent->m_overloads = overload_; - - // If we have no documentation, get the docs from the overload - if (!m_doc) - m_doc = overload_->m_doc; -} - -namespace -{ - char const* const binary_operator_names[] = - { - "add__", - "and__", - "div__", - "divmod__", - "eq__", - "floordiv__", - "ge__", - "gt__", - "le__", - "lshift__", - "lt__", - "mod__", - "mul__", - "ne__", - "or__", - "pow__", - "radd__", - "rand__", - "rdiv__", - "rdivmod__", - "rfloordiv__", - "rlshift__", - "rmod__", - "rmul__", - "ror__", - "rpow__", - "rrshift__", - "rshift__", - "rsub__", - "rtruediv__", - "rxor__", - "sub__", - "truediv__", - "xor__" - }; - - struct less_cstring - { - bool operator()(char const* x, char const* y) const - { - return BOOST_CSTD_::strcmp(x,y) < 0; - } - }; - - inline bool is_binary_operator(char const* name) - { - return name[0] == '_' - && name[1] == '_' - && std::binary_search( - &binary_operator_names[0] - , binary_operator_names + sizeof(binary_operator_names)/sizeof(*binary_operator_names) - , name + 2 - , less_cstring() - ); - } - - // Something for the end of the chain of binary operators - PyObject* not_implemented_impl(PyObject*, PyObject*) - { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - handle not_implemented_function() - { - static object keeper(function_object(¬_implemented_impl, 2, 3)); - return handle(borrowed(downcast(keeper.ptr()))); - } -} - -void function::add_to_namespace( - object const& name_space, char const* name_, object const& attribute) -{ - str const name(name_); - PyObject* const ns = name_space.ptr(); - - if (attribute.ptr()->ob_type == &function_type) - { - function* new_func = downcast(attribute.ptr()); - PyObject* dict = 0; - - if (PyClass_Check(ns)) - dict = ((PyClassObject*)ns)->cl_dict; - else if (PyType_Check(ns)) - dict = ((PyTypeObject*)ns)->tp_dict; - else - dict = PyObject_GetAttrString(ns, "__dict__"); - - if (dict == 0) - throw_error_already_set(); - - // This isn't quite typesafe. We'll shoot first by assuming - // the thing is a function*, then ask questions later. The code works nicer that way. - handle existing( - allow_null(downcast(::PyObject_GetItem(dict, name.ptr()))) - ); - - if (existing) - { - if (existing->ob_type == &function_type) - new_func->add_overload(existing); - } - else if (is_binary_operator(name_)) - { - // Binary operators need an additional overload which - // returns NotImplemented, so that Python will try the - // lxxx functions on the other operand. We add this when - // no overloads for the operator already exist. - new_func->add_overload(not_implemented_function()); - } - - // A function is named the first time it is added to a namespace. - if (new_func->name().ptr() == Py_None) - new_func->m_name = name; - } - - // The PyObject_GetAttrString() call above left an active error - PyErr_Clear(); - if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0) - throw_error_already_set(); -} - -void function::add_to_namespace( - object const& name_space, char const* name_, object const& attribute, char const* doc) -{ - add_to_namespace(name_space, name_, attribute); - if (doc != 0) - { - object attr_copy(attribute); - attr_copy.attr("__doc__") = doc; - } -} - -namespace -{ - struct bind_return - { - bind_return(PyObject*& result, function const* f, PyObject* args, PyObject* keywords) - : m_result(result) - , m_f(f) - , m_args(args) - , m_keywords(keywords) - {} - - void operator()() const - { - m_result = m_f->call(m_args, m_keywords); - } - - private: - PyObject*& m_result; - function const* m_f; - PyObject* m_args; - PyObject* m_keywords; - }; -} - -extern "C" -{ - // Stolen from Python's funcobject.c - static PyObject * - function_descr_get(PyObject *func, PyObject *obj, PyObject *type_) - { - if (obj == Py_None) - obj = NULL; - return PyMethod_New(func, obj, type_); - } - - static void - function_dealloc(PyObject* p) - { - delete static_cast(p); - } - - static PyObject * - function_call(PyObject *func, PyObject *args, PyObject *kw) - { - PyObject* result = 0; - handle_exception(bind_return(result, static_cast(func), args, kw)); - return result; - } - - // - // Here we're using the function's tp_getset rather than its - // tp_members to set up __doc__ and __name__, because tp_members - // really depends on having a POD object type (it relies on - // offsets). It might make sense to reformulate function as a POD - // at some point, but this is much more expedient. - // - static PyObject* function_get_doc(PyObject* op, void*) - { - function* f = downcast(op); - return python::incref(f->doc().ptr()); - } - - static int function_set_doc(PyObject* op, PyObject* doc, void*) - { - function* f = downcast(op); - f->doc(doc ? object(python::detail::borrowed_reference(doc)) : object()); - return 0; - } - - static PyObject* function_get_name(PyObject* op, void*) - { - function* f = downcast(op); - if (f->name().ptr() == Py_None) - return PyString_InternFromString(""); - else - return python::incref(f->name().ptr()); - } -} - -static PyGetSetDef function_getsetlist[] = { - {"__name__", (getter)function_get_name, 0 }, - {"__doc__", (getter)function_get_doc, (setter)function_set_doc}, - {NULL} /* Sentinel */ -}; - -PyTypeObject function_type = { - PyObject_HEAD_INIT(0) - 0, - "Boost.Python.function", - sizeof(function), - 0, - (destructor)function_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, //(reprfunc)func_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - function_call, /* tp_call */ - 0, /* tp_str */ - 0, // PyObject_GenericGetAttr, /* tp_getattro */ - 0, // PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */ - 0, /* tp_doc */ - 0, // (traverseproc)func_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, // func_memberlist, /* tp_members */ - function_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - function_descr_get, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, - 0 /* tp_new */ -}; - -object function_object_impl(py_function const& f, unsigned min_args, unsigned max_args) -{ - return python::object( - python::detail::new_non_null_reference( - new function(f, min_args, max_args))); -} - -handle<> function_handle_impl(py_function const& f, unsigned min_args, unsigned max_args) -{ - return python::handle<>( - allow_null( - new function(f, min_args, max_args))); -} - -BOOST_PYTHON_DECL void add_to_namespace( - object const& name_space, char const* name, object const& attribute) -{ - function::add_to_namespace(name_space, name, attribute); -} - -BOOST_PYTHON_DECL void add_to_namespace( - object const& name_space, char const* name, object const& attribute, char const* doc) -{ - function::add_to_namespace(name_space, name, attribute, doc); -} - - -}}} // namespace boost::python::objects diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp deleted file mode 100644 index 13dfaef0..00000000 --- a/src/object/inheritance.cpp +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#include -#include -#include -#if _MSC_FULL_VER >= 13102171 && _MSC_FULL_VER <= 13102179 -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Procedure: -// -// The search is a BFS over the space of (type,address) pairs -// guided by the edges of the casting graph whose nodes -// correspond to classes, and whose edges are traversed by -// applying associated cast functions to an address. We use -// vertex distance to the goal node in the cast_graph to rate the -// paths. The vertex distance to any goal node is calculated on -// demand and outdated by the addition of edges to the graph. - -namespace boost { -namespace -{ - enum edge_cast_t { edge_cast = 8010 }; -} - -// Install properties -BOOST_INSTALL_PROPERTY(edge, cast); - -namespace -{ - typedef void*(*cast_function)(void*); - - // - // Here we put together the low-level data structures of the - // casting graph representation. - // - typedef python::type_info class_id; - - // represents a graph of available casts - -#if 0 - struct cast_graph - : -#else - typedef -#endif - adjacency_list > > -#if 0 - {}; -#else - cast_graph; -#endif - - typedef cast_graph::vertex_descriptor vertex_t; - typedef cast_graph::edge_descriptor edge_t; - - struct smart_graph - { - typedef std::vector::const_iterator node_distance_map; - - typedef std::pair out_edges_t; - - // Return a map of the distances from any node to the given - // target node - node_distance_map distances_to(vertex_t target) const - { - std::size_t n = num_vertices(m_topology); - if (m_distances.size() != n * n) - { - m_distances.clear(); - m_distances.resize(n * n, std::numeric_limits::max()); - m_known_vertices = n; - } - - std::vector::iterator to_target = m_distances.begin() + n * target; - - // this node hasn't been used as a target yet - if (to_target[target] != 0) - { - typedef reverse_graph reverse_cast_graph; - reverse_cast_graph reverse_topology(m_topology); - - to_target[target] = 0; - - breadth_first_search( - reverse_topology, target - , visitor( - make_bfs_visitor( - record_distances( - make_iterator_property_map( - to_target - , get(vertex_index, reverse_topology) -# ifdef BOOST_NO_STD_ITERATOR_TRAITS - , *to_target -# endif - ) - , on_tree_edge() - )))); - } - - return to_target; - } - - cast_graph& topology() { return m_topology; } - cast_graph const& topology() const { return m_topology; } - - std::size_t known_vertices() const { return m_known_vertices; } - - smart_graph() - : m_known_vertices(0) - {} - - private: - cast_graph m_topology; - mutable std::vector m_distances; - mutable std::size_t m_known_vertices; - }; - - smart_graph& full_graph() - { - static smart_graph x; - return x; - } - - smart_graph& up_graph() - { - static smart_graph x; - return x; - } - - // - // Our index of class types - // - using boost::python::objects::dynamic_id_function; - typedef tuples::tuple< - class_id // static type - , vertex_t // corresponding vertex - , dynamic_id_function // dynamic_id if polymorphic, or 0 - > - index_entry_interface; - typedef index_entry_interface::inherited index_entry; - enum { ksrc_static_t, kvertex, kdynamic_id }; - - typedef std::vector type_index_t; - - - type_index_t& type_index() - { - static type_index_t x; - return x; - } - - template - struct select1st - { - typedef typename tuples::element<0, Tuple>::type result_type; - - result_type const& operator()(Tuple const& x) const - { - return tuples::get<0>(x); - } - }; - - // map a type to a position in the index - inline type_index_t::iterator type_position(class_id type) - { - typedef index_entry entry; - - return std::lower_bound( - type_index().begin(), type_index().end() - , boost::make_tuple(type, vertex_t(), dynamic_id_function(0)) - , boost::bind(std::less() - , boost::bind(select1st(), _1) - , boost::bind(select1st(), _2))); - } - - inline index_entry* seek_type(class_id type) - { - type_index_t::iterator p = type_position(type); - if (p == type_index().end() || tuples::get(*p) != type) - return 0; - else - return &*p; - } - - // Get the entry for a type, inserting if neccessary - inline type_index_t::iterator demand_type(class_id type) - { - type_index_t::iterator p = type_position(type); - - if (p != type_index().end() && tuples::get(*p) == type) - return p; - - vertex_t v = add_vertex(full_graph().topology()); - vertex_t v2 = add_vertex(up_graph().topology()); - assert(v == v2); - return type_index().insert(p, boost::make_tuple(type, v, dynamic_id_function(0))); - } - - // Map a two types to a vertex in the graph, inserting if neccessary - typedef std::pair - type_index_iterator_pair; - - inline type_index_iterator_pair - demand_types(class_id t1, class_id t2) - { - // be sure there will be no reallocation - type_index().reserve(type_index().size() + 2); - type_index_t::iterator first = demand_type(t1); - type_index_t::iterator second = demand_type(t2); - if (first == second) - ++first; - return std::make_pair(first, second); - } - - struct q_elt - { - q_elt(std::size_t distance - , void* src_address - , vertex_t target - , cast_function cast - ) - : distance(distance) - , src_address(src_address) - , target(target) - , cast(cast) - {} - - std::size_t distance; - void* src_address; - vertex_t target; - cast_function cast; - - bool operator<(q_elt const& rhs) const - { - return distance < rhs.distance; - } - }; - - // Optimization: - // - // Given p, src_t, dst_t - // - // Get a pointer pd to the most-derived object - // if it's polymorphic, dynamic_cast to void* - // otherwise pd = p - // - // Get the most-derived typeid src_td - // - // ptrdiff_t offset = p - pd - // - // Now we can keep a cache, for [src_t, offset, src_td, dst_t] of - // the cast transformation function to use on p and the next src_t - // in the chain. src_td, dst_t don't change throughout this - // process. In order to represent unreachability, when a pair is - // found to be unreachable, we stick a 0-returning "dead-cast" - // function in the cache. - - // This is needed in a few places below - inline void* identity_cast(void* p) - { - return p; - } - - void* search(smart_graph const& g, void* p, vertex_t src, vertex_t dst) - { - // I think this test was thoroughly bogus -- dwa - // If we know there's no path; bail now. - // if (src > g.known_vertices() || dst > g.known_vertices()) - // return 0; - - smart_graph::node_distance_map d(g.distances_to(dst)); - - if (d[src] == std::numeric_limits::max()) - return 0; - - typedef property_map::const_type cast_map; - cast_map casts = get(edge_cast, g.topology()); - - typedef std::pair search_state; - typedef std::vector visited_t; - visited_t visited; - std::priority_queue q; - - q.push(q_elt(d[src], p, src, identity_cast)); - while (!q.empty()) - { - q_elt top = q.top(); - q.pop(); - - // Check to see if we have a real state - void* dst_address = top.cast(top.src_address); - if (dst_address == 0) - continue; - - if (top.target == dst) - return dst_address; - - search_state s(top.target,dst_address); - - visited_t::iterator pos = std::lower_bound( - visited.begin(), visited.end(), s); - - // If already visited, continue - if (pos != visited.end() && *pos == s) - continue; - - visited.insert(pos, s); // mark it - - // expand it: - smart_graph::out_edges_t edges = out_edges(s.first, g.topology()); - for (cast_graph::out_edge_iterator p = edges.first - , finish = edges.second - ; p != finish - ; ++p - ) - { - edge_t e = *p; - q.push(q_elt( - d[target(e, g.topology())] - , dst_address - , target(e, g.topology()) - , boost::get(casts, e))); - } - } - return 0; - } - - struct cache_element - { - typedef tuples::tuple< - class_id // source static type - , class_id // target type - , std::ptrdiff_t // offset within source object - , class_id // source dynamic type - >::inherited key_type; - - cache_element(key_type const& k) - : key(k) - , offset(0) - {} - - key_type key; - std::ptrdiff_t offset; - - BOOST_STATIC_CONSTANT( - std::ptrdiff_t, not_found = integer_traits::const_min); - - bool operator<(cache_element const& rhs) const - { - return this->key < rhs.key; - } - - bool unreachable() const - { - return offset == not_found; - } - }; - - enum { kdst_t = ksrc_static_t + 1, koffset, ksrc_dynamic_t }; - typedef std::vector cache_t; - - cache_t& cache() - { - static cache_t x; - return x; - } - - inline void* convert_type(void* const p, class_id src_t, class_id dst_t, bool polymorphic) - { - // Quickly rule out unregistered types - index_entry* src_p = seek_type(src_t); - if (src_p == 0) - return 0; - - index_entry* dst_p = seek_type(dst_t); - if (dst_p == 0) - return 0; - - // Look up the dynamic_id function and call it to get the dynamic - // info - boost::python::objects::dynamic_id_t dynamic_id = polymorphic - ? tuples::get(*src_p)(p) - : std::make_pair(p, src_t); - - // Look in the cache first for a quickie address translation - std::ptrdiff_t offset = (char*)p - (char*)dynamic_id.first; - - cache_element seek(boost::make_tuple(src_t, dst_t, offset, dynamic_id.second)); - cache_t& c = cache(); - cache_t::iterator const cache_pos - = std::lower_bound(c.begin(), c.end(), seek); - - - // if found in the cache, we're done - if (cache_pos != c.end() && cache_pos->key == seek.key) - { - return cache_pos->offset == cache_element::not_found - ? 0 : (char*)p + cache_pos->offset; - } - - // If we are starting at the most-derived type, only look in the up graph - smart_graph const& g = polymorphic && dynamic_id.second != src_t - ? full_graph() : up_graph(); - - void* result = search( - g, p, tuples::get(*src_p) - , tuples::get(*dst_p)); - - // update the cache - c.insert(cache_pos, seek)->offset - = (result == 0) ? cache_element::not_found : (char*)result - (char*)p; - - return result; - } -} - -namespace python { namespace objects { - -BOOST_PYTHON_DECL void* find_dynamic_type(void* p, class_id src_t, class_id dst_t) -{ - return convert_type(p, src_t, dst_t, true); -} - -BOOST_PYTHON_DECL void* find_static_type(void* p, class_id src_t, class_id dst_t) -{ - return convert_type(p, src_t, dst_t, false); -} - -BOOST_PYTHON_DECL void add_cast( - class_id src_t, class_id dst_t, cast_function cast, bool is_downcast) -{ - // adding an edge will invalidate any record of unreachability in - // the cache. - static std::size_t expected_cache_len = 0; - cache_t& c = cache(); - if (c.size() > expected_cache_len) - { - c.erase(std::remove_if( - c.begin(), c.end(), - mem_fn(&cache_element::unreachable)) - , c.end()); - - // If any new cache entries get added, we'll have to do this - // again when the next edge is added - expected_cache_len = c.size(); - } - - type_index_iterator_pair types = demand_types(src_t, dst_t); - vertex_t src = tuples::get(*types.first); - vertex_t dst = tuples::get(*types.second); - - cast_graph* const g[2] = { &up_graph().topology(), &full_graph().topology() }; - - for (cast_graph*const* p = g + (is_downcast ? 1 : 0); p < g + 2; ++p) - { - edge_t e; - bool added; - - tie(e, added) = add_edge(src, dst, **p); - assert(added); - - put(get(edge_cast, **p), e, cast); - put(get(edge_index, **p), e, num_edges(full_graph().topology()) - 1); - } -} - -BOOST_PYTHON_DECL void register_dynamic_id_aux( - class_id static_id, dynamic_id_function get_dynamic_id) -{ - tuples::get(*demand_type(static_id)) = get_dynamic_id; -} - -}}} // namespace boost::python::objects diff --git a/src/object/iterator.cpp b/src/object/iterator.cpp deleted file mode 100644 index 384d6845..00000000 --- a/src/object/iterator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include -#include - -namespace boost { namespace python { namespace objects { - -static PyObject* identity(PyObject* args_, PyObject*) -{ - PyObject* x = PyTuple_GET_ITEM(args_,0); - Py_INCREF(x); - return x; -} - -BOOST_PYTHON_DECL object const& identity_function() -{ - static object result(function_object(&identity, 1)); - return result; -} - -void set_stop_iteration_error() -{ - PyErr_SetObject(PyExc_StopIteration, Py_None); -} - -}}} // namespace boost::python::objects diff --git a/src/object/life_support.cpp b/src/object/life_support.cpp deleted file mode 100644 index ae414bbe..00000000 --- a/src/object/life_support.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#include -#include -#include - -namespace boost { namespace python { namespace objects { - -struct life_support -{ - PyObject_HEAD - PyObject* patient; -}; - -extern "C" -{ - static void - life_support_dealloc(PyObject* self) - { - Py_XDECREF(((life_support*)self)->patient); - self->ob_type->tp_free(self); - } - - static PyObject * - life_support_call(PyObject *self, PyObject *arg, PyObject *kw) - { - // Let the patient die now - Py_XDECREF(((life_support*)self)->patient); - ((life_support*)self)->patient = 0; - // Let the weak reference die. This probably kills us. - Py_XDECREF(PyTuple_GET_ITEM(arg, 0)); - return detail::none(); - } -} - -PyTypeObject life_support_type = { - PyObject_HEAD_INIT(0)//(&PyType_Type) - 0, - "Boost.Python.life_support", - sizeof(life_support), - 0, - life_support_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, //(reprfunc)func_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - life_support_call, /* tp_call */ - 0, /* tp_str */ - 0, // PyObject_GenericGetAttr, /* tp_getattro */ - 0, // PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */ - 0, /* tp_doc */ - 0, // (traverseproc)func_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, //offsetof(PyLife_SupportObject, func_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, // func_memberlist, /* tp_members */ - 0, //func_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, - 0 /* tp_new */ -}; - -PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient) -{ - if (nurse == Py_None) - return incref(nurse); - - if (life_support_type.ob_type == 0) - { - life_support_type.ob_type = &PyType_Type; - PyType_Ready(&life_support_type); - } - - life_support* system = PyObject_New(life_support, &life_support_type); - if (!system) - return 0; - - system->patient = 0; - - // We're going to leak this reference, but don't worry; the - // life_support system decrements it when the nurse dies. - PyObject* weakref = PyWeakref_NewRef(nurse, (PyObject*)system); - if (!weakref) - { - Py_XDECREF(system); - return 0; - } - - system->patient = patient; - Py_XINCREF(patient); // hang on to the patient until death - return weakref; -} - -}}} // namespace boost::python::objects diff --git a/src/object/pickle_support.cpp b/src/object/pickle_support.cpp deleted file mode 100644 index 6f37517f..00000000 --- a/src/object/pickle_support.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// (C) Copyright R.W. Grosse-Kunstleve 2002. -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. This -// software is provided "as is" without express or implied warranty, and -// with no claim as to its suitability for any purpose. - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { - -namespace { - - tuple instance_reduce(object instance_obj) - { - list result; - object instance_class(instance_obj.attr("__class__")); - result.append(instance_class); - object none; - object getinitargs = getattr(instance_obj, "__getinitargs__", none); - tuple initargs; - if (getinitargs.ptr() != none.ptr()) { - initargs = tuple(getinitargs()); - } - result.append(initargs); - object getstate = getattr(instance_obj, "__getstate__", none); - object instance_dict = getattr(instance_obj, "__dict__", none); - long len_instance_dict = 0; - if (instance_dict.ptr() != none.ptr()) { - len_instance_dict = len(instance_dict); - } - if (getstate.ptr() != none.ptr()) { - if (len_instance_dict > 0) { - object getstate_manages_dict = getattr( - instance_obj, "__getstate_manages_dict__", none); - if (getstate_manages_dict.ptr() == none.ptr()) { - PyErr_SetString(PyExc_RuntimeError, - "Incomplete pickle support" - " (__getstate_manages_dict__ not set)"); - throw_error_already_set(); - } - } - result.append(getstate()); - } - else if (len_instance_dict > 0) { - result.append(instance_dict); - } - return tuple(result); - } - -} // namespace - -object const& make_instance_reduce_function() -{ - static object result(&instance_reduce); - return result; -} - -}} // namespace boost::python diff --git a/src/object_operators.cpp b/src/object_operators.cpp deleted file mode 100644 index b7c984ef..00000000 --- a/src/object_operators.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include - -namespace boost { namespace python { namespace api { - -#define BOOST_PYTHON_BINARY_OPERATOR(op, name) \ -BOOST_PYTHON_DECL object operator op(object const& l, object const& r) \ -{ \ - return object( \ - detail::new_reference( \ - PyNumber_##name(l.ptr(), r.ptr())) \ - ); \ -} - -BOOST_PYTHON_BINARY_OPERATOR(+, Add) -BOOST_PYTHON_BINARY_OPERATOR(-, Subtract) -BOOST_PYTHON_BINARY_OPERATOR(*, Multiply) -BOOST_PYTHON_BINARY_OPERATOR(/, Divide) -BOOST_PYTHON_BINARY_OPERATOR(%, Remainder) -BOOST_PYTHON_BINARY_OPERATOR(<<, Lshift) -BOOST_PYTHON_BINARY_OPERATOR(>>, Rshift) -BOOST_PYTHON_BINARY_OPERATOR(&, And) -BOOST_PYTHON_BINARY_OPERATOR(^, Xor) -BOOST_PYTHON_BINARY_OPERATOR(|, Or) -#undef BOOST_PYTHON_BINARY_OPERATOR - -#define BOOST_PYTHON_INPLACE_OPERATOR(op, name) \ -BOOST_PYTHON_DECL object& operator op##=(object& l, object const& r) \ -{ \ - return l = object( \ - (detail::new_reference) \ - PyNumber_InPlace##name(l.ptr(), r.ptr())); \ -} - -BOOST_PYTHON_INPLACE_OPERATOR(+, Add) -BOOST_PYTHON_INPLACE_OPERATOR(-, Subtract) -BOOST_PYTHON_INPLACE_OPERATOR(*, Multiply) -BOOST_PYTHON_INPLACE_OPERATOR(/, Divide) -BOOST_PYTHON_INPLACE_OPERATOR(%, Remainder) -BOOST_PYTHON_INPLACE_OPERATOR(<<, Lshift) -BOOST_PYTHON_INPLACE_OPERATOR(>>, Rshift) -BOOST_PYTHON_INPLACE_OPERATOR(&, And) -BOOST_PYTHON_INPLACE_OPERATOR(^, Xor) -BOOST_PYTHON_INPLACE_OPERATOR(|, Or) -#undef BOOST_PYTHON_INPLACE_OPERATOR - -BOOST_PYTHON_DECL object::object(handle<> const& x) - : object_base(python::incref(python::expect_non_null(x.get()))) -{} - -}}} // namespace boost::python diff --git a/src/object_protocol.cpp b/src/object_protocol.cpp deleted file mode 100755 index 11979f8f..00000000 --- a/src/object_protocol.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include - -namespace boost { namespace python { namespace api { - -BOOST_PYTHON_DECL object getattr(object const& target, object const& key) -{ - return object(detail::new_reference(PyObject_GetAttr(target.ptr(), key.ptr()))); -} - -BOOST_PYTHON_DECL object getattr(object const& target, object const& key, object const& default_) -{ - PyObject* result = PyObject_GetAttr(target.ptr(), key.ptr()); - if (result == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) - { - PyErr_Clear(); - return default_; - } - return object(detail::new_reference(result)); -} - -BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value) -{ - if (PyObject_SetAttr(target.ptr(), key.ptr(), value.ptr()) == -1) - throw_error_already_set(); -} - -BOOST_PYTHON_DECL void delattr(object const& target, object const& key) -{ - if (PyObject_DelAttr(target.ptr(), key.ptr()) == -1) - throw_error_already_set(); -} - -BOOST_PYTHON_DECL object getattr(object const& target, char const* key) -{ - return object( - detail::new_reference( - PyObject_GetAttrString(target.ptr(), const_cast(key)) - )); -} - -BOOST_PYTHON_DECL object getattr(object const& target, char const* key, object const& default_) -{ - PyObject* result = PyObject_GetAttrString(target.ptr(), const_cast(key)); - if (result == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) - { - PyErr_Clear(); - return default_; - } - return object(detail::new_reference(result)); - -} -BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value) -{ - if (PyObject_SetAttrString( - target.ptr(), const_cast(key), value.ptr()) == -1 - ) - { - throw_error_already_set(); - } -} - -BOOST_PYTHON_DECL void delattr(object const& target, char const* key) -{ - if (PyObject_DelAttrString( - target.ptr(), const_cast(key)) == -1 - ) - { - throw_error_already_set(); - } -} - -BOOST_PYTHON_DECL object getitem(object const& target, object const& key) -{ - return object(detail::new_reference( - PyObject_GetItem(target.ptr(), key.ptr()))); -} - -BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value) -{ - if (PyObject_SetItem(target.ptr(), key.ptr(), value.ptr()) == -1) - throw_error_already_set(); -} - -BOOST_PYTHON_DECL void delitem(object const& target, object const& key) -{ - if (PyObject_DelItem(target.ptr(), key.ptr()) == -1) - throw_error_already_set(); -} - -namespace // slicing code copied directly out of the Python implementation -{ - #undef ISINT - #define ISINT(x) ((x) == NULL || PyInt_Check(x) || PyLong_Check(x)) - - static PyObject * - apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */ - { - PyTypeObject *tp = u->ob_type; - PySequenceMethods *sq = tp->tp_as_sequence; - - if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) { - int ilow = 0, ihigh = INT_MAX; - if (!_PyEval_SliceIndex(v, &ilow)) - return NULL; - if (!_PyEval_SliceIndex(w, &ihigh)) - return NULL; - return PySequence_GetSlice(u, ilow, ihigh); - } - else { - PyObject *slice = PySlice_New(v, w, NULL); - if (slice != NULL) { - PyObject *res = PyObject_GetItem(u, slice); - Py_DECREF(slice); - return res; - } - else - return NULL; - } - } - - static int - assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x) - /* u[v:w] = x */ - { - PyTypeObject *tp = u->ob_type; - PySequenceMethods *sq = tp->tp_as_sequence; - - if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) { - int ilow = 0, ihigh = INT_MAX; - if (!_PyEval_SliceIndex(v, &ilow)) - return -1; - if (!_PyEval_SliceIndex(w, &ihigh)) - return -1; - if (x == NULL) - return PySequence_DelSlice(u, ilow, ihigh); - else - return PySequence_SetSlice(u, ilow, ihigh, x); - } - else { - PyObject *slice = PySlice_New(v, w, NULL); - if (slice != NULL) { - int res; - if (x != NULL) - res = PyObject_SetItem(u, slice, x); - else - res = PyObject_DelItem(u, slice); - Py_DECREF(slice); - return res; - } - else - return -1; - } - } -} - -BOOST_PYTHON_DECL object getslice(object const& target, handle<> const& begin, handle<> const& end) -{ - return object( - detail::new_reference( - apply_slice(target.ptr(), begin.get(), end.get()))); -} - -BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, handle<> const& end, object const& value) -{ - if (assign_slice( - target.ptr(), begin.get(), end.get(), value.ptr()) == -1 - ) - { - throw_error_already_set(); - } -} - -BOOST_PYTHON_DECL void delslice(object const& target, handle<> const& begin, handle<> const& end) -{ - if (assign_slice( - target.ptr(), begin.get(), end.get(), 0) == -1 - ) - { - throw_error_already_set(); - } -} - -}}} // namespace boost::python::api diff --git a/src/objects.cpp b/src/objects.cpp deleted file mode 100644 index f446919d..00000000 --- a/src/objects.cpp +++ /dev/null @@ -1,488 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -// TODO: Move inline implementations from objects.cpp here - -#ifndef BOOST_PYTHON_SOURCE -# define BOOST_PYTHON_SOURCE -#endif - -#include -#include - -namespace boost { namespace python { - -template -T object_from_python(PyObject* p, type) -{ - ref x(p, ref::increment_count); - if (!T::accepts(x)) - { - PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); - throw_error_already_set(); - } - return T(x); -} - -inline PyObject* object_to_python(const object& x) -{ - return x.reference().release(); -} - -object::object(ref p) - : m_p(p) {} - -// Return a reference to the held object -ref object::reference() const -{ - return m_p; -} - -// Return a raw pointer to the held object -PyObject* object::get() const -{ - return m_p.get(); -} - -}} // namespace boost::python - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -BOOST_PYTHON_DECL PyObject* to_python(const boost::python::tuple& x) -{ - return object_to_python(x); -} - -BOOST_PYTHON_DECL boost::python::tuple from_python(PyObject* p, boost::python::type type) -{ - return boost::python::object_from_python(p, type); -} - -BOOST_PYTHON_DECL PyObject* to_python(const boost::python::list& x) -{ - return object_to_python(x); -} - -BOOST_PYTHON_DECL boost::python::list from_python(PyObject* p, boost::python::type type) -{ - return boost::python::object_from_python(p, type); -} - -BOOST_PYTHON_DECL PyObject* to_python(const boost::python::dictionary& x) -{ - return object_to_python(x); -} - -BOOST_PYTHON_DECL boost::python::dictionary from_python(PyObject* p, boost::python::type type) -{ - return boost::python::object_from_python(p, type); -} - -BOOST_PYTHON_DECL PyObject* to_python(const boost::python::string& x) -{ - return object_to_python(x); -} - -BOOST_PYTHON_DECL boost::python::string from_python(PyObject* p, boost::python::type type) -{ - return boost::python::object_from_python(p, type); -} - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -tuple_base::tuple_base(std::size_t n) - : object(ref(PyTuple_New(n))) -{ - for (std::size_t i = 0; i < n; ++i) - PyTuple_SET_ITEM(get(), i, detail::none()); -} - -tuple_base::tuple_base(ref p) - : object(p) -{ - assert(accepts(p)); - if (!accepts(p)) - { - PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); - throw_error_already_set(); - } -} - -PyTypeObject* tuple_base::type_obj() -{ - return &PyTuple_Type; -} - -bool tuple_base::accepts(ref p) -{ - return PyTuple_Check(p.get()); -} - -std::size_t tuple_base::size() const -{ - return PyTuple_Size(get()); -} - -ref tuple_base::operator[](std::size_t pos) const -{ - return ref(PyTuple_GetItem(get(), static_cast(pos)), - ref::increment_count); -} - -void tuple_base::set_item(std::size_t pos, const ref& rhs) -{ - int failed = PyTuple_SetItem( - get(), static_cast(pos), ref(rhs).release()); // A reference is stolen here. - (void)failed; - assert(failed == 0); -} - -tuple tuple_base::slice(int low, int high) const -{ - return tuple(ref(PyTuple_GetSlice(get(), low, high))); -} - -BOOST_PYTHON_DECL tuple& operator+=(tuple& self, const tuple& rhs) -{ - return self = self + rhs; -} - - -// Construct from an owned PyObject*. -// Precondition: p must point to a python string. -string::string(ref p) - : object(p) -{ - assert(accepts(p)); - if (!accepts(p)) - { - PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); - throw_error_already_set(); - } -} - -string::string(const char* s) - : object(ref(PyString_FromString(s))) {} - -string::string(const char* s, std::size_t length) - : object(ref(PyString_FromStringAndSize(s, length))) {} - -string::string(const char* s, interned_t) - : object(ref(PyString_InternFromString(s))) {} - -#if 0 -string::string(const char* s, std::size_t length, interned_t) - : object(ref(PyString_InternFromStringAndSize(s, length))) {} -#endif - -string::string(const string& rhs) - : object(rhs.reference()) {} - -// Get the type object for Strings -PyTypeObject* string::type_obj() -{ return &PyString_Type; } - -// Return true if the given object is a python string -bool string::accepts(ref o) -{ return PyString_Check(o.get()); } - -// Return the length of the string. -std::size_t string::size() const -{ - int size = PyString_GET_SIZE(get()); - assert(size >= 0); - return static_cast(size); -} - -// Returns a null-terminated representation of the contents of string. -// The pointer refers to the internal buffer of string, not a copy. -// The data must not be modified in any way. It must not be de-allocated. -const char* string::c_str() const -{ return PyString_AS_STRING(get()); } - -void string::intern() -{ // UNTESTED!! - *this = string(ref(PyString_InternFromString(c_str()), ref::increment_count)); -} - -string& string::operator*=(unsigned int repeat_count) -{ - *this = string(ref(PySequence_Repeat(get(), repeat_count))); - return *this; -} - -dictionary_base::dictionary_base(ref p) - : object(p) -{ - assert(accepts(p)); - if (!accepts(p)) - { - PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); - throw_error_already_set(); - } -} - -dictionary_base::dictionary_base() - : object(ref(PyDict_New())) {} - -PyTypeObject* dictionary_base::type_obj() -{ return &PyDict_Type; } - -bool dictionary_base::accepts(ref p) -{ return PyDict_Check(p.get()); } - -void dictionary_base::clear() -{ PyDict_Clear(get()); } - -const ref& dictionary_proxy::operator=(const ref& rhs) -{ - if (PyDict_SetItem(m_dict.get(), m_key.get(), rhs.get()) == -1) - throw_error_already_set(); - return rhs; -} - -dictionary_proxy::operator ref() const -{ - return ref(m_dict->ob_type->tp_as_mapping->mp_subscript(m_dict.get(), m_key.get())); -} - -dictionary_proxy::dictionary_proxy(const ref& dict, const ref& key) - : m_dict(dict), m_key(key) {} - -dictionary_proxy dictionary_base::operator[](ref key) -{ return proxy(reference(), key); } - -ref dictionary_base::operator[](ref key) const { - // An odd MSVC bug causes the ".operator Ptr()" to be needed - return proxy(reference(), key).operator ref(); -} - - -ref dictionary_base::get_item(const ref& key) const -{ - return get_item(key, ref()); -} - -ref dictionary_base::get_item(const ref& key, const ref& default_) const -{ - PyObject* value_or_null = PyDict_GetItem(get(), key.get()); - if (value_or_null == 0 && !PyErr_Occurred()) - return default_; - else - return ref(value_or_null, ref::increment_count); // Will throw if there was another error -} - -void dictionary_base::set_item(const ref& key, const ref& value) -{ - if (PyDict_SetItem(get(), key.get(), value.get()) == -1) - throw_error_already_set(); -} - -void dictionary_base::erase(ref key) { - if (PyDict_DelItem(get(), key.get()) == -1) - throw_error_already_set(); -} - -list dictionary_base::items() const { return list(ref(PyDict_Items(get()))); } -list dictionary_base::keys() const { return list(ref(PyDict_Keys(get()))); } -list dictionary_base::values() const { return list(ref(PyDict_Values(get()))); } - -std::size_t dictionary_base::size() const { return static_cast(PyDict_Size(get())); } - -string operator+(string x, string y) -{ - PyObject* io_string = x.reference().release(); - PyString_Concat(&io_string, y.get()); - return string(ref(io_string)); -} - -string& string::operator+=(const string& rhs) -{ - return *this = *this + rhs; -} - -string& string::operator+=(const char* y) -{ - return *this += string(y); -} - -string operator%(const string& format, const tuple& args) -{ - return string(ref(PyString_Format(format.get(), args.reference().get()))); -} - -string operator+(string x, const char* y) -{ - return x + string(y); -} - -string operator+(const char* x, string y) -{ - return string(x) + y; -} - -tuple operator+(const tuple& x, const tuple& y) -{ - tuple result(x.size() + y.size()); - for (std::size_t xi = 0; xi < x.size(); ++xi) - result.set_item(xi, x[xi]); - for (std::size_t yi = 0; yi < y.size(); ++yi) - result.set_item(yi + x.size(), y[yi]); - return result; -} - - -list_base::list_base(ref p) - : object(p) -{ - assert(accepts(p)); - if (!accepts(p)) - { - PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); - throw_error_already_set(); - } -} - -list_base::list_base(std::size_t sz) - : object(ref(PyList_New(sz))) -{ -} - -PyTypeObject* list_base::type_obj() -{ - return &PyList_Type; -} - -bool list_base::accepts(ref p) -{ - return PyList_Check(p.get()); -} - -std::size_t list_base::size() const -{ - return PyList_Size(get()); -} - -ref list_base::operator[](std::size_t pos) const -{ - return ref(PyList_GetItem(get(), pos), ref::increment_count); -} - -list_proxy list_base::operator[](std::size_t pos) -{ - return proxy(reference(), pos); -} - -void list_base::insert(std::size_t index, const ref& item) -{ - if (PyList_Insert(get(), index, item.get()) == -1) - throw_error_already_set(); -} - -void list_base::push_back(const ref& item) -{ - if (PyList_Append(get(), item.get()) == -1) - throw_error_already_set(); -} - -void list_base::append(const ref& item) -{ - this->push_back(item); -} - -list list_base::slice(int low, int high) const -{ - return list(ref(PyList_GetSlice(get(), low, high))); -} - -list_slice_proxy list_base::slice(int low, int high) -{ - return list_slice_proxy(reference(), low, high); -} - -void list_base::sort() -{ - if (PyList_Sort(get()) == -1) - throw_error_already_set(); -} - -void list_base::reverse() -{ - if (PyList_Reverse(get()) == -1) - throw_error_already_set(); -} - -tuple list_base::as_tuple() const -{ - return tuple(ref(PyList_AsTuple(get()))); -} - -const ref& list_proxy::operator=(const ref& rhs) -{ - m_list.set_item(m_index, rhs); - return rhs; -} - -list_proxy::operator ref() const -{ - return ref(PyList_GetItem(m_list.get(), m_index), ref::increment_count); -} - -ref list_base::get_item(std::size_t pos) const -{ - return ref(PyList_GetItem(this->get(), pos), ref::increment_count); -} - -void list_base::set_item(std::size_t pos, const ref& rhs) -{ - int result = PyList_SetItem(this->get(), pos, rhs.get()); - if (result == -1) - throw_error_already_set(); - Py_INCREF(rhs.get()); -} - -list_proxy::list_proxy(const ref& list, std::size_t index) - : m_list(list), m_index(index) -{ -} - -const list& list_slice_proxy::operator=(const list& rhs) -{ - if (PyList_SetSlice(m_list.get(), m_low, m_high, rhs.get()) == -1) - throw_error_already_set(); - return rhs; -} - -list_slice_proxy::operator ref() const -{ - return ref(PyList_GetSlice(m_list.get(), m_low, m_high)); -} - -list_slice_proxy::operator list() const -{ - return list(this->operator ref()); -} - -std::size_t list_slice_proxy::size() const -{ - return this->operator list().size(); -} - -ref list_slice_proxy::operator[](std::size_t pos) const -{ - return this->operator list()[pos].operator ref(); -} - -list_slice_proxy::list_slice_proxy(const ref& list, int low, int high) - : m_list(list), m_low(low), m_high(high) -{ -} - -}} // namespace boost::python diff --git a/src/py_interface.cpp b/src/py_interface.cpp deleted file mode 100644 index e34bf6f9..00000000 --- a/src/py_interface.cpp +++ /dev/null @@ -1,1103 +0,0 @@ -// Automatically generated from py_api_gen.py - -#include - -namespace boost { namespace python { namespace api { - -namespace api_detail { - -BOOST_PYTHON_DECL object get_func(const char* name) { - object __builtin__((python::detail::borrowed_reference)::PyImport_AddModule(const_cast("__builtin__"))); - return object(__builtin__.attr(name)); -} - -inline handle<> get_current_frame() -{ - return handle<>(allow_null(borrowed((PyObject*)(PyThreadState_Get()->frame)))); -} - -inline object get_global_dict(call_dict_usage cdu, handle<> const& frame) -{ - if(frame.get()) - return object(object(frame).attr("f_globals")); - else - return api::globals(); -} - -object get_local_dict(call_dict_usage cdu, handle<> const& frame, object const& global_dict) -{ - switch(cdu) { - case use_new_dict: - return api::dict(); - case use_global_dict: - return global_dict; - default: - if(frame.get()) - return object(object(frame).attr("f_locals")); - else - return api::dict(); - } -} - -inline object call_statement(const char *stmt, object const& global_dict, object& local_dict) -{ - local_dict["_0"] = object((python::detail::borrowed_reference)Py_None); - api::run_string(stmt, Py_file_input, global_dict, local_dict); - return object(local_dict["_0"]); -} - -object call_statement(const char *stmt) -{ - handle<> frame(get_current_frame()); - if(frame.get()) { - object f(frame); - object gd(f.attr("f_globals")); - object ld(f.attr("f_locals")); - return call_statement(stmt, gd, ld); - } else { - object gd(api::globals()); - object ld(api::dict()); - return call_statement(stmt, gd, ld); - } -} - -object call_statement_du(const char *stmt, call_dict_usage cdu) -{ - handle<> frame(get_current_frame()); - object gd(get_global_dict(cdu, frame)); - return call_statement(stmt, gd, get_local_dict(cdu, frame, gd)); -} - -inline object call_statement(const char *stmt, object const& global_dict, object& local_dict, int n, va_list mk) -{ - static const char *(idx[]) = { "_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8", "_9", "_10" }; - local_dict["_0"] = object((python::detail::borrowed_reference)Py_None); - for(int i = 0; i < n; ++i) - { - object const* p_arg = va_arg(mk, object const*); - object const& arg = *p_arg; - if(i < (int) (sizeof(idx) / sizeof(idx[0]))) - local_dict[idx[i]] = arg; - else { - local_dict[object("_") + object((python::detail::new_reference)PyObject_Str(object(i + 1).ptr()))] = arg; - } - } - va_end(mk); - api::run_string(stmt, Py_file_input, global_dict, local_dict); - return object(local_dict["_0"]); -} - -BOOST_PYTHON_DECL object call_statement(const char *stmt, int n, ...) -{ - va_list mk; - va_start(mk, n); - handle<> frame(get_current_frame()); - if(frame.get()) { - object f(frame); - object gd(f.attr("f_globals")); - object ld(f.attr("f_locals")); - return call_statement(stmt, gd, ld, n, mk); - } else { - object gd(api::globals()); - object ld(api::dict()); - return call_statement(stmt, gd, ld, n, mk); - } -} - -BOOST_PYTHON_DECL object call_statement_du(const char *stmt, call_dict_usage cdu, int n, ...) -{ - handle<> frame(get_current_frame()); - object gd(get_global_dict(cdu, frame)); - va_list mk; - va_start(mk, n); - return call_statement(stmt, gd, get_local_dict(cdu, frame, gd), n, mk); -} - -} - -BOOST_PYTHON_DECL object locals() -{ - handle<> frame(api_detail::get_current_frame()); - if(frame.get()) - return object(object(frame).attr("f_locals")); - else - return api::dict(); -} - - -BOOST_PYTHON_DECL object abs(object const& a0) { - return api_detail::get_func("abs")(a0); -} - -BOOST_PYTHON_DECL object abs(short a0) { - return api_detail::get_func("abs")(object(a0)); -} - -BOOST_PYTHON_DECL object abs(int a0) { - return api_detail::get_func("abs")(object(a0)); -} - -BOOST_PYTHON_DECL object abs(long a0) { - return api_detail::get_func("abs")(object(a0)); -} - -BOOST_PYTHON_DECL object abs(double const & a0) { - return api_detail::get_func("abs")(object(a0)); -} - -BOOST_PYTHON_DECL object apply(object const& a0, object const& a1) { - return object((python::detail::new_reference)::PyObject_CallObject(a0.ptr(), a1.ptr())); -} - -BOOST_PYTHON_DECL object apply(object const& a0, object const& a1, object const& a2) { - return object((python::detail::new_reference)::PyObject_Call(a0.ptr(), a1.ptr(), a2.ptr())); -} - -BOOST_PYTHON_DECL bool callable(object const& a0) { - return ::PyCallable_Check(a0.ptr()); -} - -BOOST_PYTHON_DECL object chr(object const& a0) { - return api_detail::get_func("chr")(a0); -} - -BOOST_PYTHON_DECL object chr(short a0) { - return api_detail::get_func("chr")(object(a0)); -} - -BOOST_PYTHON_DECL object chr(int a0) { - return api_detail::get_func("chr")(object(a0)); -} - -BOOST_PYTHON_DECL object chr(long a0) { - return api_detail::get_func("chr")(object(a0)); -} - -BOOST_PYTHON_DECL int cmp(object const& a0, object const& a1) { - int rslt; - int r = ::PyObject_Cmp(a0.ptr(), a1.ptr(), &rslt); - if(r == -1) - throw_error_already_set(); - return rslt; -} - -BOOST_PYTHON_DECL object coerce(object const& a0, object const& a1) { - return api_detail::get_func("coerce")(a0, a1); -} - -BOOST_PYTHON_DECL object compile(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("compile")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object compile(const char* a0, const char* a1, const char* a2) { - return api_detail::get_func("compile")(object(a0), object(a1), object(a2)); -} - -BOOST_PYTHON_DECL object compile(object const& a0, object const& a1, object const& a2, object const& a3) { - return api_detail::get_func("compile")(a0, a1, a2, a3); -} - -BOOST_PYTHON_DECL object compile(const char* a0, const char* a1, const char* a2, int a3) { - return api_detail::get_func("compile")(object(a0), object(a1), object(a2), object(a3)); -} - -BOOST_PYTHON_DECL object compile(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::get_func("compile")(a0, a1, a2, a3, a4); -} - -BOOST_PYTHON_DECL object compile(const char* a0, const char* a1, const char* a2, int a3, int a4) { - return api_detail::get_func("compile")(object(a0), object(a1), object(a2), object(a3), object(a4)); -} - -BOOST_PYTHON_DECL object complex(object const& a0) { - return api_detail::get_func("complex")(a0); -} - -BOOST_PYTHON_DECL object complex(double const& a0) { - return api_detail::get_func("complex")(object(a0)); -} - -BOOST_PYTHON_DECL object complex(object const& a0, object const& a1) { - return api_detail::get_func("complex")(a0, a1); -} - -BOOST_PYTHON_DECL object complex(double const& a0, double const& a1) { - return api_detail::get_func("complex")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object dict() { - return api_detail::get_func("dict")(); -} - -BOOST_PYTHON_DECL object dict(object const& a0) { - return api_detail::get_func("dict")(a0); -} - -BOOST_PYTHON_DECL object dir() { - return object((python::detail::new_reference)::PyObject_Dir(NULL)); -} - -BOOST_PYTHON_DECL object dir(object const& a0) { - return object((python::detail::new_reference)::PyObject_Dir(a0.ptr())); -} - -BOOST_PYTHON_DECL object divmod(object const& a0, object const& a1) { - return api_detail::get_func("divmod")(a0, a1); -} - -BOOST_PYTHON_DECL object divmod(int a0, int a1) { - return api_detail::get_func("divmod")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object divmod(long a0, long a1) { - return api_detail::get_func("divmod")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object divmod(double const& a0, double const& a1) { - return api_detail::get_func("divmod")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object eval(const char* a0) { - return object((python::detail::new_reference)::PyRun_String(const_cast(a0), Py_eval_input, globals().ptr(), globals().ptr())); -} - -BOOST_PYTHON_DECL object eval(const char* a0, object const& a2) { - return object((python::detail::new_reference)::PyRun_String(const_cast(a0), Py_eval_input, a2.ptr(), globals().ptr())); -} - -BOOST_PYTHON_DECL object eval(const char* a0, object const& a2, object const& a3) { - return object((python::detail::new_reference)::PyRun_String(const_cast(a0), Py_eval_input, a2.ptr(), a3.ptr())); -} - -BOOST_PYTHON_DECL object exec(const char* a0) { - return object((python::detail::new_reference)::PyRun_String(const_cast(a0), Py_file_input, globals().ptr(), globals().ptr())); -} - -BOOST_PYTHON_DECL object exec(const char* a0, object const& a2) { - return object((python::detail::new_reference)::PyRun_String(const_cast(a0), Py_file_input, a2.ptr(), globals().ptr())); -} - -BOOST_PYTHON_DECL object exec(const char* a0, object const& a2, object const& a3) { - return object((python::detail::new_reference)::PyRun_String(const_cast(a0), Py_file_input, a2.ptr(), a3.ptr())); -} - -BOOST_PYTHON_DECL object execfile(object const& a0) { - return api_detail::get_func("execfile")(a0); -} - -BOOST_PYTHON_DECL object execfile(object const& a0, object const& a1) { - return api_detail::get_func("execfile")(a0, a1); -} - -BOOST_PYTHON_DECL object execfile(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("execfile")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object file(object const& a0) { - return api_detail::get_func("file")(a0); -} - -BOOST_PYTHON_DECL object file(const char* a0) { - return api_detail::get_func("file")(object(a0)); -} - -BOOST_PYTHON_DECL object file(object const& a0, object const& a1) { - return api_detail::get_func("file")(a0, a1); -} - -BOOST_PYTHON_DECL object file(const char* a0, const char* a1) { - return api_detail::get_func("file")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object file(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("file")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object file(const char* a0, const char* a1, int a2) { - return api_detail::get_func("file")(object(a0), object(a1), object(a2)); -} - -BOOST_PYTHON_DECL object filter(object const& a0, object const& a1) { - return api_detail::get_func("filter")(a0, a1); -} - -BOOST_PYTHON_DECL object float_(object const& a0) { - return api_detail::get_func("float")(a0); -} - -BOOST_PYTHON_DECL object float_(const char* a0) { - return api_detail::get_func("float")(object(a0)); -} - -BOOST_PYTHON_DECL object float_(double const& a0) { - return api_detail::get_func("float")(object(a0)); -} - -BOOST_PYTHON_DECL object getattr(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("getattr")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object getattr(object const& a0, const char * a1, object const& a2) { - return api_detail::get_func("getattr")(a0, object(a1), a2); -} - -BOOST_PYTHON_DECL object globals() { - return object((python::detail::borrowed_reference)::PyModule_GetDict(PyImport_AddModule("__main__"))); -} - -BOOST_PYTHON_DECL bool hasattr(object const& a0, object const& a1) { - return ::PyObject_HasAttr(a0.ptr(), a1.ptr()); -} - -BOOST_PYTHON_DECL bool hasattr(object const& a0, const char* a1) { - return ::PyObject_HasAttrString(a0.ptr(), const_cast(a1)); -} - -BOOST_PYTHON_DECL long hash(object const& a0) { - long r = ::PyObject_Hash(a0.ptr()); - if(r == -1) - throw_error_already_set(); - return r; -} - -BOOST_PYTHON_DECL object hex(object const& a0) { - return api_detail::get_func("hex")(a0); -} - -BOOST_PYTHON_DECL object hex(char a0) { - return api_detail::get_func("hex")(object(a0)); -} - -BOOST_PYTHON_DECL object hex(short a0) { - return api_detail::get_func("hex")(object(a0)); -} - -BOOST_PYTHON_DECL object hex(int a0) { - return api_detail::get_func("hex")(object(a0)); -} - -BOOST_PYTHON_DECL object hex(long a0) { - return api_detail::get_func("hex")(object(a0)); -} - -BOOST_PYTHON_DECL long id(object const& a0) { - object r(api_detail::get_func("id")(a0)); - return boost::python::arg_from_python(r.ptr())(r.ptr()); -} - -BOOST_PYTHON_DECL object input() { - return api_detail::get_func("input")(); -} - -BOOST_PYTHON_DECL object input(object const& a0) { - return api_detail::get_func("input")(a0); -} - -BOOST_PYTHON_DECL object input(const char* a0) { - return api_detail::get_func("input")(object(a0)); -} - -BOOST_PYTHON_DECL object int_(object const& a0) { - return api_detail::get_func("int")(a0); -} - -BOOST_PYTHON_DECL object int_(long a0) { - return api_detail::get_func("int")(object(a0)); -} - -BOOST_PYTHON_DECL object int_(const char* a0) { - return api_detail::get_func("int")(object(a0)); -} - -BOOST_PYTHON_DECL object intern(object const& a0) { - return api_detail::get_func("intern")(a0); -} - -BOOST_PYTHON_DECL object intern(const char* a0) { - return api_detail::get_func("intern")(object(a0)); -} - -BOOST_PYTHON_DECL bool isinstance(object const& a0, object const& a1) { - return ::PyObject_IsInstance(a0.ptr(), a1.ptr()); -} - -BOOST_PYTHON_DECL bool issubclass(object const& a0, object const& a1) { - return ::PyObject_IsSubclass(a0.ptr(), a1.ptr()); -} - -BOOST_PYTHON_DECL object iter(object const& a0) { - return object((python::detail::new_reference)::PyObject_GetIter(a0.ptr())); -} - -BOOST_PYTHON_DECL object iter(object const& a0, object const& a1) { - return api_detail::get_func("iter")(a0, a1); -} - -BOOST_PYTHON_DECL long len(object const& a0) { - long r = ::PyObject_Length(a0.ptr()); - if(r == -1) - throw_error_already_set(); - return r; -} - -BOOST_PYTHON_DECL object list() { - return api_detail::get_func("list")(); -} - -BOOST_PYTHON_DECL object list(object const& a0) { - return api_detail::get_func("list")(a0); -} - -BOOST_PYTHON_DECL object long_(object const& a0) { - return api_detail::get_func("long")(a0); -} - -BOOST_PYTHON_DECL object long_(long a0) { - return api_detail::get_func("long")(object(a0)); -} - -BOOST_PYTHON_DECL object long_(const char* a0) { - return api_detail::get_func("long")(object(a0)); -} - -BOOST_PYTHON_DECL object map(object const& a0) { - return api_detail::get_func("map")(a0); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1) { - return api_detail::get_func("map")(a0, a1); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("map")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3) { - return api_detail::get_func("map")(a0, a1, a2, a3); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::get_func("map")(a0, a1, a2, a3, a4); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::get_func("map")(a0, a1, a2, a3, a4, a5); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::get_func("map")(a0, a1, a2, a3, a4, a5, a6); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::get_func("map")(a0, a1, a2, a3, a4, a5, a6, a7); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::get_func("map")(a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::get_func("map")(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -BOOST_PYTHON_DECL object max(object const& a0) { - return api_detail::get_func("max")(a0); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1) { - return api_detail::get_func("max")(a0, a1); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("max")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3) { - return api_detail::get_func("max")(a0, a1, a2, a3); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::get_func("max")(a0, a1, a2, a3, a4); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::get_func("max")(a0, a1, a2, a3, a4, a5); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::get_func("max")(a0, a1, a2, a3, a4, a5, a6); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::get_func("max")(a0, a1, a2, a3, a4, a5, a6, a7); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::get_func("max")(a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::get_func("max")(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -BOOST_PYTHON_DECL object min(object const& a0) { - return api_detail::get_func("min")(a0); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1) { - return api_detail::get_func("min")(a0, a1); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("min")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3) { - return api_detail::get_func("min")(a0, a1, a2, a3); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::get_func("min")(a0, a1, a2, a3, a4); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::get_func("min")(a0, a1, a2, a3, a4, a5); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::get_func("min")(a0, a1, a2, a3, a4, a5, a6); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::get_func("min")(a0, a1, a2, a3, a4, a5, a6, a7); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::get_func("min")(a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::get_func("min")(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -BOOST_PYTHON_DECL object oct(object const& a0) { - return api_detail::get_func("oct")(a0); -} - -BOOST_PYTHON_DECL object oct(char a0) { - return api_detail::get_func("oct")(object(a0)); -} - -BOOST_PYTHON_DECL object oct(short a0) { - return api_detail::get_func("oct")(object(a0)); -} - -BOOST_PYTHON_DECL object oct(int a0) { - return api_detail::get_func("oct")(object(a0)); -} - -BOOST_PYTHON_DECL object oct(long a0) { - return api_detail::get_func("oct")(object(a0)); -} - -BOOST_PYTHON_DECL object open(object const& a0) { - return api_detail::get_func("open")(a0); -} - -BOOST_PYTHON_DECL object open(const char* a0) { - return api_detail::get_func("open")(object(a0)); -} - -BOOST_PYTHON_DECL object open(object const& a0, object const& a1) { - return api_detail::get_func("open")(a0, a1); -} - -BOOST_PYTHON_DECL object open(const char* a0, const char* a1) { - return api_detail::get_func("open")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object open(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("open")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object open(const char* a0, const char* a1, int a2) { - return api_detail::get_func("open")(object(a0), object(a1), object(a2)); -} - -BOOST_PYTHON_DECL long ord(object const& a0) { - object r(api_detail::get_func("ord")(a0)); - return boost::python::arg_from_python(r.ptr())(r.ptr()); -} - -BOOST_PYTHON_DECL long ord(const char* a0) { - object r(api_detail::get_func("ord")(object(a0))); - return boost::python::arg_from_python(r.ptr())(r.ptr()); -} - -BOOST_PYTHON_DECL object pow(object const& a0, object const& a1) { - return api_detail::get_func("pow")(a0, a1); -} - -BOOST_PYTHON_DECL object pow(double const& a0, double const& a1) { - return api_detail::get_func("pow")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object pow(double const& a0, double const& a1, double const& a2) { - return api_detail::get_func("pow")(object(a0), object(a1), object(a2)); -} - -BOOST_PYTHON_DECL object print(object const& a0) { - return api_detail::call_statement_du("print _1", use_new_dict, 1, &a0); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1) { - return api_detail::call_statement_du("print _1, _2", use_new_dict, 2, &a0, &a1); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2) { - return api_detail::call_statement_du("print _1, _2, _3", use_new_dict, 3, &a0, &a1, &a2); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3) { - return api_detail::call_statement_du("print _1, _2, _3, _4", use_new_dict, 4, &a0, &a1, &a2, &a3); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::call_statement_du("print _1, _2, _3, _4, _5", use_new_dict, 5, &a0, &a1, &a2, &a3, &a4); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6", use_new_dict, 6, &a0, &a1, &a2, &a3, &a4, &a5); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7", use_new_dict, 7, &a0, &a1, &a2, &a3, &a4, &a5, &a6); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7, _8", use_new_dict, 8, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7, _8, _9", use_new_dict, 9, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8); -} - -BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7, _8, _9, _10", use_new_dict, 10, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1) { - return api_detail::call_statement_du("print >>_1, _2", use_new_dict, 2, &a0, &a1); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2) { - return api_detail::call_statement_du("print >>_1, _2, _3", use_new_dict, 3, &a0, &a1, &a2); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4", use_new_dict, 4, &a0, &a1, &a2, &a3); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5", use_new_dict, 5, &a0, &a1, &a2, &a3, &a4); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6", use_new_dict, 6, &a0, &a1, &a2, &a3, &a4, &a5); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7", use_new_dict, 7, &a0, &a1, &a2, &a3, &a4, &a5, &a6); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8", use_new_dict, 8, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8, _9", use_new_dict, 9, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8, _9, _10", use_new_dict, 10, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9); -} - -BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10) { - return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11", use_new_dict, 11, &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10); -} - -BOOST_PYTHON_DECL object range(object const& a0) { - return api_detail::get_func("range")(a0); -} - -BOOST_PYTHON_DECL object range(int a0) { - return api_detail::get_func("range")(object(a0)); -} - -BOOST_PYTHON_DECL object range(object const& a0, object const& a1) { - return api_detail::get_func("range")(a0, a1); -} - -BOOST_PYTHON_DECL object range(int a0, int a1) { - return api_detail::get_func("range")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object range(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("range")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object range(int a0, int a1, int a2) { - return api_detail::get_func("range")(object(a0), object(a1), object(a2)); -} - -BOOST_PYTHON_DECL object raw_input() { - return api_detail::get_func("raw_input")(); -} - -BOOST_PYTHON_DECL object raw_input(object const& a0) { - return api_detail::get_func("raw_input")(a0); -} - -BOOST_PYTHON_DECL object raw_input(const char* a0) { - return api_detail::get_func("raw_input")(object(a0)); -} - -BOOST_PYTHON_DECL object reduce(object const& a0, object const& a1) { - return api_detail::get_func("reduce")(a0, a1); -} - -BOOST_PYTHON_DECL object reduce(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("reduce")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object reload(object const& a0) { - return object((python::detail::new_reference)::PyImport_ReloadModule(a0.ptr())); -} - -BOOST_PYTHON_DECL object repr(object const& a0) { - return object((python::detail::new_reference)::PyObject_Repr(a0.ptr())); -} - -BOOST_PYTHON_DECL object round(object const& a0) { - return api_detail::get_func("round")(a0); -} - -BOOST_PYTHON_DECL object round(double const& a0) { - return api_detail::get_func("round")(object(a0)); -} - -BOOST_PYTHON_DECL object round(object const& a0, object const& a1) { - return api_detail::get_func("round")(a0, a1); -} - -BOOST_PYTHON_DECL object round(double const& a0, double const& a1) { - return api_detail::get_func("round")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object slice(object const& a0) { - return api_detail::get_func("slice")(a0); -} - -BOOST_PYTHON_DECL object slice(int a0) { - return api_detail::get_func("slice")(object(a0)); -} - -BOOST_PYTHON_DECL object slice(object const& a0, object const& a1) { - return api_detail::get_func("slice")(a0, a1); -} - -BOOST_PYTHON_DECL object slice(int a0, int a1) { - return api_detail::get_func("slice")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object slice(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("slice")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object slice(int a0, int a1, int a2) { - return api_detail::get_func("slice")(object(a0), object(a1), object(a2)); -} - -BOOST_PYTHON_DECL object str(object const& a0) { - return object((python::detail::new_reference)::PyObject_Str(a0.ptr())); -} - -BOOST_PYTHON_DECL object tuple() { - return api_detail::get_func("tuple")(); -} - -BOOST_PYTHON_DECL object tuple(object const& a0) { - return api_detail::get_func("tuple")(a0); -} - -BOOST_PYTHON_DECL object type_(object const& a0) { - return object((python::detail::new_reference)::PyObject_Type(a0.ptr())); -} - -BOOST_PYTHON_DECL object unichr(object const& a0) { - return api_detail::get_func("unichr")(a0); -} - -BOOST_PYTHON_DECL object unichr(short a0) { - return api_detail::get_func("unichr")(object(a0)); -} - -BOOST_PYTHON_DECL object unichr(int a0) { - return api_detail::get_func("unichr")(object(a0)); -} - -BOOST_PYTHON_DECL object unichr(long a0) { - return api_detail::get_func("unichr")(object(a0)); -} - -BOOST_PYTHON_DECL object unicode(object const& a0) { - return object((python::detail::new_reference)::PyObject_Unicode(a0.ptr())); -} - -BOOST_PYTHON_DECL object unicode(object const& a0, object const& a1) { - return api_detail::get_func("unicode")(a0, a1); -} - -BOOST_PYTHON_DECL object unicode(object const& a0, const char* a1) { - return api_detail::get_func("unicode")(a0, object(a1)); -} - -BOOST_PYTHON_DECL object unicode(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("unicode")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object unicode(object const& a0, const char* a1, const char* a2) { - return api_detail::get_func("unicode")(a0, object(a1), object(a2)); -} - -BOOST_PYTHON_DECL object vars() { - return api_detail::get_func("vars")(); -} - -BOOST_PYTHON_DECL object vars(object const& a0) { - return api_detail::get_func("vars")(a0); -} - -BOOST_PYTHON_DECL object xrange(object const& a0) { - return api_detail::get_func("xrange")(a0); -} - -BOOST_PYTHON_DECL object xrange(int a0) { - return api_detail::get_func("xrange")(object(a0)); -} - -BOOST_PYTHON_DECL object xrange(object const& a0, object const& a1) { - return api_detail::get_func("xrange")(a0, a1); -} - -BOOST_PYTHON_DECL object xrange(int a0, int a1) { - return api_detail::get_func("xrange")(object(a0), object(a1)); -} - -BOOST_PYTHON_DECL object xrange(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("xrange")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object xrange(int a0, int a1, int a2) { - return api_detail::get_func("xrange")(object(a0), object(a1), object(a2)); -} - -BOOST_PYTHON_DECL object zip(object const& a0) { - return api_detail::get_func("zip")(a0); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1) { - return api_detail::get_func("zip")(a0, a1); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2) { - return api_detail::get_func("zip")(a0, a1, a2); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3) { - return api_detail::get_func("zip")(a0, a1, a2, a3); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::get_func("zip")(a0, a1, a2, a3, a4); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::get_func("zip")(a0, a1, a2, a3, a4, a5); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::get_func("zip")(a0, a1, a2, a3, a4, a5, a6); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::get_func("zip")(a0, a1, a2, a3, a4, a5, a6, a7); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::get_func("zip")(a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::get_func("zip")(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -BOOST_PYTHON_DECL object compile_string(const char* a0, const char* a1, int a2) { - return object((python::detail::new_reference)::Py_CompileString(const_cast(a0), const_cast(a1), a2)); -} - -BOOST_PYTHON_DECL int import_append_inittab(const char* a0, void(*a1)(void)) { - int r = ::PyImport_AppendInittab(const_cast(a0), a1); - if(r == -1) - throw_error_already_set(); - return r; -} - -BOOST_PYTHON_DECL object import_add_module(const char* a0) { - return object((python::detail::borrowed_reference)::PyImport_AddModule(const_cast(a0))); -} - -BOOST_PYTHON_DECL object import_get_module_dict() { - return object((python::detail::borrowed_reference)::PyImport_GetModuleDict()); -} - -BOOST_PYTHON_DECL object import_import(object const& a0) { - return object((python::detail::new_reference)::PyImport_Import(a0.ptr())); -} - -BOOST_PYTHON_DECL object import_import(const char* a0) { - return object((python::detail::new_reference)::PyImport_Import(object(a0).ptr())); -} - -BOOST_PYTHON_DECL object import_import_module(const char* a0) { - return object((python::detail::new_reference)::PyImport_ImportModule(const_cast(a0))); -} - -BOOST_PYTHON_DECL object import_import_module_ex(const char* a0, object const& a1, object const& a2, object const& a3) { - return object((python::detail::new_reference)::PyImport_ImportModuleEx(const_cast(a0), a1.ptr(), a2.ptr(), a3.ptr())); -} - -BOOST_PYTHON_DECL object module_get_dict(object const& a0) { - return object((python::detail::borrowed_reference)::PyModule_GetDict(a0.ptr())); -} - -BOOST_PYTHON_DECL int object_print(object const& a0, FILE* a1, int a2) { - int r = ::PyObject_Print(a0.ptr(), a1, a2); - if(r == -1) - throw_error_already_set(); - return r; -} - -BOOST_PYTHON_DECL object run_file(FILE* a0, const char* a1, int a2, object const& a3, object const& a4) { - return object((python::detail::new_reference)::PyRun_File(a0, const_cast(a1), a2, a3.ptr(), a4.ptr())); -} - -BOOST_PYTHON_DECL int run_simple_file(FILE* a0, const char* a1) { - int r = ::PyRun_SimpleFile(a0, const_cast(a1)); - if(r == -1) - throw_error_already_set(); - return r; -} - -BOOST_PYTHON_DECL int run_simple_string(const char* a0) { - int r = ::PyRun_SimpleString(const_cast(a0)); - if(r == -1) - throw_error_already_set(); - return r; -} - -BOOST_PYTHON_DECL object run_string(const char* a0, int a1, object const& a2, object const& a3) { - return object((python::detail::new_reference)::PyRun_String(const_cast(a0), a1, a2.ptr(), a3.ptr())); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0) { - return api_detail::call_statement(a0); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1) { - return api_detail::call_statement_du(a0, a1); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1) { - return api_detail::call_statement(a0, 1, &a1); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2) { - return api_detail::call_statement(a0, 2, &a1, &a2); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3) { - return api_detail::call_statement(a0, 3, &a1, &a2, &a3); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4) { - return api_detail::call_statement(a0, 4, &a1, &a2, &a3, &a4); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::call_statement(a0, 5, &a1, &a2, &a3, &a4, &a5); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::call_statement(a0, 6, &a1, &a2, &a3, &a4, &a5, &a6); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::call_statement(a0, 7, &a1, &a2, &a3, &a4, &a5, &a6, &a7); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::call_statement(a0, 8, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::call_statement(a0, 9, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10) { - return api_detail::call_statement(a0, 10, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2) { - return api_detail::call_statement_du(a0, a1, 1, &a2); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3) { - return api_detail::call_statement_du(a0, a1, 2, &a2, &a3); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4) { - return api_detail::call_statement_du(a0, a1, 3, &a2, &a3, &a4); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5) { - return api_detail::call_statement_du(a0, a1, 4, &a2, &a3, &a4, &a5); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6) { - return api_detail::call_statement_du(a0, a1, 5, &a2, &a3, &a4, &a5, &a6); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7) { - return api_detail::call_statement_du(a0, a1, 6, &a2, &a3, &a4, &a5, &a6, &a7); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8) { - return api_detail::call_statement_du(a0, a1, 7, &a2, &a3, &a4, &a5, &a6, &a7, &a8); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9) { - return api_detail::call_statement_du(a0, a1, 8, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10) { - return api_detail::call_statement_du(a0, a1, 9, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10); -} - -BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10, object const& a11) { - return api_detail::call_statement_du(a0, a1, 10, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11); -} - - -}}} - diff --git a/src/str.cpp b/src/str.cpp deleted file mode 100644 index f36de233..00000000 --- a/src/str.cpp +++ /dev/null @@ -1,384 +0,0 @@ -#include -#include - -namespace boost { namespace python { - -BOOST_PYTHON_DECL detail::new_reference str::call(object const& arg_) -{ - return (detail::new_reference)PyObject_CallFunction( - (PyObject*)&PyString_Type, "(O)", - arg_.ptr()); -} - -BOOST_PYTHON_DECL str::str() - : object(detail::new_reference(PyString_FromString(""))) -{} - -BOOST_PYTHON_DECL str::str(const char* s) - : object(detail::new_reference(PyString_FromString(s))) -{} - -BOOST_PYTHON_DECL str::str(object_cref other) - : object(str::call(other)) -{} - -namespace -{ - // When returning str objects from methods, it may turn out that the - // derived class is returning something else, perhaps something not - // even derived from str. Since it is generally harmless for a - // Boost.Python wrapper object to hold an object of a different - // type, and because calling str() with an object may in fact - // perform a conversion, the least-bad alternative is to assume that - // we have a Python str object and stuff it into the str result. - str assume_str(object const& o) - { - return str(detail::borrowed_reference(o.ptr())); - } -} -BOOST_PYTHON_DECL str str::capitalize() const -{ - return assume_str(this->attr("capitalize")()); -} - -BOOST_PYTHON_DECL str str::center(object_cref width) const -{ - return assume_str( - this->attr("center")(width) - ); -} - -BOOST_PYTHON_DECL long str::count(object_cref sub) const -{ - return extract(this->attr("count")(sub)); -} - -BOOST_PYTHON_DECL long str::count(object_cref sub, object_cref start) const -{ - return extract(this->attr("count")(sub,start)); -} - -BOOST_PYTHON_DECL long str::count(object_cref sub, object_cref start, object_cref end) const -{ - return extract(this->attr("count")(sub,start,end)); -} - -BOOST_PYTHON_DECL object str::decode() const -{ - return this->attr("decode")(); -} - -BOOST_PYTHON_DECL object str::decode(object_cref encoding) const -{ - return this->attr("decode")(encoding); -} - -BOOST_PYTHON_DECL object str::decode(object_cref encoding, object_cref errors) const -{ - return this->attr("decode")(encoding,errors); -} - -BOOST_PYTHON_DECL object str::encode() const -{ - return this->attr("encode")(); -} - -BOOST_PYTHON_DECL object str::encode(object_cref encoding) const -{ - return this->attr("encode")(encoding); -} - -BOOST_PYTHON_DECL object str::encode(object_cref encoding, object_cref errors) const -{ - return this->attr("encode")(encoding,errors); -} - -BOOST_PYTHON_DECL bool str::endswith(object_cref suffix) const -{ - bool result = PyInt_AsLong(this->attr("endswith")(suffix).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL str str::expandtabs() const -{ - return assume_str(this->attr("expandtabs")()); -} - -BOOST_PYTHON_DECL str str::expandtabs(object_cref tabsize) const -{ - return assume_str(this->attr("expandtabs")(tabsize)); -} - -BOOST_PYTHON_DECL long str::find(object_cref sub) const -{ - long result = PyInt_AsLong(this->attr("find")(sub).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::find(object_cref sub, object_cref start) const -{ - long result = PyInt_AsLong(this->attr("find")(sub,start).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::find(object_cref sub, object_cref start, object_cref end) const -{ - long result = PyInt_AsLong(this->attr("find")(sub,start,end).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::index(object_cref sub) const -{ - long result = PyInt_AsLong(this->attr("index")(sub).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::index(object_cref sub, object_cref start) const -{ - long result = PyInt_AsLong(this->attr("index")(sub,start).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::index(object_cref sub, object_cref start, object_cref end) const -{ - long result = PyInt_AsLong(this->attr("index")(sub,start,end).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::isalnum() const -{ - bool result = PyInt_AsLong(this->attr("isalnum")().ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::isalpha() const -{ - bool result = PyInt_AsLong(this->attr("isalpha")().ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::isdigit() const -{ - bool result = PyInt_AsLong(this->attr("isdigit")().ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::islower() const -{ - bool result = PyInt_AsLong(this->attr("islower")().ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::isspace() const -{ - bool result = PyInt_AsLong(this->attr("isspace")().ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::istitle() const -{ - bool result = PyInt_AsLong(this->attr("istitle")().ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::isupper() const -{ - bool result = PyInt_AsLong(this->attr("isupper")().ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL str str::join(object_cref sequence) const -{ - return assume_str(this->attr("join")(sequence)); -} - -BOOST_PYTHON_DECL str str::ljust(object_cref width) const -{ - return assume_str(this->attr("ljust")(width)); -} - -BOOST_PYTHON_DECL str str::lower() const -{ - return assume_str(this->attr("lower")()); -} - -BOOST_PYTHON_DECL str str::lstrip() const -{ - return assume_str(this->attr("lstrip")()); -} - -BOOST_PYTHON_DECL str str::replace(object_cref old, object_cref new_) const -{ - return assume_str(this->attr("replace")(old,new_)); -} - -BOOST_PYTHON_DECL str str::replace(object_cref old, object_cref new_, object_cref maxsplit) const { - return assume_str(this->attr("replace")(old,new_,maxsplit)); -} - -BOOST_PYTHON_DECL long str::rfind(object_cref sub) const -{ - long result = PyInt_AsLong(this->attr("rfind")(sub).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::rfind(object_cref sub, object_cref start) const -{ - long result = PyInt_AsLong(this->attr("rfind")(sub,start).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::rfind(object_cref sub, object_cref start, object_cref end) const -{ - long result = PyInt_AsLong(this->attr("rfind")(sub,start,end).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::rindex(object_cref sub) const -{ - long result = PyInt_AsLong(this->attr("rindex")(sub).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::rindex(object_cref sub, object_cref start) const -{ - long result = PyInt_AsLong(this->attr("rindex")(sub,start).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL long str::rindex(object_cref sub, object_cref start, object_cref end) const -{ - long result = PyInt_AsLong(this->attr("rindex")(sub,start,end).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL str str::rjust(object_cref width) const -{ - return assume_str(this->attr("rjust")(width)); -} - -BOOST_PYTHON_DECL str str::rstrip() const -{ - return assume_str(this->attr("rstrip")()); -} - -BOOST_PYTHON_DECL list str::split() const -{ - return list(this->attr("split")()); -} - -BOOST_PYTHON_DECL list str::split(object_cref sep) const -{ - return list(this->attr("split")(sep)); -} - -BOOST_PYTHON_DECL list str::split(object_cref sep, object_cref maxsplit) const -{ - return list(this->attr("split")(sep,maxsplit)); -} - -BOOST_PYTHON_DECL list str::splitlines() const -{ - return list(this->attr("splitlines")()); -} - -BOOST_PYTHON_DECL list str::splitlines(object_cref keepends) const -{ - return list(this->attr("splitlines")(keepends)); -} - -BOOST_PYTHON_DECL bool str::startswith(object_cref prefix) const -{ - bool result = PyInt_AsLong(this->attr("startswith")(prefix).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::startswith(object_cref prefix, object_cref start) const -{ - bool result = PyInt_AsLong(this->attr("startswith")(prefix,start).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL bool str::startswith(object_cref prefix, object_cref start, object_cref end) const -{ - bool result = PyInt_AsLong(this->attr("startswith")(prefix,start,end).ptr()); - if (PyErr_Occurred()) - throw_error_already_set(); - return result; -} - -BOOST_PYTHON_DECL str str::strip() const -{ - return assume_str(this->attr("strip")()); -} - -BOOST_PYTHON_DECL str str::swapcase() const -{ - return assume_str(this->attr("swapcase")()); -} - -BOOST_PYTHON_DECL str str::title() const -{ - return assume_str(this->attr("title")()); -} - -BOOST_PYTHON_DECL str str::translate(object_cref table) const -{ - return assume_str(this->attr("translate")(table)); -} - -BOOST_PYTHON_DECL str str::translate(object_cref table, object_cref deletechars) const -{ - return assume_str(this->attr("translate")(table,deletechars)); -} - -BOOST_PYTHON_DECL str str::upper() const -{ - return assume_str(this->attr("upper")()); -} - -}} // namespace boost::python diff --git a/src/tuple.cpp b/src/tuple.cpp deleted file mode 100644 index d6a33a56..00000000 --- a/src/tuple.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include - -namespace boost { namespace python { - -BOOST_PYTHON_DECL detail::new_reference tuple::call(object const& arg_) -{ - return (detail::new_reference)PyObject_CallFunction( - (PyObject*)&PyTuple_Type, "(O)", - arg_.ptr()); -} - -BOOST_PYTHON_DECL tuple::tuple() - : object(detail::new_reference(PyTuple_New(0))) -{} - -BOOST_PYTHON_DECL tuple::tuple(object_cref sequence) - : object(tuple::call(sequence)) -{} - -}} // namespace boost::python diff --git a/src/types.cpp b/src/types.cpp deleted file mode 100644 index eae9adff..00000000 --- a/src/types.cpp +++ /dev/null @@ -1,1272 +0,0 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -#define BOOST_PYTHON_SOURCE - -#include -#include -#include // for handle_exception() -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { - -namespace -{ - using detail::type_object_base; - using detail::call_object; - - - // Define a family of forwarding functions that can be called from a - // PyTypeObject's slots. These functions dispatch through a (virtual) member - // function pointer in the type_object_base, and handle exceptions in a - // uniform way, preventing us from having to rewrite the dispatching code over - // and over. - - // Given a function object f with signature - // - // PyObject* f(PyTypeObject*,PyObject*) - // - // calls f inside of handle_exception, and returns the result. If an exception - // is thrown by f, returns 0. - template - PyObject* obj_call(PyObject* obj, F f) - { - PyObject* result; - return call_object(result, obj, f) ? 0 : result; - } - - // Call the given integer-returning function object inside of - // handle_exception, returning a value_holder. F is a function - // object with "signature" - // - // R F(PyTypeObject*, PyObject*) - // - // where R is an integer type. - template - R int_call(PyObject* obj, F f, R* = 0) - { - R result; - return call_object(result, obj, f) ? -1 : result; - } - - // Implemented in terms of obj_call, above - PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*) const) - { - return obj_call(obj, bind(f, _1, _2)); - } - - // Implemented in terms of int_call, above - int call(PyObject* obj, int (type_object_base::*f)(PyObject*) const) - { - return int_call(obj, bind(f, _1, _2)); - } - - template - PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*, A1) const, A1 a1) - { - return obj_call(obj, bind(f, _1, _2, a1)); - } - - template - int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1) const, A1 a1) - { - return int_call(obj, bind(f, _1, _2, a1)); - } - - template - PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) - { - return obj_call(obj, bind(f, _1, _2, a1, a2)); - } - - template - int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) - { - return int_call(obj, bind(f, _1, _2, a1, a2)); - } - - template - int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1, A2, A3) const, A1 a1, A2 a2, A3 a3) - { - return int_call(obj, bind(f, _1, _2, a1, a2, a3)); - } - - int call_length_function(PyObject* obj, int (type_object_base::*f)(PyObject*) const) - { - int result; - if (call_object(result, obj, bind(f, _1, _2))) - return -1; - - if (result >= 0) - return result; - - PyErr_SetString(PyExc_ValueError, "__len__() should return >= 0"); - return -1; - } -} // anonymous namespace - -extern "C" { - -// -// These functions actually go into the type object's slots, and dispatch to the -// "call" wrappers defined above. -// -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); -} - -static PyObject* do_instance_str(PyObject* obj) -{ - return call(obj, &type_object_base::instance_str); -} - -static long do_instance_hash(PyObject* obj) -{ - return int_call(obj, bind(&type_object_base::instance_hash, _1, _2)); -} - -static PyObject* do_instance_call(PyObject* obj, PyObject* args, PyObject* keywords) -{ - return call(obj, &type_object_base::instance_call, args, keywords); -} - -static void do_instance_dealloc(PyObject* obj) -{ - if (handle_exception( - bind(&type_object_base::instance_dealloc - , static_cast(obj->ob_type) - , obj)) - ) - { - assert(!"exception during destruction!"); - } -} - -static PyObject* do_instance_getattr(PyObject* obj, char* name) -{ - const char* name_ = name; - return call(obj, &type_object_base::instance_getattr, name_); -} - -static int do_instance_setattr(PyObject* obj, char* name, PyObject* value) -{ - const char* name_ = name; - return call(obj, &type_object_base::instance_setattr, name_, value); -} - -static int do_instance_mp_length(PyObject* obj) -{ - return call_length_function(obj, &type_object_base::instance_mapping_length); -} - -static int do_instance_sq_length(PyObject* obj) -{ - return call_length_function(obj, &type_object_base::instance_sequence_length); -} - -static PyObject* do_instance_mp_subscript(PyObject* obj, PyObject* index) -{ - return call(obj, &type_object_base::instance_mapping_subscript, index); -} - -static PyObject* do_instance_sq_item(PyObject* obj, int index) -{ - // This is an extension to standard class behavior. If sequence_length - // is implemented and n >= sequence_length(), raise an IndexError. That - // keeps users from having to worry about raising it themselves - const PyTypeObject* const type = obj->ob_type; - if (type->tp_as_sequence != 0 && type->tp_as_sequence->sq_length != 0 - && index >= type->tp_as_sequence->sq_length(obj)) - { - PyErr_SetString(PyExc_IndexError, type->tp_name); - return 0; - } - - return obj_call( - obj - , bind(&type_object_base::instance_sequence_item, _1, _2, index)); -} - -static int do_instance_mp_ass_subscript(PyObject* obj, PyObject* index, PyObject* value) -{ - return call(obj, &type_object_base::instance_mapping_ass_subscript, index, value); -} - -static int do_instance_sq_ass_item(PyObject* obj, int index, PyObject* value) -{ - return call(obj, &type_object_base::instance_sequence_ass_item, index, value); -} - -static PyObject* do_instance_sq_concat(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_sequence_concat, other); -} - -static PyObject* do_instance_sq_repeat(PyObject* obj, int n) -{ - return call(obj, &type_object_base::instance_sequence_repeat, n); -} - -static PyObject* do_instance_sq_slice( - PyObject* obj, int start, int finish) -{ - return call(obj, &type_object_base::instance_sequence_slice, start, finish); -} - -static int do_instance_sq_ass_slice( - PyObject* obj, int start, int finish, PyObject* value) -{ - return call(obj, &type_object_base::instance_sequence_ass_slice, start, finish, value); -} - -static PyObject* do_instance_nb_add(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_add, other); -} - -static PyObject* do_instance_nb_subtract(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_subtract, other); -} - -static PyObject* do_instance_nb_multiply(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_multiply, other); -} - -static PyObject* do_instance_nb_divide(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_divide, other); -} - -static PyObject* do_instance_nb_remainder(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_remainder, other); -} - -static PyObject* do_instance_nb_divmod(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_divmod, other); -} - -static PyObject* do_instance_nb_power(PyObject* obj, PyObject* exponent, PyObject* modulus) -{ - return call(obj, &type_object_base::instance_number_power, exponent, modulus); -} - -static PyObject* do_instance_nb_negative(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_negative); -} - -static PyObject* do_instance_nb_positive(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_positive); -} - -static PyObject* do_instance_nb_absolute(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_absolute); -} - -static int do_instance_nb_nonzero(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_nonzero); -} - -static PyObject* do_instance_nb_invert(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_invert); -} - - -static PyObject* do_instance_nb_lshift(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_lshift, other); -} - -static PyObject* do_instance_nb_rshift(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_rshift, other); -} - -static PyObject* do_instance_nb_and(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_and, other); -} - -static PyObject* do_instance_nb_xor(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_xor, other); -} - -static PyObject* do_instance_nb_or(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_or, other); -} - -static int do_instance_nb_coerce(PyObject**obj, PyObject**other) -{ - // no call() overload for this oddball function, so we'll do it manually - return int_call( - *obj, bind( - &type_object_base::instance_number_coerce, _1, _2, obj, other)); -} -static PyObject* do_instance_nb_int(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_int); -} - -static PyObject* do_instance_nb_long(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_long); -} - -static PyObject* do_instance_nb_float(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_float); -} - -static PyObject* do_instance_nb_oct(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_oct); -} - -static PyObject* do_instance_nb_hex(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_hex); -} - -static PyObject* do_instance_nb_inplace_add(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_add, other); -} - -static PyObject* do_instance_nb_inplace_subtract(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_subtract, other); -} - -static PyObject* do_instance_nb_inplace_multiply(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_multiply, other); -} - -static PyObject* do_instance_nb_inplace_divide(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_divide, other); -} - -static PyObject* do_instance_nb_inplace_remainder(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_remainder, other); -} - -static PyObject* do_instance_nb_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus) -{ - return call(obj, &type_object_base::instance_number_inplace_power, exponent, modulus); -} - -static PyObject* do_instance_nb_inplace_lshift(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_lshift, other); -} - -static PyObject* do_instance_nb_inplace_rshift(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_rshift, other); -} - -static PyObject* do_instance_nb_inplace_and(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_and, other); -} - -static PyObject* do_instance_nb_inplace_or(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_or, other); -} - -static PyObject* do_instance_nb_inplace_xor(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_inplace_xor, other); -} - -} // extern "C" - -namespace -{ - -#define ENABLE_GENERAL_CAPABILITY(field) \ - case type_object_base::field: \ - dest->tp_##field = &do_instance_##field; \ - return true - -bool add_capability_general(type_object_base::capability capability, PyTypeObject* dest) -{ - assert(dest != 0); - - switch(capability) - { - ENABLE_GENERAL_CAPABILITY(hash); - ENABLE_GENERAL_CAPABILITY(call); - ENABLE_GENERAL_CAPABILITY(str); - ENABLE_GENERAL_CAPABILITY(getattr); - ENABLE_GENERAL_CAPABILITY(setattr); - ENABLE_GENERAL_CAPABILITY(compare); - ENABLE_GENERAL_CAPABILITY(repr); - default: - return false; - } -} - - -template -void create_method_table_if_null(T*& table) -{ - if(table == 0) - { - detail::shared_pod_manager::create(table); - } - else - { - detail::shared_pod_manager::make_unique_copy(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_INPLACE_CAPABILITY(field) \ - case type_object_base::number_##field: \ - create_method_table_if_null(dest->tp_as_number); \ - dest->tp_as_number->nb_##field = &do_instance_nb_##field; \ - detail::shared_pod_manager::replace_if_equal(dest->tp_as_number); \ - dest->tp_flags |= Py_TPFLAGS_HAVE_INPLACEOPS; \ - return true - -bool add_capability_inplace(type_object_base::capability capability, PyTypeObject* dest) -{ - assert(dest != 0); - switch (capability) - { -#if PYTHON_API_VERSION >= 1010 - ENABLE_INPLACE_CAPABILITY (inplace_add); - ENABLE_INPLACE_CAPABILITY (inplace_subtract); - ENABLE_INPLACE_CAPABILITY (inplace_multiply); - ENABLE_INPLACE_CAPABILITY (inplace_divide); - ENABLE_INPLACE_CAPABILITY (inplace_remainder); - ENABLE_INPLACE_CAPABILITY (inplace_power); - ENABLE_INPLACE_CAPABILITY (inplace_lshift); - ENABLE_INPLACE_CAPABILITY (inplace_rshift); - ENABLE_INPLACE_CAPABILITY (inplace_and); - ENABLE_INPLACE_CAPABILITY (inplace_or); - ENABLE_INPLACE_CAPABILITY (inplace_xor); -#endif - default: - return false; - } -} - -#define ENABLE_MAPPING_CAPABILITY(field) \ - case type_object_base::mapping_##field: \ - create_method_table_if_null(dest); \ - dest->mp_##field = &do_instance_mp_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_mapping(type_object_base::capability capability, PyMappingMethods*& dest) -{ - switch(capability) - { - ENABLE_MAPPING_CAPABILITY(length); - ENABLE_MAPPING_CAPABILITY(subscript); - ENABLE_MAPPING_CAPABILITY(ass_subscript); - default: - return false; - } -} - -#define ENABLE_SEQUENCE_CAPABILITY(field) \ - case type_object_base::sequence_##field: \ - create_method_table_if_null(dest); \ - dest->sq_##field = &do_instance_sq_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_sequence(type_object_base::capability capability, PySequenceMethods*& dest) -{ - switch(capability) - { - ENABLE_SEQUENCE_CAPABILITY(length); - ENABLE_SEQUENCE_CAPABILITY(item); - ENABLE_SEQUENCE_CAPABILITY(ass_item); - ENABLE_SEQUENCE_CAPABILITY(concat); - ENABLE_SEQUENCE_CAPABILITY(repeat); - ENABLE_SEQUENCE_CAPABILITY(slice); - ENABLE_SEQUENCE_CAPABILITY(ass_slice); - default: - return false; - } -} - -#define ENABLE_NUMBER_CAPABILITY(field) \ - case type_object_base::number_##field: \ - create_method_table_if_null(dest); \ - dest->nb_##field = &do_instance_nb_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_number(type_object_base::capability capability, PyNumberMethods*& dest) -{ - switch(capability) - { - ENABLE_NUMBER_CAPABILITY(add); - ENABLE_NUMBER_CAPABILITY(subtract); - ENABLE_NUMBER_CAPABILITY(multiply); - ENABLE_NUMBER_CAPABILITY(divide); - ENABLE_NUMBER_CAPABILITY(remainder); - ENABLE_NUMBER_CAPABILITY(divmod); - ENABLE_NUMBER_CAPABILITY(power); - ENABLE_NUMBER_CAPABILITY(negative); - ENABLE_NUMBER_CAPABILITY(positive); - ENABLE_NUMBER_CAPABILITY(absolute); - ENABLE_NUMBER_CAPABILITY(nonzero); - ENABLE_NUMBER_CAPABILITY(invert); - ENABLE_NUMBER_CAPABILITY(lshift); - ENABLE_NUMBER_CAPABILITY(rshift); - ENABLE_NUMBER_CAPABILITY(and); - ENABLE_NUMBER_CAPABILITY(xor); - ENABLE_NUMBER_CAPABILITY(or); - ENABLE_NUMBER_CAPABILITY(coerce); - ENABLE_NUMBER_CAPABILITY(int); - ENABLE_NUMBER_CAPABILITY(long); - ENABLE_NUMBER_CAPABILITY(float); - ENABLE_NUMBER_CAPABILITY(oct); - ENABLE_NUMBER_CAPABILITY(hex); - default: - return false; - } -} - -#define ENABLE_BUFFER_CAPABILITY(field) \ - case type_object_base::buffer_##field: \ - create_method_table_if_null(dest); \ - dest->bf_##field = &do_instance_bf_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_buffer(type_object_base::capability capability, PyBufferProcs*& dest) -{ - (void)dest; // suppress unused argument warning - (void)capability; // likwise -#if 0 - switch(capability) - { - // nothing defined yet - default: - return false; - } -#endif - return false; -} - -} // anonymous namespace - -namespace detail { - - void add_capability( - type_object_base::capability capability, - PyTypeObject* dest_) - { - if(add_capability_general(capability, dest_)) - return; - if(add_capability_richcompare(capability, dest_)) - return; - if(add_capability_inplace(capability, dest_)) - return; - if(add_capability_mapping(capability, dest_->tp_as_mapping)) - return; - if(add_capability_sequence(capability, dest_->tp_as_sequence)) - return; - if(add_capability_number(capability, dest_->tp_as_number)) - return; - if(add_capability_buffer(capability, dest_->tp_as_buffer)) - return; - - // no one recognized the capability - throw std::runtime_error("py::detail::add_capability(): unknown capability"); - } -} // namespace detail - -type_object_base::~type_object_base() -{ - detail::shared_pod_manager::dispose(tp_as_mapping); - detail::shared_pod_manager::dispose(tp_as_sequence); - detail::shared_pod_manager::dispose(tp_as_number); - detail::shared_pod_manager::dispose(tp_as_buffer); -} - -void type_object_base::enable(type_object_base::capability capability) -{ - detail::add_capability(capability, this); -} - -type_object_base::type_object_base(PyTypeObject* t) - : python_type(t) -{ - this->tp_dealloc = do_instance_dealloc; -} - -namespace -{ - typedef long pod_refcount; - - inline pod_refcount pod_refcount_offset(std::size_t size) - { - const std::size_t alignment = boost::alignment_of::value; - return (size + alignment - 1) / alignment * alignment; - } - - inline pod_refcount* counted_pod_refcount(char* pod, std::size_t size) - { - if(pod == 0) - return 0; - - return reinterpret_cast(pod + pod_refcount_offset(size)); - } - - #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST - int pod_instance_counter = 0; - #endif - - inline pod_refcount counted_pod_getref(char* pod, std::size_t size) - { - pod_refcount* ref_count = counted_pod_refcount(pod, size); - return ref_count == 0 ? -1 : *ref_count; - } - - inline pod_refcount counted_pod_decref(char* pod, std::size_t size) - { - pod_refcount* const ref_count = counted_pod_refcount(pod, size); - if (ref_count == 0) - return -1; - --(*ref_count); - if (*ref_count <= 0) - { - #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST - --pod_instance_counter; - #endif - ::operator delete(pod); - return 0; - } - return *ref_count; - } - - pod_refcount counted_pod_incref(char* pod, std::size_t size) - { - pod_refcount* ref_count = counted_pod_refcount(pod, size); - return ref_count == 0 ? -1 : ++(*ref_count); - } - -} // anonymous namespace - -namespace detail -{ - struct shared_pod_manager::compare - { - bool operator()(const std::pair& x1, - const std::pair& x2) const - { - const std::size_t n1 = x1.second; - const std::size_t n2 = x2.second; - return n1 < n2 || n1 == n2 && BOOST_CSTD_::memcmp(x1.first, x2.first, n1) < 0; - } - }; - - struct shared_pod_manager::identical - { - identical(char* p) : pod(p) {} - - bool operator()(const std::pair& x) const - { - return pod == x.first; - } - - char* pod; - }; - - shared_pod_manager& shared_pod_manager::obj() - { - static shared_pod_manager spm; - return spm; - } - - shared_pod_manager::~shared_pod_manager() - { - } - - void* shared_pod_manager::replace_if_equal(void* pod, std::size_t size) - { - if(pod == 0) - return 0; - - const holder element(static_cast(pod), size); - - const storage::iterator found - = std::lower_bound(m_storage.begin(), m_storage.end(), element, compare()); - - if (found != m_storage.end() && pod == found->first) - { - // pod already in list => do nothing - return pod; - } - else if (found != m_storage.end() && !compare()(element, *found)) - { - // equal element in list => replace - void* replacement = found->first; - counted_pod_incref(found->first, size); - dec_ref(element.first, size); // invalidates iterator 'found' - return replacement; - } - else - { - // new element => insert - m_storage.insert(found, element); - return pod; - } - } - - void* shared_pod_manager::make_unique_copy(void* pod, std::size_t size) - { - if(pod == 0) - return 0; - if(counted_pod_getref(static_cast(pod), size) == 1) - { - erase_from_list(pod); - return pod; - } - else - { - void* copy = create(size); - memmove(copy, pod, size); - dec_ref(pod, size); - return copy; - } - } - - void* shared_pod_manager::create(std::size_t size) - { - std::size_t total_size = pod_refcount_offset(size) + sizeof(pod_refcount); - char* pod = static_cast(::operator new(total_size)); - #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST - ++pod_instance_counter; - #endif - memset(pod, 0, total_size); - - *counted_pod_refcount(pod, size) = 1; - - return pod; - } - - void shared_pod_manager::dec_ref(void* pod, std::size_t size) - { - if(pod == 0) - return; - - int ref_count = counted_pod_decref(static_cast(pod), size); - - if(ref_count <= 0) - erase_from_list(pod); - } - - void shared_pod_manager::erase_from_list(void* pod) - { - if(pod == 0) - return; - - const storage::iterator found = - std::find_if(m_storage.begin(), m_storage.end(), - identical(static_cast(pod))); - - if(found != m_storage.end()) - { - m_storage.erase(found); - } - } -} // namespace detail - -namespace { - struct error_type { - operator PyObject*() const { return 0; } - operator int() const { return -1; } - }; - - error_type unimplemented(const char* name) - { - assert(!"Control should never reach here"); - string s("Unimplemented "); - s += string(name); - PyErr_SetObject(PyExc_RuntimeError, s.get()); - return error_type(); - } -} - -PyObject* type_object_base::instance_repr(PyObject*) const -{ - return unimplemented("instance_repr"); -} - -int type_object_base::instance_compare(PyObject*, PyObject*) const -{ - return unimplemented("instance_compare"); -} - -PyObject* type_object_base::instance_str(PyObject*) const -{ - return unimplemented("instance_str"); -} - -long type_object_base::instance_hash(PyObject* /* obj */) const -{ - return unimplemented("instance_hash"); -} - -PyObject* type_object_base::instance_call(PyObject* /*obj*/, PyObject* /*args*/, PyObject* /*kw*/) const -{ - return unimplemented("instance_call"); -} - -PyObject* type_object_base::instance_getattr(PyObject* /*obj*/, const char* /*name*/) const -{ - return unimplemented("instance_getattr"); -} - -int type_object_base::instance_setattr(PyObject* /*obj*/, const char* /*name*/, PyObject* /*value*/) const -{ - return unimplemented("instance_setattr"); -} - -int type_object_base::instance_mapping_length(PyObject*) const -{ - return unimplemented("instance_mapping_length"); -} - -int type_object_base::instance_sequence_length(PyObject*) const -{ - return unimplemented("instance_sequence_length"); -} - -PyObject* type_object_base::instance_mapping_subscript(PyObject*, PyObject*) const -{ - return unimplemented("instance_mapping_subscript"); -} - -PyObject* type_object_base::instance_sequence_item(PyObject*, int) const -{ - return unimplemented("instance_sequence_item"); -} - -int type_object_base::instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const -{ - return unimplemented("instance_mapping_ass_subscript"); -} - -int type_object_base::instance_sequence_ass_item(PyObject*, int, PyObject*) const -{ - return unimplemented("instance_sequence_ass_item"); -} - -PyObject* type_object_base::instance_sequence_concat(PyObject*, PyObject*) const -{ - return unimplemented("instance_sequence_concat"); -} - -PyObject* type_object_base::instance_sequence_repeat(PyObject*, int) const -{ - return unimplemented("instance_sequence_repeat"); -} - -PyObject* type_object_base::instance_sequence_slice(PyObject*, int, int) const -{ - return unimplemented("instance_sequence_slice"); -} - -int type_object_base::instance_sequence_ass_slice(PyObject*, int, int, PyObject*) const -{ - return unimplemented("instance_sequence_ass_slice"); -} - -PyObject* type_object_base::instance_number_add(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_add"); -} - -PyObject* type_object_base::instance_number_subtract(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_subtract"); -} - -PyObject* type_object_base::instance_number_multiply(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_multiply"); -} - -PyObject* type_object_base::instance_number_divide(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_divide"); -} - -PyObject* type_object_base::instance_number_remainder(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_remainder"); -} - -PyObject* type_object_base::instance_number_divmod(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_divmod"); -} - -PyObject* type_object_base::instance_number_power(PyObject*, PyObject*, PyObject*) const -{ - return unimplemented("instance_number_power"); -} - -PyObject* type_object_base::instance_number_negative(PyObject*) const -{ - return unimplemented("instance_number_negative"); -} - -PyObject* type_object_base::instance_number_positive(PyObject*) const -{ - return unimplemented("instance_number_positive"); -} - -PyObject* type_object_base::instance_number_absolute(PyObject*) const -{ - return unimplemented("instance_number_absolute"); -} - -int type_object_base::instance_number_nonzero(PyObject*) const -{ - return unimplemented("instance_number_nonzero"); -} - -PyObject* type_object_base::instance_number_invert(PyObject*) const -{ - return unimplemented("instance_number_invert"); -} - -PyObject* type_object_base::instance_number_lshift(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_lshift"); -} - -PyObject* type_object_base::instance_number_rshift(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_rshift"); -} - -PyObject* type_object_base::instance_number_and(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_and"); -} - -PyObject* type_object_base::instance_number_xor(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_xor"); -} - -PyObject* type_object_base::instance_number_or(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_or"); -} - -int type_object_base::instance_number_coerce(PyObject*, PyObject**, PyObject**) const -{ - return unimplemented("instance_number_coerce"); -} - -PyObject* type_object_base::instance_number_int(PyObject*) const -{ - return unimplemented("instance_number_int"); -} - -PyObject* type_object_base::instance_number_long(PyObject*) const -{ - return unimplemented("instance_number_long"); -} - -PyObject* type_object_base::instance_number_float(PyObject*) const -{ - return unimplemented("instance_number_float"); -} - -PyObject* type_object_base::instance_number_oct(PyObject*) const -{ - return unimplemented("instance_number_oct"); -} - -PyObject* type_object_base::instance_number_hex(PyObject*) const -{ - return unimplemented("instance_number_hex"); -} - -PyObject* type_object_base::instance_number_inplace_add(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_add"); -} - -PyObject* type_object_base::instance_number_inplace_subtract(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_subtract"); -} - -PyObject* type_object_base::instance_number_inplace_multiply(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_multiply"); -} - -PyObject* type_object_base::instance_number_inplace_divide(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_divide"); -} - -PyObject* type_object_base::instance_number_inplace_remainder(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_remainder"); -} - -PyObject* type_object_base::instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_power"); -} - -PyObject* type_object_base::instance_number_inplace_lshift(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_lshift"); -} - -PyObject* type_object_base::instance_number_inplace_rshift(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_rshift"); -} - -PyObject* type_object_base::instance_number_inplace_and(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_and"); -} - -PyObject* type_object_base::instance_number_inplace_or(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_or"); -} - -PyObject* type_object_base::instance_number_inplace_xor(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_inplace_xor"); -} - -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 - -struct TestTypeObject : boost::python::type_object_base -{ - TestTypeObject() - : boost::python::type_object_base(Py_None->ob_type->ob_type) - {} - - void instance_dealloc(PyObject*) const {} -}; - -struct POD1 -{ - unsigned char data; -}; - -int main() -{ - boost::python::type_object_base *o1, *o2, *o3; - -// POD1 * pod1; -// boost::python::detail::shared_pod_manager::create(pod1); - - o1 = new TestTypeObject; - o2 = new TestTypeObject; - o3 = new TestTypeObject; - - assert(boost::python::pod_instance_counter == 0); - - o1->enable(boost::python::type_object_base::number_add); - o1->enable(boost::python::type_object_base::compare); - - o2->enable(boost::python::type_object_base::number_add); - o2->enable(boost::python::type_object_base::mapping_length); - - o3->enable(boost::python::type_object_base::number_add); - o3->enable(boost::python::type_object_base::sequence_length); - - assert(boost::python::pod_instance_counter == 3); - assert(o1->tp_as_number && !o1->tp_as_mapping && !o1->tp_as_sequence); - assert(o2->tp_as_number && o2->tp_as_mapping && !o2->tp_as_sequence); - assert(o3->tp_as_number && !o3->tp_as_mapping && o3->tp_as_sequence); - assert(o1->tp_as_number == o2->tp_as_number); - assert(o1->tp_as_number == o3->tp_as_number); - assert((void*)o2->tp_as_number != o2->tp_as_mapping); - assert((void*)o2->tp_as_mapping != o3->tp_as_sequence); - - o1->enable(boost::python::type_object_base::number_subtract); - - assert(boost::python::pod_instance_counter == 4); - assert(o1->tp_as_number != o2->tp_as_number); - assert(o2->tp_as_number == o3->tp_as_number); - - o3->enable(boost::python::type_object_base::mapping_subscript); - - assert(boost::python::pod_instance_counter == 5); - assert(o3->tp_as_number && o3->tp_as_mapping && o3->tp_as_sequence); - assert(o2->tp_as_mapping != o3->tp_as_mapping); - - o2->enable(boost::python::type_object_base::mapping_subscript); - o3->enable(boost::python::type_object_base::mapping_length); - - assert(boost::python::pod_instance_counter == 4); - assert(o2->tp_as_number && o2->tp_as_mapping && !o2->tp_as_sequence); - assert(o3->tp_as_number && o3->tp_as_mapping && o3->tp_as_sequence); - assert(o2->tp_as_mapping == o3->tp_as_mapping); - - boost::python::type_object_base *o4 = new TestTypeObject; - - assert(boost::python::pod_instance_counter == 4); - - o4->enable(boost::python::type_object_base::number_add); - - assert(boost::python::pod_instance_counter == 4); - assert(o4->tp_as_number && !o4->tp_as_mapping && !o4->tp_as_sequence); - assert(o4->tp_as_number == o3->tp_as_number); - - delete o3; - - assert(boost::python::pod_instance_counter == 3); - assert(o1->tp_as_number && !o1->tp_as_mapping && !o1->tp_as_sequence); - assert(o2->tp_as_number && o2->tp_as_mapping && !o2->tp_as_sequence); - assert(o4->tp_as_number && !o4->tp_as_mapping && !o4->tp_as_sequence); - assert(o4->tp_as_number == o2->tp_as_number); - - o3 = new TestTypeObject; - - assert(boost::python::pod_instance_counter == 3); - - o3->enable(boost::python::type_object_base::number_add); - o3->enable(boost::python::type_object_base::sequence_length); - - assert(boost::python::pod_instance_counter == 4); - assert(o3->tp_as_number && !o3->tp_as_mapping && o3->tp_as_sequence); - assert(o1->tp_as_number != o3->tp_as_number); - assert(o2->tp_as_number == o3->tp_as_number); - - delete o1; - - assert(boost::python::pod_instance_counter == 3); - - delete o4; - - assert(boost::python::pod_instance_counter == 3); - - delete o3; - - assert(boost::python::pod_instance_counter == 2); - - delete o2; - - assert(boost::python::pod_instance_counter == 0); - - assert(boost::python::detail::shared_pod_manager::obj().m_storage.size() == 0); -} - -#endif diff --git a/todo.txt b/todo.txt deleted file mode 100644 index 3bcd16ac..00000000 --- a/todo.txt +++ /dev/null @@ -1,11 +0,0 @@ -Wrap enums as a subclass of Python int - -Write "inside the Python type system", a survey of typeobject.c in -Python source -- may go hand-in-hand with enum wrapping - -Better overload resolution - choose best match - -Implement type_info streaming for GCC -(http://mail.python.org/pipermail/c++-sig/2002-June/001277.html) - -