2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-26 18:52:26 +00:00

Compare commits

..

17 Commits

Author SHA1 Message Date
Dave Abrahams
0eb039a500 NULL shared_ptr conversions, more tests for custom to-python shared_ptr registrations
[SVN r18263]
2003-04-16 14:32:14 +00:00
nobody
ba3b0a7c5d This commit was manufactured by cvs2svn to create branch
'unlabeled-1.1.2'.

[SVN r17835]
2003-03-12 12:47:45 +00:00
Dave Abrahams
b990d7580d Changes for MPL v2
[SVN r13504]
2002-04-16 14:29:30 +00:00
nobody
536dbe28a6 This commit was manufactured by cvs2svn to create branch
'unlabeled-1.1.2'.

[SVN r13257]
2002-03-24 15:19:57 +00:00
Dave Abrahams
27f99ba783 no message
[SVN r10384]
2001-06-21 22:49:06 +00:00
nobody
4c30bb98f9 This commit was manufactured by cvs2svn to create branch
'unlabeled-1.1.2'.

[SVN r9436]
2001-03-04 19:00:43 +00:00
Ralf W. Grosse-Kunstleve
582dc47885 Makefile for Windows mingw32 (a gcc type compiler).
[SVN r9388]
2001-03-03 02:54:03 +00:00
Ralf W. Grosse-Kunstleve
5666c21037 Enhanced pickle safety measures.
[SVN r9358]
2001-02-27 18:56:57 +00:00
Ralf W. Grosse-Kunstleve
16264a3f2d Safer pickle support (explicit auto_pickle parameter)
[SVN r9313]
2001-02-22 20:47:36 +00:00
Ralf W. Grosse-Kunstleve
046fb553c5 map [plain] char '\0' <-> "" (Python string of length 0)
[SVN r9306]
2001-02-21 10:00:27 +00:00
Ralf W. Grosse-Kunstleve
3eb98f54a1 Mapping of std::complex<T> <-> Python complex.
[SVN r9305]
2001-02-21 08:01:54 +00:00
Ralf W. Grosse-Kunstleve
f1d4a38121 Added to/from_python converters for [plain] char.
Reverted to original converters for un/signed char.


[SVN r9046]
2001-02-09 03:31:32 +00:00
Ralf W. Grosse-Kunstleve
6d3b960cb7 -lm on link-line for comprehensive.so eliminates warning.
[SVN r9021]
2001-02-08 01:37:27 +00:00
Ralf W. Grosse-Kunstleve
2aed6f022e rational.hpp (used in comprehensive.cpp) requires -ftemplate-depth-21
[SVN r9020]
2001-02-08 01:35:55 +00:00
nobody
724c91b7b2 This commit was manufactured by cvs2svn to create branch
'unlabeled-1.1.2'.

[SVN r9018]
2001-02-07 23:58:45 +00:00
Ralf W. Grosse-Kunstleve
1e272b9c14 BPL support for exporting/importing class wrappers.
[SVN r8788]
2001-01-27 17:35:02 +00:00
nobody
2ceaa9133d This commit was manufactured by cvs2svn to create branch
'unlabeled-1.1.2'.

[SVN r8787]
2001-01-27 17:35:01 +00:00
29 changed files with 2313 additions and 180 deletions

2
build/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
Makefile
patch_tru64_to_gcc

36
build/Jamfile Normal file
View File

@@ -0,0 +1,36 @@
subproject libs/python/build ;
SOURCES = classes.cpp conversions.cpp extension_class.cpp functions.cpp
init_function.cpp module_builder.cpp
objects.cpp types.cpp cross_module.cpp ;
PYTHON_ROOT ?= c:/tools/python ;
PYTHON_INCLUDES = $(BOOST_ROOT) $(PYTHON_ROOT)$(SLASH)include ;
lib libboost_python : ../src/$(SOURCES) : <include>$(PYTHON_INCLUDES) <shared-linkable>true ;
rule boost-python
{
dll $(<) : $(>) :
$(3) <include>$(PYTHON_INCLUDES)
<msvc><library-path>$(PYTHON_ROOT)/libs
<gcc><*><library-file>$(PYTHON_ROOT)/libs/python20.lib
: $(4) ;
}
boost-python boost_python_test : <lib>libboost_python ../test/comprehensive.cpp ;
boost-python abstract : <lib>libboost_python ../example/abstract.cpp ;
boost-python getting_started1 : <lib>libboost_python ../example/getting_started1.cpp ;
boost-python getting_started2 : <lib>libboost_python ../example/getting_started2.cpp ;
boost-python simple_vector : <lib>libboost_python ../example/simple_vector.cpp ;
boost-python do_it_yourself_converters : <lib>libboost_python ../example/do_it_yourself_converters.cpp ;
boost-python pickle1 : <lib>libboost_python ../example/pickle1.cpp ;
boost-python pickle2 : <lib>libboost_python ../example/pickle2.cpp ;
boost-python pickle3 : <lib>libboost_python ../example/pickle3.cpp ;
boost-python noncopyable_export : <lib>libboost_python ../example/noncopyable_export.cpp ;
boost-python noncopyable_import : <lib>libboost_python ../example/noncopyable_import.cpp ;
boost-python ivect : <lib>libboost_python ../example/ivect.cpp ;
boost-python dvect : <lib>libboost_python ../example/dvect.cpp ;

194
build/Makefile.gcc Normal file
View File

