mirror of
https://github.com/boostorg/python.git
synced 2026-01-23 17:52:17 +00:00
This commit was manufactured by cvs2svn to create tag
'before_adding_complex'. [SVN r9301]
This commit is contained in:
2
build/.cvsignore
Normal file
2
build/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
patch_tru64_to_gcc
|
||||
188
build/Makefile.gcc
Normal file
188
build/Makefile.gcc
Normal file
@@ -0,0 +1,188 @@
|
||||
# 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)/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_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 \
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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 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
|
||||
193
build/Makefile.tru64
Normal file
193
build/Makefile.tru64
Normal file
@@ -0,0 +1,193 @@
|
||||
# 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)/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_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 \
|
||||
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
|
||||
|
||||
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 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
|
||||
@@ -63,8 +63,8 @@ LIB32=link.exe -lib
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W4 /WX /Gm /GR /GX /ZI /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W4 /WX /Gm /GR /GX /ZI /Od /I "d:\boost\type_traits" /I "..\..\.." /I "c:\progra~1\python20\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#
|
||||
# Tested with:
|
||||
# Compaq C++ V6.2-024 for Digital UNIX V5.0 (Rev. 910)
|
||||
#
|
||||
# Python 1.5.2 was installed without any customizations.
|
||||
# boost_all.zip vers. 1.18.1 was unpacked using unzip -aa and not modified.
|
||||
# STLport-4.1b3 was unpacked using unzip -aa and not modified.
|
||||
#
|
||||
# Initial version 2000-10-20: Ralf W. Grosse-Kunstleve, rwgk@cci.lbl.gov
|
||||
#
|
||||
|
||||
PYINC= /usr/local/include/python1.5
|
||||
BOOSTINC= /usr/local/boost_1_18_1
|
||||
STLPORTINC= /usr/local/STLport-4.1b3/stlport
|
||||
STLPORTOPTS= \
|
||||
-D__USE_STD_IOSTREAM \
|
||||
-D__STL_NO_SGI_IOSTREAMS \
|
||||
-D__STL_NO_NEW_C_HEADERS \
|
||||
-D_RWSTD_COMPILE_INSTANTIATE=1
|
||||
|
||||
STDOPTS= -std strict_ansi
|
||||
WARNOPTS= -msg_disable 186,450,1115
|
||||
# use -msg_display_number to obtain integer tags for -msg_disable
|
||||
|
||||
CPP= cxx
|
||||
CPPOPTS= -I$(STLPORTINC) $(STLPORTOPTS) -I$(BOOSTINC) -I$(PYINC) \
|
||||
$(STDOPTS) $(WARNOPTS)
|
||||
|
||||
LD= cxx
|
||||
LDOPTS= -shared -expect_unresolved '*'
|
||||
|
||||
OBJ = extclass.o functions.o init_function.o module.o newtypes.o \
|
||||
objects.o py.o subclass.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
all: demo.so hello.so
|
||||
|
||||
demo.so: $(OBJ) extclass_demo.o
|
||||
$(LD) $(LDOPTS) $(OBJ) extclass_demo.o -o demo.so
|
||||
|
||||
hello.so: $(OBJ) example1.o
|
||||
$(LD) $(LDOPTS) $(OBJ) example1.o -o hello.so
|
||||
|
||||
.cpp.o:
|
||||
-$(CPP) $(CPPOPTS) $(INC) -c $*.cpp
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) extclass_demo.o example1.o demo.so hello.so so_locations
|
||||
rm -rf cxx_repository
|
||||
rm -f *.pyc
|
||||
@@ -12,14 +12,14 @@
|
||||
<h2>Synopsis</h2>
|
||||
<p>
|
||||
Use the Boost Python Library to quickly and easily export a C++ library to <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org">Python</a> such that the Python interface is
|
||||
href="http://www.python.org">Python</a> such that the Python interface is
|
||||
very similar to the C++ interface. It is designed to be minimally
|
||||
intrusive on your C++ design. In most cases, you should not have to alter
|
||||
your C++ classes in any way in order to use them with BPL. The system
|
||||
<em>should</em> simply ``reflect'' your C++ classes and functions into
|
||||
Python. The major features of BPL include support for:
|
||||
<ul>
|
||||
<li><a href="inheritance.hml">Subclassing extension types in Python</a>
|
||||
<li><a href="inheritance.html">Subclassing extension types in Python</a>
|
||||
<li><a href="overriding.html">Overriding virtual functions in Python</a>
|
||||
<li><a href="overloading.html">[Member] function Overloading</a>
|
||||
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace scope as Python member functions.
|
||||
<ul>
|
||||
|
||||
<li>Attribute lookup for extension classes proceeds in <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/tut/node11.html#SECTION0011510000000000000000">the
|
||||
href="http://www.python.org/doc/current/tut/node11.html#SECTION0011510000000000000000">the
|
||||
usual Python way</a> using a depth-first, left-to-right search. When a
|
||||
class is found which has a matching attribute, only functions overloaded
|
||||
in the context of that class are candidates for overload resolution. In
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</h2>
|
||||
<p>
|
||||
BPL supports all of the standard <a href=
|
||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
|
||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||
special method names</a> supported by real Python class instances <em>
|
||||
except</em> <code>__complex__</code> (more on the reasons <a href=
|
||||
"#reasons">below</a>). In addition, it can quickly and easily expose
|
||||
@@ -33,7 +33,7 @@
|
||||
Python provides a number of special operators for basic customization of a
|
||||
class. Only a brief description is provided below; more complete
|
||||
documentation can be found <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/customization.html">here</a>.
|
||||
href="http://www.python.org/doc/current/ref/customization.html">here</a>.
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
@@ -114,7 +114,7 @@ foo_class.def(&to_string, "__str__");
|
||||
<p>
|
||||
Numeric operators can be exposed manually, by <code>def</code>ing C++
|
||||
[member] functions that support the standard Python <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/numeric-types.html">numeric
|
||||
href="http://www.python.org/doc/current/ref/numeric-types.html">numeric
|
||||
protocols</a>. This is the same basic technique used to expose
|
||||
<code>to_string()</code> as <code>__str__()</code> above, and is <a
|
||||
href="#numeric_manual">covered in detail below</a>. BPL also supports
|
||||
@@ -398,7 +398,7 @@ Note that "__rrpow__" is an extension not present in plain Python.
|
||||
<h2><a name="numeric_table">Table of Automatically Wrapped Methods</a></h2>
|
||||
<p>
|
||||
BPL can automatically wrap the following <a href=
|
||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
|
||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||
special methods</a>:
|
||||
|
||||
<p>
|
||||
@@ -672,12 +672,12 @@ for (iterator i = S.begin(), end = S.end(); i != end; ++i)
|
||||
|
||||
<p>
|
||||
It is a better idea to support the standard <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/sequence-types.html">Python
|
||||
href="http://www.python.org/doc/current/ref/sequence-types.html">Python
|
||||
sequence and mapping protocols</a> for your wrapped containers. These
|
||||
operators have to be wrapped manually because there are no corresponding
|
||||
C++ operators that could be used for automatic wrapping. The Python
|
||||
documentation lists the relevant <a href=
|
||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/sequence-types.html">
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html">
|
||||
container operators</a>. In particular, expose __getitem__, __setitem__
|
||||
and remember to raise the appropriate Python exceptions
|
||||
(<code>PyExc_IndexError</code> for sequences,
|
||||
@@ -773,7 +773,7 @@ KeyError: 2
|
||||
|
||||
<p>
|
||||
Just like built-in Python classes, BPL extension classes support <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/attribute-access.html">special
|
||||
href="http://www.python.org/doc/current/ref/attribute-access.html">special
|
||||
the usual attribute access methods</a> <code>__getattr__</code>,
|
||||
<code>__setattr__</code>, and <code>__delattr__</code>.
|
||||
Because writing these functions can
|
||||
|
||||
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");
|
||||
}
|
||||
69
example/dvect.cpp
Normal file
69
example/dvect.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "ivect.h"
|
||||
#include "dvect.h"
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace {
|
||||
|
||||
vects::ivect dvect_as_ivect(const vects::dvect& dv)
|
||||
{
|
||||
vects::ivect iv(dv.size());
|
||||
vects::ivect::iterator iviter = iv.begin();
|
||||
for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast<int>(dv[i]);
|
||||
return iv;
|
||||
}
|
||||
|
||||
boost::python::tuple ivect_as_tuple(const vects::ivect& iv)
|
||||
{
|
||||
return iv.as_tuple();
|
||||
}
|
||||
|
||||
std::auto_ptr<vects::ivect> auto_ptr_ivect(const vects::dvect& dv)
|
||||
{
|
||||
return std::auto_ptr<vects::ivect>(new vects::ivect(dvect_as_ivect(dv)));
|
||||
}
|
||||
|
||||
boost::shared_ptr<vects::ivect> shared_ptr_ivect(const vects::dvect& dv)
|
||||
{
|
||||
return boost::shared_ptr<vects::ivect>(new vects::ivect(dvect_as_ivect(dv)));
|
||||
}
|
||||
|
||||
boost::python::tuple auto_ptr_ivect_as_tuple(std::auto_ptr<vects::ivect>& iv)
|
||||
{
|
||||
return iv->as_tuple();
|
||||
}
|
||||
|
||||
boost::python::tuple shared_ptr_ivect_as_tuple(boost::shared_ptr<vects::ivect>& iv)
|
||||
{
|
||||
return iv->as_tuple();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initdvect()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("dvect");
|
||||
|
||||
python::x_class_builder<vects::dvect> dvect_class(this_module, "dvect");
|
||||
|
||||
python::import_class_builder<vects::ivect> ivect_class("ivect", "ivect");
|
||||
|
||||
dvect_class.def(python::constructor<python::tuple>());
|
||||
dvect_class.def(&vects::dvect::as_tuple, "as_tuple");
|
||||
dvect_class.def(dvect_as_ivect, "as_ivect");
|
||||
|
||||
this_module.def(ivect_as_tuple, "ivect_as_tuple");
|
||||
dvect_class.def(auto_ptr_ivect, "auto_ptr_ivect");
|
||||
dvect_class.def(shared_ptr_ivect, "shared_ptr_ivect");
|
||||
this_module.def(auto_ptr_ivect_as_tuple, "auto_ptr_ivect_as_tuple");
|
||||
this_module.def(shared_ptr_ivect_as_tuple, "shared_ptr_ivect_as_tuple");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
32
example/dvect.h
Normal file
32
example/dvect.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef DVECT_H
|
||||
#define DVECT_H
|
||||
|
||||
#include <vector>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
namespace vects {
|
||||
|
||||
struct dvect : public std::vector<double>
|
||||
{
|
||||
dvect() : std::vector<double>() {}
|
||||
dvect(size_t n) : std::vector<double>(n) {}
|
||||
dvect(boost::python::tuple tuple) : std::vector<double>(tuple.size())
|
||||
{
|
||||
std::vector<double>::iterator v_it = begin();
|
||||
for (int i = 0; i < tuple.size(); i++)
|
||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
||||
boost::python::type<double>());
|
||||
}
|
||||
|
||||
boost::python::tuple as_tuple() const
|
||||
{
|
||||
boost::python::tuple t(size());
|
||||
for (int i = 0; i < size(); i++)
|
||||
t.set_item(i,
|
||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DVECT_H
|
||||
@@ -1,54 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
namespace hello {
|
||||
class world
|
||||
{
|
||||
public:
|
||||
world(int) {}
|
||||
~world() {}
|
||||
const char* get() const { return "hi, world"; }
|
||||
};
|
||||
|
||||
size_t length(const world& x) { return strlen(x.get()); }
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
// Python requires an exported function called init<module-name> in every
|
||||
// extension module. This is where we build the module contents.
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void inithello()
|
||||
{
|
||||
try
|
||||
{
|
||||
// create an object representing this extension module
|
||||
boost::python::module_builder hello("hello");
|
||||
|
||||
// Create the Python type object for our extension class
|
||||
boost::python::class_builder<hello::world> world_class(hello, "world");
|
||||
|
||||
// Add the __init__ function
|
||||
world_class.def(boost::python::constructor<int>());
|
||||
// Add a regular member function
|
||||
world_class.def(&hello::world::get, "get");
|
||||
|
||||
// Add a regular function to the module
|
||||
hello.def(hello::length, "length");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
boost::python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
// Win32 DLL boilerplate
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif // _WIN32
|
||||
@@ -8,21 +8,18 @@ namespace { // Avoid cluttering the global namespace.
|
||||
}
|
||||
|
||||
#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"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void initrwgk1()
|
||||
DL_EXPORT(void)
|
||||
initgetting_started1()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("rwgk1");
|
||||
python::module_builder this_module("getting_started1");
|
||||
|
||||
// Add regular functions to the module.
|
||||
this_module.def(greet, "greet");
|
||||
@@ -33,9 +30,3 @@ void initrwgk1()
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
// Win32 DLL boilerplate
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; }
|
||||
#endif // _WIN32
|
||||
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
|
||||
}
|
||||
}
|
||||
122
example/getting_started3.cpp
Normal file
122
example/getting_started3.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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__");
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
128
example/getting_started5.cpp
Normal file
128
example/getting_started5.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
This example shows how to convert a class from and to native
|
||||
Python objects, such as tuples.
|
||||
|
||||
We do not want to expose the helper class MillerIndex as an
|
||||
Extension Class. However, in order to simplify the wrapper code,
|
||||
we want to define from_python() and to_python() functions for
|
||||
class MillerIndex.
|
||||
|
||||
Consider the alternatives:
|
||||
|
||||
- Expose MillerIndex as an Extension Class.
|
||||
We need a constructor MillerIndex(python::tuple).
|
||||
Python function calls become more complex:
|
||||
foo(MillerIndex((1,2,3)) instead of foo((1,2,3))
|
||||
We need a method such as MillerIndex().as_tuple().
|
||||
|
||||
- Define a wrapper function for each function that we
|
||||
want to expose, e.g.:
|
||||
void add(const IndexingSet& ixset, const python::tuple PyMIx)
|
||||
|
||||
The first alternative introduces a new type that the user has to
|
||||
deal with. Other modules using Miller indices might organize them in
|
||||
different ways, for example to increase runtime efficiency for
|
||||
important procedures. This means, the user has to know how to
|
||||
convert between the different kinds of Miller index representations.
|
||||
This can quickly become a nuisance. Relying on native Python data
|
||||
structures minimizes the number of special types the user has to
|
||||
learn and convert. Of course, this argument is only valid for
|
||||
small and relatively simply classes.
|
||||
|
||||
If there are many member functions with MillerIndex arguments, the
|
||||
second alternative is impractical, and concentrating the conversion
|
||||
mechanism in one central place is essential for code
|
||||
maintainability. An added benefit is that more convenient (smarter)
|
||||
conversion functions can be provided without cluttering the rest of
|
||||
the wrapper code.
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// The helper class.
|
||||
//
|
||||
class MillerIndex {
|
||||
public:
|
||||
int v[3];
|
||||
};
|
||||
|
||||
// The main class. Imagine that there are MANY member functions
|
||||
// like add() and get().
|
||||
//
|
||||
class IndexingSet {
|
||||
private:
|
||||
std::vector<MillerIndex> VMIx;
|
||||
public:
|
||||
void add(const MillerIndex& MIx) { VMIx.push_back(MIx); }
|
||||
MillerIndex get(const std::size_t i) const { return VMIx[i]; }
|
||||
};
|
||||
}
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
// Convert a Python tuple to a MillerIndex object.
|
||||
//
|
||||
MillerIndex from_python(PyObject* p, python::type<const MillerIndex&>)
|
||||
{
|
||||
python::tuple tup
|
||||
= python::tuple(python::ref(p, python::ref::increment_count));
|
||||
if (tup.size() != 3) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"expecting exactly 3 values in tuple.");
|
||||
throw python::error_already_set();
|
||||
}
|
||||
MillerIndex result;
|
||||
for (int i = 0; i < 3; i++)
|
||||
result.v[i] = from_python(tup[i].get(), python::type<int>());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Similar conversion for MillerIndex objects passed by value.
|
||||
// Not actually used, but included to show the principle.
|
||||
//
|
||||
MillerIndex from_python(PyObject* p, python::type<MillerIndex>)
|
||||
{
|
||||
return from_python(p, python::type<const MillerIndex&>());
|
||||
}
|
||||
|
||||
// Convert a MillerIndex object to a Python tuple.
|
||||
//
|
||||
PyObject* to_python(const MillerIndex& hkl)
|
||||
{
|
||||
python::tuple result(3);
|
||||
for (int i = 0; i < 3; i++)
|
||||
result.set_item(i, to_python(hkl.v[i]));
|
||||
return result.reference().release();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initgetting_started5()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started5");
|
||||
|
||||
// Create the Python type object for our extension class.
|
||||
python::class_builder<IndexingSet> ixset_class(this_module, "IndexingSet");
|
||||
|
||||
// Add the __init__ function.
|
||||
ixset_class.def(python::constructor<>());
|
||||
// Add the member functions.
|
||||
ixset_class.def(&IndexingSet::add, "add");
|
||||
ixset_class.def(&IndexingSet::get, "get");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
69
example/ivect.cpp
Normal file
69
example/ivect.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "ivect.h"
|
||||
#include "dvect.h"
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace {
|
||||
|
||||
vects::dvect ivect_as_dvect(const vects::ivect& iv)
|
||||
{
|
||||
vects::dvect dv(iv.size());
|
||||
vects::dvect::iterator dviter = dv.begin();
|
||||
for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast<double>(iv[i]);
|
||||
return dv;
|
||||
}
|
||||
|
||||
boost::python::tuple dvect_as_tuple(const vects::dvect& dv)
|
||||
{
|
||||
return dv.as_tuple();
|
||||
}
|
||||
|
||||
std::auto_ptr<vects::dvect> auto_ptr_dvect(const vects::ivect& iv)
|
||||
{
|
||||
return std::auto_ptr<vects::dvect>(new vects::dvect(ivect_as_dvect(iv)));
|
||||
}
|
||||
|
||||
boost::shared_ptr<vects::dvect> shared_ptr_dvect(const vects::ivect& iv)
|
||||
{
|
||||
return boost::shared_ptr<vects::dvect>(new vects::dvect(ivect_as_dvect(iv)));
|
||||
}
|
||||
|
||||
boost::python::tuple auto_ptr_dvect_as_tuple(std::auto_ptr<vects::dvect>& dv)
|
||||
{
|
||||
return dv->as_tuple();
|
||||
}
|
||||
|
||||
boost::python::tuple shared_ptr_dvect_as_tuple(boost::shared_ptr<vects::dvect>& dv)
|
||||
{
|
||||
return dv->as_tuple();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initivect()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("ivect");
|
||||
|
||||
python::x_class_builder<vects::ivect> ivect_class(this_module, "ivect");
|
||||
|
||||
python::import_class_builder<vects::dvect> dvect_class("dvect", "dvect");
|
||||
|
||||
ivect_class.def(python::constructor<python::tuple>());
|
||||
ivect_class.def(&vects::ivect::as_tuple, "as_tuple");
|
||||
ivect_class.def(ivect_as_dvect, "as_dvect");
|
||||
|
||||
this_module.def(dvect_as_tuple, "dvect_as_tuple");
|
||||
ivect_class.def(auto_ptr_dvect, "auto_ptr_dvect");
|
||||
ivect_class.def(shared_ptr_dvect, "shared_ptr_dvect");
|
||||
this_module.def(auto_ptr_dvect_as_tuple, "auto_ptr_dvect_as_tuple");
|
||||
this_module.def(shared_ptr_dvect_as_tuple, "shared_ptr_dvect_as_tuple");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
32
example/ivect.h
Normal file
32
example/ivect.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef IVECT_H
|
||||
#define IVECT_H
|
||||
|
||||
#include <vector>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
namespace vects {
|
||||
|
||||
struct ivect : public std::vector<int>
|
||||
{
|
||||
ivect() : std::vector<int>() {}
|
||||
ivect(size_t n) : std::vector<int>(n) {}
|
||||
ivect(boost::python::tuple tuple) : std::vector<int>(tuple.size())
|
||||
{
|
||||
std::vector<int>::iterator v_it = begin();
|
||||
for (int i = 0; i < tuple.size(); i++)
|
||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
||||
boost::python::type<int>());
|
||||
}
|
||||
|
||||
boost::python::tuple as_tuple() const
|
||||
{
|
||||
boost::python::tuple t(size());
|
||||
for (int i = 0; i < size(); i++)
|
||||
t.set_item(i,
|
||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // IVECT_H
|
||||
24
example/noncopyable_export.cpp
Normal file
24
example/noncopyable_export.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
#include "store.h"
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initnoncopyable_export()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("noncopyable_export");
|
||||
|
||||
python::xptr_class_builder<store> store_class(this_module, "store");
|
||||
|
||||
store_class.def(python::constructor<int>());
|
||||
store_class.def(&store::recall, "recall");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
42
example/noncopyable_import.cpp
Normal file
42
example/noncopyable_import.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
#include "store.h"
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A function with store objects as both input and output parameters.
|
||||
// Because the copy constructor is disabled, we cannot pass a store
|
||||
// object by value. Instead, we pass a smart pointer.
|
||||
std::auto_ptr<store> add_stores(const store& s1, const store& s2)
|
||||
{
|
||||
int sum = s1.recall() + s2.recall();
|
||||
std::auto_ptr<store> ss = std::auto_ptr<store>(new store(sum));
|
||||
return ss;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initnoncopyable_import()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("noncopyable_import");
|
||||
|
||||
python::import_class_builder<store>
|
||||
dvect_class("noncopyable_export", "store");
|
||||
|
||||
// Imagine all the additional classes with member functions
|
||||
// that have store objects as input and output parameters.
|
||||
// Lots and lots of them.
|
||||
// However, to keep this example simple, we only define a
|
||||
// module-level function.
|
||||
this_module.def(add_stores, "add_stores");
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
14
example/store.h
Normal file
14
example/store.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef STORE_H
|
||||
#define STORE_H
|
||||
|
||||
class store
|
||||
{
|
||||
private:
|
||||
store(const store&) { } // Disable the copy constructor.
|
||||
int number;
|
||||
public:
|
||||
store(const int i) : number(i) { }
|
||||
int recall() const { return number; }
|
||||
};
|
||||
|
||||
#endif // STORE_H
|
||||
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()
|
||||
@@ -1,50 +0,0 @@
|
||||
r'''
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
That's it! If we build this shared library and put it on our PYTHONPATH we can
|
||||
now access our C++ class and function from Python.
|
||||
|
||||
>>> import hello
|
||||
>>> hi_world = hello.world(3)
|
||||
>>> hi_world.get()
|
||||
'hi, world'
|
||||
>>> hello.length(hi_world)
|
||||
9
|
||||
|
||||
We can even make a subclass of hello.world:
|
||||
|
||||
|
||||
>>> class my_subclass(hello.world):
|
||||
... def get(self):
|
||||
... return 'hello, world'
|
||||
...
|
||||
>>> y = my_subclass(2)
|
||||
>>> y.get()
|
||||
'hello, world'
|
||||
|
||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
||||
|
||||
>>> hello.length(y)
|
||||
9
|
||||
|
||||
Of course, you may now have a slightly empty feeling in the pit of your little
|
||||
pythonic stomach. Perhaps you feel your subclass deserves to have a length() of
|
||||
12? If so, read on...
|
||||
'''
|
||||
from hello import *
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_example1
|
||||
doctest.testmod(test_example1)
|
||||
|
||||
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()
|
||||
@@ -1,17 +0,0 @@
|
||||
r'''>>> import rwgk1
|
||||
>>> print rwgk1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', rwgk1.square(number)
|
||||
11 * 11 = 121
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_rwgk1
|
||||
doctest.testmod(test_rwgk1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
16
example/tst_dvect.py
Normal file
16
example/tst_dvect.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import dvect
|
||||
print dvect.dvect.__converters__
|
||||
dv = dvect.dvect((1,2,3,4,5))
|
||||
print dv
|
||||
print dv.as_tuple()
|
||||
iv = dv.as_ivect()
|
||||
print iv
|
||||
print iv.as_tuple()
|
||||
print dvect.ivect_as_tuple(iv)
|
||||
aiv = dv.auto_ptr_ivect()
|
||||
print aiv
|
||||
siv = dv.shared_ptr_ivect()
|
||||
print dvect.auto_ptr_ivect_as_tuple(aiv)
|
||||
print dvect.ivect_as_tuple(aiv)
|
||||
print dvect.shared_ptr_ivect_as_tuple(siv)
|
||||
print dvect.ivect_as_tuple(siv)
|
||||
16
example/tst_ivect.py
Normal file
16
example/tst_ivect.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import ivect
|
||||
print ivect.ivect.__converters__
|
||||
iv = ivect.ivect((1,2,3,4,5))
|
||||
print iv
|
||||
print iv.as_tuple()
|
||||
dv = iv.as_dvect()
|
||||
print dv
|
||||
print dv.as_tuple()
|
||||
print ivect.dvect_as_tuple(dv)
|
||||
adv = iv.auto_ptr_dvect()
|
||||
print adv
|
||||
sdv = iv.shared_ptr_dvect()
|
||||
print ivect.auto_ptr_dvect_as_tuple(adv)
|
||||
print ivect.dvect_as_tuple(adv)
|
||||
print ivect.shared_ptr_dvect_as_tuple(sdv)
|
||||
print ivect.dvect_as_tuple(sdv)
|
||||
8
example/tst_noncopyable.py
Normal file
8
example/tst_noncopyable.py
Normal file
@@ -0,0 +1,8 @@
|
||||
import noncopyable_export
|
||||
import noncopyable_import
|
||||
s1 = noncopyable_export.store(1)
|
||||
print s1.recall()
|
||||
s2 = noncopyable_export.store(2)
|
||||
print s2.recall()
|
||||
s3 = noncopyable_import.add_stores(s1, s2)
|
||||
print s3.recall()
|
||||
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]
|
||||
@@ -100,6 +100,10 @@ PyObject* to_python(unsigned short);
|
||||
unsigned short from_python(PyObject*, boost::python::type<unsigned short>);
|
||||
unsigned short from_python(PyObject*, boost::python::type<const unsigned short&>);
|
||||
|
||||
PyObject* to_python(char);
|
||||
char from_python(PyObject*, boost::python::type<char>);
|
||||
char from_python(PyObject*, boost::python::type<const char&>);
|
||||
|
||||
PyObject* to_python(signed char);
|
||||
signed char from_python(PyObject*, boost::python::type<signed char>);
|
||||
signed char from_python(PyObject*, boost::python::type<const signed char&>);
|
||||
@@ -304,6 +308,11 @@ inline unsigned short from_python(PyObject* p, boost::python::type<const unsigne
|
||||
return from_python(p, boost::python::type<unsigned short>());
|
||||
}
|
||||
|
||||
inline char from_python(PyObject* p, boost::python::type<const char&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<char>());
|
||||
}
|
||||
|
||||
inline signed char from_python(PyObject* p, boost::python::type<const signed char&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<signed char>());
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file automatically generated for 5-argument constructors by
|
||||
// This file automatically generated for 10-argument constructors by
|
||||
// gen_extclass.python
|
||||
|
||||
#ifndef EXTENSION_CLASS_DWA052000_H_
|
||||
@@ -363,8 +363,8 @@ class extension_class
|
||||
~extension_class();
|
||||
|
||||
// define constructors
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
inline void def(constructor<A1, A2, A3, A4, A5>)
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
inline void def(constructor<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>)
|
||||
// The following incantation builds a signature1, signature2,... object. It
|
||||
// should _all_ get optimized away.
|
||||
{ add_constructor(
|
||||
@@ -373,7 +373,12 @@ class extension_class
|
||||
prepend(type<A3>::id(),
|
||||
prepend(type<A4>::id(),
|
||||
prepend(type<A5>::id(),
|
||||
signature0()))))));
|
||||
prepend(type<A6>::id(),
|
||||
prepend(type<A7>::id(),
|
||||
prepend(type<A8>::id(),
|
||||
prepend(type<A9>::id(),
|
||||
prepend(type<A10>::id(),
|
||||
signature0())))))))))));
|
||||
}
|
||||
|
||||
|
||||
@@ -608,23 +613,33 @@ class extension_class
|
||||
|
||||
// A simple wrapper over a T which allows us to use extension_class<T> with a
|
||||
// single template parameter only. See extension_class<T>, above.
|
||||
template <class T>
|
||||
class held_instance : public T
|
||||
template <class Held>
|
||||
class held_instance : public Held
|
||||
{
|
||||
// There are no member functions: we want to avoid inadvertently overriding
|
||||
// any virtual functions in T.
|
||||
public:
|
||||
held_instance(PyObject*) : T() {}
|
||||
held_instance(PyObject*) : Held() {}
|
||||
template <class A1>
|
||||
held_instance(PyObject*, A1 a1) : T(a1) {}
|
||||
held_instance(PyObject*, A1 a1) : Held(a1) {}
|
||||
template <class A1, class A2>
|
||||
held_instance(PyObject*, A1 a1, A2 a2) : T(a1, a2) {}
|
||||
held_instance(PyObject*, A1 a1, A2 a2) : Held(a1, a2) {}
|
||||
template <class A1, class A2, class A3>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3) {}
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held(a1, a2, a3) {}
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {}
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held(a1, a2, a3, a4) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {}
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : Held(a1, a2, a3, a4, a5) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : Held(a1, a2, a3, a4, a5, a6) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : Held(a1, a2, a3, a4, a5, a6, a7) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : Held(a1, a2, a3, a4, a5, a6, a7, a8) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : Held(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : Held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
};
|
||||
|
||||
// Abstract base class for all obj holders. Base for template class
|
||||
@@ -676,6 +691,21 @@ public:
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
|
||||
m_held(p, a1, a2, a3, a4, a5) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
|
||||
public: // implementation of instance_holder_base required interface
|
||||
bool held_by_value() { return true; }
|
||||
@@ -829,4 +859,3 @@ std::vector<derived_class_info> class_registry<T>::static_derived_class_info;
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // EXTENSION_CLASS_DWA052000_H_
|
||||
|
||||
|
||||
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_
|
||||
@@ -110,11 +110,11 @@ template <class T, class A1, class A2> struct init2;
|
||||
template <class T, class A1, class A2, class A3> struct init3;
|
||||
template <class T, class A1, class A2, class A3, class A4> struct init4;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5> struct init5;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct Init6;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct Init7;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct Init8;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct Init9;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct Init10;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct init6;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct init7;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct init8;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct init9;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct init10;
|
||||
|
||||
template <class T>
|
||||
struct init_function
|
||||
@@ -165,7 +165,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
|
||||
return new Init6<T,
|
||||
return new init6<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -176,7 +176,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
|
||||
return new Init7<T,
|
||||
return new init7<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -188,7 +188,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
|
||||
return new Init8<T,
|
||||
return new init8<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -201,7 +201,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
|
||||
return new Init9<T,
|
||||
return new init9<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -215,7 +215,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
|
||||
return new Init10<T,
|
||||
return new init10<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -353,7 +353,7 @@ struct init5 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct Init6 : init
|
||||
struct init6 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -379,7 +379,7 @@ struct Init6 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
struct Init7 : init
|
||||
struct init7 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -407,7 +407,7 @@ struct Init7 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
struct Init8 : init
|
||||
struct init8 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -437,7 +437,7 @@ struct Init8 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
struct Init9 : init
|
||||
struct init9 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -469,7 +469,7 @@ struct Init9 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
struct Init10 : init
|
||||
struct init10 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
// (C) Copyright Ullrich Koethe and David Abrahams 2000-2001. Permission to
|
||||
// copy, use, modify, sell and distribute this software is granted provided
|
||||
// this copyright notice appears in all copies. This software is provided "as
|
||||
// is" without express or implied warranty, and with no claim as to its
|
||||
// suitability for any purpose.
|
||||
//
|
||||
// The authors gratefully acknowlege the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 23 Jan 2001 - Another stupid typo fix by Ralf W. Grosse-Kunstleve (David Abrahams)
|
||||
// 20 Jan 2001 - Added a fix from Ralf W. Grosse-Kunstleve (David Abrahams)
|
||||
#ifndef OPERATORS_UK112000_H_
|
||||
#define OPERATORS_UK112000_H_
|
||||
|
||||
@@ -7,7 +19,11 @@
|
||||
// When STLport is used with native streams, _STL::ostringstream().str() is not
|
||||
// _STL::string, but std::string. This confuses to_python(), so we'll use
|
||||
// strstream instead. Also, GCC 2.95.2 doesn't have sstream.
|
||||
# if defined(__SGI_STL_PORT) ? __SGI_STL_OWN_IOSTREAMS : !defined(__GNUC__) || __GNUC__ > 2
|
||||
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
# define BOOST_PYTHON_USE_SSTREAM
|
||||
# endif
|
||||
|
||||
#if defined(BOOST_PYTHON_USE_SSTREAM)
|
||||
# include <sstream>
|
||||
# else
|
||||
# include <strstream>
|
||||
@@ -468,6 +484,16 @@ namespace detail
|
||||
static const char * rname() { return "__rcmp__"; }
|
||||
};
|
||||
|
||||
# ifndef BOOST_PYTHON_USE_SSTREAM
|
||||
class unfreezer {
|
||||
public:
|
||||
unfreezer(std::ostrstream& s) : m_stream(s) {}
|
||||
~unfreezer() { m_stream.freeze(false); }
|
||||
private:
|
||||
std::ostrstream& m_stream;
|
||||
};
|
||||
# endif
|
||||
|
||||
// str(): Manual specialization needed because the string conversion does not follow
|
||||
// the standard pattern relized by the macros.
|
||||
template <>
|
||||
@@ -482,15 +508,16 @@ namespace detail
|
||||
|
||||
// When STLport is used with native streams, _STL::ostringstream().str() is not
|
||||
// _STL::string, but std::string.
|
||||
#if defined(__SGI_STL_PORT) ? __SGI_STL_OWN_IOSTREAMS : !defined(__GNUC__)
|
||||
# ifdef BOOST_PYTHON_USE_SSTREAM
|
||||
std::ostringstream s;
|
||||
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>());
|
||||
return BOOST_PYTHON_CONVERSION::to_python(s.str());
|
||||
#else
|
||||
# else
|
||||
std::ostrstream s;
|
||||
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()) << char();
|
||||
auto unfreezer unfreeze(s);
|
||||
return BOOST_PYTHON_CONVERSION::to_python(const_cast<char const *>(s.str()));
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
@@ -506,4 +533,5 @@ namespace detail
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# undef BOOST_PYTHON_USE_SSTREAM
|
||||
#endif /* OPERATORS_UK112000_H_ */
|
||||
|
||||
@@ -160,6 +160,25 @@ unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(char c)
|
||||
{
|
||||
return PyString_FromStringAndSize(&c, 1);
|
||||
}
|
||||
|
||||
char from_python(PyObject* p, boost::python::type<char>)
|
||||
{
|
||||
if (! PyString_Check(p)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expected string with exactly one character");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
const char* s = PyString_AsString(p);
|
||||
if (! s || s[0] == '\0' || s[1] != '\0') {
|
||||
PyErr_SetString(PyExc_ValueError, "expected string with exactly one character");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
return s[0];
|
||||
}
|
||||
|
||||
PyObject* to_python(unsigned char i)
|
||||
{
|
||||
return integer_to_python(i);
|
||||
|
||||
@@ -6,12 +6,12 @@ from gen_singleton import *
|
||||
from gen_extclass import *
|
||||
|
||||
def gen_all(args):
|
||||
open('callback.h', 'w').write(gen_callback(args))
|
||||
open('caller.h', 'w').write(gen_caller(args))
|
||||
open('init_function.h', 'w').write(gen_init_function(args))
|
||||
open('signatures.h', 'w').write(gen_signatures(args))
|
||||
open('instance.h', 'w').write(gen_singleton(args))
|
||||
open('extclass.h', 'w').write(gen_extclass(args))
|
||||
open('callback.hpp', 'w').write(gen_callback(args))
|
||||
open('caller.hpp', 'w').write(gen_caller(args))
|
||||
open('init_function.hpp', 'w').write(gen_init_function(args))
|
||||
open('signatures.hpp', 'w').write(gen_signatures(args))
|
||||
open('instance.hpp', 'w').write(gen_singleton(args))
|
||||
open('extension_class.hpp', 'w').write(gen_extclass(args))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user