mirror of
https://github.com/boostorg/python.git
synced 2026-01-26 18:52:26 +00:00
Compare commits
17 Commits
boost-0.9.
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0eb039a500 | ||
|
|
ba3b0a7c5d | ||
|
|
b990d7580d | ||
|
|
536dbe28a6 | ||
|
|
27f99ba783 | ||
|
|
4c30bb98f9 | ||
|
|
582dc47885 | ||
|
|
5666c21037 | ||
|
|
16264a3f2d | ||
|
|
046fb553c5 | ||
|
|
3eb98f54a1 | ||
|
|
f1d4a38121 | ||
|
|
6d3b960cb7 | ||
|
|
2aed6f022e | ||
|
|
724c91b7b2 | ||
|
|
1e272b9c14 | ||
|
|
2ceaa9133d |
2
build/.cvsignore
Normal file
2
build/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
patch_tru64_to_gcc
|
||||
36
build/Jamfile
Normal file
36
build/Jamfile
Normal 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
194
build/Makefile.gcc
Normal 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
269
build/Makefile.mingw32
Normal 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
199
build/Makefile.tru64
Normal 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
223
doc/pickle.html
Normal 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
6
example/README
Normal 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
34
example/abstract.cpp
Normal 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
42
example/cmplx.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
32
example/getting_started1.cpp
Normal file
32
example/getting_started1.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
51
example/getting_started2.cpp
Normal file
51
example/getting_started2.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
147
example/getting_started3.cpp
Normal file
147
example/getting_started3.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
104
example/getting_started4.cpp
Normal file
104
example/getting_started4.cpp
Normal 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
52
example/passing_char.cpp
Normal 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
23
example/test_abstract.py
Normal 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()
|
||||
17
example/test_getting_started1.py
Normal file
17
example/test_getting_started1.py
Normal 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()
|
||||
19
example/test_getting_started2.py
Normal file
19
example/test_getting_started2.py
Normal 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()
|
||||
56
example/test_getting_started3.py
Normal file
56
example/test_getting_started3.py
Normal 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()
|
||||
35
example/test_getting_started4.py
Normal file
35
example/test_getting_started4.py
Normal 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()
|
||||
22
example/test_getting_started5.py
Normal file
22
example/test_getting_started5.py
Normal 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
20
example/tst_cmplx.py
Normal 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
|
||||
20
example/tst_passing_char.py
Normal file
20
example/tst_passing_char.py
Normal 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]
|
||||
21
include/boost/python/args.hpp
Normal file
21
include/boost/python/args.hpp
Normal 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
|
||||
60
include/boost/python/bases.hpp
Normal file
60
include/boost/python/bases.hpp
Normal 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
|
||||
361
include/boost/python/detail/import_extension_class.hpp
Normal file
361
include/boost/python/detail/import_extension_class.hpp
Normal 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_
|
||||
180
pyste/NEWS
180
pyste/NEWS
@@ -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.
|
||||
118
src/import_extension_class.cpp
Normal file
118
src/import_extension_class.cpp
Normal 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
75
test/opaque.cpp
Normal 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
75
test/opaque.cpp
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user