@@ -0,0 +1,194 @@
# 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"
# Set the MYBOOST pathname 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
MYBOOST= /net/cci/rwgk/myboost
PYEXE= /usr/local/Python-1.5.2/bin/python
PYINC= -I/usr/local/Python-1.5.2/include/python1.5
#PYEXE= /usr/local/Python-2.0/bin/python
#PYINC= -I/usr/local/Python-2.0/include/python2.0
#STLPORTINC= -I/usr/local/STLport-4.1b3/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/usr/local/STLport-4.1b4/stlport
#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS
#STLPORTINC= -I/net/cci/xp/C++_C_headers
STDOPTS= -ftemplate-depth-21
WARNOPTS=
CPP= g++
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(MYBOOST) $(PYINC) \
$(STDOPTS) $(WARNOPTS) -g
LD= g++
LDOPTS= -shared
BPL_SRC = $(MYBOOST)/libs/python/src
BPL_TST = $(MYBOOST)/libs/python/test
BPL_EXA = $(MYBOOST)/libs/python/example
SOFTLINKS = \
$(BPL_SRC)/classes.cpp \
$(BPL_SRC)/conversions.cpp \
$(BPL_SRC)/extension_class.cpp \
$(BPL_SRC)/functions.cpp \
$(BPL_SRC)/import_extension_class.cpp \
$(BPL_SRC)/init_function.cpp \
$(BPL_SRC)/module_builder.cpp \
$(BPL_SRC)/objects.cpp \
$(BPL_SRC)/types.cpp \
$(BPL_TST)/comprehensive.cpp \
$(BPL_TST)/comprehensive.hpp \
$(BPL_TST)/comprehensive.py \
$(BPL_TST)/doctest.py \
$(BPL_EXA)/abstract.cpp \
$(BPL_EXA)/dvect.cpp \
$(BPL_EXA)/dvect.h \
$(BPL_EXA)/getting_started1.cpp \
$(BPL_EXA)/getting_started2.cpp \
$(BPL_EXA)/getting_started3.cpp \
$(BPL_EXA)/getting_started4.cpp \
$(BPL_EXA)/getting_started5.cpp \
$(BPL_EXA)/passing_char.cpp \
$(BPL_EXA)/cmplx.cpp \
$(BPL_EXA)/ivect.cpp \
$(BPL_EXA)/ivect.h \
$(BPL_EXA)/noncopyable_export.cpp \
$(BPL_EXA)/noncopyable_import.cpp \
$(BPL_EXA)/store.h \
$(BPL_EXA)/test_abstract.py \
$(BPL_EXA)/test_getting_started1.py \
$(BPL_EXA)/test_getting_started2.py \
$(BPL_EXA)/test_getting_started3.py \
$(BPL_EXA)/test_getting_started4.py \
$(BPL_EXA)/test_getting_started5.py \
$(BPL_EXA)/tst_passing_char.py \
$(BPL_EXA)/tst_cmplx.py \
$(BPL_EXA)/tst_dvect.py \
$(BPL_EXA)/tst_ivect.py \
$(BPL_EXA)/tst_noncopyable.py
OBJ = classes.o conversions.o extension_class.o functions.o \
import_extension_class.o init_function.o module_builder.o \
objects.o types.o
.SUFFIXES: .o .cpp
all: libbpl.a test.so abstract.so \
getting_started1.so getting_started2.so getting_started3.so \
getting_started4.so getting_started5.so \
passing_char.so cmplx.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so
softlinks:
@ for pn in $(SOFTLINKS); \
do \
bn=`basename "$$pn"`; \
if [ ! -e "$$bn" ]; then \
echo "ln -s $$pn ."; \
ln -s "$$pn" .; \
else \
echo "info: no softlink created (file exists): $$bn"; \
fi; \
done
unlink:
@ for pn in $(SOFTLINKS); \
do \
bn=`basename "$$pn"`; \
if [ -L "$$bn" ]; then \
echo "rm $$bn"; \
rm "$$bn"; \
elif [ -e "$$bn" ]; then \
echo "info: not a softlink: $$bn"; \
fi; \
done
libbpl.a: $(OBJ)
rm -f libbpl.a
ar r libbpl.a $(OBJ)
test.so: $(OBJ) comprehensive.o
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o 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
getting_started3.so: $(OBJ) getting_started3.o
$(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so
getting_started4.so: $(OBJ) getting_started4.o
$(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so
getting_started5.so: $(OBJ) getting_started5.o
$(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so
passing_char.so: $(OBJ) passing_char.o
$(LD) $(LDOPTS) $(OBJ) passing_char.o -o passing_char.so
cmplx.so: $(OBJ) cmplx.o
$(LD) $(LDOPTS) $(OBJ) cmplx.o -o cmplx.so -lm
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.cpp: ivect.h dvect.h
ivect.so: $(OBJ) ivect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
dvect.cpp: ivect.h dvect.h
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.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_getting_started3.py
$(PYEXE) test_getting_started4.py
$(PYEXE) test_getting_started5.py
clean:
rm -f $(OBJ) libbpl.a libbpl.a.input
rm -f comprehensive.o 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 getting_started3.o getting_started3.so
rm -f getting_started4.o getting_started4.so
rm -f getting_started5.o getting_started5.so
rm -f passing_char.o passing_char.so
rm -f cmplx.o cmplx.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 so_locations *.pyc
rm -rf cxx_repository

269
build/Makefile.mingw32 Normal file
View File

@@ -0,0 +1,269 @@
# 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"
# Set the MYBOOST_* pathnames below.
#
# The idea is that the build directory is on a Unix filesystem that
# is mounted on a PC using SAMBA. Use this makefile under both Unix
# and Windows:
#
# Unix: make softlinks Create softlinks to source code and tests
# Win: make Compile all sources
# Win: make test Run doctest tests
# Unix: make clean Remove all object files
# Unix: make unlink Remove softlinks
# 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.
# Could this be fixed with compiler options?
MYBOOST_UNIX= /net/cci/rwgk/myboost
MYBOOST_WIN= "L:\myboost"
PYEXE= "C:\Program files\Python\python.exe"
PYINC= -I"C:\usr\include\python1.5"
PYLIB= "C:\usr\lib\libpython15.a"
STDOPTS= -ftemplate-depth-21
WARNOPTS=
CPP= g++
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(MYBOOST_WIN) $(PYINC) \
$(STDOPTS) $(WARNOPTS) -g
LD= g++
LDOPTS= -shared
BPL_SRC = $(MYBOOST_UNIX)/libs/python/src
BPL_TST = $(MYBOOST_UNIX)/libs/python/test
BPL_EXA = $(MYBOOST_UNIX)/libs/python/example
SOFTLINKS = \
$(BPL_SRC)/classes.cpp \
$(BPL_SRC)/conversions.cpp \
$(BPL_SRC)/extension_class.cpp \
$(BPL_SRC)/functions.cpp \
$(BPL_SRC)/import_extension_class.cpp \
$(BPL_SRC)/init_function.cpp \
$(BPL_SRC)/module_builder.cpp \
$(BPL_SRC)/objects.cpp \
$(BPL_SRC)/types.cpp \
$(BPL_TST)/comprehensive.cpp \
$(BPL_TST)/comprehensive.hpp \
$(BPL_TST)/comprehensive.py \
$(BPL_TST)/doctest.py \
$(BPL_EXA)/abstract.cpp \
$(BPL_EXA)/dvect.cpp \
$(BPL_EXA)/dvect.h \
$(BPL_EXA)/getting_started1.cpp \
$(BPL_EXA)/getting_started2.cpp \
$(BPL_EXA)/getting_started3.cpp \
$(BPL_EXA)/getting_started4.cpp \
$(BPL_EXA)/getting_started5.cpp \
$(BPL_EXA)/passing_char.cpp \
$(BPL_EXA)/cmplx.cpp \
$(BPL_EXA)/ivect.cpp \
$(BPL_EXA)/ivect.h \
$(BPL_EXA)/noncopyable_export.cpp \
$(BPL_EXA)/noncopyable_import.cpp \
$(BPL_EXA)/store.h \
$(BPL_EXA)/test_abstract.py \
$(BPL_EXA)/test_getting_started1.py \
$(BPL_EXA)/test_getting_started2.py \
$(BPL_EXA)/test_getting_started3.py \
$(BPL_EXA)/test_getting_started4.py \
$(BPL_EXA)/test_getting_started5.py \
$(BPL_EXA)/tst_passing_char.py \
$(BPL_EXA)/tst_cmplx.py \
$(BPL_EXA)/tst_dvect.py \
$(BPL_EXA)/tst_ivect.py \
$(BPL_EXA)/tst_noncopyable.py
DEFS= \
test \
abstract \
getting_started1 \
getting_started2 \
getting_started3 \
getting_started4 \
getting_started5 \
passing_char \
cmplx \
noncopyable_export \
noncopyable_import \
ivect \
dvect
OBJ = classes.o conversions.o extension_class.o functions.o \
import_extension_class.o init_function.o module_builder.o \
objects.o types.o
.SUFFIXES: .o .cpp
all: libbpl.a test.pyd abstract.pyd \
getting_started1.pyd getting_started2.pyd getting_started3.pyd \
getting_started4.pyd getting_started5.pyd \
passing_char.pyd cmplx.pyd \
noncopyable_export.pyd noncopyable_import.pyd \
ivect.pyd dvect.pyd
softlinks: defs
@ for pn in $(SOFTLINKS); \
do \
bn=`basename "$$pn"`; \
if [ ! -e "$$bn" ]; then \
echo "ln -s $$pn ."; \
ln -s "$$pn" .; \
else \
echo "info: no softlink created (file exists): $$bn"; \
fi; \
done
unlink: rmdefs
@ for pn in $(SOFTLINKS); \
do \
bn=`basename "$$pn"`; \
if [ -L "$$bn" ]; then \
echo "rm $$bn"; \
rm "$$bn"; \
elif [ -e "$$bn" ]; then \
echo "info: not a softlink: $$bn"; \
fi; \
done
defs:
@ for def in $(DEFS); \
do \
echo "EXPORTS\n\tinit$$def" > $$def.def; \
done
rmdefs:
@ for def in $(DEFS); \
do \
rm $$def.def; \
done
libbpl.a: $(OBJ)
del libbpl.a
ar r libbpl.a $(OBJ)
DLLWRAPOPTS= --driver-name g++ -s \
--entry _DllMainCRTStartup@12 --target=i386-mingw32
test.pyd: $(OBJ) comprehensive.o
dllwrap $(DLLWRAPOPTS) \
--dllname test.pyd \
--def 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)
getting_started3.pyd: $(OBJ) getting_started3.o
dllwrap $(DLLWRAPOPTS) \
--dllname getting_started3.pyd \
--def getting_started3.def \
$(OBJ) getting_started3.o $(PYLIB)
getting_started4.pyd: $(OBJ) getting_started4.o
dllwrap $(DLLWRAPOPTS) \
--dllname getting_started4.pyd \
--def getting_started4.def \
$(OBJ) getting_started4.o $(PYLIB)
getting_started5.pyd: $(OBJ) getting_started5.o
dllwrap $(DLLWRAPOPTS) \
--dllname getting_started5.pyd \
--def getting_started5.def \
$(OBJ) getting_started5.o $(PYLIB)
passing_char.pyd: $(OBJ) passing_char.o
dllwrap $(DLLWRAPOPTS) \
--dllname passing_char.pyd \
--def passing_char.def \
$(OBJ) passing_char.o $(PYLIB)
cmplx.pyd: $(OBJ) cmplx.o
dllwrap $(DLLWRAPOPTS) \
--dllname cmplx.pyd \
--def cmplx.def \
$(OBJ) cmplx.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.cpp: ivect.h dvect.h
ivect.pyd: $(OBJ) ivect.o
dllwrap $(DLLWRAPOPTS) \
--dllname ivect.pyd \
--def ivect.def \
$(OBJ) ivect.o $(PYLIB)
dvect.cpp: ivect.h dvect.h
dvect.pyd: $(OBJ) dvect.o
dllwrap $(DLLWRAPOPTS) \
--dllname dvect.pyd \
--def dvect.def \
$(OBJ) dvect.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_getting_started3.py
$(PYEXE) test_getting_started4.py
$(PYEXE) test_getting_started5.py
clean:
rm -f $(OBJ) libbpl.a libbpl.a.input
rm -f comprehensive.o test.pyd
rm -f abstract.o abstract.pyd
rm -f getting_started1.o getting_started1.pyd
rm -f getting_started2.o getting_started2.pyd
rm -f getting_started3.o getting_started3.pyd
rm -f getting_started4.o getting_started4.pyd
rm -f getting_started5.o getting_started5.pyd
rm -f passing_char.o passing_char.pyd
rm -f cmplx.o cmplx.pyd
rm -f noncopyable_export.o noncopyable_export.pyd
rm -f noncopyable_import.o noncopyable_import.pyd
rm -f ivect.o ivect.pyd
rm -f dvect.o dvect.pyd
rm -f so_locations *.pyc
rm -rf cxx_repository

199
build/Makefile.tru64 Normal file
View File

@@ -0,0 +1,199 @@
# 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"
# Set the MYBOOST pathname 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
MYBOOST= /net/cci/rwgk/myboost
PYEXE= /usr/local/Python-1.5.2/bin/python
PYINC= -I/usr/local/Python-1.5.2/include/python1.5
#PYEXE= /usr/local/Python-2.0/bin/python
#PYINC= -I/usr/local/Python-2.0/include/python2.0
#STLPORTINC= -I/usr/local/STLport-4.1b3/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/usr/local/STLport-4.1b4/stlport
#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS
STLPORTINC= -I/net/cci/xp/C++_C_headers
STDOPTS= -std strict_ansi
WARNOPTS= -msg_disable 186,450,1115
# use -msg_display_number to obtain integer tags for -msg_disable
CPP= cxx
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(MYBOOST) $(PYINC) \
$(STDOPTS) $(WARNOPTS) -g
LD= cxx
LDOPTS= -shared -expect_unresolved 'Py*' -expect_unresolved '_Py*'
#HIDDEN= -hidden
BPL_SRC = $(MYBOOST)/libs/python/src
BPL_TST = $(MYBOOST)/libs/python/test
BPL_EXA = $(MYBOOST)/libs/python/example
SOFTLINKS = \
$(BPL_SRC)/classes.cpp \
$(BPL_SRC)/conversions.cpp \
$(BPL_SRC)/extension_class.cpp \
$(BPL_SRC)/functions.cpp \
$(BPL_SRC)/import_extension_class.cpp \
$(BPL_SRC)/init_function.cpp \
$(BPL_SRC)/module_builder.cpp \
$(BPL_SRC)/objects.cpp \
$(BPL_SRC)/types.cpp \
$(BPL_TST)/comprehensive.cpp \
$(BPL_TST)/comprehensive.hpp \
$(BPL_TST)/comprehensive.py \
$(BPL_TST)/doctest.py \
$(BPL_EXA)/abstract.cpp \
$(BPL_EXA)/dvect.cpp \
$(BPL_EXA)/dvect.h \
$(BPL_EXA)/getting_started1.cpp \
$(BPL_EXA)/getting_started2.cpp \
$(BPL_EXA)/getting_started3.cpp \
$(BPL_EXA)/getting_started4.cpp \
$(BPL_EXA)/getting_started5.cpp \
$(BPL_EXA)/passing_char.cpp \
$(BPL_EXA)/cmplx.cpp \
$(BPL_EXA)/ivect.cpp \
$(BPL_EXA)/ivect.h \
$(BPL_EXA)/noncopyable_export.cpp \
$(BPL_EXA)/noncopyable_import.cpp \
$(BPL_EXA)/store.h \
$(BPL_EXA)/test_abstract.py \
$(BPL_EXA)/test_getting_started1.py \
$(BPL_EXA)/test_getting_started2.py \
$(BPL_EXA)/test_getting_started3.py \
$(BPL_EXA)/test_getting_started4.py \
$(BPL_EXA)/test_getting_started5.py \
$(BPL_EXA)/tst_passing_char.py \
$(BPL_EXA)/tst_cmplx.py \
$(BPL_EXA)/tst_dvect.py \
$(BPL_EXA)/tst_ivect.py \
$(BPL_EXA)/tst_noncopyable.py
OBJ = classes.o conversions.o extension_class.o functions.o \
import_extension_class.o init_function.o module_builder.o \
objects.o types.o
.SUFFIXES: .o .cpp
all: libbpl.a test.so abstract.so \
getting_started1.so getting_started2.so getting_started3.so \
getting_started4.so getting_started5.so \
passing_char.so cmplx.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so
softlinks:
@ for pn in $(SOFTLINKS); \
do \
bn=`basename "$$pn"`; \
if [ ! -e "$$bn" ]; then \
echo "ln -s $$pn ."; \
ln -s "$$pn" .; \
else \
echo "info: no softlink created (file exists): $$bn"; \
fi; \
done
unlink:
@ for pn in $(SOFTLINKS); \
do \
bn=`basename "$$pn"`; \
if [ -L "$$bn" ]; then \
echo "rm $$bn"; \
rm "$$bn"; \
elif [ -e "$$bn" ]; then \
echo "info: not a softlink: $$bn"; \
fi; \
done
libbpl.a: $(OBJ)
rm -f libbpl.a
ls -1 ./cxx_repository/*.o > libbpl.a.input
ar r libbpl.a $(OBJ) -input libbpl.a.input
rm -f libbpl.a.input
test.so: $(OBJ) comprehensive.o
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o 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
getting_started3.so: $(OBJ) getting_started3.o
$(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so
getting_started4.so: $(OBJ) getting_started4.o
$(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so
getting_started5.so: $(OBJ) getting_started5.o
$(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so
passing_char.so: $(OBJ) passing_char.o
$(LD) $(LDOPTS) $(OBJ) passing_char.o -o passing_char.so
cmplx.so: $(OBJ) cmplx.o
$(LD) $(LDOPTS) $(OBJ) cmplx.o -o cmplx.so -lm
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.cpp: ivect.h dvect.h
ivect.so: $(OBJ) ivect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
dvect.cpp: ivect.h dvect.h
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.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_getting_started3.py
$(PYEXE) test_getting_started4.py
$(PYEXE) test_getting_started5.py
clean:
rm -f $(OBJ) libbpl.a libbpl.a.input
rm -f comprehensive.o 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 getting_started3.o getting_started3.so
rm -f getting_started4.o getting_started4.so
rm -f getting_started5.o getting_started5.so
rm -f passing_char.o passing_char.so
rm -f cmplx.o cmplx.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 so_locations *.pyc
rm -rf cxx_repository

223
doc/pickle.html Normal file
View File

@@ -0,0 +1,223 @@
<html>
<head>
<title>BPL Pickle Support</title>
</head>
<body>
<img src="../../../c++boost.gif"
alt="c++boost.gif (8819 bytes)"
align="center"
width="277" height="86">
</body>
<hr>
<h1>BPL Pickle Support</h1>
Pickle is a Python module for object serialization, also known
as persistence, marshalling, or flattening.
<p>
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.
<p>
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
(<a href="http://www.zope.org/">http://www.zope.org/</a>).
This interface is similar to that for regular Python classes as
described in detail in the Python Library Reference for pickle:
<blockquote>
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
>http://www.python.org/doc/current/lib/module-pickle.html</a>
</blockquote>
<hr>
<h1>The BPL Pickle Interface</h1>
At the user level, the BPL pickle interface involves three special
methods:
<dl>
<dt>
<strong>__getinitargs__</strong>
<dd>
When an instance of a BPL extension class is pickled, the pickler
tests if the instance has a __getinitargs__ method. This method must
return a Python tuple. When the instance is restored by the
unpickler, the contents of this tuple are used as the arguments for
the class constructor.
<p>
If __getinitargs__ is not defined, the class constructor will be
called without arguments.
<p>
<dt>
<strong>__getstate__</strong>
<dd>
When an instance of a BPL 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.
<p>
If __getstate__ is not defined, the instance's __dict__ is pickled
(if it is not empty).
<p>
<dt>
<strong>__setstate__</strong>
<dd>
When an instance of a BPL 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.
<p>
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__.
</dl>
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.
<hr>
<h1>Pitfalls and Safety Guards</h1>
In BPL 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 BPL 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 BPL
extension module might not be aware of:
<dl>
<dt>
<strong>Pitfall 1:</strong>
Both __getinitargs__ and __getstate__ are not defined.
<dd>
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.
<p>
However, most C++ classes wrapped with the BPL 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, the BPL tests if the class has an
attribute __dict_defines_state__. An exception is raised if this
attribute is not defined:
<pre>
RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
</pre>
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.:
<pre>
class_builder<your_class> py_your_class(your_module, "your_class");
py_your_class.dict_defines_state();
</pre>
It is also possible to override the safety guard at the Python level.
E.g.:
<pre>
import your_bpl_module
class your_class(your_bpl_module.your_class):
__dict_defines_state__ = 1
</pre>
<p>
<dt>
<strong>Pitfall 2:</strong>
__getstate__ is defined and the instance's __dict__ is not empty.
<dd>
The author of a BPL extension class might provide a __getstate__
method without considering the possibilities that:
<p>
<ul>
<li>
his class is used 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.
<p>
<li>
the user adds items to the instance's __dict__ directly. Again,
the __dict__ of the instance then needs to be pickled.
</ul>
<p>
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, the BPL tests if the class has an attribute
__getstate_manages_dict__. An exception is raised if this attribute
is not defined:
<pre>
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
</pre>
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++:
<pre>
class_builder<your_class> py_your_class(your_module, "your_class");
py_your_class.getstate_manages_dict();
</pre>
In Python:
<pre>
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
</pre>
</dl>
<hr>
<h1>Practical Advice</h1>
<ul>
<li>
Avoid using __getstate__ if the instance can also be reconstructed
by way of __getinitargs__. This automatically avoids Pitfall 2.
<p>
<li>
If __getstate__ is required, include the instance's __dict__ in the
Python object that is returned.
</ul>
<hr>
<address>
Author: Ralf W. Grosse-Kunstleve, March 2001
</address>
</html>

6
example/README Normal file
View File

@@ -0,0 +1,6 @@
To get started with the Boost Python Library, use the examples
getting_started?.cpp and abstract.cpp.
The files example1.cpp and rwgk1.cpp are obsolete. They are only
included because the makefiles in the build directory still refer to
them. This will be fixed later.

34
example/abstract.cpp Normal file
View File

@@ -0,0 +1,34 @@
// Example by Ullrich Koethe
#include "boost/python/class_builder.hpp"
#include <string>
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<std::string>::call_method(m_self, "test");
}
PyObject * m_self;
};
extern "C"
DL_EXPORT(void)
initabstract()
{
boost::python::module_builder a("abstract");
boost::python::class_builder<Abstract, Abstract_callback>
a_class(a, "Abstract");
a_class.def(boost::python::constructor<>()); // wrap a constructor
a_class.def(&Abstract::test, "test");
}

42
example/cmplx.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include <iostream>
#include <complex>
namespace { // Avoid cluttering the global namespace.
std::complex<double> dpolar(double rho, double theta) {
return std::polar(rho, theta);
}
double dreal(const std::complex<double>& c) { return c.real(); }
double dimag(std::complex<double> c) { return c.imag(); }
std::complex<float> fpolar(float rho, float theta) {
return std::polar(rho, theta);
}
double freal(const std::complex<float>& c) { return c.real(); }
double fimag(std::complex<float> c) { return c.imag(); }
}
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
extern "C"
DL_EXPORT(void)
initcmplx()
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("cmplx");
this_module.def(dpolar, "dpolar");
this_module.def(dreal, "dreal");
this_module.def(dimag, "dimag");
this_module.def(fpolar, "fpolar");
this_module.def(freal, "freal");
this_module.def(fimag, "fimag");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -0,0 +1,32 @@
#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; }
}
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
extern "C"
DL_EXPORT(void)
initgetting_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(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -0,0 +1,51 @@
#include <iostream>
#include <string>
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class world
{
private:
std::string country;
public:
world(const std::string& country) { this->country = country; }
std::string greet() const { return "Hello from " + country + "!"; }
};
// A function taking a world object as an argument.
std::string invite(const world& w) {
return w.greet() + " Please come soon!";
}
}
extern "C"
DL_EXPORT(void)
initgetting_started2()
{
try
{
// 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<world> world_class(this_module, "world");
// Add the __init__ function.
world_class.def(python::constructor<std::string>());
// Add a regular member function.
world_class.def(&world::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 world_class!!!
world_class.def(invite, "invite");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -0,0 +1,147 @@
/*
This example shows how to make an Extension Class "pickleable".
Python's pickle module implements a basic but powerful algorithm
for "pickling" (a.k.a. serializing, marshalling or flattening)
nearly arbitrary Python objects.
The user can influence how an Extension Class instance is pickled
by defining three special methods: __getinitargs__(),
__getstate__(), and __setstate(). This interface is similar to
that for regular Python classes as described in detail in the
Python Library Reference for pickle:
http://www.python.org/doc/current/lib/module-pickle.html
When an Extension Class instance is pickled, __getinitargs__() is
called, if implemented. This method should return a tuple
containing the arguments to be passed to the class constructor when
the object is restored.
If there is no __getstate__() method, the instance's __dict__ is
pickled if it is not empty. If __getstate__() is defined, it should
return an object representing the state of the instance.
If there is no __setstate__() method, __getstate__() must return a
dictionary. When the instance is restored, the items in this dictionary
are added to the instance's __dict__.
If the Extension Class defines __setstate__(), the pickle loader
calls it with the result of __getstate__() as arguments. In this
case, the state object need not be a dictionary. The
__getstate__() and __setstate__() methods can do what they want.
If both __getinitargs__() and __getstate__() are defined, the
instance is restored by first calling the constructor with
the result of __getinitargs__() as argument. After the instance
is reconstructed, the __dict__ is updated or __setstate__() is
called if implemented.
The mechanism described here is an exact replication of that one
implemented by Jim Fulton's ExtensionClass (included in Zope 2.2.2).
*/
#include <iostream>
#include <string>
#include <boost/python/class_builder.hpp>
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; }
void set_secret_number(int number) { secret_number = number; }
int get_secret_number() const { return secret_number; }
};
// Support for pickle.
python::tuple world_getinitargs(const world& w) {
python::tuple result(1);
result.set_item(0, w.get_country());
return result;
}
python::tuple world_getstate(const world& w) {
python::tuple result(1);
result.set_item(0, w.get_secret_number());
return result;
}
void world_setstate(world& w, python::tuple state) {
if (state.size() != 1) {
PyErr_SetString(PyExc_ValueError,
"Unexpected argument in call to __setstate__.");
throw python::error_already_set();
}
int number = BOOST_PYTHON_CONVERSION::from_python(state[0].get(),
python::type<int>());
if (number != 42)
w.set_secret_number(number);
}
template <class T>
class a_number {
private:
T m_number;
public:
a_number() : m_number(0) {}
a_number(T number) : m_number(number) {}
const T get() const { return m_number; }
};
}
extern "C"
DL_EXPORT(void)
initgetting_started3()
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("getting_started3");
// Create the Python type object for our extension class.
python::class_builder<world> world_class(this_module, "world");
// Add the __init__ function.
world_class.def(python::constructor<std::string>());
// 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__");
// This Python class has no pickle support.
python::class_builder<a_number<int> >
py_a_lame_number(this_module, "a_lame_number");
py_a_lame_number.def(python::constructor<>());
py_a_lame_number.def(python::constructor<int>());
py_a_lame_number.def(&a_number<int>::get, "get");
// Enable pickling of the object's __dict__.
python::class_builder<a_number<double> >
py_a_number(this_module, "a_number");
py_a_number.dict_defines_state();
py_a_number.def(python::constructor<>());
py_a_number.def(python::constructor<double>());
py_a_number.def(&a_number<double>::get, "get");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -0,0 +1,104 @@
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
namespace { // Avoid cluttering the global namespace.
// A wrapper is used to define additional constructors.
//
struct vector_double_wrapper: std::vector<double>
{
// Tell the compiler how to convert a base class object to
// this wrapper object.
vector_double_wrapper(PyObject*, const std::vector<double>& vd)
: std::vector<double>(vd) {}
vector_double_wrapper(PyObject* self)
: std::vector<double>() {}
vector_double_wrapper(PyObject* self, const int n)
: std::vector<double>(n) {}
vector_double_wrapper(PyObject* self, python::tuple tuple)
: std::vector<double>(tuple.size())
{
std::vector<double>::iterator vd = begin();
for (int i = 0; i < tuple.size(); i++)
vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
python::type<double>());
}
};
double getitem(const std::vector<double>& vd, const std::size_t key) {
return vd[key];
}
void setitem(std::vector<double>& vd, const std::size_t key,
const double &d) {
std::vector<double>::iterator vditer = vd.begin();
vditer[key] = d;
}
void delitem(std::vector<double>& vd, const std::size_t key) {
std::vector<double>::iterator vditer = vd.begin();
vd.erase(&vditer[key]);
}
// Convert vector_double to a regular Python tuple.
//
python::tuple as_tuple(const std::vector<double>& 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<double> foo(const int n)
{
std::vector<double> vd(n);
std::vector<double>::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<std::vector<double> > bar(const int n)
{
std::auto_ptr<std::vector<double> > vdptr(new std::vector<double>(n));
std::vector<double>::iterator vditer = vdptr->begin();
for (int i = 0; i < n; i++) vditer[i] = double(10 * i);
return vdptr;
}
}
extern "C"
DL_EXPORT(void)
initgetting_started4()
{
try
{
python::module_builder this_module("getting_started4");
python::class_builder<std::vector<double>, vector_double_wrapper>
vector_double(this_module, "vector_double");
vector_double.def(python::constructor<>());
vector_double.def(python::constructor<const int>());
vector_double.def(python::constructor<python::tuple>());
vector_double.def(&std::vector<double>::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");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

52
example/passing_char.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include <iostream>
namespace { // Avoid cluttering the global namespace.
// In C++, char, signed char and unsigned char are three distinct types.
// The Boost Python Library maps signed & unsigned char to
// Python integers. Plain char is mapped to a Python string with
// exactly one character.
// Plain char.
char get_char() { return 'ÿ'; }
void use_char(char c) {
std::cout << c << std::endl;
}
// signed char.
signed char get_signed_char() { return -128; }
void use_signed_char(signed char c) {
std::cout << c << " " << static_cast<int>(c) << std::endl;
}
// unsigned char.
unsigned char get_unsigned_char() { return 128; }
void use_unsigned_char(unsigned char c) {
std::cout << c << " " << static_cast<unsigned int>(c) << std::endl;
}
}
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
extern "C"
DL_EXPORT(void)
initpassing_char()
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("passing_char");
this_module.def(get_char, "get_char");
this_module.def(use_char, "use_char");
this_module.def(get_signed_char, "get_signed_char");
this_module.def(use_signed_char, "use_signed_char");
this_module.def(get_unsigned_char, "get_unsigned_char");
this_module.def(use_unsigned_char, "use_unsigned_char");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

23
example/test_abstract.py Normal file
View File

@@ -0,0 +1,23 @@
# 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
doctest.testmod(test_abstract)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,17 @@
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
doctest.testmod(test_getting_started1)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,19 @@
r'''>>> import getting_started2
>>> w = getting_started2.world('California')
>>> print w.greet()
Hello from California!
>>> print getting_started2.invite(w)
Hello from California! Please come soon!
>>> print w.invite()
Hello from California! Please come soon!
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started2
doctest.testmod(test_getting_started2)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,56 @@
r'''>>> import getting_started3
>>> import re
>>> import pickle
>>> getting_started3.world.__module__
'getting_started3'
>>> getting_started3.world.__safe_for_unpickling__
1
>>> getting_started3.world.__reduce__()
'world'
>>> assert re.match(
... "\(<extension class getting_started3.world at [0-9a-fA-FxX]+>, \('Hello',\), \(0,\)\)",
... repr(getting_started3.world('Hello').__reduce__()))
>>>
>>> for number in (24, 42):
... wd = getting_started3.world('California')
... wd.set_secret_number(number)
... pstr = pickle.dumps(wd)
... print pstr
... wl = pickle.loads(pstr)
... print wd.greet(), wd.get_secret_number()
... print wl.greet(), wl.get_secret_number()
cgetting_started3
world
p0
(S'California'
p1
tp2
R(I24
tp3
bp4
.
Hello from California! 24
Hello from California! 24
cgetting_started3
world
p0
(S'California'
p1
tp2
R(I42
tp3
bp4
.
Hello from California! 42
Hello from California! 0
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started3
doctest.testmod(test_getting_started3)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,35 @@
r'''>>> import getting_started4
>>> v=getting_started4.vector_double()
>>> print v.as_tuple()
()
>>> v=getting_started4.vector_double(5)
>>> print v.as_tuple()
(0.0, 0.0, 0.0, 0.0, 0.0)
>>> print len(v)
5
>>> v=getting_started4.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)
>>> del v[1]
>>> print v.as_tuple()
(3.0, 5.0)
>>> print getting_started4.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 getting_started4.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_getting_started4
doctest.testmod(test_getting_started4)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,22 @@
r'''>>> import getting_started5
>>> ixset = getting_started5.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_getting_started5
doctest.testmod(test_getting_started5)
if __name__ == '__main__':
run()

20
example/tst_cmplx.py Normal file
View File

@@ -0,0 +1,20 @@
import cmplx
c = cmplx.dpolar(1, 1)
print c
print cmplx.dreal(c)
print cmplx.dimag(c)
c = cmplx.fpolar(1, 1)
print c
print cmplx.freal(c)
print cmplx.fimag(c)
print cmplx.dreal(c)
print cmplx.dimag(c)
try:
cmplx.freal("")
except TypeError:
pass
else:
raise SystemError

View File

@@ -0,0 +1,20 @@
import passing_char
print passing_char.get_char()
print passing_char.get_signed_char()
print passing_char.get_unsigned_char()
for arg in (-97, 97, -140, 140, "a", "ab", ""):
try:
print 'char', arg, ':'
passing_char.use_char(arg)
except (TypeError, ValueError), e:
print e.args[0]
try:
print 'signed char', arg, ':'
passing_char.use_signed_char(arg)
except (TypeError, ValueError), e:
print e.args[0]
try:
print 'unsigned char', arg, ':'
passing_char.use_unsigned_char(arg)
except (TypeError, ValueError), e:
print e.args[0]

View File

@@ -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 ARGS_DWA2002323_HPP
# define ARGS_DWA2002323_HPP
# include <boost/mpl/list.hpp>
# include <boost/preprocessor/enum_params_with_a_default.hpp>
# include <boost/preprocessor/enum_params.hpp>
namespace boost { namespace python {
// A type list for specifying arguments
template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_LIMIT_LIST_SIZE, typename A, ::boost::mpl::aux::none) >
struct args : ::boost::mpl::list< BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_LIST_SIZE,A) >::type
{};
}} // namespace boost::python
#endif // ARGS_DWA2002323_HPP

View File

@@ -0,0 +1,60 @@
// 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 BASES_DWA2002321_HPP
# define BASES_DWA2002321_HPP
# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/list.hpp>
# include <boost/mpl/select_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/preprocessor/enum_params_with_a_default.hpp>
# include <boost/preprocessor/enum_params.hpp>
namespace boost { namespace python {
// A type list for specifying bases
template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_LIMIT_LIST_SIZE, typename B, ::boost::mpl::aux::none) >
struct bases : ::boost::mpl::list< BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_LIST_SIZE,B) >
{};
namespace detail
{
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T> struct specifies_bases
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template < BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_LIST_SIZE,class B) >
struct specifies_bases< bases< BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_LIST_SIZE,B) > >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
# else
template < BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_LIST_SIZE,class B) >
static char is_bases_helper(bases< BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_LIST_SIZE,B) > const&);
static char (& is_bases_helper(...) )[256];
template <class T> struct specifies_bases
{
private:
static typename add_reference<T>::type make();
BOOST_STATIC_CONSTANT(bool, non_ref = !is_reference<T>::value);
public:
BOOST_STATIC_CONSTANT(bool, value = non_ref & (sizeof(is_bases_helper(make())) == 1));
};
# endif
template <class T, class Prev = bases<> >
struct select_bases
: mpl::select_if_c<
specifies_bases<T>::value
, T
, Prev
>
{
};
}
}} // namespace boost::python
#endif // BASES_DWA2002321_HPP

View File

@@ -0,0 +1,361 @@
#ifndef IMPORT_EXTENSION_CLASS_HPP_
# define IMPORT_EXTENSION_CLASS_HPP_
# include <boost/python/class_builder.hpp>
//QUESTIONMARK
// Do we really need the special PyCvtsObject?
// Is there a better way of creating the special PyCvtsObject?
// My solution adds a lot of code including several reinterpret_cast.
//#define SPECIAL_PYCVTSOBJECT
namespace boost { namespace python {
struct import_error : error_already_set {};
struct export_error : error_already_set {};
}}
namespace boost { namespace python { namespace detail {
// Concept: throw exception if api_major is changed
// show warning on stderr if api_minor is changed
const int EXPORT_CONVERTERS_API_MAJOR = 1;
const int EXPORT_CONVERTERS_API_MINOR = 1;
const std::string converters_attribute_name = "__converters__";
#ifndef SPECIAL_PYCVTSOBJECT
void *import_converters(const std::string& module_name,
const std::string& klass_name,
const std::string& attribute_name);
#else
PyObject *new_import_converters(const std::string& module_name,
const std::string& klass_name,
const std::string& attribute_name);
#endif
void check_export_converters_api(const int importing_major,
const int importing_minor,
const int imported_major,
const int imported_minor);
}}}
// forward declaration
namespace boost { namespace python { namespace detail {
template <class T> class import_extension_class;
}}}
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
//QUESTIONMARK
// This class is a look-alike of class python_extension_class_converters.
// Is there a way to ensure that the siblings stay in sync?
template <class T>
class python_import_extension_class_converters
{
public:
friend python_import_extension_class_converters py_extension_class_converters(boost::python::type<T>)
{
return python_import_extension_class_converters();
}
PyObject* to_python(const T& x) const
{
return boost::python::detail::import_extension_class<T>::get_converters()->to_python(x);
}
friend T* from_python(PyObject* obj, boost::python::type<T*>)
{
return boost::python::detail::import_extension_class<T>::get_converters()->Tptr_from_python(obj);
}
// Convert to const T*
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
{ return from_python(p, boost::python::type<T*>()); }
// Convert to const T* const&
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
{ return from_python(p, boost::python::type<const T*>()); }
// Convert to T* const&
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
{ return from_python(p, boost::python::type<T*>()); }
// Convert to T&
friend T& from_python(PyObject* p, boost::python::type<T&>)
{ return *boost::python::detail::check_non_null(from_python(p, boost::python::type<T*>())); }
// Convert to const T&
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
{ return from_python(p, boost::python::type<T&>()); }
// Convert to T
friend const T& from_python(PyObject* p, boost::python::type<T>)
{ return from_python(p, boost::python::type<T&>()); }
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>) {
return boost::python::detail::import_extension_class<T>::get_converters()->auto_ptr_from_python(p);
}
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >) {
return boost::python::detail::import_extension_class<T>::get_converters()->auto_ptr_from_python(p);
}
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>) {
return boost::python::detail::import_extension_class<T>::get_converters()->auto_ptr_from_python(p);
}
friend PyObject* to_python(std::auto_ptr<T> x) {
return boost::python::detail::import_extension_class<T>::get_converters()->to_python(x);
}
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>) {
return boost::python::detail::import_extension_class<T>::get_converters()->shared_ptr_from_python(p);
}
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >) {
return boost::python::detail::import_extension_class<T>::get_converters()->shared_ptr_from_python(p);
}
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>) {
return boost::python::detail::import_extension_class<T>::get_converters()->shared_ptr_from_python(p);
}
friend PyObject* to_python(boost::shared_ptr<T> x) {
return boost::python::detail::import_extension_class<T>::get_converters()->to_python(x);
}
};
BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python {
BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters);
// A pointer to this class is exported/imported via the Python API.
// All functions are virtual. This is, what we really export/import
// is essentially just a pointer to a vtbl.
template <class T>
struct export_converters_base
{
virtual const int get_api_major() const {
return detail::EXPORT_CONVERTERS_API_MAJOR; }
virtual const int get_api_minor() const {
return detail::EXPORT_CONVERTERS_API_MINOR; }
virtual PyObject *to_python(const T& x) = 0;
virtual PyObject *to_python(std::auto_ptr<T> x) = 0;
virtual PyObject *to_python(boost::shared_ptr<T> x) = 0;
virtual T* Tptr_from_python(PyObject* obj) = 0;
virtual std::auto_ptr<T>& auto_ptr_from_python(PyObject *obj) = 0;
virtual boost::shared_ptr<T>& shared_ptr_from_python(PyObject *obj) = 0;
};
// Converters to be used if T is not copyable.
template <class T>
struct export_ptr_converters : export_converters_base<T>
{
virtual PyObject *to_python(const T& x) {
PyErr_SetString(PyExc_RuntimeError,
"to_python(const T&) converter not exported");
throw import_error();
}
virtual PyObject *to_python(std::auto_ptr<T> x) {
return BOOST_PYTHON_CONVERSION::to_python(x);
}
virtual PyObject *to_python(boost::shared_ptr<T> x) {
return BOOST_PYTHON_CONVERSION::to_python(x);
}
virtual T* Tptr_from_python(PyObject* obj) {
return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type<T*>());
}
virtual std::auto_ptr<T>& auto_ptr_from_python(PyObject *obj) {
return BOOST_PYTHON_CONVERSION::python_extension_class_converters<T>::ptr_from_python(obj, boost::python::type<std::auto_ptr<T> >());
}
virtual boost::shared_ptr<T>& shared_ptr_from_python(PyObject *obj) {
return BOOST_PYTHON_CONVERSION::python_extension_class_converters<T>::ptr_from_python(obj, boost::python::type<boost::shared_ptr<T> >());
}
};
// The addditional to_python() converter that can be used if T is copyable.
template <class T>
struct export_converters : export_ptr_converters<T>
{
virtual PyObject *to_python(const T& x) {
BOOST_PYTHON_CONVERSION::python_extension_class_converters<T> cv;
return cv.to_python(x);
}
};
namespace detail {
//QUESTIONMARK
// A stripped-down, modified version of class extension_class.
// Would it make sense to establish a formal relationship
// between the two classes?
template <class T>
class import_extension_class
: public python_import_extension_class_converters<T>
{
public:
inline import_extension_class(const char *module, const char* klass) {
m_module = module;
m_klass = klass;
}
static boost::python::export_converters_base<T>* get_converters();
private:
static std::string m_module;
static std::string m_klass;
static boost::python::export_converters_base<T>* imported_converters;
};
template <class T> std::string import_extension_class<T>::m_module;
template <class T> std::string import_extension_class<T>::m_klass;
template <class T>
boost::python::export_converters_base<T>*
import_extension_class<T>::imported_converters = 0;
#ifdef SPECIAL_PYCVTSOBJECT
// A special PyObject for passing pointers to export_converters_base<T>
template <class T>
struct PyCvtsObject {
PyObject_HEAD
export_converters_base<T>* cvts;
};
template <class T>
void DEL_PyCvtsObject(PyCvtsObject<T>* self) { PyMem_DEL(self); }
template <class T>
PyObject *create_PyCvtsObject(export_converters_base<T>* cvts)
{
static char PyCvtsObject_Type__doc__[] =
"Boost Python Library (BPL) converters objects to be exported from\n"
"one extension module to another.";
static PyTypeObject PyCvtsObject_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"PyCvtsObject", /*tp_name*/
sizeof(PyCvtsObject<T>), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)(static_cast<void (*)(PyCvtsObject<T>*)>
(DEL_PyCvtsObject)), /*tp_dealloc*/
(printfunc)0, /*tp_print*/
(getattrfunc)0, /*tp_getattr*/
(setattrfunc)0, /*tp_setattr*/
(cmpfunc)0, /*tp_compare*/
(reprfunc)0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
PyCvtsObject_Type__doc__ /* Documentation string */
};
PyCvtsObject<T>* self = PyObject_NEW(PyCvtsObject<T>, &PyCvtsObject_Type);
if (self == 0) throw export_error();
self->cvts = cvts;
return reinterpret_cast<PyObject*>(self);
}
#endif // SPECIAL_PYCVTSOBJECT
template <class T>
boost::python::export_converters_base<T>*
import_extension_class<T>::get_converters() {
if (imported_converters == 0) {
#ifndef SPECIAL_PYCVTSOBJECT
void *cobject
= import_converters(m_module, m_klass, converters_attribute_name);
imported_converters
= static_cast<boost::python::export_converters_base<T>*>(cobject);
#else
ref cvts_obj(
new_import_converters(m_module, m_klass, converters_attribute_name));
PyCvtsObject<T>* cvts = reinterpret_cast<PyCvtsObject<T>*>(cvts_obj.get());
imported_converters = cvts->cvts;
#endif
check_export_converters_api(
EXPORT_CONVERTERS_API_MAJOR,
EXPORT_CONVERTERS_API_MINOR,
imported_converters->get_api_major(),
imported_converters->get_api_minor());
}
return imported_converters;
}
}}} // namespace boost::python::detail
namespace boost { namespace python {
//QUESTIONMARK
// A stripped-down, modified version of class class_builder.
// Would it make sense to establish a formal relationship
// between the two classes?
template <class T>
class import_class_builder
: python_import_extension_class_converters<T>
{
public:
import_class_builder(const char *module, const char* klass)
: m_class(new detail::import_extension_class<T>(module, klass))
{ }
private:
//QUESTIONMARK
//reference<detail::import_extension_class<T> > m_class;
boost::shared_ptr<detail::import_extension_class<T> > m_class;
};
}} // namespace boost::python
namespace boost { namespace python {
// A class_builder that exports the converter functions.
template <class T, class U = detail::held_instance<T>,
class C = export_converters<T> >
class x_class_builder
: public class_builder<T, U>
{
private:
static C export_cvts;
public:
x_class_builder(module_builder& module, const char* name)
: class_builder<T, U>(module, name) {
#ifndef SPECIAL_PYCVTSOBJECT
add(
ref(PyCObject_FromVoidPtr(reinterpret_cast<void*>(&export_cvts), NULL)),
const_cast<char*>(detail::converters_attribute_name.c_str()));
#else
add(ref(detail::create_PyCvtsObject(&export_cvts)),
const_cast<char*>(detail::converters_attribute_name.c_str()));
#endif
}
};
template <class T, class U, class C>
C x_class_builder<T, U, C>::export_cvts;
//QUESTIONMARK
// Is there a better way of making it easy for the end-user
// to choose between x_class_builder and xptr_class_builder?
template <class T, class U = detail::held_instance<T>,
class C = export_ptr_converters<T> >
class xptr_class_builder : public x_class_builder<T, U, C>
{
public:
xptr_class_builder(module_builder& module, const char* name)
: x_class_builder<T, U, C >(module, name) { }
};
}} // namespace boost::python
#endif // IMPORT_EXTENSION_CLASS_HPP_

View File

@@ -1,180 +0,0 @@
23 October 2003
Fixed bug where a class would appear more than one in the generated code.
6 October 2003
Fixed bug reported by Niall Douglas (using his patch) about UniqueInt not
appearing correctly with --multiple.
Added precompiled header support on windows systems (using #pragma hdrstop).
Suggested by Niall Douglas.
Fixed a bug with -I directive and AllFromHeader. Reported by Scott Snyder.
4 October 2003
Added return_self, thanks for Niall Douglas for pointing out that it was
missing.
Added --file-list, where you can pass a file where the pyste files are listed
one per line. Also suggested by Niall Douglas.
Documentation has been finally updated, after a long wait. Please let me know
if you spot any mistake!
2 October 2003
Scott Snyder found a typo in ClassExporter that prevented -= and *= operators
from being exported. Thanks Scott!
20 September 2003
Added return_by_value in the list of policies supported. Thanks to Niall
Douglas for the remainder.
19 September 2003
Better support for unnamed enums, plus they are by default exported to the
parent's namespace. Normal enums can have the same behaviour using the function
export_values on the Enum object. Feature requested by Niall Douglas.
10 September 2003
A new variable is accessible in the Pyste files: INTERFACE_FILE contains the
full path of the pyste file.
4 September 2003
Now it is possible to override protected and private pure virtual functions
in Python, as requested by Roman Yakovenko.
23 August 2003
Fixed bug where some Imports where not writing their include files.
Now whenever the declarations change, the cache files are rebuilt
automatically.
19 August 2003
Fixed a bug related to the generation of the bases<> template.
17 August 2003
Added support for insertion of user code in the generated code.
16 August 2003
Applied a patch by Gottfried Ganssauge that adds exception specifiers to
wrapper functions and pointer declarations. Thanks a lot Gottfried!!
Applied a patch by Prabhu Ramachandran that fixes ae problem with the
pure virtual method generation. Thanks again Prabhu!
10 August 2003
Support for incremental generation of the code has been added. This changes
how --multiple works; documentation of this new feature will follow. Thanks
to Prabhu Ramachandran, that saw the need for this feature and discussed a
solution.
Automatically convert \ to / in Windows systems before passing the paths to
gccxml.
Fixed a bug reported by Prabhu Ramachandran, where in some classes the virtual
methods were being definied incorrectly. Thanks a lot Prabhu!
7 July 2003
Applied 2 patches by Prabhu Ramachandran: a fix in the new --multiple method,
and two new functions "hold_with_shared_ptr" and its counterpart for auto_ptr.
Thanks a lot Prabhu!
Fixed a bug where the macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID was being
called multiple times for the same type.
Thanks to Gottfried Ganßauge for reporting this!
Fixed bug where using AllFromHeader didn't use bases<> when exporting
hierarchies.
Fixed the staticmethod bug.
5 July 2003
Changed how --multiple works: now it generates one cpp file for each pyste
file, makeing easier to integrate Pyste with build systems.
4 July 2003
Applied patch that solved a bug in ClassExporter and added a distutils install
script (install/setup.py), both contributed by Prabhu Ramachandran.
Thanks Prabhu!
2 July 2003
Jim Wilson found a bug where types like "char**" were being interpreted as
"char*". Thanks Jim!
16 June 2003
Thanks to discussions with David Abrahams and Roman Sulzhyk, some behaviours
have changed:
- If you export a derived class without exporting its base classes, the derived
class will explicitly export the bases's methods and attributes. Before, if
you were interested in the bases's methods, you had to export the base
classes too.
- Added a new function, no_override. When a member function is specified as
"no_override", no virtual wrappers are generated for it, improving
performance and letting the code more clean.
- There was a bug in which the policy of virtual member functions was being
ignored (patch by Roman Sulzhyk).
Thanks again to Roman Sulzhyk for the patches and discussion in the c++-sig.
4 June 2003
Major improvements in memory usage.
3 June 2003
Appliced a patch from Giulio Eulisse that allows unnamed enumerations to be
exported with an AllFromHeader construct. Thanks a lot Giulio!
2 June 2003
Added a new construct, add_method. See documentation.
23 May 2003
Support for global variables added.
Various bug fixes.
08 May 2003
Fixed bug where in a certain cases the GCCXMLParser would end up with multiple
declarations of the same class
22 Apr 2003
- Now shows a warning when the user tries to export a forward-declared class.
Forward-declared classes are ignored by the AllFromHeader construct.
- Fixed a bug where classes, functions and enums where being exported, even if
excluded from a AllFromHeader construct.
16 Apr 2003
Added a more generic (but ugly) code to declare the smart pointer converters.
07 Apr 2003
- Removed the warnings about forward declarations: it was not accurate enough.
Another strategy must be thought of.
- Fixed bug in the --multiple mode, where the order of the class instantiations
could end up wrong.
- Lots of fixes in the documentation, pointed out by Dirk Gerrits. Thanks Dirk!
- Fixed support for the return_opaque_pointer policy (the support macro was not
being declared).
06 Apr 2003
Support for the improved static data members support of Boost.Python.
05 Apr 2003
New option for generating the bindings: --multiple.
02 Apr 2003
Forward declarations are now detected and a warning is generated.
24 Mar 2003
Default policy for functions/methods that return const T& is now
return_value_policy<copy_const_reference>().
22 Mar 2003
Exporting virtual methods of the base classes in the derived classes too.
21 Mar 2003
Added manual support for boost::shared_ptr and std::auto_ptr (see doc).
19 Mar 2003
Added support for int, double, float and long operators acting as expected in
python.
14 Mar 2003
Fixed bug: Wrappers for protected and virtual methods were not being generated.

View File

@@ -0,0 +1,118 @@
# include <boost/python/detail/import_extension_class.hpp>
namespace python = boost::python;
# include <stdio.h> // MSVC6.0SP4 does not know std::fprintf
# include <string.h> // 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) throw python::import_error();
return module_dict;
}
}
namespace boost { namespace python { namespace detail {
#ifndef SPECIAL_PYCVTSOBJECT
void *import_converters(const std::string& module_name,
const std::string& klass_name,
const std::string& attribute_name)
{
static std::string err;
PyObject *module_dict
= get_module_dict(const_cast<char*>(module_name.c_str()));
PyObject *klass
= PyDict_GetItemString(module_dict, const_cast<char*>(klass_name.c_str()));
if (klass == 0) {
err = std::string("module ") + module_name + " has no attribute "
+ klass_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
python::ref c_obj(PyObject_GetAttrString(klass,
const_cast<char*>(attribute_name.c_str())), ref::null_ok);
if (c_obj.get() == 0) {
err = std::string("object ") + module_name + "." + klass_name
+ " has no attribute " + attribute_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
if (! PyCObject_Check(c_obj.get())) {
err = std::string("object ") + module_name + "." + klass_name + "."
+ attribute_name + " is not a PyCObject";
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
return PyCObject_AsVoidPtr(c_obj.get());
}
#else
PyObject *new_import_converters(const std::string& module_name,
const std::string& klass_name,
const std::string& attribute_name)
{
static std::string err;
PyObject *module_dict
= get_module_dict(const_cast<char*>(module_name.c_str()));
PyObject *klass
= PyDict_GetItemString(module_dict, const_cast<char*>(klass_name.c_str()));
if (klass == 0) {
err = std::string("module ") + module_name + " has no attribute "
+ klass_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
python::ref cvts_obj(PyObject_GetAttrString(klass,
const_cast<char*>(attribute_name.c_str())), ref::null_ok);
if (cvts_obj.get() == 0) {
err = std::string("object ") + module_name + "." + klass_name
+ " has no attribute " + attribute_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
// Weak point: direct access to ob_type->tp_name
if (strcmp(cvts_obj->ob_type->tp_name, "PyCvtsObject") != 0) {
err = std::string("object ") + module_name + "." + klass_name + "."
+ attribute_name + " is not a PyCvtsObject";
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
return cvts_obj.release();
}
#endif // SPECIAL_PYCVTSOBJECT
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

75
test/opaque.cpp Normal file
View File

@@ -0,0 +1,75 @@
// Copyright David Abrahams and Gottfried Ganssauge 2003. 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 <boost/python/return_opaque_pointer.hpp>
# include <boost/python/def.hpp>
# include <boost/python/module.hpp>
# include <boost/python/return_value_policy.hpp>
typedef struct opaque_ *opaque;
typedef struct opaque2_ *opaque2;
opaque the_op = ((opaque) 0x47110815);
opaque2 the_op2 = ((opaque2) 0x08154711);
opaque get() { return the_op; }
void use(opaque op)
{
if (op != the_op)
throw std::runtime_error (std::string ("failed"));
}
int useany(opaque op)
{
return op ? 1 : 0;
}
opaque getnull()
{
return 0;
}
void failuse (opaque op)
{
if (op == the_op)
throw std::runtime_error (std::string ("success"));
}
opaque2 get2 () { return the_op2; }
void use2 (opaque2 op)
{
if (op != the_op2)
throw std::runtime_error (std::string ("failed"));
}
void failuse2 (opaque2 op)
{
if (op == the_op2)
throw std::runtime_error (std::string ("success"));
}
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque2_)
namespace bpl = boost::python;
BOOST_PYTHON_MODULE(opaque_ext)
{
bpl::def (
"get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
bpl::def ("use", &::use);
bpl::def ("useany", &::useany);
bpl::def ("getnull", &::getnull, bpl::return_value_policy<bpl::return_opaque_pointer>());
bpl::def ("failuse", &::failuse);
bpl::def (
"get2",
&::get2,
bpl::return_value_policy<bpl::return_opaque_pointer>());
bpl::def ("use2", &::use2);
bpl::def ("failuse2", &::failuse2);
}

75
test/opaque.cpp Normal file
View File

@@ -0,0 +1,75 @@
// Copyright David Abrahams and Gottfried Ganssauge 2003. 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 <boost/python/return_opaque_pointer.hpp>
# include <boost/python/def.hpp>
# include <boost/python/module.hpp>
# include <boost/python/return_value_policy.hpp>
typedef struct opaque_ *opaque;
typedef struct opaque2_ *opaque2;
opaque the_op = ((opaque) 0x47110815);
opaque2 the_op2 = ((opaque2) 0x08154711);
opaque get() { return the_op; }
void use(opaque op)
{
if (op != the_op)
throw std::runtime_error (std::string ("failed"));
}
int useany(opaque op)
{
return op ? 1 : 0;
}
opaque getnull()
{
return 0;
}
void failuse (opaque op)
{
if (op == the_op)
throw std::runtime_error (std::string ("success"));
}
opaque2 get2 () { return the_op2; }
void use2 (opaque2 op)
{
if (op != the_op2)
throw std::runtime_error (std::string ("failed"));
}
void failuse2 (opaque2 op)
{
if (op == the_op2)
throw std::runtime_error (std::string ("success"));
}
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque2_)
namespace bpl = boost::python;
BOOST_PYTHON_MODULE(opaque_ext)
{
bpl::def (
"get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
bpl::def ("use", &::use);
bpl::def ("useany", &::useany);
bpl::def ("getnull", &::getnull, bpl::return_value_policy<bpl::return_opaque_pointer>());
bpl::def ("failuse", &::failuse);
bpl::def (
"get2",
&::get2,
bpl::return_value_policy<bpl::return_opaque_pointer>());
bpl::def ("use2", &::use2);
bpl::def ("failuse2", &::failuse2);
}