mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
1 Commits
svn-branch
...
boost-1.21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9de57f922 |
@@ -4,7 +4,7 @@
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=bpl_static - Win32 Debug
|
||||
CFG=bpl_static - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
@@ -13,12 +13,13 @@ CFG=bpl_static - Win32 Debug
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "bpl_static.mak" CFG="bpl_static - Win32 Debug"
|
||||
!MESSAGE NMAKE /f "bpl_static.mak" CFG="bpl_static - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "bpl_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "bpl_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "bpl_static - Win32 DebugPython" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
@@ -63,8 +64,31 @@ 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 "..\..\.." /I "c:\tools\python\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
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "bpl_static - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "bpl_static___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "bpl_static___Win32_DebugPython"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE 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 CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /EHs /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@@ -80,6 +104,7 @@ LIB32=link.exe -lib
|
||||
|
||||
# Name "bpl_static - Win32 Release"
|
||||
# Name "bpl_static - Win32 Debug"
|
||||
# Name "bpl_static - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
@@ -30,6 +30,40 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "getting_started1"=.\getting_started1\getting_started1.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name bpl_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "getting_started2"=.\getting_started2\getting_started2.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
getting_started2
|
||||
.\getting_started2
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name bpl_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "rwgk1"=.\rwgk1\rwgk1.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
BIN
build/build.opt
Normal file
BIN
build/build.opt
Normal file
Binary file not shown.
@@ -1,3 +1,7 @@
|
||||
# Revision History:
|
||||
# 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams)
|
||||
# 04 Mar 01 Changed library name to libboost_python.a (David Abrahams)
|
||||
|
||||
LIBSRC = \
|
||||
classes.cpp \
|
||||
conversions.cpp \
|
||||
@@ -30,8 +34,8 @@ endif
|
||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
example1: example1.o libpycpp.a
|
||||
como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lpycpp
|
||||
example1: example1.o libboost_python.a
|
||||
como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYTHON_LIB) example1.o -L. -lboost_python
|
||||
python ../example/test_example1.py
|
||||
|
||||
example1.o: ../example/example1.cpp
|
||||
@@ -40,9 +44,9 @@ example1.o: ../example/example1.cpp
|
||||
clean:
|
||||
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||
|
||||
libpycpp.a: $(LIBOBJ)
|
||||
rm -f libpycpp.a
|
||||
ar cq libpycpp.a $(LIBOBJ)
|
||||
libboost_python.a: $(LIBOBJ)
|
||||
rm -f libboost_python.a
|
||||
ar cq libboost_python.a $(LIBOBJ)
|
||||
|
||||
DEP = $(OBJ:.o=.d)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=example1 - Win32 Debug
|
||||
CFG=example1 - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
@@ -13,12 +13,13 @@ CFG=example1 - Win32 Debug
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "example1.mak" CFG="example1 - Win32 Debug"
|
||||
!MESSAGE NMAKE /f "example1.mak" CFG="example1 - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "example1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "example1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "example1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
@@ -68,8 +69,8 @@ LINK32=link.exe
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
@@ -79,7 +80,34 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "example1 - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "example1___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "example1___Win32_DebugPython"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /EHs /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/hello_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||
|
||||
!ENDIF
|
||||
|
||||
@@ -87,6 +115,7 @@ LINK32=link.exe
|
||||
|
||||
# Name "example1 - Win32 Release"
|
||||
# Name "example1 - Win32 Debug"
|
||||
# Name "example1 - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
73
build/gcc.mak
Normal file
73
build/gcc.mak
Normal file
@@ -0,0 +1,73 @@
|
||||
# Revision History
|
||||
|
||||
# 04 Mar 01 Changed library name to libboost_python.a, various cleanups,
|
||||
# attempted Cygwin compatibility. Still needs testing on Linux
|
||||
# (David Abrahams)
|
||||
|
||||
|
||||
LIBSRC = \
|
||||
classes.cpp \
|
||||
conversions.cpp \
|
||||
extension_class.cpp \
|
||||
functions.cpp \
|
||||
init_function.cpp \
|
||||
module_builder.cpp \
|
||||
objects.cpp \
|
||||
types.cpp
|
||||
|
||||
LIBOBJ = $(LIBSRC:.cpp=.o)
|
||||
OBJ = $(LIBOBJ)
|
||||
|
||||
PYTHON_INC=$(ROOT)/usr/local/include/python2.0
|
||||
# libpython2.0.dll
|
||||
|
||||
ifeq "$(OS)" "Windows_NT"
|
||||
ROOT=c:/cygnus
|
||||
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -I$(PYTHON_INC)
|
||||
MODULE_EXTENSION=dll
|
||||
PYTHON_LIB=c:/cygnus/usr/local/lib/python2.0/config/libpython2.0.dll.a
|
||||
else
|
||||
INC = -I$(PYTHON_INC)
|
||||
MODULE_EXTENSION=so
|
||||
endif
|
||||
|
||||
%.o: ../src/%.cpp
|
||||
g++ -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
%.d: ../src/%.cpp
|
||||
@echo creating $@
|
||||
@set -e; g++ -M $(INC) -c $< \
|
||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
|
||||
PYTHON = python
|
||||
|
||||
test: comprehensive.o libboost_python.a
|
||||
g++ $(CXXFLAGS) -shared -o ../test/boost_python_test.$(MODULE_EXTENSION) comprehensive.o -L. -lboost_python $(PYTHON_LIB)
|
||||
$(PYTHON) ../test/comprehensive.py
|
||||
|
||||
comprehensive.o: ../test/comprehensive.cpp
|
||||
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
|
||||
example1: example1.o libboost_python.a
|
||||
g++ $(CXXFLAGS) -shared -o ../example/hellomodule.$(MODULE_EXTENSION) example1.o -L. -lboost_python $(PYTHON_LIB)
|
||||
$(PYTHON) ../example/test_example1.py
|
||||
|
||||
example1.o: ../example/example1.cpp
|
||||
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||
|
||||
libboost_python.a: $(LIBOBJ)
|
||||
rm -f libboost_python.a
|
||||
ar cq libboost_python.a $(LIBOBJ)
|
||||
|
||||
DEP = $(OBJ:.o=.d)
|
||||
|
||||
ifneq "$(MAKECMDGOALS)" "clean"
|
||||
include $(DEP)
|
||||
endif
|
||||
166
build/linux_gcc.mak
Normal file
166
build/linux_gcc.mak
Normal file
@@ -0,0 +1,166 @@
|
||||
# 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 BOOST 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
|
||||
|
||||
BOOST= /net/cci/rwgk/boost
|
||||
|
||||
PYEXE= /usr/local/Python-1.5.2/bin/python
|
||||
PYINC= -I/usr/local/Python-1.5.2/include/python1.5
|
||||
#PYEXE= /usr/local/Python-2.0/bin/python
|
||||
#PYINC= -I/usr/local/Python-2.0/include/python2.0
|
||||
#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=
|
||||
# use -msg_display_number to obtain integer tags for -msg_disable
|
||||
|
||||
CPP= g++
|
||||
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
||||
$(STDOPTS) $(WARNOPTS) -g
|
||||
MAKEDEP= -M
|
||||
|
||||
LD= g++
|
||||
LDOPTS= -shared
|
||||
|
||||
#HIDDEN= -hidden
|
||||
|
||||
BPL_SRC = $(BOOST)/libs/python/src
|
||||
BPL_TST = $(BOOST)/libs/python/test
|
||||
BPL_EXA = $(BOOST)/libs/python/example
|
||||
SOFTLINKS = \
|
||||
$(BPL_SRC)/classes.cpp \
|
||||
$(BPL_SRC)/conversions.cpp \
|
||||
$(BPL_SRC)/extension_class.cpp \
|
||||
$(BPL_SRC)/functions.cpp \
|
||||
$(BPL_SRC)/init_function.cpp \
|
||||
$(BPL_SRC)/module_builder.cpp \
|
||||
$(BPL_SRC)/objects.cpp \
|
||||
$(BPL_SRC)/types.cpp \
|
||||
$(BPL_TST)/comprehensive.cpp \
|
||||
$(BPL_TST)/comprehensive.hpp \
|
||||
$(BPL_TST)/comprehensive.py \
|
||||
$(BPL_TST)/doctest.py \
|
||||
$(BPL_EXA)/abstract.cpp \
|
||||
$(BPL_EXA)/getting_started1.cpp \
|
||||
$(BPL_EXA)/getting_started2.cpp \
|
||||
$(BPL_EXA)/getting_started3.cpp \
|
||||
$(BPL_EXA)/getting_started4.cpp \
|
||||
$(BPL_EXA)/getting_started5.cpp \
|
||||
$(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
|
||||
|
||||
OBJ = classes.o conversions.o extension_class.o functions.o \
|
||||
init_function.o module_builder.o \
|
||||
objects.o types.o
|
||||
DEPOBJ= $(OBJ) comprehensive.o abstract.o \
|
||||
getting_started1.o getting_started2.o getting_started3.o \
|
||||
getting_started4.o getting_started5.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
all: libboost_python.a boost_python_test.so abstract.so \
|
||||
getting_started1.so getting_started2.so getting_started3.so \
|
||||
getting_started4.so getting_started5.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
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
rm -f libboost_python.a
|
||||
ar r libboost_python.a $(OBJ)
|
||||
|
||||
boost_python_test.so: $(OBJ) comprehensive.o
|
||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
||||
|
||||
abstract.so: $(OBJ) abstract.o
|
||||
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
||||
|
||||
getting_started1.so: $(OBJ) getting_started1.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
||||
|
||||
getting_started2.so: $(OBJ) getting_started2.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
||||
|
||||
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
|
||||
|
||||
.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) libboost_python.a libboost_python.a.input
|
||||
rm -f comprehensive.o boost_python_test.so
|
||||
rm -f abstract.o abstract.so
|
||||
rm -f getting_started1.o getting_started1.so
|
||||
rm -f getting_started2.o getting_started2.so
|
||||
rm -f getting_started3.o getting_started3.so
|
||||
rm -f getting_started4.o getting_started4.so
|
||||
rm -f getting_started5.o getting_started5.so
|
||||
rm -f so_locations *.pyc
|
||||
rm -rf cxx_repository
|
||||
|
||||
depend:
|
||||
@ cat Makefile.nodepend; \
|
||||
for obj in $(DEPOBJ); \
|
||||
do \
|
||||
bn=`echo "$$obj" | cut -d. -f1`; \
|
||||
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
||||
done
|
||||
|
||||
210
build/mingw32.mak
Normal file
210
build/mingw32.mak
Normal file
@@ -0,0 +1,210 @@
|
||||
# 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 BOOST_* pathnames below.
|
||||
#
|
||||
# The idea is that the build directory is on a Unix filesystem that
|
||||
# is mounted on a PC using SAMBA. Use this makefile under both Unix
|
||||
# and Windows:
|
||||
#
|
||||
# Unix: make softlinks Create softlinks to source code and tests
|
||||
# Win: make Compile all sources
|
||||
# Win: make test Run doctest tests
|
||||
# Unix: make clean Remove all object files
|
||||
# Unix: make unlink Remove softlinks
|
||||
|
||||
# To install mingw32, follow instructions at:
|
||||
# http://starship.python.net/crew/kernr/mingw32/Notes.html
|
||||
# In particular, install:
|
||||
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/gcc-2.95.2-msvcrt.exe
|
||||
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/fixes/quote-fix-msvcrt.exe
|
||||
# http://starship.python.net/crew/kernr/mingw32/Python-1.5.2-mingw32.zip
|
||||
# Unpack the first two archives in the default locations and update your PATH.
|
||||
# Unpack the third archive in \usr.
|
||||
|
||||
# Note: comprehensive.cpp generates compiler errors and later crashes.
|
||||
# L:\boost\boost\python\detail\extension_class.hpp:643: warning:
|
||||
# alignment of `vtable for class
|
||||
# boost::python::detail::held_instance<bpl_test::Derived1>'
|
||||
# is greater than maximum object file alignment. Using 16.
|
||||
# Could this be fixed with compiler options?
|
||||
# -fhuge-objects looks interesting, but requires recompiling the C++ library.
|
||||
# (what exactly does that mean?)
|
||||
# -fvtable-thunks eliminates the compiler warning,
|
||||
# but "import boost_python_test" still causes a crash.
|
||||
|
||||
BOOST_UNIX= /net/cci/rwgk/boost
|
||||
BOOST_WIN= "L:\boost"
|
||||
|
||||
PYEXE= "C:\Program files\Python\python.exe"
|
||||
PYINC= -I"C:\usr\include\python1.5"
|
||||
PYLIB= "C:\usr\lib\libpython15.a"
|
||||
|
||||
STDOPTS= -ftemplate-depth-21
|
||||
WARNOPTS=
|
||||
|
||||
CPP= g++
|
||||
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \
|
||||
$(STDOPTS) $(WARNOPTS) -g
|
||||
|
||||
LD= g++
|
||||
LDOPTS= -shared
|
||||
|
||||
BPL_SRC = $(BOOST_UNIX)/libs/python/src
|
||||
BPL_TST = $(BOOST_UNIX)/libs/python/test
|
||||
BPL_EXA = $(BOOST_UNIX)/libs/python/example
|
||||
SOFTLINKS = \
|
||||
$(BPL_SRC)/classes.cpp \
|
||||
$(BPL_SRC)/conversions.cpp \
|
||||
$(BPL_SRC)/extension_class.cpp \
|
||||
$(BPL_SRC)/functions.cpp \
|
||||
$(BPL_SRC)/init_function.cpp \
|
||||
$(BPL_SRC)/module_builder.cpp \
|
||||
$(BPL_SRC)/objects.cpp \
|
||||
$(BPL_SRC)/types.cpp \
|
||||
$(BPL_TST)/comprehensive.cpp \
|
||||
$(BPL_TST)/comprehensive.hpp \
|
||||
$(BPL_TST)/comprehensive.py \
|
||||
$(BPL_TST)/doctest.py \
|
||||
$(BPL_EXA)/abstract.cpp \
|
||||
$(BPL_EXA)/getting_started1.cpp \
|
||||
$(BPL_EXA)/getting_started2.cpp \
|
||||
$(BPL_EXA)/getting_started3.cpp \
|
||||
$(BPL_EXA)/getting_started4.cpp \
|
||||
$(BPL_EXA)/getting_started5.cpp \
|
||||
$(BPL_EXA)/passing_char.cpp \
|
||||
$(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
|
||||
|
||||
DEFS= \
|
||||
boost_python_test \
|
||||
abstract \
|
||||
getting_started1 \
|
||||
getting_started2 \
|
||||
getting_started3 \
|
||||
getting_started4 \
|
||||
getting_started5
|
||||
|
||||
OBJ = classes.o conversions.o extension_class.o functions.o \
|
||||
init_function.o module_builder.o \
|
||||
objects.o types.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
all: libboost_python.a boost_python_test.pyd abstract.pyd \
|
||||
getting_started1.pyd getting_started2.pyd getting_started3.pyd \
|
||||
getting_started4.pyd getting_started5.pyd
|
||||
|
||||
softlinks: defs
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ ! -e "$$bn" ]; then \
|
||||
echo "ln -s $$pn ."; \
|
||||
ln -s "$$pn" .; \
|
||||
else \
|
||||
echo "info: no softlink created (file exists): $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
unlink: rmdefs
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ -L "$$bn" ]; then \
|
||||
echo "rm $$bn"; \
|
||||
rm "$$bn"; \
|
||||
elif [ -e "$$bn" ]; then \
|
||||
echo "info: not a softlink: $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
defs:
|
||||
@ for def in $(DEFS); \
|
||||
do \
|
||||
echo "EXPORTS\n\tinit$$def" > $$def.def; \
|
||||
done
|
||||
|
||||
rmdefs:
|
||||
@ for def in $(DEFS); \
|
||||
do \
|
||||
rm $$def.def; \
|
||||
done
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
del libboost_python.a
|
||||
ar r libboost_python.a $(OBJ)
|
||||
|
||||
DLLWRAPOPTS= -s --driver-name g++ -s
|
||||
--entry _DllMainCRTStartup@12 --target=i386-mingw32
|
||||
|
||||
boost_python_test.pyd: $(OBJ) comprehensive.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname boost_python_test.pyd \
|
||||
--def boost_python_test.def \
|
||||
$(OBJ) comprehensive.o $(PYLIB)
|
||||
|
||||
abstract.pyd: $(OBJ) abstract.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname abstract.pyd \
|
||||
--def abstract.def \
|
||||
$(OBJ) abstract.o $(PYLIB)
|
||||
|
||||
getting_started1.pyd: $(OBJ) getting_started1.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started1.pyd \
|
||||
--def getting_started1.def \
|
||||
$(OBJ) getting_started1.o $(PYLIB)
|
||||
|
||||
getting_started2.pyd: $(OBJ) getting_started2.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started2.pyd \
|
||||
--def getting_started2.def \
|
||||
$(OBJ) getting_started2.o $(PYLIB)
|
||||
|
||||
getting_started3.pyd: $(OBJ) getting_started3.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started3.pyd \
|
||||
--def getting_started3.def \
|
||||
$(OBJ) getting_started3.o $(PYLIB)
|
||||
|
||||
getting_started4.pyd: $(OBJ) getting_started4.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started4.pyd \
|
||||
--def getting_started4.def \
|
||||
$(OBJ) getting_started4.o $(PYLIB)
|
||||
|
||||
getting_started5.pyd: $(OBJ) getting_started5.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started5.pyd \
|
||||
--def getting_started5.def \
|
||||
$(OBJ) getting_started5.o $(PYLIB)
|
||||
|
||||
.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) libboost_python.a libboost_python.a.input
|
||||
rm -f comprehensive.o boost_python_test.pyd
|
||||
rm -f abstract.o abstract.pyd
|
||||
rm -f getting_started1.o getting_started1.pyd
|
||||
rm -f getting_started2.o getting_started2.pyd
|
||||
rm -f getting_started3.o getting_started3.pyd
|
||||
rm -f getting_started4.o getting_started4.pyd
|
||||
rm -f getting_started5.o getting_started5.pyd
|
||||
rm -f so_locations *.pyc
|
||||
rm -rf cxx_repository
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=rwgk1 - Win32 Debug
|
||||
CFG=rwgk1 - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
@@ -13,12 +13,13 @@ CFG=rwgk1 - Win32 Debug
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "rwgk1.mak" CFG="rwgk1 - Win32 Debug"
|
||||
!MESSAGE NMAKE /f "rwgk1.mak" CFG="rwgk1 - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "rwgk1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "rwgk1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "rwgk1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
@@ -65,9 +66,10 @@ LINK32=link.exe
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
@@ -77,7 +79,34 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "rwgk1 - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "rwgk1___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "rwgk1___Win32_DebugPython"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/rwgk1_d.dll" /pdbtype:sept /libpath:"C:\tools\python\src\PCbuild"
|
||||
|
||||
!ENDIF
|
||||
|
||||
@@ -85,6 +114,7 @@ LINK32=link.exe
|
||||
|
||||
# Name "rwgk1 - Win32 Release"
|
||||
# Name "rwgk1 - Win32 Debug"
|
||||
# Name "rwgk1 - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=test - Win32 Debug
|
||||
CFG=test - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
@@ -13,12 +13,13 @@ CFG=test - Win32 Debug
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug"
|
||||
!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "test - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
@@ -44,6 +45,7 @@ RSC=rc.exe
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /Zm200 /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
@@ -53,7 +55,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/boost_python_test.dll" /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "test - Win32 Debug"
|
||||
|
||||
@@ -68,8 +70,9 @@ LINK32=link.exe
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
@@ -79,7 +82,36 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/boost_python_test.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "test - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "test___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "test___Win32_DebugPython"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /Zm200 /EHs /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/boost_python_test_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
@@ -88,6 +120,7 @@ LINK32=link.exe
|
||||
|
||||
# Name "test - Win32 Release"
|
||||
# Name "test - Win32 Debug"
|
||||
# Name "test - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
170
build/tru64_cxx.mak
Normal file
170
build/tru64_cxx.mak
Normal file
@@ -0,0 +1,170 @@
|
||||
# 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 BOOST 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
|
||||
|
||||
BOOST= /net/cci/rwgk/boost
|
||||
|
||||
PYEXE= /usr/local/Python-1.5.2/bin/python
|
||||
PYINC= -I/usr/local/Python-1.5.2/include/python1.5
|
||||
#PYEXE= /usr/local/Python-2.0/bin/python
|
||||
#PYINC= -I/usr/local/Python-2.0/include/python2.0
|
||||
#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$(BOOST) $(PYINC) \
|
||||
$(STDOPTS) $(WARNOPTS) -g
|
||||
MAKEDEP= -Em
|
||||
|
||||
LD= cxx
|
||||
LDOPTS= -shared -expect_unresolved 'Py*' -expect_unresolved '_Py*'
|
||||
|
||||
#HIDDEN= -hidden
|
||||
|
||||
BPL_SRC = $(BOOST)/libs/python/src
|
||||
BPL_TST = $(BOOST)/libs/python/test
|
||||
BPL_EXA = $(BOOST)/libs/python/example
|
||||
SOFTLINKS = \
|
||||
$(BPL_SRC)/classes.cpp \
|
||||
$(BPL_SRC)/conversions.cpp \
|
||||
$(BPL_SRC)/extension_class.cpp \
|
||||
$(BPL_SRC)/functions.cpp \
|
||||
$(BPL_SRC)/init_function.cpp \
|
||||
$(BPL_SRC)/module_builder.cpp \
|
||||
$(BPL_SRC)/objects.cpp \
|
||||
$(BPL_SRC)/types.cpp \
|
||||
$(BPL_TST)/comprehensive.cpp \
|
||||
$(BPL_TST)/comprehensive.hpp \
|
||||
$(BPL_TST)/comprehensive.py \
|
||||
$(BPL_TST)/doctest.py \
|
||||
$(BPL_EXA)/abstract.cpp \
|
||||
$(BPL_EXA)/getting_started1.cpp \
|
||||
$(BPL_EXA)/getting_started2.cpp \
|
||||
$(BPL_EXA)/getting_started3.cpp \
|
||||
$(BPL_EXA)/getting_started4.cpp \
|
||||
$(BPL_EXA)/getting_started5.cpp \
|
||||
$(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
|
||||
|
||||
OBJ = classes.o conversions.o extension_class.o functions.o \
|
||||
init_function.o module_builder.o \
|
||||
objects.o types.o
|
||||
DEPOBJ= $(OBJ) comprehensive.o abstract.o \
|
||||
getting_started1.o getting_started2.o getting_started3.o \
|
||||
getting_started4.o getting_started5.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
all: libboost_python.a boost_python_test.so abstract.so \
|
||||
getting_started1.so getting_started2.so getting_started3.so \
|
||||
getting_started4.so getting_started5.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
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
rm -f libboost_python.a
|
||||
cd cxx_repository; \
|
||||
ls -1 > ../libboost_python.a.input; \
|
||||
ar r ../libboost_python.a -input ../libboost_python.a.input
|
||||
rm -f libboost_python.a.input
|
||||
ar r libboost_python.a $(OBJ)
|
||||
|
||||
boost_python_test.so: $(OBJ) comprehensive.o
|
||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
||||
|
||||
abstract.so: $(OBJ) abstract.o
|
||||
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
||||
|
||||
getting_started1.so: $(OBJ) getting_started1.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
||||
|
||||
getting_started2.so: $(OBJ) getting_started2.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
||||
|
||||
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
|
||||
|
||||
.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) libboost_python.a libboost_python.a.input
|
||||
rm -f comprehensive.o boost_python_test.so
|
||||
rm -f abstract.o abstract.so
|
||||
rm -f getting_started1.o getting_started1.so
|
||||
rm -f getting_started2.o getting_started2.so
|
||||
rm -f getting_started3.o getting_started3.so
|
||||
rm -f getting_started4.o getting_started4.so
|
||||
rm -f getting_started5.o getting_started5.so
|
||||
rm -f so_locations *.pyc
|
||||
rm -rf cxx_repository
|
||||
|
||||
depend:
|
||||
@ cat Makefile.nodepend; \
|
||||
for obj in $(DEPOBJ); \
|
||||
do \
|
||||
bn=`echo "$$obj" | cut -d. -f1`; \
|
||||
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
||||
done
|
||||
|
||||
157
doc/building.html
Normal file
157
doc/building.html
Normal file
@@ -0,0 +1,157 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
|
||||
<title>Building an Extension Module</title>
|
||||
|
||||
<div>
|
||||
<h1><img width="277" height="86" id="_x0000_i1025" align="center" src=
|
||||
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Building an
|
||||
Extension Module</h1>
|
||||
|
||||
<p>The build process for Boost is currently undergoing some evolution,
|
||||
and, it is to be hoped, improvement. The following facts may help:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Makefiles for various platforms reside in the Boost subdirectory
|
||||
<tt>libs/python/build</tt>:
|
||||
|
||||
<ul>
|
||||
<li><a href="../build/como.mak">como.mak</a> (Comeau C++ on Linux)
|
||||
|
||||
<li><a href="../build/linux_gcc.mak">linux_gcc.mak</a> (GCC on
|
||||
Linux/Unix)
|
||||
|
||||
<li><a href="../build/gcc.mak">gcc.mak</a> (older makefile for GCC
|
||||
on Linux/Unix. Deprecated.)
|
||||
|
||||
<li><a href="../build/mingw32.mak">mingw32.mak</a>
|
||||
(highly-specialized makefile for mingw32 (Win32-targeted) GCC. Read
|
||||
the header comment).
|
||||
|
||||
<li><a href="../build/tru64_cxx.mak">tru64_cxx.mak</a> (Compaq
|
||||
Alpha).
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<li>
|
||||
A project workspace for Microsoft Visual Studio is provided at <tt><a
|
||||
href="../build/build.dsw">libs/python/build/build.dsw</a></tt>. The
|
||||
include paths for this project may need to be changed for your
|
||||
installation. They currently assume that python has been installed at
|
||||
<tt>c:\tools\python</tt>. Three configurations of all targets are
|
||||
supported:
|
||||
|
||||
<ul>
|
||||
<li>Release (optimization, <tt>-DNDEBUG</tt>)
|
||||
|
||||
<li>Debug (no optimization <tt>-D_DEBUG</tt>)
|
||||
|
||||
<li>DebugPython (no optimization, <tt>-D_DEBUG
|
||||
-DBOOST_DEBUG_PYTHON</tt>)
|
||||
</ul>
|
||||
|
||||
<p>When extension modules are built with Visual C++ using
|
||||
<tt>-D_DEBUG</tt>, Python defaults to <i>force</i> linking with a
|
||||
special debugging version of the Python DLL. Since this debug DLL
|
||||
isn't supplied with the default Python installation for Windows,
|
||||
Boost.Python uses <tt><a href=
|
||||
"../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a></tt>
|
||||
to temporarily undefine <tt>_DEBUG</tt> when <tt>Python.h</tt> is
|
||||
<tt>#include</tt>d.
|
||||
|
||||
<p>If you want the extra runtime checks available with the debugging
|
||||
version of the library, <tt>#define BOOST_DEBUG_PYTHON</tt> to
|
||||
re-enable library forcing, and link with the DebugPython version of
|
||||
<tt>boost_python.lib</tt>. You'll need to get the debugging version
|
||||
of the Python executable (<tt>python_d.exe</tt>) and DLL
|
||||
(<tt>python20_d.dll</tt> or <tt>python15_d.dll</tt>). The Python
|
||||
sources include project files for building these. If you <a href=
|
||||
"http://www.python.org">download</a> them, change the name of the
|
||||
top-level directory to <tt>src</tt>, and install it under
|
||||
<tt>c:\tools\python</tt>, the workspace supplied by Boost.Python will
|
||||
be able to use it without modification. Just open
|
||||
<tt>c:\tools\python\src\pcbuild\pcbuild.dsw</tt> and invoke "build
|
||||
all" to generate all the debugging targets.
|
||||
|
||||
<p>If you do not <tt>#define BOOST_DEBUG_PYTHON</tt>, be sure that
|
||||
any source files <tt>#include <<a href=
|
||||
"../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a>></tt>
|
||||
instead of the usual <tt>Python.h</tt>, or you will have link
|
||||
incompatibilities.<br>
|
||||
<br>
|
||||
|
||||
|
||||
<li>
|
||||
The makefiles and Visual Studio project can all build at least the
|
||||
following:
|
||||
|
||||
<ul>
|
||||
<li>The <tt>boost_python</tt> library for static linking with your
|
||||
extension module. On the various Unices, this library will be
|
||||
called <tt>libboost_python.a</tt>. On Win32 platforms, the library
|
||||
will be called <tt>boost_python.lib</tt>.
|
||||
|
||||
<li>A comprehensive test of Boost.Python features. This test builds
|
||||
a Boost.Python extension module, then runs Python to import the
|
||||
module, and runs a series of tests on it using <tt><a href=
|
||||
"../test/doctest.py">doctest</a></tt>. Source code for the module
|
||||
and tests is available in the Boost subdirectory
|
||||
<tt>libs/python/test</tt>.<br>
|
||||
|
||||
|
||||
<li>Various examples from the Boost subdirectory
|
||||
<tt>libs/python/example</tt>. Which examples are built currently
|
||||
depends on the platform. The most up-to-date examples are
|
||||
<tt>getting_started</tt><i>n</i><tt>.cpp</tt> from <a href=
|
||||
"http://cci.lbl.gov/staff/ralf_grosse-kunstleve.html">Ralf W.
|
||||
Grosse-Kunstleve</a>. All these examples include a doctest modeled
|
||||
on the comprehensive test above.<br>
|
||||
<br>
|
||||
|
||||
</ul>
|
||||
|
||||
<li>
|
||||
If your platform isn't directly supported, you can build a static
|
||||
library from the following source files (in the Boost subdirectory
|
||||
<tt>libs/python/src</tt>), or compile them directly and link the
|
||||
resulting objects into your extension module:
|
||||
|
||||
<ul>
|
||||
<li><a href=
|
||||
"../../../libs/python/src/extension_class.cpp">extension_class.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/functions.cpp">functions.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/init_function.cpp">init_function.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/module_builder.cpp">module_builder.cpp</a>
|
||||
|
||||
<li><a href="../../../libs/python/src/types.cpp">types.cpp</a>
|
||||
|
||||
<li><a href="../../../libs/python/src/objects.cpp">objects.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/conversions.cpp">conversions.cpp</a>
|
||||
|
||||
<li><a href="../../../libs/python/src/classes.cpp">classes.cpp</a>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<p>Next: <a href="enums.html">Wrapping Enums</a> Previous: <a href=
|
||||
"under-the-hood.html">A Peek Under the Hood</a> Up: <a href=
|
||||
"index.html">Top</a>
|
||||
|
||||
<p>© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as is'' without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
|
||||
<p>Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Comparisons with
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
||||
Comparisons with
|
||||
Other Systems
|
||||
</h1>
|
||||
|
||||
<h2>CXX</h2>
|
||||
<p>
|
||||
Like BPL, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
||||
Like Boost.Python, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
||||
provide a C++-oriented interface to Python. In most cases, as with the
|
||||
boost library, it relieves the user from worrying about
|
||||
reference-counts. Both libraries automatically convert thrown C++
|
||||
@@ -40,9 +41,15 @@
|
||||
<p>
|
||||
As far as I can tell, CXX enables one to write what is essentially
|
||||
idiomatic Python code in C++, manipulating Python objects through the
|
||||
same fully-generic interfaces we use in Python. While you're hardly programming directly to the ``bare
|
||||
metal'' with CXX, it basically presents a ``C++-ized''
|
||||
version of the Python 'C' API.
|
||||
same fully-generic interfaces we use in Python. While you're hardly
|
||||
programming directly to the ``bare metal'' with CXX, it basically
|
||||
presents a ``C++-ized'' version of the Python 'C' API. Some fraction of
|
||||
that capability is available in Boost.Python through <tt><a
|
||||
href="../../../boost/python/objects.hpp">boost/python/objects.hpp</a></tt>,
|
||||
which provides C++ objects corresponding to Python lists, tuples,
|
||||
strings, and dictionaries, and through <tt><a
|
||||
href="../../../boost/python/callback.hpp">boost/python/callback.hpp</a></tt>,
|
||||
which allows you to call back into python with C++ arguments.
|
||||
|
||||
<p>
|
||||
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
|
||||
@@ -65,7 +72,7 @@ that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
languages. Swig relies on a parser to read your source code and produce
|
||||
additional source code files which can be compiled into a Python (or
|
||||
Perl or Tcl) extension module. It has been successfully used to create
|
||||
many Python extension modules. Like BPL, SWIG is trying to allow an
|
||||
many Python extension modules. Like Boost.Python, SWIG is trying to allow an
|
||||
existing interface to be wrapped with little or no change to the
|
||||
existing code. The documentation says ``SWIG parses a form of ANSI C
|
||||
syntax that has been extended with a number of special directives. As a
|
||||
@@ -78,15 +85,15 @@ that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
couldnt handle templates, didnt do func overloading properly etc. For
|
||||
ANSI C libraries this was fine. But for usual C++ code this was a
|
||||
problem. Simple things work. But for anything very complicated (or
|
||||
realistic), one had to write code by hand. I believe BPL doesn't have
|
||||
realistic), one had to write code by hand. I believe Boost.Python doesn't have
|
||||
this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
|
||||
wrap correctly.''<br><i>-Prabhu Ramachandran</i>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
By contrast, BPL doesn't attempt to parse C++ - the problem is simply
|
||||
By contrast, Boost.Python doesn't attempt to parse C++ - the problem is simply
|
||||
too complex to do correctly. <a name="sic">Technically</a>, one does
|
||||
write code by hand to use BPL. The goal, however, has been to make
|
||||
write code by hand to use Boost.Python. The goal, however, has been to make
|
||||
that code nearly as simple as listing the names of the classes and
|
||||
member functions you want to expose in Python.
|
||||
|
||||
@@ -95,7 +102,7 @@ that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
<a
|
||||
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
|
||||
is a system similar to SWIG, though seemingly more
|
||||
C++-oriented. The author says that like BPL, SIP supports overriding
|
||||
C++-oriented. The author says that like Boost.Python, SIP supports overriding
|
||||
extension class member functions in Python subclasses. It appears to
|
||||
have been designed specifically to directly support some features of
|
||||
PyQt/PyKDE, which is its primary client. Documentation is almost
|
||||
@@ -113,7 +120,7 @@ that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
to a wide range of computer languages, including Common Lisp, C++, C,
|
||||
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
|
||||
header file describing the interface, of which the user is expected to
|
||||
provide an implementation. Unlike BPL, this means that the system
|
||||
provide an implementation. Unlike Boost.Python, this means that the system
|
||||
imposes implementation details on your C++ code at the deepest level. It
|
||||
is worth noting that some of the C++ names generated by ILU are supposed
|
||||
to be reserved to the C++ implementation. It is unclear from the
|
||||
@@ -148,7 +155,7 @@ an inheritance relationship?
|
||||
<h2>Zope ExtensionClasses</h2>
|
||||
<p>
|
||||
<a href="http:http://www.digicool.com/releases/ExtensionClass">
|
||||
ExtensionClasses in Zope</a> use the same underlying mechanism as BPL
|
||||
ExtensionClasses in Zope</a> use the same underlying mechanism as Boost.Python
|
||||
to support subclassing of extension types in Python, including
|
||||
multiple-inheritance. Both systems support pickling/unpickling of
|
||||
extension class instances in very similar ways. Both systems rely on the
|
||||
@@ -158,31 +165,35 @@ an inheritance relationship?
|
||||
<p>
|
||||
The major differences are:
|
||||
<ul>
|
||||
<li>Zope is entirely 'C' language-based. It doesn't require a C++
|
||||
compiler, so it's much more portable than Boost.Python, which stresses
|
||||
the limits of even some modern C++ implementations.
|
||||
|
||||
<li>
|
||||
BPL lifts the burden on the user to parse and convert function
|
||||
Boost.Python lifts the burden on the user to parse and convert function
|
||||
argument types. Zope provides no such facility.
|
||||
<li>
|
||||
BPL lifts the burden on the user to maintain Python
|
||||
Boost.Python lifts the burden on the user to maintain Python
|
||||
reference-counts.
|
||||
<li>
|
||||
BPL supports function overloading; Zope does not.
|
||||
Boost.Python supports function overloading; Zope does not.
|
||||
<li>
|
||||
BPL supplies a simple mechanism for exposing read-only and
|
||||
Boost.Python supplies a simple mechanism for exposing read-only and
|
||||
read/write access to data members of the wrapped C++ type as Python
|
||||
attributes.
|
||||
<li>
|
||||
Writing a Zope ExtensionClass is significantly more complex than
|
||||
exposing a C++ class to python using BPL (mostly a summary of the
|
||||
exposing a C++ class to python using Boost.Python (mostly a summary of the
|
||||
previous 4 items). <a href=
|
||||
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
|
||||
Zope Example</a> illustrates the differences.
|
||||
<li>
|
||||
Zope's ExtensionClasses are specifically motivated by ``the need for a
|
||||
C-based persistence mechanism''. BPL's are motivated by the desire
|
||||
C-based persistence mechanism''. Boost.Python's are motivated by the desire
|
||||
to simply reflect a C++ API into Python with as little modification as
|
||||
possible.
|
||||
<li>
|
||||
The following Zope restriction does not apply to BPL: ``At most one
|
||||
The following Zope restriction does not apply to Boost.Python: ``At most one
|
||||
base extension direct or indirect super class may define C data
|
||||
members. If an extension subclass inherits from multiple base
|
||||
extension classes, then all but one must be mix-in classes that
|
||||
@@ -191,21 +202,21 @@ an inheritance relationship?
|
||||
Zope requires use of the somewhat funky inheritedAttribute (search for
|
||||
``inheritedAttribute'' on <a
|
||||
href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
|
||||
method to access base class methods. In BPL, base class methods can
|
||||
method to access base class methods. In Boost.Python, base class methods can
|
||||
be accessed in the usual way by writing
|
||||
``<code>BaseClass.method</code>''.
|
||||
<li>
|
||||
Zope supplies some creative but esoteric idioms such as <a href=
|
||||
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
|
||||
Acquisition</a>. No specific support for this is built into BPL.
|
||||
Acquisition</a>. No specific support for this is built into Boost.Python.
|
||||
<li>
|
||||
Zope's ComputedAttribute support is designed to be used from Python.
|
||||
<a href="special.html#getter_setter">The analogous feature of
|
||||
BPL</a> can be used from C++ or Python. The feature is arguably
|
||||
easier to use in BPL.
|
||||
Boost.Python</a> can be used from C++ or Python. The feature is arguably
|
||||
easier to use in Boost.Python.
|
||||
</ul>
|
||||
<p>
|
||||
Next: <a href="example1.html">A Simple Example Using BPL</a>
|
||||
Next: <a href="example1.html">A Simple Example Using Boost.Python</a>
|
||||
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
@@ -215,6 +226,6 @@ an inheritance relationship?
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Wrapping enums
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
||||
Wrapping enums
|
||||
</h1>
|
||||
|
||||
<p>Because there is in general no way to deduce that a value of arbitrary type T
|
||||
@@ -17,24 +18,39 @@ enums). Once you have done that, you can write some simple
|
||||
<code>from_python()</code> and <code>to_python()</code> functions.
|
||||
|
||||
<p>If you are satisfied with a Python int as a way to represent your enum
|
||||
values, we provide a shorthand for these functions. You just need to
|
||||
instantiate <code>boost::python::enum_as_int_converters<EnumType></code> where
|
||||
values, we provide a shorthand for these functions. You just need to cause
|
||||
<code>boost::python::enum_as_int_converters<EnumType></code> to be
|
||||
instantiated, where
|
||||
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
|
||||
|
||||
<ol>
|
||||
<li><blockquote>
|
||||
<li>Explicit instantiation:
|
||||
|
||||
<blockquote><pre>
|
||||
template class boost::python::enum_as_int_converters<my_enum>;
|
||||
</blockquote></pre>
|
||||
|
||||
Some buggy C++ implementations require a class to be instantiated in the same
|
||||
namespace in which it is defined. In that case, the simple incantation above becomes:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
...
|
||||
} // close my_namespace
|
||||
|
||||
// drop into namespace python and explicitly instantiate
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
template class enum_as_int_converters<extclass_demo::EnumOwner::enum_type>;
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
namespace boost { namespace python {
|
||||
template class enum_as_int_converters<my_enum_type>;
|
||||
}} // namespace boost::python
|
||||
|
||||
namespace my_namespace { // re-open my_namespace
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
<li><blockquote><pre>
|
||||
|
||||
|
||||
<li>If you have such an implementation, you may find this technique more convenient
|
||||
<blockquote><pre>
|
||||
// instantiate as base class in any namespace
|
||||
struct EnumTypeConverters
|
||||
: boost::python::enum_as_int_converters<EnumType>
|
||||
@@ -71,7 +87,8 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
<code>long</code> type.
|
||||
|
||||
You may also want to add a bunch of lines like this to your module
|
||||
initialization:
|
||||
initialization. These bind the corresponding enum values to the appropriate
|
||||
names so they can be used from Python:
|
||||
|
||||
<blockquote><pre>
|
||||
mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
||||
@@ -83,12 +100,12 @@ You can also add these to an extension class definition, if your enum happens to
|
||||
be local to a class and you want the analogous interface in Python:
|
||||
|
||||
<blockquote><pre>
|
||||
my_class.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
||||
my_class.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
||||
my_class_builder.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
||||
my_class_builder.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
||||
...
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
Next: <a href="pointers.html">Pointers</a>
|
||||
Next: <a href="pointers.html">Pointers and Smart Pointers</a>
|
||||
Previous: <a href="building.html">Building an Extension Module</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
@@ -98,6 +115,6 @@ my_class.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
82
doc/example1.html
Normal file
82
doc/example1.html
Normal file
@@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
A Simple Example
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
||||
"c++boost.gif (8819 bytes)">
|
||||
</h1>
|
||||
<h1>
|
||||
A Simple Example
|
||||
</h1>
|
||||
<p>
|
||||
Suppose we have the following C++ API which we want to expose in
|
||||
Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A couple of simple C++ functions that we want to expose to Python.
|
||||
std::string greet() { return "hello, world"; }
|
||||
int square(int number) { return number * number; }
|
||||
}
|
||||
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Here is the C++ code for a python module called <tt>getting_started1</tt>
|
||||
which exposes the API.
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started1");
|
||||
|
||||
// Add regular functions to the module.
|
||||
this_module.def(greet, "greet");
|
||||
this_module.def(square, "square");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
That's it! If we build this shared library and put it on our <code>
|
||||
PYTHONPATH</code> we can now access our C++ functions from
|
||||
Python.
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> import getting_started1
|
||||
>>> print getting_started1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||
11 * 11 = 121
|
||||
</pre>
|
||||
<p>
|
||||
Next: <a href="exporting_classes.html">Exporting Classes</a>
|
||||
Previous: <a href="comparisons.html">Comparisons with other systems</a> Up:
|
||||
<a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2000
|
||||
</div>
|
||||
|
||||
144
doc/exporting_classes.html
Normal file
144
doc/exporting_classes.html
Normal file
@@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Exporting Classes
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
||||
"c++boost.gif (8819 bytes)">
|
||||
</h1>
|
||||
<h1>
|
||||
Exporting Classes
|
||||
</h1>
|
||||
<p>
|
||||
Now let's expose a C++ class to Python:
|
||||
|
||||
<blockquote><pre>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A friendly class.
|
||||
class hello
|
||||
{
|
||||
public:
|
||||
hello(const std::string& country) { this->country = country; }
|
||||
std::string greet() const { return "Hello from " + country; }
|
||||
private:
|
||||
std::string country;
|
||||
};
|
||||
|
||||
// A function taking a hello object as an argument.
|
||||
std::string invite(const hello& w) {
|
||||
return w.greet() + "! Please come soon!";
|
||||
}
|
||||
}
|
||||
|
||||
</blockquote></pre> <p>
|
||||
To expose the class, we use a <tt>class_builder</tt> in addition to the
|
||||
<tt>module_builder</tt> from the previous example. Class member functions
|
||||
are exposed by using the <tt>def()</tt> member function on the
|
||||
<tt>class_builder</tt>:
|
||||
<blockquote><pre>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_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<hello> hello_class(this_module, "hello");
|
||||
|
||||
// Add the __init__ function.
|
||||
hello_class.def(python::constructor<std::string>());
|
||||
// Add a regular member function.
|
||||
hello_class.def(&hello::greet, "greet");
|
||||
|
||||
// Add invite() as a regular function to the module.
|
||||
this_module.def(invite, "invite");
|
||||
|
||||
// Even better, invite() can also be made a member of hello_class!!!
|
||||
hello_class.def(invite, "invite");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
</blockquote></pre>
|
||||
<p>
|
||||
Now we can use the class normally from Python:
|
||||
|
||||
<blockquote><pre>
|
||||
>>> from getting_started2 import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
'Hello from California'
|
||||
>>> invite(hi)
|
||||
'Hello from California! Please come soon!'
|
||||
>>> hi.invite()
|
||||
'Hello from California! Please come soon!'
|
||||
</blockquote></pre>
|
||||
|
||||
Notes:<ul>
|
||||
<li> We expose the class' constructor by calling <tt>def()</tt> on the
|
||||
<tt>class_builder</tt> with an argument whose type is
|
||||
<tt>constructor<</tt><i>params</i><tt>></tt>, where <i>params</i>
|
||||
matches the list of constructor argument types:
|
||||
|
||||
|
||||
<li>Regular member functions are defined by calling <tt>def()</tt> with a
|
||||
member function pointer and its Python name:
|
||||
|
||||
<li>Any function added to a class whose initial argument matches the class (or
|
||||
any base) will act like a member function in Python.
|
||||
</ul>
|
||||
<p>
|
||||
We can even make a subclass of <code>hello.world</code>:
|
||||
|
||||
<blockquote><pre>
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida! Please come soon!'
|
||||
</blockquote></pre>
|
||||
<p>
|
||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
||||
|
||||
Of course, you may now have a slightly empty feeling in the pit of
|
||||
your little pythonic stomach. Perhaps you wanted to see the following
|
||||
<tt>wordy</tt> invitation:
|
||||
|
||||
<blockquote><pre>
|
||||
'Hello from Florida, where the weather is fine! Please come soon!'
|
||||
</blockquote></pre>
|
||||
|
||||
After all, <tt>invite</tt> calls <tt>hello::greet()</tt>, and you
|
||||
reimplemented that in your Python subclass, <tt>wordy</tt>. If so, <a
|
||||
href= "overriding.html">read on</a>...
|
||||
|
||||
<p>
|
||||
Next: <a href="overriding.html">Overridable virtual functions</a>
|
||||
Previous: <a href="example1.html">A Simple Example</a> Up:
|
||||
<a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -56,10 +56,10 @@
|
||||
sublcassing the extension type. Aside from being tedious, it's not really
|
||||
the same as having a true class, because there's no way for the user to
|
||||
override a method of the extension type which is called from the
|
||||
extension module. BPL solves this problem by taking advantage of <a
|
||||
extension module. Boost.Python solves this problem by taking advantage of <a
|
||||
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
|
||||
feature</a> to provide objects which look, walk, and hiss almost exactly
|
||||
like regular Python classes. BPL classes are actually cleaner than
|
||||
like regular Python classes. Boost.Python classes are actually cleaner than
|
||||
Python classes in some subtle ways; a more detailed discussion will
|
||||
follow (someday).</p>
|
||||
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
|
||||
@@ -2,24 +2,24 @@
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>
|
||||
The Boost Python Library (BPL)
|
||||
The Boost Python Library (Boost.Python)
|
||||
</title>
|
||||
<h1>
|
||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
|
||||
align="center" height="86">The Boost Python Library (BPL)
|
||||
align="center" height="86"><br>The Boost Python Library (Boost.Python)
|
||||
</h1>
|
||||
|
||||
<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
|
||||
your C++ classes in any way in order to use them with Boost.Python. The system
|
||||
<em>should</em> simply ``reflect'' your C++ classes and functions into
|
||||
Python. The major features of BPL include support for:
|
||||
Python. The major features of Boost.Python 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>
|
||||
@@ -28,9 +28,27 @@ among others.
|
||||
|
||||
|
||||
<h2>Supported Platforms</h2>
|
||||
<p>BPL has been tested in the following configurations:
|
||||
<p>Boost.Python is known to have been tested in the following configurations:
|
||||
|
||||
<ul>
|
||||
<li>Against Python 2.0 using the following compiler/library combinations:
|
||||
<ul>
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
|
||||
with the native library.
|
||||
|
||||
<li>An upcoming release of <a
|
||||
href="http://www.metrowerks.com/products/windows/">Metrowerks
|
||||
CodeWarrior Pro6 for Windows</a> with the native library (the first
|
||||
release has a bug that's fatal to Boost.Python)
|
||||
|
||||
<li><a
|
||||
href="http://developer.intel.com/software/products/compilers/c50/">Intel
|
||||
C++ 5.0</a>. Compilation succeeds, but tests <font
|
||||
color="#FF0000"><b>FAILED at runtime</b></font> due to a bug in its
|
||||
exception-handling implementation.
|
||||
</ul>
|
||||
|
||||
<li>Against Python 1.5.2 using the following compiler/library:
|
||||
|
||||
<ul>
|
||||
@@ -52,24 +70,17 @@ among others.
|
||||
href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve</a>]
|
||||
|
||||
<li>An upcoming release of <a href="http://www.metrowerks.com/products/windows/">Metrowerks CodeWarrior
|
||||
Pro6 for Windows</a> (the first release has a bug that's fatal to BPL)
|
||||
Pro6 for Windows</a> (the first release has a bug that's fatal to Boost.Python)
|
||||
</ul>
|
||||
<br>
|
||||
<li>Against Python 2.0 using the following compiler/library combinations:
|
||||
<ul>
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a> [by
|
||||
<a href="mailto:aleaxit@yahoo.com">Alex Martelli</a>]
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<h2>Credits</h2>
|
||||
<ul>
|
||||
<li><a href="../../../people/dave_abrahams.htm">David Abrahams</a> originated
|
||||
and wrote the library.
|
||||
and wrote most of the library, and continues to coordinate development.
|
||||
|
||||
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
|
||||
had independently developed a similar system. When he discovered BPL,
|
||||
had independently developed a similar system. When he discovered Boost.Python,
|
||||
he generously contributed countless hours of coding and much insight into
|
||||
improving it. He is responsible for an early version of the support for <a
|
||||
href="overloading.html">function overloading</a> and wrote the support for
|
||||
@@ -78,16 +89,22 @@ among others.
|
||||
Python and C++, and has designed an extremely easy-to-use way of
|
||||
exposing <a href="special.html#numeric">numeric operators</a>, including
|
||||
a way to avoid explicit coercion by means of overloading.
|
||||
|
||||
<li><a href="http://cci.lbl.gov/staff/ralf_grosse-kunstleve.html">Ralf W.
|
||||
Grosse-Kunstleve</a> contributed <a href="pickle.html">pickle support</a>
|
||||
and numerous other small improvements. He's working on a way to allow
|
||||
types exported by multiple modules to interact.
|
||||
|
||||
<li>The members of the boost mailing list and the Python community
|
||||
supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans,
|
||||
Anton Gluck, Ralf W. Grosse-Kunstleve, Chuck Ingold, Prabhu Ramachandran,
|
||||
and Barry Scott took the brave step of trying to use BPL while it was
|
||||
still in early stages of development.
|
||||
Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott took the
|
||||
brave step of trying to use Boost.Python while it was still in early
|
||||
stages of development.
|
||||
|
||||
<li>The development of BPL wouldn't have been
|
||||
possible without the generous support of <a href="http://www.dragonsys.com/">Dragon Systems/Lernout and
|
||||
Hauspie, Inc</a> who supported its development as an open-source project.
|
||||
<li>The development of Boost.Python wouldn't have been possible without
|
||||
the generous support of <a href="http://www.dragonsys.com/">Dragon
|
||||
Systems/Lernout and Hauspie, Inc</a> who supported its development as an
|
||||
open-source project.
|
||||
</ul>
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
@@ -96,11 +113,13 @@ among others.
|
||||
<li><a href="extending.html">A Brief Introduction to writing Python
|
||||
extension modules</a>
|
||||
|
||||
<li><a href="comparisons.html">Comparisons between BPL and other
|
||||
<li><a href="comparisons.html">Comparisons between Boost.Python and other
|
||||
systems for extending Python</a>
|
||||
|
||||
<li><a href="example1.html">A Simple Example</a>
|
||||
|
||||
<li><a href="exporting_classes.html">Exporting Classes</a>
|
||||
|
||||
<li><a href="overriding.html">Overridable Virtual Functions</a>
|
||||
|
||||
<li><a href="overloading.html">Function Overloading</a>
|
||||
@@ -113,33 +132,19 @@ among others.
|
||||
|
||||
<li><a href="building.html">Building an Extension Module</a>
|
||||
|
||||
<li>Advanced Topics
|
||||
<li><a href="pickle.html">Pickle Support</a>
|
||||
|
||||
<ol>
|
||||
<li>Pickling
|
||||
<li><a href="enums.html">Wrapping Enums</a>
|
||||
|
||||
<li>class_builder<>
|
||||
<li><a href="pointers.html">Pointers and Smart Pointers</a>
|
||||
|
||||
<li><a href="enums.html">enums</a>
|
||||
|
||||
<li>References
|
||||
|
||||
<li><a href="pointers.html">Pointers and Smart Pointers</a>
|
||||
|
||||
<li>Built-in Python Types
|
||||
|
||||
<li>Other Extension Types
|
||||
|
||||
<li>Templates
|
||||
|
||||
<li><a href="data_structures.txt">Internal Data Structures</a>
|
||||
</ol>
|
||||
<li><a href="data_structures.txt">Internal Data Structures</a>
|
||||
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Documentation is a major ongoing project; assistance is greatly
|
||||
appreciated! In the meantime, useful examples of every BPL feature should
|
||||
appreciated! In the meantime, useful examples of every Boost.Python feature should
|
||||
be evident in the regression test files <code>test/comprehensive.[<a
|
||||
href="../test/comprehensive.py">py</a>/<a
|
||||
href="../test/comprehensive.hpp">hpp</a>/<a
|
||||
@@ -150,11 +155,11 @@ among others.
|
||||
"http://www.egroups.com/list/boost">the boost mailing list</a>.
|
||||
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as is'' without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
Updated: Mar 6, 2001
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
<h2>Inheritance in Python</h2>
|
||||
|
||||
<p>
|
||||
BPL extension classes support single and multiple-inheritance in
|
||||
Boost.Python extension classes support single and multiple-inheritance in
|
||||
Python, just like regular Python classes. You can arbitrarily mix
|
||||
built-in Python classes with extension classes in a derived class'
|
||||
tuple of bases. Whenever a BPL extension class is among the bases for a
|
||||
tuple of bases. Whenever a Boost.Python extension class is among the bases for a
|
||||
new class in Python, the result is an extension class:
|
||||
<blockquote>
|
||||
<pre>
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
||||
<p>
|
||||
BPL also allows us to represent C++ inheritance relationships so that
|
||||
Boost.Python also allows us to represent C++ inheritance relationships so that
|
||||
wrapped derived classes may be passed where values, pointers, or
|
||||
references to a base class are expected as arguments. The
|
||||
<code>declare_base</code> member function of
|
||||
@@ -76,11 +76,7 @@ int get_derived_x(const Derived& d) {
|
||||
// namespace alias for code brevity
|
||||
namespace python = boost::python;
|
||||
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void initmy_module()
|
||||
BOOST_PYTHON_MODULE_INIT(my_module)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -115,11 +111,19 @@ void initmy_module()
|
||||
>>> derived = Derived()
|
||||
>>> get_name(base)
|
||||
'Base'
|
||||
</pre><i>objects of wrapped class Derived may be passed where Base is expected</i><pre>
|
||||
</pre>
|
||||
</blockquote>
|
||||
<i>objects of wrapped class Derived may be passed where Base is expected</i>
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> get_name(derived)
|
||||
'Derived'
|
||||
</pre><i>objects of wrapped class Derived can be passed where Derived is
|
||||
expected but where type information has been lost.</i><pre>
|
||||
</pre>
|
||||
</blockquote>
|
||||
<i>objects of wrapped class Derived can be passed where Derived is
|
||||
expected but where type information has been lost.</i>
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> get_derived_x(derived_as_base())
|
||||
-1
|
||||
</pre>
|
||||
@@ -29,7 +29,7 @@ private:
|
||||
};
|
||||
...
|
||||
|
||||
void initoverload_demo()
|
||||
BOOST_PYTHON_MODULE_INIT(overload_demo)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -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
|
||||
@@ -144,12 +144,12 @@ namespace scope as Python member functions.
|
||||
Previous: <a href="overriding.html">Overridable Virtual Functions</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<h1>Overridable Virtual Functions</h1>
|
||||
|
||||
<p>
|
||||
In the <a href="example1.html">previous example</a> we exposed a simple
|
||||
In the <a href="exporting_classes.html">previous example</a> we exposed a simple
|
||||
C++ class in Python and showed that we could write a subclass. We even
|
||||
redefined one of the functions in our derived class. Now we will learn
|
||||
how to make the function behave virtually <em>when called from C++</em>.
|
||||
@@ -17,16 +17,17 @@
|
||||
|
||||
<h2><a name="overriding_example">Example</a></h2>
|
||||
|
||||
<p>In this example, it is assumed that <code>world::greet()</code> is a virtual
|
||||
<p>In this example, it is assumed that <code>hello::greet()</code> is a virtual
|
||||
member function:
|
||||
|
||||
<blockquote><pre>
|
||||
class world
|
||||
class hello
|
||||
{
|
||||
public:
|
||||
world(int);
|
||||
virtual ~world();
|
||||
<b>virtual</b> std::string greet() const { return "hi, world"; }
|
||||
hello(const std::string& country) { this->country = country; }
|
||||
<b>virtual</b> std::string greet() const { return "Hello from " + country; }
|
||||
virtual ~hello(); // Good practice
|
||||
...
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -37,21 +38,28 @@ class world
|
||||
|
||||
<ol>
|
||||
|
||||
<li><a name="derived_1">A</a> <code>PyObject*</code> data member that holds a
|
||||
reference to the corresponding Python object.
|
||||
<li><a name="derived_1">A</a> <code>PyObject*</code> data member (usually
|
||||
called <tt>self</tt>) that holds a pointer to the Python object corresponding
|
||||
to our C++ <tt>hello</tt> instance.
|
||||
|
||||
<li><a name="derived_2">A</a> constructor for each exposed constructor of the
|
||||
base class which stores an additional initial <code>PyObject*</code> argument
|
||||
in the data member described above.
|
||||
<li><a name="derived_2">For</a> each exposed constructor of the
|
||||
base class <tt>T</tt>, a constructor which takes the same parameters preceded by an initial
|
||||
<code>PyObject*</code> argument. The initial argument should be stored in the <tt>self</tt> data
|
||||
member described above.
|
||||
|
||||
<li>If the class being wrapped is ever returned <i>by
|
||||
value</i> from a wrapped function, be sure you do the same for the
|
||||
<tt>T</tt>'s copy constructor: you'll need a constructor taking arguments
|
||||
<tt>(PyObject*, const T&)</tt>.
|
||||
|
||||
<li><a name="derived_3">An</a> implementation of each virtual function you may
|
||||
wish to override in Python which uses
|
||||
<code>boost::python::callback<<i>return-type</i>>::call_method()</code> to call
|
||||
<tt>callback<</tt><i>return-type</i><tt>>::call_method(self, "</tt><i>name</i><tt>", </tt><i>args...</i><tt>)</tt> to call
|
||||
the Python override.
|
||||
|
||||
<li><a name="derived_4">For</a> each non-pure virtual function meant to be
|
||||
overridable from Python, a static member function (or a free function) taking
|
||||
a reference or pointer to the base type as the first parameter and which
|
||||
a reference or pointer to the <tt>T</tt> as the first parameter and which
|
||||
forwards any additional parameters neccessary to the <i>default</i>
|
||||
implementation of the virtual function. See also <a href="#private">this
|
||||
note</a> if the base class virtual function is private.
|
||||
@@ -59,52 +67,60 @@ class world
|
||||
</ol>
|
||||
|
||||
<blockquote><pre>
|
||||
struct world_callback : world
|
||||
struct hello_callback : hello
|
||||
{
|
||||
world_callback(PyObject* self, int x) // <a href="#derived_2">2</a>
|
||||
: world(x),
|
||||
m_self(self) {}
|
||||
// hello constructor storing initial self_ parameter
|
||||
hello_callback(PyObject* self_, const std::string& x) // <a href="#derived_2">2</a>
|
||||
: hello(x), self(self_) {}
|
||||
|
||||
std::string greet() const // <a href="#derived_3">3</a>
|
||||
{ return boost::python::callback<std::string>::call_method(m_self, "get"); }
|
||||
// In case hello is returned by-value from a wrapped function
|
||||
hello_callback(PyObject* self_, const hello& x) // <a href="#derived_3">3</a>
|
||||
: hello(x), self(self_) {}
|
||||
|
||||
static std::string <a name= "default_implementation">default_get</a>(const hello::world& self) const // <a href="#derived_4">4</a>
|
||||
{ return self.world::greet(); }
|
||||
// Override greet to call back into Python
|
||||
std::string greet() const // <a href="#derived_4">4</a>
|
||||
{ return boost::python::callback<std::string>::call_method(m_self, "greet"); }
|
||||
|
||||
// Supplies the default implementation of greet
|
||||
static std::string <a name= "default_implementation">default_greet</a>(const hello& self) const // <a href="#derived_5">5</a>
|
||||
{ return self.hello::greet(); }
|
||||
private:
|
||||
PyObject* m_self; // <a href="#derived_1">1</a>
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Finally, we add <code>world_callback</code> to the <code>
|
||||
class_builder<></code> declaration in our module initialization
|
||||
function, and when we define the function, we must tell py_cpp about the default
|
||||
Finally, we add <tt>hello_callback</tt> to the <tt>
|
||||
class_builder<></tt> declaration in our module initialization
|
||||
function, and when we define the function, we must tell Boost.Python about the default
|
||||
implementation:
|
||||
|
||||
<blockquote><pre>
|
||||
// Create the <a name=
|
||||
"world_class">Python type object</a> for our extension class
|
||||
boost::python::class_builder<hello::world<strong>,world_callback></strong> world_class(hello, "world");
|
||||
"hello_class">Python type object</a> for our extension class
|
||||
boost::python::class_builder<hello<strong>,hello_callback></strong> hello_class(hello, "hello");
|
||||
// Add a virtual member function
|
||||
world_class.def(&world::get, "get", &<b>world_callback::default_get</b>);
|
||||
hello_class.def(&hello::greet, "greet", &<b>hello_callback::default_greet</b>);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Now our subclass of <code>hello.world</code> behaves as expected:
|
||||
Now our Python subclass of <tt>hello</tt> behaves as expected:
|
||||
|
||||
<blockquote><pre>
|
||||
>>> class my_subclass(hello.world):
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return 'hello, world'
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hello.length(my_subclass())
|
||||
12
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida, where the weather is fine! Please come soon!'
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<a name="why_derived">*</a>You may ask, "Why do we need this derived
|
||||
class? This could have been designed so that everything gets done right
|
||||
inside of <code>hello::world</code>." One of the goals of py_cpp is to be
|
||||
inside of <tt>hello</tt>." One of the goals of Boost.Python is to be
|
||||
minimally intrusive on an existing C++ design. In principle, it should be
|
||||
possible to expose the interface for a 3rd party library without changing
|
||||
it. To unintrusively hook into the virtual functions so that a Python
|
||||
@@ -117,10 +133,10 @@ world_class.def(&world::get, "get", &<b>world_callback::default_get</b>)
|
||||
deal with than a virtual function with a default implementation. First of
|
||||
all, you obviously don't need to <a href="#default_implementation"> supply
|
||||
a default implementation</a>. Secondly, you don't need to call
|
||||
<code>def()</code> on the <code>extension_class<></code> instance
|
||||
<tt>def()</tt> on the <tt>extension_class<></tt> instance
|
||||
for the virtual function. In fact, you wouldn't <em>want</em> to: if the
|
||||
corresponding attribute on the Python class stays undefined, you'll get an
|
||||
<code>AttributeError</code> in Python when you try to call the function,
|
||||
<tt>AttributeError</tt> in Python when you try to call the function,
|
||||
indicating that it should have been implemented. For example:
|
||||
<blockquote>
|
||||
<pre>
|
||||
@@ -132,11 +148,7 @@ struct baz_callback {
|
||||
int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
|
||||
};
|
||||
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
initfoobar()
|
||||
BOOST_PYTHON_MODULE_INIT(foobar)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -182,14 +194,14 @@ href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</
|
||||
|
||||
<p>
|
||||
Next: <a href="overloading.html">Function Overloading</a>
|
||||
Previous: <a href="example1.html">A Simple Example Using py_cpp</a>
|
||||
Previous: <a href="exporting_classes.html">Exporting Classes</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
Updated: Mar 6, 2001
|
||||
|
||||
223
doc/pickle.html
Normal file
223
doc/pickle.html
Normal file
@@ -0,0 +1,223 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost.Python Pickle Support</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<img src="../../../c++boost.gif"
|
||||
alt="c++boost.gif (8819 bytes)"
|
||||
align="center"
|
||||
width="277" height="86">
|
||||
|
||||
</body>
|
||||
<hr>
|
||||
<h1>Boost.Python Pickle Support</h1>
|
||||
|
||||
Pickle is a Python module for object serialization, also known
|
||||
as persistence, marshalling, or flattening.
|
||||
|
||||
<p>
|
||||
It is often necessary to save and restore the contents of an object to
|
||||
a file. One approach to this problem is to write a pair of functions
|
||||
that read and write data from a file in a special format. A powerful
|
||||
alternative approach is to use Python's pickle module. Exploiting
|
||||
Python's ability for introspection, the pickle module recursively
|
||||
converts nearly arbitrary Python objects into a stream of bytes that
|
||||
can be written to a file.
|
||||
|
||||
<p>
|
||||
The Boost Python Library supports the pickle module by emulating the
|
||||
interface implemented by Jim Fulton's ExtensionClass module that is
|
||||
included in the ZOPE distribution
|
||||
(<a href="http://www.zope.org/">http://www.zope.org/</a>).
|
||||
This interface is similar to that for regular Python classes as
|
||||
described in detail in the Python Library Reference for pickle:
|
||||
|
||||
<blockquote>
|
||||
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
|
||||
>http://www.python.org/doc/current/lib/module-pickle.html</a>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
<h1>The Boost.Python Pickle Interface</h1>
|
||||
|
||||
At the user level, the Boost.Python pickle interface involves three special
|
||||
methods:
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<strong>__getinitargs__</strong>
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is pickled, the pickler
|
||||
tests if the instance has a __getinitargs__ method. This method must
|
||||
return a Python tuple. When the instance is restored by the
|
||||
unpickler, the contents of this tuple are used as the arguments for
|
||||
the class constructor.
|
||||
|
||||
<p>
|
||||
If __getinitargs__ is not defined, the class constructor will be
|
||||
called without arguments.
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong>__getstate__</strong>
|
||||
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is pickled, the pickler
|
||||
tests if the instance has a __getstate__ method. This method should
|
||||
return a Python object representing the state of the instance.
|
||||
|
||||
<p>
|
||||
If __getstate__ is not defined, the instance's __dict__ is pickled
|
||||
(if it is not empty).
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong>__setstate__</strong>
|
||||
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is restored by the
|
||||
unpickler, it is first constructed using the result of
|
||||
__getinitargs__ as arguments (see above). Subsequently the unpickler
|
||||
tests if the new instance has a __setstate__ method. If so, this
|
||||
method is called with the result of __getstate__ (a Python object) as
|
||||
the argument.
|
||||
|
||||
<p>
|
||||
If __setstate__ is not defined, the result of __getstate__ must be
|
||||
a Python dictionary. The items of this dictionary are added to
|
||||
the instance's __dict__.
|
||||
</dl>
|
||||
|
||||
If both __getstate__ and __setstate__ are defined, the Python object
|
||||
returned by __getstate__ need not be a dictionary. The __getstate__ and
|
||||
__setstate__ methods can do what they want.
|
||||
|
||||
<hr>
|
||||
<h1>Pitfalls and Safety Guards</h1>
|
||||
|
||||
In Boost.Python extension modules with many extension classes, providing
|
||||
complete pickle support for all classes would be a significant
|
||||
overhead. In general complete pickle support should only be implemented
|
||||
for extension classes that will eventually be pickled. However, the
|
||||
author of a Boost.Python extension module might not anticipate correctly which
|
||||
classes need support for pickle. Unfortunately, the pickle protocol
|
||||
described above has two important pitfalls that the end user of a Boost.Python
|
||||
extension module might not be aware of:
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<strong>Pitfall 1:</strong>
|
||||
Both __getinitargs__ and __getstate__ are not defined.
|
||||
|
||||
<dd>
|
||||
In this situation the unpickler calls the class constructor without
|
||||
arguments and then adds the __dict__ that was pickled by default to
|
||||
that of the new instance.
|
||||
|
||||
<p>
|
||||
However, most C++ classes wrapped with Boost.Python will have member data
|
||||
that are not restored correctly by this procedure. To alert the user
|
||||
to this problem, a safety guard is provided. If both __getinitargs__
|
||||
and __getstate__ are not defined, Boost.Python tests if the class has an
|
||||
attribute __dict_defines_state__. An exception is raised if this
|
||||
attribute is not defined:
|
||||
|
||||
<pre>
|
||||
RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
|
||||
</pre>
|
||||
|
||||
In the rare cases where this is not the desired behavior, the safety
|
||||
guard can deliberately be disabled. The corresponding C++ code for
|
||||
this is, e.g.:
|
||||
|
||||
<pre>
|
||||
class_builder<your_class> py_your_class(your_module, "your_class");
|
||||
py_your_class.dict_defines_state();
|
||||
</pre>
|
||||
|
||||
It is also possible to override the safety guard at the Python level.
|
||||
E.g.:
|
||||
|
||||
<pre>
|
||||
import your_bpl_module
|
||||
class your_class(your_bpl_module.your_class):
|
||||
__dict_defines_state__ = 1
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong>Pitfall 2:</strong>
|
||||
__getstate__ is defined and the instance's __dict__ is not empty.
|
||||
|
||||
<dd>
|
||||
The author of a Boost.Python extension class might provide a __getstate__
|
||||
method without considering the possibilities that:
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
his class is used as a base class. Most likely the __dict__ of
|
||||
instances of the derived class needs to be pickled in order to
|
||||
restore the instances correctly.
|
||||
|
||||
<p>
|
||||
<li>
|
||||
the user adds items to the instance's __dict__ directly. Again,
|
||||
the __dict__ of the instance then needs to be pickled.
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
To alert the user to this highly unobvious problem, a safety guard is
|
||||
provided. If __getstate__ is defined and the instance's __dict__ is
|
||||
not empty, Boost.Python tests if the class has an attribute
|
||||
__getstate_manages_dict__. An exception is raised if this attribute
|
||||
is not defined:
|
||||
|
||||
<pre>
|
||||
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
|
||||
</pre>
|
||||
|
||||
To resolve this problem, it should first be established that the
|
||||
__getstate__ and __setstate__ methods manage the instances's __dict__
|
||||
correctly. Note that this can be done both at the C++ and the Python
|
||||
level. Finally, the safety guard should intentionally be overridden.
|
||||
E.g. in C++:
|
||||
|
||||
<pre>
|
||||
class_builder<your_class> py_your_class(your_module, "your_class");
|
||||
py_your_class.getstate_manages_dict();
|
||||
</pre>
|
||||
|
||||
In Python:
|
||||
|
||||
<pre>
|
||||
import your_bpl_module
|
||||
class your_class(your_bpl_module.your_class):
|
||||
__getstate_manages_dict__ = 1
|
||||
def __getstate__(self):
|
||||
# your code here
|
||||
def __setstate__(self, state):
|
||||
# your code here
|
||||
</pre>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<h1>Practical Advice</h1>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Avoid using __getstate__ if the instance can also be reconstructed
|
||||
by way of __getinitargs__. This automatically avoids Pitfall 2.
|
||||
|
||||
<p>
|
||||
<li>
|
||||
If __getstate__ is required, include the instance's __dict__ in the
|
||||
Python object that is returned.
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<address>
|
||||
Author: Ralf W. Grosse-Kunstleve, March 2001
|
||||
</address>
|
||||
</html>
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<p>
|
||||
In general, raw pointers passed to or returned from functions are problematic
|
||||
for BPL because pointers have too many potential meanings. Is it an iterator?
|
||||
for Boost.Python because pointers have too many potential meanings. Is it an iterator?
|
||||
A pointer to a single element? An array? When used as a return value, is the
|
||||
caller expected to manage (delete) the pointed-to object or is the pointer
|
||||
really just a reference? If the latter, what happens to Python references to the
|
||||
@@ -46,7 +46,7 @@ const Foo& f_wrapper() { return *f(); }
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
Foo must have a public copy constructor for this technique to work, since BPL
|
||||
Foo must have a public copy constructor for this technique to work, since Boost.Python
|
||||
converts <code>const T&</code> values <code>to_python</code> by copying the <code>T</code>
|
||||
value into a new extension instance.
|
||||
|
||||
@@ -85,12 +85,12 @@ code before the last Python reference to it disappears:
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
PyObject* to_python(Foo* p)
|
||||
{
|
||||
return boost::python::PyExtensionClassConverters<Foo>::ptr_to_python(p);
|
||||
return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p);
|
||||
}
|
||||
|
||||
PyObject* to_python(const Foo* p)
|
||||
{
|
||||
return to_python(const_cast<Foo*>(p));
|
||||
return to_python(const_cast<Foo*>(p));
|
||||
}
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
</pre></blockquote>
|
||||
@@ -12,8 +12,8 @@
|
||||
Overview
|
||||
</h2>
|
||||
<p>
|
||||
BPL supports all of the standard <a href=
|
||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
|
||||
Boost.Python supports all of the standard <a href=
|
||||
"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>
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
<pre> my_class.def(boost::python::constructor<...>())</pre>
|
||||
|
||||
(see section <a href="example1.html">"A Simple Example Using BPL"</a>).<p>
|
||||
(see section <a href="example1.html">"A Simple Example Using Boost.Python"</a>).<p>
|
||||
<dt>
|
||||
<b><tt class='method'>__del__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
@@ -104,7 +104,7 @@ std::string to_string(Foo const& f)
|
||||
boost::python::class_builder<Foo> foo_class(my_module, "Foo");
|
||||
foo_class.def(&to_string, "__str__");
|
||||
</pre></blockquote>
|
||||
Note that BPL also supports <em>automatic wrapping</em> of
|
||||
Note that Boost.Python also supports <em>automatic wrapping</em> of
|
||||
<code>__str__</code> and <code>__cmp__</code>. This is explained in the <a
|
||||
href="#numeric">next section</a> and the <a href="#numeric_table">Table of
|
||||
Automatically Wrapped Methods</a>.
|
||||
@@ -114,10 +114,10 @@ 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
|
||||
href="#numeric_manual">covered in detail below</a>. Boost.Python also supports
|
||||
<i>automatic wrapping</i> of numeric operators whenever they have already
|
||||
been defined in C++.
|
||||
|
||||
@@ -174,7 +174,7 @@ a = i + b;
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>());
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>());
|
||||
</pre></blockquote>
|
||||
BPL uses overloading to register several variants of the same
|
||||
Boost.Python uses overloading to register several variants of the same
|
||||
operation (more on this in the context of <a href="#coercion">
|
||||
coercion</a>). Again, several operators can be exported at once:
|
||||
<blockquote><pre>
|
||||
@@ -283,13 +283,13 @@ bignum_class.def(&rmod, "__rmod__");
|
||||
coercion functions can be difficult if many type combinations must be
|
||||
supported.
|
||||
<p>
|
||||
BPL solves this problem the same way that C++ does: with <em><a
|
||||
Boost.Python solves this problem the same way that C++ does: with <em><a
|
||||
href="overloading.html">overloading</a></em>. This technique drastically
|
||||
simplifies the code neccessary to support operators: you just register
|
||||
operators for all desired type combinations, and BPL automatically
|
||||
operators for all desired type combinations, and Boost.Python automatically
|
||||
ensures that the correct function is called in each case; there is no
|
||||
need for user-defined coercion functions. To enable operator
|
||||
overloading, BPL provides a standard coercion which is <em>implicitly
|
||||
overloading, Boost.Python provides a standard coercion which is <em>implicitly
|
||||
registered</em> whenever automatic operator wrapping is used.
|
||||
<p>
|
||||
If you wrap all operator functions manually, but still want to use
|
||||
@@ -370,7 +370,7 @@ bignum_class.def((ternary_function2)&power, "__pow__");
|
||||
|
||||
In the second variant, however, <code>BigNum</code> appears only as second
|
||||
argument, and in the last one it's the third argument. These functions
|
||||
must be presented to BPL such that that the <code>BigNum</code>
|
||||
must be presented to Boost.Python such that that the <code>BigNum</code>
|
||||
argument appears in first position:
|
||||
|
||||
<blockquote><pre>
|
||||
@@ -397,8 +397,8 @@ 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">
|
||||
Boost.Python can automatically wrap the following <a href=
|
||||
"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,
|
||||
@@ -772,13 +772,13 @@ KeyError: 2
|
||||
<h2><a name="getter_setter">Customized Attribute Access</a></h2>
|
||||
|
||||
<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
|
||||
Just like built-in Python classes, Boost.Python extension classes support <a
|
||||
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
|
||||
be tedious in the common case where the attributes being accessed are
|
||||
known statically, BPL checks the special names
|
||||
known statically, Boost.Python checks the special names
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -794,7 +794,7 @@ KeyError: 2
|
||||
following shows how we can implement a ``computed attribute'' in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> class Range(AnyBPLExtensionClass):
|
||||
>>> class Range(AnyBoost.PythonExtensionClass):
|
||||
... def __init__(self, start, end):
|
||||
... self.start = start
|
||||
... self.end = end
|
||||
@@ -810,7 +810,7 @@ KeyError: 2
|
||||
Direct Access to Data Members
|
||||
</h4>
|
||||
<p>
|
||||
BPL uses the special <code>
|
||||
Boost.Python uses the special <code>
|
||||
__xxxattr__<em><name></em>__</code> functionality described above
|
||||
to allow direct access to data members through the following special
|
||||
functions on <code>class_builder<></code> and <code>
|
||||
@@ -22,7 +22,7 @@
|
||||
"example1.html#add_world_class">add it to the module</a> it goes into the
|
||||
module's dictionary to be looked up under the name "world".
|
||||
<p>
|
||||
BPL uses C++'s template argument deduction mechanism to determine the
|
||||
Boost.Python uses C++'s template argument deduction mechanism to determine the
|
||||
types of arguments to functions (except constructors, for which we must
|
||||
<a href="example1.html#Constructor_example">provide an argument list</a>
|
||||
because they can't be named in C++). Then, it calls the appropriate
|
||||
@@ -48,7 +48,7 @@
|
||||
the top of your module's init function, then <code>def</code> the member
|
||||
functions later to avoid problems with inter-class dependencies.
|
||||
<p>
|
||||
Next: <a href="building.html">Building a Module with BPL</a>
|
||||
Next: <a href="building.html">Building a Module with Boost.Python</a>
|
||||
Previous: <a href="special.html">Special Method and Operator Support</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
6
example/README
Normal file
6
example/README
Normal file
@@ -0,0 +1,6 @@
|
||||
To get started with the Boost Python Library, use the examples
|
||||
getting_started?.cpp and abstract.cpp.
|
||||
|
||||
The files example1.cpp and rwgk1.cpp are obsolete. They are only
|
||||
included because the makefiles in the build directory still refer to
|
||||
them. This will be fixed later.
|
||||
34
example/abstract.cpp
Normal file
34
example/abstract.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Example by Ullrich Koethe
|
||||
#include "boost/python/class_builder.hpp"
|
||||
#include <string>
|
||||
|
||||
struct Abstract
|
||||
{
|
||||
virtual std::string test() = 0;
|
||||
};
|
||||
|
||||
struct Abstract_callback: Abstract
|
||||
{
|
||||
Abstract_callback(PyObject * self)
|
||||
: m_self(self)
|
||||
{}
|
||||
|
||||
std::string test()
|
||||
{
|
||||
return boost::python::callback<std::string>::call_method(m_self, "test");
|
||||
}
|
||||
|
||||
PyObject * m_self;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initabstract()
|
||||
{
|
||||
boost::python::module_builder a("abstract");
|
||||
|
||||
boost::python::class_builder<Abstract, Abstract_callback>
|
||||
a_class(a, "Abstract");
|
||||
a_class.def(boost::python::constructor<>()); // wrap a constructor
|
||||
a_class.def(&Abstract::test, "test");
|
||||
}
|
||||
30
example/getting_started1.cpp
Normal file
30
example/getting_started1.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A couple of simple C++ functions that we want to expose to Python.
|
||||
std::string greet() { return "hello, world"; }
|
||||
int square(int number) { return number * number; }
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
// Python requires an exported function called init<module-name> in every
|
||||
// extension module. This is where we build the module contents.
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started1");
|
||||
|
||||
// Add regular functions to the module.
|
||||
this_module.def(greet, "greet");
|
||||
this_module.def(square, "square");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
50
example/getting_started2.cpp
Normal file
50
example/getting_started2.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A friendly class.
|
||||
class hello
|
||||
{
|
||||
public:
|
||||
hello(const std::string& country) { this->country = country; }
|
||||
std::string greet() const { return "Hello from " + country; }
|
||||
private:
|
||||
std::string country;
|
||||
};
|
||||
|
||||
// A function taking a hello object as an argument.
|
||||
std::string invite(const hello& w) {
|
||||
return w.greet() + "! Please come soon!";
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_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<hello> hello_class(this_module, "hello");
|
||||
|
||||
// Add the __init__ function.
|
||||
hello_class.def(python::constructor<std::string>());
|
||||
// Add a regular member function.
|
||||
hello_class.def(&hello::greet, "greet");
|
||||
|
||||
// Add invite() as a regular function to the module.
|
||||
this_module.def(invite, "invite");
|
||||
|
||||
// Even better, invite() can also be made a member of hello_class!!!
|
||||
hello_class.def(invite, "invite");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
120
example/getting_started3.cpp
Normal file
120
example/getting_started3.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_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
|
||||
}
|
||||
}
|
||||
102
example/getting_started4.cpp
Normal file
102
example/getting_started4.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_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
|
||||
}
|
||||
}
|
||||
126
example/getting_started5.cpp
Normal file
126
example/getting_started5.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
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, python::ref(to_python(hkl.v[i])));
|
||||
return result.reference().release();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_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
|
||||
}
|
||||
}
|
||||
23
example/test_abstract.py
Normal file
23
example/test_abstract.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Example by Ullrich Koethe
|
||||
r'''>>> from abstract import *
|
||||
>>> class A(Abstract):
|
||||
... def __init__(self, text):
|
||||
... Abstract.__init__(self) # call the base class constructor
|
||||
... self.text = text
|
||||
... def test(self): # implement abstract function
|
||||
... return self.text
|
||||
...
|
||||
>>> a = A("Hello")
|
||||
>>> a.test()
|
||||
'Hello'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_abstract
|
||||
doctest.testmod(test_abstract)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
17
example/test_getting_started1.py
Normal file
17
example/test_getting_started1.py
Normal file
@@ -0,0 +1,17 @@
|
||||
r'''>>> import getting_started1
|
||||
>>> print getting_started1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||
11 * 11 = 121
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started1
|
||||
doctest.testmod(test_getting_started1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
29
example/test_getting_started2.py
Normal file
29
example/test_getting_started2.py
Normal file
@@ -0,0 +1,29 @@
|
||||
r'''>>> from getting_started2 import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
'Hello from California'
|
||||
>>> invite(hi)
|
||||
'Hello from California! Please come soon!'
|
||||
>>> hi.invite()
|
||||
'Hello from California! Please come soon!'
|
||||
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida! Please come soon!'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started2
|
||||
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()
|
||||
829
include/boost/python/callback.hpp
Normal file
829
include/boost/python/callback.hpp
Normal file
@@ -0,0 +1,829 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file was generated for 10-argument python callbacks by gen_callback.python
|
||||
|
||||
#ifndef CALLBACK_DWA_052100_H_
|
||||
# define CALLBACK_DWA_052100_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/conversions.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
template <class T>
|
||||
inline void callback_adjust_refcount(PyObject*, type<T>) {}
|
||||
|
||||
inline void callback_adjust_refcount(PyObject* p, type<PyObject*>)
|
||||
{ Py_INCREF(p); }
|
||||
}
|
||||
|
||||
// Calling Python from C++
|
||||
template <class R>
|
||||
struct callback
|
||||
{
|
||||
static R call_method(PyObject* self, const char* name)
|
||||
{
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("()")));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
static R call(PyObject* self)
|
||||
{
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("()")));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(O)"),
|
||||
p1.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
static R call(PyObject* self, const A1& a1)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(O)"),
|
||||
p1.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OO)"),
|
||||
p1.get(),
|
||||
p2.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OO)"),
|
||||
p1.get(),
|
||||
p2.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref p10(to_python(a10));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get(),
|
||||
p10.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref p10(to_python(a10));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get(),
|
||||
p10.get()));
|
||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||
return from_python(result.get(), type<R>());
|
||||
}
|
||||
};
|
||||
|
||||
// This specialization wouldn't be needed, but MSVC6 doesn't correctly allow the following:
|
||||
// void g();
|
||||
// void f() { return g(); }
|
||||
template <>
|
||||
struct callback<void>
|
||||
{
|
||||
|
||||
static void call_method(PyObject* self, const char* name)
|
||||
{
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("()")));
|
||||
}
|
||||
|
||||
static void call(PyObject* self)
|
||||
{
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("()")));
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(O)"),
|
||||
p1.get()));
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
static void call(PyObject* self, const A1& a1)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(O)"),
|
||||
p1.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OO)"),
|
||||
p1.get(),
|
||||
p2.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OO)"),
|
||||
p1.get(),
|
||||
p2.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref p10(to_python(a10));
|
||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||
const_cast<char*>("(OOOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get(),
|
||||
p10.get()));
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||
{
|
||||
ref p1(to_python(a1));
|
||||
ref p2(to_python(a2));
|
||||
ref p3(to_python(a3));
|
||||
ref p4(to_python(a4));
|
||||
ref p5(to_python(a5));
|
||||
ref p6(to_python(a6));
|
||||
ref p7(to_python(a7));
|
||||
ref p8(to_python(a8));
|
||||
ref p9(to_python(a9));
|
||||
ref p10(to_python(a10));
|
||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOOO)"),
|
||||
p1.get(),
|
||||
p2.get(),
|
||||
p3.get(),
|
||||
p4.get(),
|
||||
p5.get(),
|
||||
p6.get(),
|
||||
p7.get(),
|
||||
p8.get(),
|
||||
p9.get(),
|
||||
p10.get()));
|
||||
}
|
||||
};
|
||||
|
||||
// Make it a compile-time error to try to return a const char* from a virtual
|
||||
// function. The standard conversion
|
||||
//
|
||||
// from_python(PyObject* string, boost::python::type<const char*>)
|
||||
//
|
||||
// returns a pointer to the character array which is internal to string. The
|
||||
// problem with trying to do this in a standard callback function is that the
|
||||
// Python string would likely be destroyed upon return from the calling function
|
||||
// (boost::python::callback<const char*>::call[_method]) when its reference count is
|
||||
// decremented. If you absolutely need to do this and you're sure it's safe (it
|
||||
// usually isn't), you can use
|
||||
//
|
||||
// boost::python::string result(boost::python::callback<boost::python::string>::call[_method](...args...));
|
||||
// ...result.c_str()... // access the char* array
|
||||
template <>
|
||||
struct callback<const char*>
|
||||
{
|
||||
// Try hard to generate a readable error message
|
||||
typedef struct unsafe_since_python_string_may_be_destroyed {} call, call_method;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CALLBACK_DWA_052100_H_
|
||||
1279
include/boost/python/caller.hpp
Normal file
1279
include/boost/python/caller.hpp
Normal file
File diff suppressed because it is too large
Load Diff
166
include/boost/python/class_builder.hpp
Normal file
166
include/boost/python/class_builder.hpp
Normal file
@@ -0,0 +1,166 @@
|
||||
// Revision History:
|
||||
// Mar 03 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve)
|
||||
|
||||
#ifndef CLASS_WRAPPER_DWA101000_H_
|
||||
# define CLASS_WRAPPER_DWA101000_H_
|
||||
|
||||
#include <boost/python/detail/extension_class.hpp>
|
||||
#include <boost/python/operators.hpp>
|
||||
#include <boost/python/module_builder.hpp>
|
||||
#include <boost/python/conversions.hpp>
|
||||
#include <boost/python/detail/cast.hpp>
|
||||
#include <boost/python/reference.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// Syntactic sugar to make wrapping classes more convenient
|
||||
template <class T, class U = detail::held_instance<T> >
|
||||
class class_builder
|
||||
: python_extension_class_converters<T, U> // Works around MSVC6.x/GCC2.95.2 bug described below
|
||||
{
|
||||
public:
|
||||
class_builder(module_builder& module, const char* name)
|
||||
: m_class(new detail::extension_class<T, U>(name))
|
||||
{
|
||||
module.add(ref(as_object(m_class.get()), ref::increment_count), name);
|
||||
}
|
||||
|
||||
~class_builder()
|
||||
{}
|
||||
|
||||
inline void dict_defines_state() {
|
||||
add(ref(BOOST_PYTHON_CONVERSION::to_python(1)), "__dict_defines_state__");
|
||||
}
|
||||
inline void getstate_manages_dict() {
|
||||
add(ref(BOOST_PYTHON_CONVERSION::to_python(1)), "__getstate_manages_dict__");
|
||||
}
|
||||
|
||||
// define constructors
|
||||
template <class signature>
|
||||
void def(const signature& s)
|
||||
{ m_class->def(s); }
|
||||
|
||||
// export heterogeneous reverse-argument operators
|
||||
// (type of lhs: 'left', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||
// boost::python::left_operand<int const &>());
|
||||
template <long which, class left, class right>
|
||||
void def(operators<which, right> o1, left_operand<left> o2)
|
||||
{ m_class->def(o1, o2); }
|
||||
|
||||
// export heterogeneous operators (type of lhs: 'left', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||
// boost::python::right_operand<int const &>());
|
||||
template <long which, class left, class right>
|
||||
void def(operators<which, left> o1, right_operand<right> o2)
|
||||
{ m_class->def(o1, o2); }
|
||||
|
||||
// define a function that passes Python arguments and keywords
|
||||
// to C++ verbatim (as a 'tuple const &' and 'dictionary const &'
|
||||
// respectively). This is useful for manual argument passing.
|
||||
// It's also the only possibility to pass keyword arguments to C++.
|
||||
// Fn must have a signatur that is compatible to
|
||||
// PyObject * (*)(PyObject * aTuple, PyObject * aDictionary)
|
||||
template <class Fn>
|
||||
void def_raw(Fn fn, const char* name)
|
||||
{ m_class->def_raw(fn, name); }
|
||||
|
||||
// define member functions. In fact this works for free functions, too -
|
||||
// they act like static member functions, or if they start with the
|
||||
// appropriate self argument (as a pointer or reference), they can be used
|
||||
// just like ordinary member functions -- just like Python!
|
||||
template <class Fn>
|
||||
void def(Fn fn, const char* name)
|
||||
{ m_class->def(fn, name); }
|
||||
|
||||
// Define a virtual member function with a default implementation.
|
||||
// default_fn should be a function which provides the default implementation.
|
||||
// Be careful that default_fn does not in fact call fn virtually!
|
||||
template <class Fn, class DefaultFn>
|
||||
void def(Fn fn, const char* name, DefaultFn default_fn)
|
||||
{ m_class->def(fn, name, default_fn); }
|
||||
|
||||
// Provide a function which implements x.<name>, reading from the given
|
||||
// member (pm) of the T obj
|
||||
template <class MemberType>
|
||||
void def_getter(MemberType T::*pm, const char* name)
|
||||
{ m_class->def_getter(pm, name); }
|
||||
|
||||
// Provide a function which implements assignment to x.<name>, writing to
|
||||
// the given member (pm) of the T obj
|
||||
template <class MemberType>
|
||||
void def_setter(MemberType T::*pm, const char* name)
|
||||
{ m_class->def_getter(pm, name); }
|
||||
|
||||
// Expose the given member (pm) of the T obj as a read-only attribute
|
||||
template <class MemberType>
|
||||
void def_readonly(MemberType T::*pm, const char* name)
|
||||
{ m_class->def_readonly(pm, name); }
|
||||
|
||||
// Expose the given member (pm) of the T obj as a read/write attribute
|
||||
template <class MemberType>
|
||||
void def_read_write(MemberType T::*pm, const char* name)
|
||||
{ m_class->def_read_write(pm, name); }
|
||||
|
||||
// define the standard coercion needed for operator overloading
|
||||
void def_standard_coerce()
|
||||
{ m_class->def_standard_coerce(); }
|
||||
|
||||
// declare the given class a base class of this one and register
|
||||
// conversion functions
|
||||
template <class S, class V>
|
||||
void declare_base(class_builder<S, V> const & base)
|
||||
{
|
||||
m_class->declare_base(base.get_extension_class());
|
||||
}
|
||||
|
||||
// declare the given class a base class of this one and register
|
||||
// upcast conversion function
|
||||
template <class S, class V>
|
||||
void declare_base(class_builder<S, V> const & base, without_downcast_t)
|
||||
{
|
||||
m_class->declare_base(base.get_extension_class(), without_downcast);
|
||||
}
|
||||
|
||||
// get the embedded ExtensioClass object
|
||||
detail::extension_class<T, U> * get_extension_class() const
|
||||
{
|
||||
return m_class.get();
|
||||
}
|
||||
|
||||
// set an arbitrary attribute. Useful for non-function class data members,
|
||||
// e.g. enums
|
||||
void add(PyObject* x, const char* name)
|
||||
{ m_class->set_attribute(name, x); }
|
||||
void add(ref x, const char* name)
|
||||
{ m_class->set_attribute(name, x); }
|
||||
private:
|
||||
// declare the given class a base class of this one and register
|
||||
// conversion functions
|
||||
template <class S, class V>
|
||||
void declare_base(detail::extension_class<S, V> * base)
|
||||
{
|
||||
m_class->declare_base(base);
|
||||
}
|
||||
|
||||
// declare the given class a base class of this one and register
|
||||
// upcast conversion function
|
||||
template <class S, class V>
|
||||
void declare_base(detail::extension_class<S, V> * base, without_downcast_t)
|
||||
{
|
||||
m_class->declare_base(base, without_downcast);
|
||||
}
|
||||
|
||||
reference<detail::extension_class<T, U> > m_class;
|
||||
};
|
||||
|
||||
// The bug mentioned at the top of this file is that on certain compilers static
|
||||
// global functions declared within the body of a class template will only be
|
||||
// generated when the class template is constructed, and when (for some reason)
|
||||
// the construction does not occur via a new-expression. Otherwise, we could
|
||||
// rely on the initialization of the m_class data member to cause all of the
|
||||
// to_/from_python functions to come into being.
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CLASS_WRAPPER_DWA101000_H_
|
||||
527
include/boost/python/classes.hpp
Normal file
527
include/boost/python/classes.hpp
Normal file
@@ -0,0 +1,527 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef SUBCLASS_DWA051500_H_
|
||||
# define SUBCLASS_DWA051500_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/types.hpp>
|
||||
# include <boost/python/objects.hpp>
|
||||
# include <boost/python/detail/singleton.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/python/conversions.hpp>
|
||||
# include <boost/python/callback.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// A simple type which acts something like a built-in Python class obj.
|
||||
class instance
|
||||
: public boost::python::detail::python_object
|
||||
{
|
||||
public:
|
||||
instance(PyTypeObject* class_);
|
||||
~instance();
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* repr();
|
||||
int compare(PyObject*);
|
||||
PyObject* str();
|
||||
long hash();
|
||||
PyObject* call(PyObject* args, PyObject* keywords);
|
||||
PyObject* getattr(const char* name, bool use_special_function = true);
|
||||
int setattr(const char* name, PyObject* value);
|
||||
|
||||
// Mapping methods
|
||||
int length();
|
||||
PyObject* get_subscript(PyObject* key);
|
||||
void set_subscript(PyObject* key, PyObject* value);
|
||||
|
||||
// Sequence methods
|
||||
PyObject* get_slice(int start, int finish);
|
||||
void set_slice(int start, int finish, PyObject* value);
|
||||
|
||||
// Number methods
|
||||
PyObject* add(PyObject* other);
|
||||
PyObject* subtract(PyObject* other);
|
||||
PyObject* multiply(PyObject* other);
|
||||
PyObject* divide(PyObject* other);
|
||||
PyObject* remainder(PyObject* other);
|
||||
PyObject* divmod(PyObject* other);
|
||||
PyObject* power(PyObject*, PyObject*);
|
||||
PyObject* negative();
|
||||
PyObject* positive();
|
||||
PyObject* absolute();
|
||||
int nonzero();
|
||||
PyObject* invert();
|
||||
PyObject* lshift(PyObject* other);
|
||||
PyObject* rshift(PyObject* other);
|
||||
PyObject* do_and(PyObject* other);
|
||||
PyObject* do_xor(PyObject* other);
|
||||
PyObject* do_or(PyObject* other);
|
||||
int coerce(PyObject**, PyObject**);
|
||||
PyObject* as_int();
|
||||
PyObject* as_long();
|
||||
PyObject* as_float();
|
||||
PyObject* oct();
|
||||
PyObject* hex();
|
||||
|
||||
private: // noncopyable, without the size bloat
|
||||
instance(const instance&);
|
||||
void operator=(const instance&);
|
||||
|
||||
private: // helper functions
|
||||
int setattr_dict(PyObject* value);
|
||||
|
||||
private:
|
||||
dictionary m_name_space;
|
||||
};
|
||||
|
||||
template <class T> class meta_class;
|
||||
|
||||
namespace detail {
|
||||
class class_base : public type_object_base
|
||||
{
|
||||
public:
|
||||
class_base(PyTypeObject* meta_class_obj, string name, tuple bases, const dictionary& name_space);
|
||||
tuple bases() const;
|
||||
string name() const;
|
||||
dictionary& dict();
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* getattr(const char* name);
|
||||
int setattr(const char* name, PyObject* value);
|
||||
PyObject* repr() const;
|
||||
void add_base(ref base);
|
||||
|
||||
protected:
|
||||
bool initialize_instance(instance* obj, PyObject* args, PyObject* keywords);
|
||||
|
||||
private: // virtual functions
|
||||
// Subclasses should override this to delete the particular obj type
|
||||
virtual void delete_instance(PyObject*) const = 0;
|
||||
|
||||
private: // boost::python::type_object_base required interface implementation
|
||||
void instance_dealloc(PyObject*) const; // subclasses should not override this
|
||||
|
||||
private:
|
||||
string m_name;
|
||||
tuple m_bases;
|
||||
dictionary m_name_space;
|
||||
};
|
||||
|
||||
void enable_named_method(class_base* type_obj, const char* name);
|
||||
}
|
||||
|
||||
// A type which acts a lot like a built-in Python class. T is the obj type,
|
||||
// so class_t<instance> is a very simple "class-alike".
|
||||
template <class T>
|
||||
class class_t
|
||||
: public boost::python::detail::class_base
|
||||
{
|
||||
public:
|
||||
class_t(meta_class<T>* meta_class_obj, string name, tuple bases, const dictionary& name_space);
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* call(PyObject* args, PyObject* keywords);
|
||||
|
||||
private: // Implement mapping methods on instances
|
||||
PyObject* instance_repr(PyObject*) const;
|
||||
int instance_compare(PyObject*, PyObject* other) const;
|
||||
PyObject* instance_str(PyObject*) const;
|
||||
long instance_hash(PyObject*) const;
|
||||
int instance_mapping_length(PyObject*) const;
|
||||
PyObject* instance_mapping_subscript(PyObject*, PyObject*) const;
|
||||
int instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const;
|
||||
|
||||
private: // Implement sequence methods on instances
|
||||
int instance_sequence_length(PyObject*) const;
|
||||
PyObject* instance_sequence_item(PyObject* obj, int n) const;
|
||||
int instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const;
|
||||
PyObject* instance_sequence_slice(PyObject*, int start, int finish) const;
|
||||
int instance_sequence_ass_slice(PyObject*, int start, int finish, PyObject* value) const;
|
||||
|
||||
private: // Implement number methods on instances
|
||||
PyObject* instance_number_add(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_subtract(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_multiply(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_divide(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_remainder(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_divmod(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_power(PyObject*, PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_negative(PyObject*) const;
|
||||
PyObject* instance_number_positive(PyObject*) const;
|
||||
PyObject* instance_number_absolute(PyObject*) const;
|
||||
int instance_number_nonzero(PyObject*) const;
|
||||
PyObject* instance_number_invert(PyObject*) const;
|
||||
PyObject* instance_number_lshift(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_rshift(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_and(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_xor(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_or(PyObject*, PyObject*) const;
|
||||
int instance_number_coerce(PyObject*, PyObject**, PyObject**) const;
|
||||
PyObject* instance_number_int(PyObject*) const;
|
||||
PyObject* instance_number_long(PyObject*) const;
|
||||
PyObject* instance_number_float(PyObject*) const;
|
||||
PyObject* instance_number_oct(PyObject*) const;
|
||||
PyObject* instance_number_hex(PyObject*) const;
|
||||
|
||||
private: // Miscellaneous "special" methods
|
||||
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const;
|
||||
PyObject* instance_getattr(PyObject* obj, const char* name) const;
|
||||
int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
|
||||
|
||||
private: // Implementation of boost::python::detail::class_base required interface
|
||||
void delete_instance(PyObject*) const;
|
||||
|
||||
private: // noncopyable, without the size bloat
|
||||
class_t(const class_t<T>&);
|
||||
void operator=(const class_t&);
|
||||
};
|
||||
|
||||
// The type of a class_t<T> object.
|
||||
template <class T>
|
||||
class meta_class
|
||||
: public boost::python::detail::reprable<
|
||||
boost::python::detail::callable<
|
||||
boost::python::detail::getattrable<
|
||||
boost::python::detail::setattrable<
|
||||
boost::python::detail::type_object<class_t<T> > > > > >,
|
||||
boost::noncopyable
|
||||
{
|
||||
public:
|
||||
meta_class();
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* call(PyObject* args, PyObject* keywords);
|
||||
|
||||
struct type_object
|
||||
: boost::python::detail::singleton<type_object,
|
||||
boost::python::detail::callable<
|
||||
boost::python::detail::type_object<meta_class> > >
|
||||
{
|
||||
type_object() : singleton_base(&PyType_Type) {}
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// Member function implementations.
|
||||
//
|
||||
template <class T>
|
||||
meta_class<T>::meta_class()
|
||||
: properties(type_object::instance())
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class_t<T>::class_t(meta_class<T>* meta_class_obj, string name, tuple bases, const dictionary& name_space)
|
||||
: boost::python::detail::class_base(meta_class_obj, name, bases, name_space)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void class_t<T>::delete_instance(PyObject* obj) const
|
||||
{
|
||||
delete downcast<T>(obj);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::call(PyObject* args, PyObject* keywords)
|
||||
{
|
||||
reference<T> result(new T(this));
|
||||
if (!this->initialize_instance(result.get(), args, keywords))
|
||||
return 0;
|
||||
else
|
||||
return result.release();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_repr(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->repr();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_compare(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->compare(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_str(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->str();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
long class_t<T>::instance_hash(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->hash();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_mapping_length(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->length();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_sequence_length(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->length();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_mapping_subscript(PyObject* obj, PyObject* key) const
|
||||
{
|
||||
return downcast<T>(obj)->get_subscript(key);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_sequence_item(PyObject* obj, int n) const
|
||||
{
|
||||
ref key(to_python(n));
|
||||
return downcast<T>(obj)->get_subscript(key.get());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const
|
||||
{
|
||||
ref key(to_python(n));
|
||||
downcast<T>(obj)->set_subscript(key.get(), value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_mapping_ass_subscript(PyObject* obj, PyObject* key, PyObject* value) const
|
||||
{
|
||||
downcast<T>(obj)->set_subscript(key, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void adjust_slice_indices(PyObject* obj, int& start, int& finish);
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_sequence_slice(PyObject* obj, int start, int finish) const
|
||||
{
|
||||
adjust_slice_indices(obj, start, finish);
|
||||
return downcast<T>(obj)->get_slice(start, finish);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_sequence_ass_slice(PyObject* obj, int start, int finish, PyObject* value) const
|
||||
{
|
||||
adjust_slice_indices(obj, start, finish);
|
||||
downcast<T>(obj)->set_slice(start, finish, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
return downcast<T>(obj)->call(args, keywords);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_getattr(PyObject* obj, const char* name) const
|
||||
{
|
||||
return downcast<T>(obj)->getattr(name);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_setattr(PyObject* obj, const char* name, PyObject* value) const
|
||||
{
|
||||
return downcast<T>(obj)->setattr(name, value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_add(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->add(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_subtract(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->subtract(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_multiply(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->multiply(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_divide(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->divide(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_remainder(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->remainder(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_divmod(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->divmod(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_power(PyObject* obj, PyObject* exponent, PyObject* modulus) const
|
||||
{
|
||||
return downcast<T>(obj)->power(exponent, modulus);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_negative(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->negative();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_positive(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->positive();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_absolute(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->absolute();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_number_nonzero(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->nonzero();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_invert(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->invert();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_lshift(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->lshift(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_rshift(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->rshift(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_and(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->do_and(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_xor(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->do_xor(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_or(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->do_or(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_number_coerce(PyObject* obj, PyObject** x, PyObject** y) const
|
||||
{
|
||||
return downcast<T>(obj)->coerce(x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_int(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->as_int();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_long(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->as_long();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_float(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->as_float();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_oct(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->oct();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_hex(PyObject* obj) const
|
||||
{
|
||||
return downcast<T>(obj)->hex();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
inline dictionary& class_base::dict()
|
||||
{
|
||||
return m_name_space;
|
||||
}
|
||||
|
||||
inline tuple class_base::bases() const
|
||||
{
|
||||
return m_bases;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* meta_class<T>::call(PyObject* args, PyObject* /*keywords*/)
|
||||
{
|
||||
PyObject* name;
|
||||
PyObject* bases;
|
||||
PyObject* name_space;
|
||||
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O!O!O!"),
|
||||
&PyString_Type, &name,
|
||||
&PyTuple_Type, &bases,
|
||||
&PyDict_Type, &name_space))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return as_object(
|
||||
new class_t<T>(this, string(ref(name, ref::increment_count)),
|
||||
tuple(ref(bases, ref::increment_count)),
|
||||
dictionary(ref(name_space, ref::increment_count)))
|
||||
);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
const string& setattr_string();
|
||||
const string& getattr_string();
|
||||
const string& delattr_string();
|
||||
|
||||
inline string class_base::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::python
|
||||
#endif
|
||||
404
include/boost/python/conversions.hpp
Normal file
404
include/boost/python/conversions.hpp
Normal file
@@ -0,0 +1,404 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 04 Mar 01 Fixed std::complex<> stuff to work with MSVC (David Abrahams)
|
||||
// 03 Mar 01 added: converters for [plain] char and std::complex
|
||||
// (Ralf W. Grosse-Kunstleve)
|
||||
|
||||
#ifndef METHOD_DWA122899_H_
|
||||
# define METHOD_DWA122899_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <boost/smart_ptr.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
# include <string>
|
||||
|
||||
# ifdef BOOST_MSVC6_OR_EARLIER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4275) // disable a bogus warning caused by <complex>
|
||||
# endif
|
||||
|
||||
# include <complex>
|
||||
|
||||
# ifdef BOOST_MSVC6_OR_EARLIER
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
|
||||
// This can be instantiated on an enum to provide the to_python/from_python
|
||||
// conversions, provided the values can fit in a long.
|
||||
template <class EnumType>
|
||||
class py_enum_as_int_converters
|
||||
{
|
||||
friend EnumType from_python(PyObject* x, boost::python::type<EnumType>)
|
||||
{
|
||||
return static_cast<EnumType>(
|
||||
from_python(x, boost::python::type<long>()));
|
||||
}
|
||||
|
||||
friend EnumType from_python(PyObject* x, boost::python::type<const EnumType&>)
|
||||
{
|
||||
return static_cast<EnumType>(
|
||||
from_python(x, boost::python::type<long>()));
|
||||
}
|
||||
|
||||
friend PyObject* to_python(EnumType x)
|
||||
{
|
||||
return to_python(static_cast<long>(x));
|
||||
}
|
||||
};
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
namespace boost { namespace python {
|
||||
template <class EnumType> class enum_as_int_converters
|
||||
: public BOOST_PYTHON_CONVERSION::py_enum_as_int_converters<EnumType> {};
|
||||
|
||||
template <class P, class T> class wrapped_pointer;
|
||||
|
||||
//#pragma warn_possunwant off
|
||||
inline void decref_impl(PyObject* p) { Py_DECREF(p); }
|
||||
inline void xdecref_impl(PyObject* p) { Py_XDECREF(p); }
|
||||
//#pragma warn_possunwant reset
|
||||
|
||||
template <class T>
|
||||
inline void decref(T* p)
|
||||
{
|
||||
char* const raw_p = reinterpret_cast<char*>(p);
|
||||
char* const p_base = raw_p - offsetof(PyObject, ob_refcnt);
|
||||
decref_impl(reinterpret_cast<PyObject*>(p_base));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void xdecref(T* p)
|
||||
{
|
||||
char* const raw_p = reinterpret_cast<char*>(p);
|
||||
char* const p_base = raw_p - offsetof(PyObject, ob_refcnt);
|
||||
xdecref_impl(reinterpret_cast<PyObject*>(p_base));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
void expect_complex(PyObject*);
|
||||
|
||||
template <class T>
|
||||
std::complex<T> complex_from_python(PyObject* p, boost::python::type<T>)
|
||||
{
|
||||
expect_complex(p);
|
||||
|
||||
return std::complex<T>(
|
||||
static_cast<T>(PyComplex_RealAsDouble(p)),
|
||||
static_cast<T>(PyComplex_ImagAsDouble(p)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* complex_to_python(const std::complex<T>& sc) {
|
||||
Py_complex pcc;
|
||||
pcc.real = sc.real();
|
||||
pcc.imag = sc.imag();
|
||||
return PyComplex_FromCComplex(pcc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
//
|
||||
// Converters
|
||||
//
|
||||
PyObject* to_python(long);
|
||||
long from_python(PyObject* p, boost::python::type<long>);
|
||||
long from_python(PyObject* p, boost::python::type<const long&>);
|
||||
|
||||
PyObject* to_python(unsigned long);
|
||||
unsigned long from_python(PyObject* p, boost::python::type<unsigned long>);
|
||||
unsigned long from_python(PyObject* p, boost::python::type<const unsigned long&>);
|
||||
|
||||
PyObject* to_python(int);
|
||||
int from_python(PyObject*, boost::python::type<int>);
|
||||
int from_python(PyObject*, boost::python::type<const int&>);
|
||||
|
||||
PyObject* to_python(unsigned int);
|
||||
unsigned int from_python(PyObject*, boost::python::type<unsigned int>);
|
||||
unsigned int from_python(PyObject*, boost::python::type<const unsigned int&>);
|
||||
|
||||
PyObject* to_python(short);
|
||||
short from_python(PyObject*, boost::python::type<short>);
|
||||
short from_python(PyObject*, boost::python::type<const short&>);
|
||||
|
||||
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&>);
|
||||
|
||||
PyObject* to_python(unsigned char);
|
||||
unsigned char from_python(PyObject*, boost::python::type<unsigned char>);
|
||||
unsigned char from_python(PyObject*, boost::python::type<const unsigned char&>);
|
||||
|
||||
PyObject* to_python(float);
|
||||
float from_python(PyObject*, boost::python::type<float>);
|
||||
float from_python(PyObject*, boost::python::type<const float&>);
|
||||
|
||||
PyObject* to_python(double);
|
||||
double from_python(PyObject*, boost::python::type<double>);
|
||||
double from_python(PyObject*, boost::python::type<const double&>);
|
||||
|
||||
PyObject* to_python(bool);
|
||||
bool from_python(PyObject*, boost::python::type<bool>);
|
||||
bool from_python(PyObject*, boost::python::type<const bool&>);
|
||||
|
||||
PyObject* to_python(void);
|
||||
void from_python(PyObject*, boost::python::type<void>);
|
||||
|
||||
PyObject* to_python(const char* s);
|
||||
const char* from_python(PyObject*, boost::python::type<const char*>);
|
||||
|
||||
PyObject* to_python(const std::string& s);
|
||||
std::string from_python(PyObject*, boost::python::type<std::string>);
|
||||
std::string from_python(PyObject*, boost::python::type<const std::string&>);
|
||||
|
||||
inline PyObject* to_python(const std::complex<float>& x)
|
||||
{
|
||||
return boost::python::detail::complex_to_python<float>(x);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(const std::complex<double>& x)
|
||||
{
|
||||
return boost::python::detail::complex_to_python<double>(x);
|
||||
}
|
||||
|
||||
inline std::complex<double> from_python(PyObject* p,
|
||||
boost::python::type<std::complex<double> >) {
|
||||
return boost::python::detail::complex_from_python(p, boost::python::type<double>());
|
||||
}
|
||||
|
||||
inline std::complex<double> from_python(PyObject* p,
|
||||
boost::python::type<const std::complex<double>&>) {
|
||||
return boost::python::detail::complex_from_python(p, boost::python::type<double>());
|
||||
}
|
||||
|
||||
inline std::complex<float> from_python(PyObject* p,
|
||||
boost::python::type<std::complex<float> >) {
|
||||
return boost::python::detail::complex_from_python(p, boost::python::type<float>());
|
||||
}
|
||||
|
||||
inline std::complex<float> from_python(PyObject* p,
|
||||
boost::python::type<const std::complex<float>&>) {
|
||||
return boost::python::detail::complex_from_python(p, boost::python::type<float>());
|
||||
}
|
||||
|
||||
// For when your C++ function really wants to pass/return a PyObject*
|
||||
PyObject* to_python(PyObject*);
|
||||
PyObject* from_python(PyObject*, boost::python::type<PyObject*>);
|
||||
|
||||
// Some standard conversions to/from smart pointer types. You can add your own
|
||||
// from these examples. These are not generated using the friend technique from
|
||||
// wrapped_pointer because:
|
||||
//
|
||||
// 1. We want to be able to extend conversion to/from WrappedPointers using
|
||||
// arbitrary smart pointer types.
|
||||
//
|
||||
// 2. It helps with compilation independence. This way, code which creates
|
||||
// wrappers for functions accepting and returning smart_ptr<T> does not
|
||||
// have to have already seen the invocation of wrapped_type<T>.
|
||||
//
|
||||
|
||||
// Unfortunately, MSVC6 is so incredibly lame that we have to rely on the friend
|
||||
// technique to auto_generate standard pointer conversions for wrapped
|
||||
// types. This means that you need to write a non-templated function for each
|
||||
// specific smart_ptr<T> which you want to convert from_python. For example,
|
||||
//
|
||||
// namespace boost { namespace python {
|
||||
// #ifdef MUST_SUPPORT_MSVC
|
||||
//
|
||||
// MyPtr<Foo> from_python(PyObject*p, type<MyPtr<Foo> >)
|
||||
// { return smart_ptr_from_python(p, type<MyPtr<Foo> >(), type<Foo>());}
|
||||
// }
|
||||
//
|
||||
// MyPtr<Bar> from_python(PyObject*p, type<MyPtr<Bar> >)
|
||||
// { return smart_ptr_from_python(p, type<MyPtr<Bar> >(), type<Bar>());}
|
||||
//
|
||||
// ... // definitions for MyPtr<Baz>, MyPtr<Mumble>, etc.
|
||||
//
|
||||
// #else
|
||||
//
|
||||
// // Just once for all MyPtr<T>
|
||||
// template <class T>
|
||||
// MyPtr<T> from_python(PyObject*p, type<MyPtr<T> >)
|
||||
// {
|
||||
// return smart_ptr_from_python(p, type<MyPtr<T> >(), type<T>());
|
||||
// }
|
||||
//
|
||||
// #endif
|
||||
// }} // namespace boost::python
|
||||
|
||||
#if !defined(BOOST_MSVC6_OR_EARLIER)
|
||||
template <class T>
|
||||
boost::shared_ptr<T> from_python(PyObject*p, boost::python::type<boost::shared_ptr<T> >)
|
||||
{
|
||||
return smart_ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >(), boost::python::type<T>());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
template <class T>
|
||||
PyObject* to_python(std::auto_ptr<T> p)
|
||||
{
|
||||
return new boost::python::wrapped_pointer<std::auto_ptr<T>, T>(p);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* to_python(boost::shared_ptr<T> p)
|
||||
{
|
||||
return new boost::python::wrapped_pointer<boost::shared_ptr<T>, T>(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// inline implementations
|
||||
//
|
||||
|
||||
#ifndef BOOST_MSVC6_OR_EARLIER
|
||||
inline PyObject* to_python(double d)
|
||||
{
|
||||
return PyFloat_FromDouble(d);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(float f)
|
||||
{
|
||||
return PyFloat_FromDouble(f);
|
||||
}
|
||||
#endif // BOOST_MSVC6_OR_EARLIER
|
||||
|
||||
inline PyObject* to_python(long l)
|
||||
{
|
||||
return PyInt_FromLong(l);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(int x)
|
||||
{
|
||||
return PyInt_FromLong(x);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(short x)
|
||||
{
|
||||
return PyInt_FromLong(x);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(bool b)
|
||||
{
|
||||
return PyInt_FromLong(b);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(void)
|
||||
{
|
||||
return boost::python::detail::none();
|
||||
}
|
||||
|
||||
inline PyObject* to_python(const char* s)
|
||||
{
|
||||
return PyString_FromString(s);
|
||||
}
|
||||
|
||||
inline std::string from_python(PyObject* p, boost::python::type<const std::string&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<std::string>());
|
||||
}
|
||||
|
||||
inline PyObject* to_python(PyObject* p)
|
||||
{
|
||||
Py_INCREF(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
inline PyObject* from_python(PyObject* p, boost::python::type<PyObject*>)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
inline const char* from_python(PyObject* p, boost::python::type<const char* const&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<const char*>());
|
||||
}
|
||||
|
||||
inline double from_python(PyObject* p, boost::python::type<const double&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<double>());
|
||||
}
|
||||
|
||||
inline float from_python(PyObject* p, boost::python::type<const float&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<float>());
|
||||
}
|
||||
|
||||
inline int from_python(PyObject* p, boost::python::type<const int&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<int>());
|
||||
}
|
||||
|
||||
inline short from_python(PyObject* p, boost::python::type<const short&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<short>());
|
||||
}
|
||||
|
||||
inline long from_python(PyObject* p, boost::python::type<const long&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<long>());
|
||||
}
|
||||
|
||||
inline bool from_python(PyObject* p, boost::python::type<const bool&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<bool>());
|
||||
}
|
||||
|
||||
inline unsigned int from_python(PyObject* p, boost::python::type<const unsigned int&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<unsigned int>());
|
||||
}
|
||||
|
||||
inline unsigned short from_python(PyObject* p, boost::python::type<const unsigned short&>)
|
||||
{
|
||||
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>());
|
||||
}
|
||||
|
||||
inline unsigned char from_python(PyObject* p, boost::python::type<const unsigned char&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<unsigned char>());
|
||||
}
|
||||
|
||||
inline unsigned long from_python(PyObject* p, boost::python::type<const unsigned long&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<unsigned long>());
|
||||
}
|
||||
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
#endif // METHOD_DWA122899_H_
|
||||
64
include/boost/python/detail/base_object.hpp
Normal file
64
include/boost/python/detail/base_object.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||
|
||||
#ifndef BASE_OBJECT_DWA051600_H_
|
||||
# define BASE_OBJECT_DWA051600_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/signatures.hpp> // really just for type<>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <cstring>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// base_object - adds a constructor and non-virtual destructor to a
|
||||
// base Python type (e.g. PyObject, PyTypeObject).
|
||||
template <class python_type>
|
||||
struct base_object : python_type
|
||||
{
|
||||
typedef python_type base_python_type;
|
||||
|
||||
// Initializes type and reference count. All other fields of base_python_type are 0
|
||||
base_object(PyTypeObject* type_obj);
|
||||
|
||||
// Decrements reference count on the type
|
||||
~base_object();
|
||||
};
|
||||
|
||||
// Easy typedefs for common usage
|
||||
typedef base_object<PyObject> python_object;
|
||||
typedef base_object<PyTypeObject> python_type;
|
||||
|
||||
|
||||
//
|
||||
// class_t template member function implementations
|
||||
//
|
||||
template <class python_type>
|
||||
base_object<python_type>::base_object(PyTypeObject* type_obj)
|
||||
{
|
||||
base_python_type* bp = this;
|
||||
#if !defined(_MSC_VER) || defined(__STLPORT)
|
||||
std::
|
||||
#endif
|
||||
memset(bp, 0, sizeof(base_python_type));
|
||||
Py_INCREF(type_obj);
|
||||
PyObject_INIT(bp, type_obj);
|
||||
}
|
||||
|
||||
template <class python_type>
|
||||
inline base_object<python_type>::~base_object()
|
||||
{
|
||||
Py_DECREF(ob_type);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // BASE_OBJECT_DWA051600_H_
|
||||
81
include/boost/python/detail/cast.hpp
Normal file
81
include/boost/python/detail/cast.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef CAST_DWA052500_H_
|
||||
# define CAST_DWA052500_H_
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/operators.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
// The default way of converting a PyObject* or PyTypeObject* to a T*
|
||||
template <class T>
|
||||
struct downcast_traits
|
||||
{
|
||||
template <class U>
|
||||
static T* cast(U* p) { return static_cast<T*>(p); }
|
||||
};
|
||||
|
||||
inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p)
|
||||
{
|
||||
return reinterpret_cast<PyTypeObject*>(p);
|
||||
}
|
||||
|
||||
inline PyObject* as_base_object(const PyObject*, PyObject* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
inline const PyTypeObject* as_base_object(const PyTypeObject*, const PyObject* p)
|
||||
{
|
||||
return reinterpret_cast<const PyTypeObject*>(p);
|
||||
}
|
||||
|
||||
inline const PyObject* as_base_object(const PyObject*, const PyObject* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// Convert a pointer to any type derived from PyObject or PyTypeObject to a PyObject*
|
||||
inline PyObject* as_object(PyObject* p) { return p; }
|
||||
inline PyObject* as_object(PyTypeObject* p) { return reinterpret_cast<PyObject*>(p); }
|
||||
|
||||
// If I didn't have to support stupid MSVC6 we could just use a simple template function:
|
||||
// template <class T> T* downcast(PyObject*).
|
||||
template <class T>
|
||||
struct downcast : boost::dereferenceable<downcast<T>, T*>
|
||||
{
|
||||
downcast(PyObject* p)
|
||||
: m_p(detail::downcast_traits<T>::cast(detail::as_base_object((T*)0, p)))
|
||||
{}
|
||||
|
||||
downcast(const PyObject* p)
|
||||
: m_p(detail::downcast_traits<T>::cast(detail::as_base_object((const T*)0, p)))
|
||||
{}
|
||||
|
||||
downcast(PyTypeObject* p)
|
||||
: m_p(detail::downcast_traits<T>::cast(p))
|
||||
{}
|
||||
|
||||
downcast(const PyTypeObject* p)
|
||||
: m_p(detail::downcast_traits<T>::cast(p))
|
||||
{}
|
||||
|
||||
operator T*() const { return m_p; }
|
||||
T* get() const { return m_p; }
|
||||
T& operator*() const { return *m_p; }
|
||||
private:
|
||||
T* m_p;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CAST_DWA052500_H_
|
||||
66
include/boost/python/detail/config.hpp
Normal file
66
include/boost/python/detail/config.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
// Revision History:
|
||||
// 04 Mar 01 Some fixes so it will compile with Intel C++ (Dave Abrahams)
|
||||
|
||||
#ifndef CONFIG_DWA052200_H_
|
||||
# define CONFIG_DWA052200_H_
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
// A gcc bug forces some symbols into the global namespace
|
||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
# define BOOST_PYTHON_CONVERSION
|
||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) using ::x
|
||||
# else
|
||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
|
||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
|
||||
# define BOOST_PYTHON_CONVERSION boost::python
|
||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';'
|
||||
# endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# if _MSC_VER <= 1200
|
||||
# define BOOST_MSVC6_OR_EARLIER 1
|
||||
# endif
|
||||
|
||||
# pragma warning (disable : 4786)
|
||||
|
||||
# endif
|
||||
|
||||
// Work around the broken library implementation/strict ansi checking on some
|
||||
// EDG-based compilers (e.g. alpha), which incorrectly warn that the result of
|
||||
// offsetof() is not an integer constant expression.
|
||||
# if defined(__DECCXX_VER) && __DECCXX_VER <= 60290024
|
||||
# define BOOST_OFFSETOF(s_name, s_member) \
|
||||
((size_t)__INTADDR__(&(((s_name *)0)->s_member)))
|
||||
# else
|
||||
# define BOOST_OFFSETOF(s_name, s_member) \
|
||||
offsetof(s_name, s_member)
|
||||
# endif
|
||||
|
||||
// The STLport puts all of the standard 'C' library names in std (as far as the
|
||||
// user is concerned), but without it you need a fix if you're using MSVC or
|
||||
// Intel C++
|
||||
# if defined(BOOST_MSVC_STD_ITERATOR)
|
||||
# define BOOST_CSTD_
|
||||
# else
|
||||
# define BOOST_CSTD_ std
|
||||
# endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name()
|
||||
#else
|
||||
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name()
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_DWA052200_H_
|
||||
915
include/boost/python/detail/extension_class.hpp
Normal file
915
include/boost/python/detail/extension_class.hpp
Normal file
@@ -0,0 +1,915 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file automatically generated for 10-argument constructors by
|
||||
// gen_extclass.python
|
||||
|
||||
// Revision History:
|
||||
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
|
||||
// to_python (Dave Abrahams)
|
||||
|
||||
#ifndef EXTENSION_CLASS_DWA052000_H_
|
||||
# define EXTENSION_CLASS_DWA052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/classes.hpp>
|
||||
# include <vector>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/objects.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
# include <memory>
|
||||
# include <boost/python/detail/init_function.hpp>
|
||||
# include <typeinfo>
|
||||
# include <boost/smart_ptr.hpp>
|
||||
# include <boost/type_traits.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// forward declarations
|
||||
template <long which, class operand> struct operators;
|
||||
template <class T> struct left_operand;
|
||||
template <class T> struct right_operand;
|
||||
|
||||
enum without_downcast_t { without_downcast };
|
||||
|
||||
namespace detail {
|
||||
|
||||
// forward declarations
|
||||
class extension_instance;
|
||||
class extension_class_base;
|
||||
template <class T> class instance_holder;
|
||||
template <class T, class U> class instance_value_holder;
|
||||
template <class ref, class T> class instance_ptr_holder;
|
||||
template <class Specified> struct operand_select;
|
||||
template <long> struct choose_op;
|
||||
template <long> struct choose_rop;
|
||||
template <long> struct choose_unary_op;
|
||||
template <long> struct define_operator;
|
||||
|
||||
meta_class<extension_instance>* extension_meta_class();
|
||||
extension_instance* get_extension_instance(PyObject* p);
|
||||
void report_missing_instance_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
|
||||
void report_missing_ptr_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
|
||||
void report_missing_class_object(const std::type_info&);
|
||||
void report_released_smart_pointer(const std::type_info&);
|
||||
|
||||
template <class T>
|
||||
T* check_non_null(T* p)
|
||||
{
|
||||
if (p == 0)
|
||||
report_released_smart_pointer(typeid(T));
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class Held> class held_instance;
|
||||
|
||||
typedef void* (*conversion_function_ptr)(void*);
|
||||
|
||||
struct base_class_info
|
||||
{
|
||||
base_class_info(extension_class_base* t, conversion_function_ptr f)
|
||||
:class_object(t), convert(f)
|
||||
{}
|
||||
|
||||
extension_class_base* class_object;
|
||||
conversion_function_ptr convert;
|
||||
};
|
||||
|
||||
typedef base_class_info derived_class_info;
|
||||
|
||||
struct add_operator_base;
|
||||
|
||||
class extension_class_base : public class_t<extension_instance>
|
||||
{
|
||||
public:
|
||||
extension_class_base(const char* name);
|
||||
|
||||
public:
|
||||
// the purpose of try_class_conversions() and its related functions
|
||||
// is explained in extclass.cpp
|
||||
void* try_class_conversions(instance_holder_base*) const;
|
||||
void* try_base_class_conversions(instance_holder_base*) const;
|
||||
void* try_derived_class_conversions(instance_holder_base*) const;
|
||||
|
||||
void set_attribute(const char* name, PyObject* x);
|
||||
void set_attribute(const char* name, ref x);
|
||||
|
||||
private:
|
||||
virtual void* extract_object_from_holder(instance_holder_base* v) const = 0;
|
||||
virtual std::vector<base_class_info> const& base_classes() const = 0;
|
||||
virtual std::vector<derived_class_info> const& derived_classes() const = 0;
|
||||
|
||||
protected:
|
||||
friend struct add_operator_base;
|
||||
void add_method(reference<function> method, const char* name);
|
||||
void add_method(function* method, const char* name);
|
||||
|
||||
void add_constructor_object(function*);
|
||||
void add_setter_method(function*, const char* name);
|
||||
void add_getter_method(function*, const char* name);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class class_registry
|
||||
{
|
||||
public:
|
||||
static extension_class_base* class_object()
|
||||
{ return static_class_object; }
|
||||
|
||||
// Register/unregister the Python class object corresponding to T
|
||||
static void register_class(extension_class_base*);
|
||||
static void unregister_class(extension_class_base*);
|
||||
|
||||
// Establish C++ inheritance relationships
|
||||
static void register_base_class(base_class_info const&);
|
||||
static void register_derived_class(derived_class_info const&);
|
||||
|
||||
// Query the C++ inheritance relationships
|
||||
static std::vector<base_class_info> const& base_classes();
|
||||
static std::vector<derived_class_info> const& derived_classes();
|
||||
private:
|
||||
static extension_class_base* static_class_object;
|
||||
static std::vector<base_class_info> static_base_class_info;
|
||||
static std::vector<derived_class_info> static_derived_class_info;
|
||||
};
|
||||
|
||||
template <bool is_pointer>
|
||||
struct is_null_helper
|
||||
{
|
||||
template <class Ptr>
|
||||
static bool test(Ptr x) { return x == 0; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_null_helper<false>
|
||||
{
|
||||
template <class Ptr>
|
||||
static bool test(const Ptr& x) { return x.get() == 0; }
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
bool is_null(const Ptr& x)
|
||||
{
|
||||
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
// This class' only job is to define from_python and to_python converters for T
|
||||
// and U. T is the class the user really intends to wrap. U is a class derived
|
||||
// from T with some virtual function overriding boilerplate, or if there are no
|
||||
// virtual functions, U = held_instance<T>.
|
||||
template <class T, class U = boost::python::detail::held_instance<T> >
|
||||
class python_extension_class_converters
|
||||
{
|
||||
public:
|
||||
// Get an object which can be used to convert T to/from python. This is used
|
||||
// as a kind of concept check by the global template
|
||||
//
|
||||
// PyObject* to_python(const T& x)
|
||||
//
|
||||
// below this class, to prevent the confusing messages that would otherwise
|
||||
// pop up. Now, if T hasn't been wrapped as an extension class, the user
|
||||
// will see an error message about the lack of an eligible
|
||||
// py_extension_class_converters() function.
|
||||
friend python_extension_class_converters py_extension_class_converters(boost::python::type<T>)
|
||||
{
|
||||
return python_extension_class_converters();
|
||||
}
|
||||
|
||||
// This is a member function because in a conforming implementation, friend
|
||||
// funcitons defined inline in the class body are all instantiated as soon
|
||||
// as the enclosing class is instantiated. If T is not copyable, that causes
|
||||
// a compiler error. Instead, we access this function through the global
|
||||
// template
|
||||
//
|
||||
// PyObject* to_python(const T& x)
|
||||
//
|
||||
// defined below this class. Since template functions are instantiated only
|
||||
// on demand, errors will be avoided unless T is noncopyable and the user
|
||||
// writes code which causes us to try to copy a T.
|
||||
PyObject* to_python(const T& x) const
|
||||
{
|
||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||
result->add_implementation(
|
||||
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
||||
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
|
||||
return result.release();
|
||||
}
|
||||
|
||||
friend
|
||||
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
|
||||
{
|
||||
// downcast to an extension_instance, then find the actual T
|
||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
|
||||
for (iterator p = self->wrapped_objects().begin();
|
||||
p != self->wrapped_objects().end(); ++p)
|
||||
{
|
||||
boost::python::detail::instance_holder<T>* held = dynamic_cast<boost::python::detail::instance_holder<T>*>(*p);
|
||||
if (held != 0)
|
||||
return held->target();
|
||||
|
||||
// see extclass.cpp for an explanation of try_class_conversions()
|
||||
void* target = boost::python::detail::class_registry<T>::class_object()->try_class_conversions(*p);
|
||||
if(target)
|
||||
return static_cast<T*>(target);
|
||||
}
|
||||
boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
|
||||
// Convert to T*
|
||||
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
||||
{
|
||||
if (obj == Py_None)
|
||||
return 0;
|
||||
else
|
||||
return non_null_from_python(obj, boost::python::type<T*>());
|
||||
}
|
||||
|
||||
// Extract from obj a mutable reference to the PtrType object which is holding a T.
|
||||
template <class PtrType>
|
||||
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
|
||||
{
|
||||
// downcast to an extension_instance, then find the actual T
|
||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
|
||||
for (iterator p = self->wrapped_objects().begin();
|
||||
p != self->wrapped_objects().end(); ++p)
|
||||
{
|
||||
boost::python::detail::instance_ptr_holder<PtrType, T>* held =
|
||||
dynamic_cast<boost::python::detail::instance_ptr_holder<PtrType, T>*>(*p);
|
||||
if (held != 0)
|
||||
return held->ptr();
|
||||
}
|
||||
boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
|
||||
// Extract from obj a reference to the PtrType object which is holding a
|
||||
// T. If it weren't for auto_ptr, it would be a constant reference. Do not
|
||||
// modify the referent except by copying an auto_ptr! If obj is None, the
|
||||
// reference denotes a default-constructed PtrType
|
||||
template <class PtrType>
|
||||
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
|
||||
{
|
||||
if (obj == Py_None)
|
||||
{
|
||||
static PtrType null_ptr;
|
||||
return null_ptr;
|
||||
}
|
||||
return smart_ptr_reference(obj, boost::python::type<PtrType>());
|
||||
}
|
||||
|
||||
template <class PtrType>
|
||||
static PyObject* smart_ptr_to_python(PtrType x)
|
||||
{
|
||||
if (boost::python::detail::is_null(x))
|
||||
{
|
||||
return boost::python::detail::none();
|
||||
}
|
||||
|
||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||
result->add_implementation(
|
||||
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
||||
new boost::python::detail::instance_ptr_holder<PtrType,T>(x)));
|
||||
return result.release();
|
||||
}
|
||||
|
||||
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
|
||||
{
|
||||
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
|
||||
if (class_object == 0)
|
||||
boost::python::detail::report_missing_class_object(typeid(T));
|
||||
|
||||
return boost::python::reference<boost::python::detail::extension_instance>(
|
||||
new boost::python::detail::extension_instance(class_object));
|
||||
}
|
||||
|
||||
// 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(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 smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
||||
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
|
||||
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(std::auto_ptr<T> x)
|
||||
{ return smart_ptr_to_python(x); }
|
||||
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
||||
{ return smart_ptr_reference(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
||||
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
|
||||
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(boost::shared_ptr<T> x)
|
||||
{ return smart_ptr_to_python(x); }
|
||||
};
|
||||
|
||||
// Convert T to_python, instantiated on demand and only if there isn't a
|
||||
// non-template overload for this function. This version is the one invoked when
|
||||
// T is a wrapped class. See the first 2 functions declared in
|
||||
// python_extension_class_converters above for more info.
|
||||
template <class T>
|
||||
PyObject* to_python(const T& x)
|
||||
{
|
||||
return py_extension_class_converters(boost::python::type<T>()).to_python(x);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters);
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T> class instance_holder;
|
||||
|
||||
class read_only_setattr_function : public function
|
||||
{
|
||||
public:
|
||||
read_only_setattr_function(const char* name);
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
const char* description() const;
|
||||
private:
|
||||
string m_name;
|
||||
};
|
||||
|
||||
template <class From, class To>
|
||||
struct define_conversion
|
||||
{
|
||||
static void* upcast_ptr(void* v)
|
||||
{
|
||||
return static_cast<To*>(static_cast<From*>(v));
|
||||
}
|
||||
|
||||
static void* downcast_ptr(void* v)
|
||||
{
|
||||
return dynamic_cast<To*>(static_cast<From*>(v));
|
||||
}
|
||||
};
|
||||
|
||||
// An easy way to make an extension base class which wraps T. Note that Python
|
||||
// subclasses of this class will simply be class_t<extension_instance> objects.
|
||||
//
|
||||
// U should be a class derived from T which overrides virtual functions with
|
||||
// boilerplate code to call back into Python. See extclass_demo.h for examples.
|
||||
//
|
||||
// U is optional, but you won't be able to override any member functions in
|
||||
// Python which are called from C++ if you don't supply it. If you just want to
|
||||
// be able to use T in python without overriding member functions, you can omit
|
||||
// U.
|
||||
template <class T, class U = held_instance<T> >
|
||||
class extension_class
|
||||
: public python_extension_class_converters<T, U>, // This generates the to_python/from_python functions
|
||||
public extension_class_base
|
||||
{
|
||||
public:
|
||||
typedef T wrapped_type;
|
||||
typedef U callback_type;
|
||||
|
||||
// Construct with a name that comes from typeid(T).name(). The name only
|
||||
// affects the objects of this class are represented through repr()
|
||||
extension_class();
|
||||
|
||||
// Construct with the given name. The name only affects the objects of this
|
||||
// class are represented through repr()
|
||||
extension_class(const char* name);
|
||||
|
||||
~extension_class();
|
||||
|
||||
// define constructors
|
||||
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(
|
||||
prepend(type<A1>::id(),
|
||||
prepend(type<A2>::id(),
|
||||
prepend(type<A3>::id(),
|
||||
prepend(type<A4>::id(),
|
||||
prepend(type<A5>::id(),
|
||||
prepend(type<A6>::id(),
|
||||
prepend(type<A7>::id(),
|
||||
prepend(type<A8>::id(),
|
||||
prepend(type<A9>::id(),
|
||||
prepend(type<A10>::id(),
|
||||
signature0())))))))))));
|
||||
}
|
||||
|
||||
|
||||
// export homogeneous operators (type of both lhs and rhs is 'operator')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>());
|
||||
|
||||
// export homogeneous operators (type of both lhs and rhs is 'T const&')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>());
|
||||
template <long which, class Operand>
|
||||
inline void def(operators<which,Operand>)
|
||||
{
|
||||
typedef typename operand_select<Operand>::template wrapped<T>::type true_operand;
|
||||
def_operators(operators<which,true_operand>());
|
||||
}
|
||||
|
||||
// export heterogeneous operators (type of lhs: 'left', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||
// boost::python::right_operand<int const&>());
|
||||
|
||||
// export heterogeneous operators (type of lhs: 'T const&', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
|
||||
// boost::python::right_operand<int const&>());
|
||||
template <long which, class Left, class Right>
|
||||
inline void def(operators<which,Left>, right_operand<Right> r)
|
||||
{
|
||||
typedef typename operand_select<Left>::template wrapped<T>::type true_left;
|
||||
def_operators(operators<which,true_left>(), r);
|
||||
}
|
||||
|
||||
// export heterogeneous reverse-argument operators
|
||||
// (type of lhs: 'left', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||
// boost::python::left_operand<int const&>());
|
||||
|
||||
// export heterogeneous reverse-argument operators
|
||||
// (type of lhs: 'left', of rhs: 'T const&')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
|
||||
// boost::python::left_operand<int const&>());
|
||||
template <long which, class Left, class Right>
|
||||
inline void def(operators<which,Right>, left_operand<Left> l)
|
||||
{
|
||||
typedef typename operand_select<Right>::template wrapped<T>::type true_right;
|
||||
def_operators(operators<which,true_right>(), l);
|
||||
}
|
||||
|
||||
// define a function that passes Python arguments and keywords
|
||||
// to C++ verbatim (as a 'tuple const&' and 'dictionary const&'
|
||||
// respectively). This is useful for manual argument passing.
|
||||
// It's also the only possibility to pass keyword arguments to C++.
|
||||
// Fn must have a signatur that is compatible to
|
||||
// PyObject* (*)(PyObject* aTuple, PyObject* aDictionary)
|
||||
template <class Fn>
|
||||
inline void def_raw(Fn fn, const char* name)
|
||||
{
|
||||
this->add_method(new_raw_arguments_function(fn), name);
|
||||
}
|
||||
|
||||
// define member functions. In fact this works for free functions, too -
|
||||
// they act like static member functions, or if they start with the
|
||||
// appropriate self argument (as a pointer), they can be used just like
|
||||
// ordinary member functions -- just like Python!
|
||||
template <class Fn>
|
||||
inline void def(Fn fn, const char* name)
|
||||
{
|
||||
this->add_method(new_wrapped_function(fn), name);
|
||||
}
|
||||
|
||||
// Define a virtual member function with a default implementation.
|
||||
// default_fn should be a function which provides the default implementation.
|
||||
// Be careful that default_fn does not in fact call fn virtually!
|
||||
template <class Fn, class DefaultFn>
|
||||
inline void def(Fn fn, const char* name, DefaultFn default_fn)
|
||||
{
|
||||
this->add_method(new_virtual_function(type<T>(), fn, default_fn), name);
|
||||
}
|
||||
|
||||
// Provide a function which implements x.<name>, reading from the given
|
||||
// member (pm) of the T obj
|
||||
template <class MemberType>
|
||||
inline void def_getter(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->add_getter_method(new getter_function<T, MemberType>(pm), name);
|
||||
}
|
||||
|
||||
// Provide a function which implements assignment to x.<name>, writing to
|
||||
// the given member (pm) of the T obj
|
||||
template <class MemberType>
|
||||
inline void def_setter(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->add_setter_method(new setter_function<T, MemberType>(pm), name);
|
||||
}
|
||||
|
||||
// Expose the given member (pm) of the T obj as a read-only attribute
|
||||
template <class MemberType>
|
||||
inline void def_readonly(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->add_setter_method(new read_only_setattr_function(name), name);
|
||||
this->def_getter(pm, name);
|
||||
}
|
||||
|
||||
// Expose the given member (pm) of the T obj as a read/write attribute
|
||||
template <class MemberType>
|
||||
inline void def_read_write(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->def_getter(pm, name);
|
||||
this->def_setter(pm, name);
|
||||
}
|
||||
|
||||
// define the standard coercion needed for operator overloading
|
||||
void def_standard_coerce();
|
||||
|
||||
// declare the given class a base class of this one and register
|
||||
// up and down conversion functions
|
||||
template <class S, class V>
|
||||
void declare_base(extension_class<S, V>* base)
|
||||
{
|
||||
// see extclass.cpp for an explanation of why we need to register
|
||||
// conversion functions
|
||||
base_class_info baseInfo(base,
|
||||
&define_conversion<S, T>::downcast_ptr);
|
||||
class_registry<T>::register_base_class(baseInfo);
|
||||
add_base(ref(as_object(base), ref::increment_count));
|
||||
|
||||
derived_class_info derivedInfo(this,
|
||||
&define_conversion<T, S>::upcast_ptr);
|
||||
class_registry<S>::register_derived_class(derivedInfo);
|
||||
}
|
||||
|
||||
// declare the given class a base class of this one and register
|
||||
// only up conversion function
|
||||
template <class S, class V>
|
||||
void declare_base(extension_class<S, V>* base, without_downcast_t)
|
||||
{
|
||||
// see extclass.cpp for an explanation of why we need to register
|
||||
// conversion functions
|
||||
base_class_info baseInfo(base, 0);
|
||||
class_registry<T>::register_base_class(baseInfo);
|
||||
add_base(ref(as_object(base), ref::increment_count));
|
||||
|
||||
derived_class_info derivedInfo(this,
|
||||
&define_conversion<T, S>::upcast_ptr);
|
||||
class_registry<S>::register_derived_class(derivedInfo);
|
||||
}
|
||||
|
||||
private: // types
|
||||
typedef instance_value_holder<T,U> holder;
|
||||
|
||||
private: // extension_class_base virtual function implementations
|
||||
std::vector<base_class_info> const& base_classes() const;
|
||||
std::vector<derived_class_info> const& derived_classes() const;
|
||||
void* extract_object_from_holder(instance_holder_base* v) const;
|
||||
|
||||
private: // Utility functions
|
||||
template <long which, class Operand>
|
||||
inline void def_operators(operators<which,Operand>)
|
||||
{
|
||||
def_standard_coerce();
|
||||
|
||||
// for some strange reason, this prevents MSVC from having an
|
||||
// "unrecoverable block scoping error"!
|
||||
typedef choose_op<(which & op_add)> choose_add;
|
||||
|
||||
choose_op<(which & op_add)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_sub)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_mul)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_div)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_mod)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_divmod)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_pow)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_lshift)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_rshift)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_and)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_xor)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_invert)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_int)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_long)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_float)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_cmp)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_str)>::template args<Operand>::add(this);
|
||||
}
|
||||
|
||||
template <long which, class Left, class Right>
|
||||
inline void def_operators(operators<which,Left>, right_operand<Right>)
|
||||
{
|
||||
def_standard_coerce();
|
||||
|
||||
choose_op<(which & op_add)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_sub)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_mul)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_div)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_mod)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_divmod)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_pow)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_lshift)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_rshift)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_and)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
|
||||
}
|
||||
|
||||
template <long which, class Left, class Right>
|
||||
inline void def_operators(operators<which,Right>, left_operand<Left>)
|
||||
{
|
||||
def_standard_coerce();
|
||||
|
||||
choose_rop<(which & op_add)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_sub)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_mul)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_div)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_mod)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_divmod)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_pow)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_lshift)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_rshift)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_and)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_xor)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_or)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_cmp)>::template args<Left,Right>::add(this);
|
||||
}
|
||||
|
||||
template <class signature>
|
||||
void add_constructor(signature sig)
|
||||
{
|
||||
this->add_constructor_object(init_function<holder>::create(sig));
|
||||
}
|
||||
};
|
||||
|
||||
// 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 Held>
|
||||
class held_instance : public Held
|
||||
{
|
||||
// There are no member functions: we want to avoid inadvertently overriding
|
||||
// any virtual functions in Held.
|
||||
public:
|
||||
held_instance(PyObject*) : Held() {}
|
||||
template <class A1>
|
||||
held_instance(PyObject*, A1 a1) : Held(a1) {}
|
||||
template <class A1, class 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) : Held(a1, a2, a3) {}
|
||||
template <class A1, class A2, class A3, class 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) : 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
|
||||
// instance_holder<>, below.
|
||||
class instance_holder_base
|
||||
{
|
||||
public:
|
||||
virtual ~instance_holder_base() {}
|
||||
virtual bool held_by_value() = 0;
|
||||
};
|
||||
|
||||
// Abstract base class which holds a Held, somehow. Provides a uniform way to
|
||||
// get a pointer to the held object
|
||||
template <class Held>
|
||||
class instance_holder : public instance_holder_base
|
||||
{
|
||||
public:
|
||||
virtual Held*target() = 0;
|
||||
};
|
||||
|
||||
// Concrete class which holds a Held by way of a wrapper class Wrapper. If Held
|
||||
// can be constructed with arguments (A1...An), Wrapper must have a
|
||||
// corresponding constructor for arguments (PyObject*, A1...An). Wrapper is
|
||||
// neccessary to implement virtual function callbacks (there must be a
|
||||
// back-pointer to the actual Python object so that we can call any
|
||||
// overrides). held_instance (above) is used as a default Wrapper class when
|
||||
// there are no virtual functions.
|
||||
template <class Held, class Wrapper>
|
||||
class instance_value_holder : public instance_holder<Held>
|
||||
{
|
||||
public:
|
||||
Held* target() { return &m_held; }
|
||||
Wrapper* value_target() { return &m_held; }
|
||||
|
||||
instance_value_holder(extension_instance* p) :
|
||||
m_held(p) {}
|
||||
template <class A1>
|
||||
instance_value_holder(extension_instance* p, A1 a1) :
|
||||
m_held(p, a1) {}
|
||||
template <class A1, class A2>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2) :
|
||||
m_held(p, a1, a2) {}
|
||||
template <class A1, class A2, class A3>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3) :
|
||||
m_held(p, a1, a2, a3) {}
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4) :
|
||||
m_held(p, a1, a2, a3, a4) {}
|
||||
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; }
|
||||
|
||||
private:
|
||||
Wrapper m_held;
|
||||
};
|
||||
|
||||
// Concrete class which holds a HeldType by way of a (possibly smart) pointer
|
||||
// PtrType. By default, these are only generated for PtrType ==
|
||||
// std::auto_ptr<HeldType> and PtrType == boost::shared_ptr<HeldType>.
|
||||
template <class PtrType, class HeldType>
|
||||
class instance_ptr_holder : public instance_holder<HeldType>
|
||||
{
|
||||
public:
|
||||
HeldType* target() { return &*m_ptr; }
|
||||
PtrType& ptr() { return m_ptr; }
|
||||
|
||||
instance_ptr_holder(PtrType ptr) : m_ptr(ptr) {}
|
||||
|
||||
public: // implementation of instance_holder_base required interface
|
||||
bool held_by_value() { return false; }
|
||||
private:
|
||||
PtrType m_ptr;
|
||||
};
|
||||
|
||||
class extension_instance : public instance
|
||||
{
|
||||
public:
|
||||
extension_instance(PyTypeObject* class_);
|
||||
~extension_instance();
|
||||
|
||||
void add_implementation(std::auto_ptr<instance_holder_base> holder);
|
||||
|
||||
typedef std::vector<instance_holder_base*> held_objects;
|
||||
const held_objects& wrapped_objects() const
|
||||
{ return m_wrapped_objects; }
|
||||
private:
|
||||
held_objects m_wrapped_objects;
|
||||
};
|
||||
|
||||
//
|
||||
// Template function implementations
|
||||
//
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::extension_class()
|
||||
: extension_class_base(typeid(T).name())
|
||||
{
|
||||
class_registry<T>::register_class(this);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::extension_class(const char* name)
|
||||
: extension_class_base(name)
|
||||
{
|
||||
class_registry<T>::register_class(this);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void extension_class<T, U>::def_standard_coerce()
|
||||
{
|
||||
ref coerce_fct = dict().get_item(string("__coerce__"));
|
||||
|
||||
if(coerce_fct.get() == 0) // not yet defined
|
||||
this->def(&standard_coerce, "__coerce__");
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
std::vector<base_class_info> const&
|
||||
extension_class<T, U>::base_classes() const
|
||||
{
|
||||
return class_registry<T>::base_classes();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
std::vector<derived_class_info> const&
|
||||
extension_class<T, U>::derived_classes() const
|
||||
{
|
||||
return class_registry<T>::derived_classes();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void* extension_class<T, U>::extract_object_from_holder(instance_holder_base* v) const
|
||||
{
|
||||
instance_holder<T>* held = dynamic_cast<instance_holder<T>*>(v);
|
||||
if(held)
|
||||
return held->target();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::~extension_class()
|
||||
{
|
||||
class_registry<T>::unregister_class(this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void class_registry<T>::register_class(extension_class_base* p)
|
||||
{
|
||||
// You're not expected to create more than one of these!
|
||||
assert(static_class_object == 0);
|
||||
static_class_object = p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void class_registry<T>::unregister_class(extension_class_base* p)
|
||||
{
|
||||
// The user should be destroying the same object they created.
|
||||
assert(static_class_object == p);
|
||||
(void)p; // unused in shipping version
|
||||
static_class_object = 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void class_registry<T>::register_base_class(base_class_info const& i)
|
||||
{
|
||||
static_base_class_info.push_back(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void class_registry<T>::register_derived_class(derived_class_info const& i)
|
||||
{
|
||||
static_derived_class_info.push_back(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::vector<base_class_info> const& class_registry<T>::base_classes()
|
||||
{
|
||||
return static_base_class_info;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::vector<derived_class_info> const& class_registry<T>::derived_classes()
|
||||
{
|
||||
return static_derived_class_info;
|
||||
}
|
||||
|
||||
//
|
||||
// Static data member declaration.
|
||||
//
|
||||
template <class T>
|
||||
extension_class_base* class_registry<T>::static_class_object;
|
||||
template <class T>
|
||||
std::vector<base_class_info> class_registry<T>::static_base_class_info;
|
||||
template <class T>
|
||||
std::vector<derived_class_info> class_registry<T>::static_derived_class_info;
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // EXTENSION_CLASS_DWA052000_H_
|
||||
306
include/boost/python/detail/functions.hpp
Normal file
306
include/boost/python/detail/functions.hpp
Normal file
@@ -0,0 +1,306 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef FUNCTIONS_DWA051400_H_
|
||||
# define FUNCTIONS_DWA051400_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <boost/python/caller.hpp>
|
||||
# include <boost/call_traits.hpp>
|
||||
# include <boost/python/objects.hpp>
|
||||
# include <boost/python/detail/base_object.hpp>
|
||||
# include <typeinfo>
|
||||
# include <vector>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// forward declaration
|
||||
class extension_instance;
|
||||
|
||||
|
||||
// function --
|
||||
// the common base class for all overloadable function and method objects
|
||||
// supplied by the library.
|
||||
class function : public python_object
|
||||
{
|
||||
public:
|
||||
function();
|
||||
// function objects are reasonably rare, so we guess we can afford a virtual table.
|
||||
// This cuts down on the number of distinct type objects which need to be defined.
|
||||
virtual ~function() {}
|
||||
|
||||
PyObject* call(PyObject* args, PyObject* keywords) const;
|
||||
static void add_to_namespace(reference<function> f, const char* name, PyObject* dict);
|
||||
|
||||
private:
|
||||
virtual PyObject* do_call(PyObject* args, PyObject* keywords) const = 0;
|
||||
virtual const char* description() const = 0;
|
||||
private:
|
||||
struct type_object;
|
||||
private:
|
||||
reference<function> m_overloads;
|
||||
};
|
||||
|
||||
// wrapped_function_pointer<> --
|
||||
// A single function or member function pointer wrapped and presented to
|
||||
// Python as a callable object.
|
||||
//
|
||||
// Template parameters:
|
||||
// R - the return type of the function pointer
|
||||
// F - the complete type of the wrapped function pointer
|
||||
template <class R, class F>
|
||||
struct wrapped_function_pointer : function
|
||||
{
|
||||
typedef F ptr_fun; // pointer-to--function or pointer-to-member-function
|
||||
|
||||
wrapped_function_pointer(ptr_fun pf)
|
||||
: m_pf(pf) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const
|
||||
{ return caller<R>::call(m_pf, args, keywords); }
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(F).name(); }
|
||||
|
||||
private:
|
||||
const ptr_fun m_pf;
|
||||
};
|
||||
|
||||
// raw_arguments_function
|
||||
// A function that passes the Python argument tuple and keyword dictionary
|
||||
// verbatim to C++ (useful for customized argument parsing and variable
|
||||
// argument lists)
|
||||
template <class Ret, class Args, class Keywords>
|
||||
struct raw_arguments_function : function
|
||||
{
|
||||
typedef Ret (*ptr_fun)(Args, Keywords);
|
||||
|
||||
raw_arguments_function(ptr_fun pf)
|
||||
: m_pf(pf) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
ref dict(keywords ?
|
||||
ref(keywords, ref::increment_count) :
|
||||
ref(PyDict_New()));
|
||||
|
||||
return to_python(
|
||||
(*m_pf)(from_python(args, boost::python::type<Args>()),
|
||||
from_python(dict.get(), boost::python::type<Keywords>())));
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(ptr_fun).name(); }
|
||||
|
||||
private:
|
||||
const ptr_fun m_pf;
|
||||
};
|
||||
|
||||
// virtual_function<> --
|
||||
// A virtual function with a default implementation wrapped and presented
|
||||
// to Python as a callable object.
|
||||
//
|
||||
// Template parameters:
|
||||
// T - the type of the target class
|
||||
// R - the return type of the function pointer
|
||||
// V - the virtual function pointer being wrapped
|
||||
// (should be of the form R(T::*)(<args>), or R (*)(T, <args>))
|
||||
// D - a function which takes a T&, const T&, T*, or const T* first
|
||||
// parameter and calls T::f on it /non-virtually/, where V
|
||||
// approximates &T::f.
|
||||
template <class T, class R, class V, class D>
|
||||
class virtual_function : public function
|
||||
{
|
||||
public:
|
||||
virtual_function(V virtual_function_ptr, D default_implementation)
|
||||
: m_virtual_function_ptr(virtual_function_ptr),
|
||||
m_default_implementation(default_implementation)
|
||||
{}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(V).name(); }
|
||||
|
||||
private:
|
||||
const V m_virtual_function_ptr;
|
||||
const D m_default_implementation;
|
||||
};
|
||||
|
||||
// A helper function for new_member_function(), below. Implements the core
|
||||
// functionality once the return type has already been deduced. R is expected to
|
||||
// be type<X>, where X is the actual return type of pmf.
|
||||
template <class F, class R>
|
||||
function* new_wrapped_function_aux(R, F pmf)
|
||||
{
|
||||
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
|
||||
typedef typename R::type return_type;
|
||||
return new wrapped_function_pointer<return_type, F>(pmf);
|
||||
}
|
||||
|
||||
// Create and return a new member function object wrapping the given
|
||||
// pointer-to-member function
|
||||
template <class F>
|
||||
inline function* new_wrapped_function(F pmf)
|
||||
{
|
||||
// Deduce the return type and pass it off to the helper function above
|
||||
return new_wrapped_function_aux(return_value(pmf), pmf);
|
||||
}
|
||||
|
||||
template <class R, class Args, class keywords>
|
||||
function* new_raw_arguments_function(R (*pmf)(Args, keywords))
|
||||
{
|
||||
return new raw_arguments_function<R, Args, keywords>(pmf);
|
||||
}
|
||||
|
||||
|
||||
// A helper function for new_virtual_function(), below. Implements the core
|
||||
// functionality once the return type has already been deduced. R is expected to
|
||||
// be type<X>, where X is the actual return type of V.
|
||||
template <class T, class R, class V, class D>
|
||||
inline function* new_virtual_function_aux(
|
||||
type<T>, R, V virtual_function_ptr, D default_implementation
|
||||
)
|
||||
{
|
||||
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
|
||||
typedef typename R::type return_type;
|
||||
return new virtual_function<T, return_type, V, D>(
|
||||
virtual_function_ptr, default_implementation);
|
||||
}
|
||||
|
||||
// Create and return a new virtual_function object wrapping the given
|
||||
// virtual_function_ptr and default_implementation
|
||||
template <class T, class V, class D>
|
||||
inline function* new_virtual_function(
|
||||
type<T>, V virtual_function_ptr, D default_implementation
|
||||
)
|
||||
{
|
||||
// Deduce the return type and pass it off to the helper function above
|
||||
return new_virtual_function_aux(
|
||||
type<T>(), return_value(virtual_function_ptr),
|
||||
virtual_function_ptr, default_implementation);
|
||||
}
|
||||
|
||||
// A function with a bundled "bound target" object. This is what is produced by
|
||||
// the expression a.b where a is an instance or extension_instance object and b
|
||||
// is a callable object not found in the obj namespace but on its class or
|
||||
// a base class.
|
||||
class bound_function : public python_object
|
||||
{
|
||||
public:
|
||||
static bound_function* create(const ref& target, const ref& fn);
|
||||
|
||||
bound_function(const ref& target, const ref& fn);
|
||||
PyObject* call(PyObject*args, PyObject* keywords) const;
|
||||
PyObject* getattr(const char* name) const;
|
||||
|
||||
private:
|
||||
struct type_object;
|
||||
friend struct type_object;
|
||||
|
||||
ref m_target;
|
||||
ref m_unbound_function;
|
||||
|
||||
private: // data members for allocation/deallocation optimization
|
||||
bound_function* m_free_list_link;
|
||||
|
||||
static bound_function* free_list;
|
||||
};
|
||||
|
||||
// Special functions designed to access data members of a wrapped C++ object.
|
||||
template <class ClassType, class MemberType>
|
||||
class getter_function : public function
|
||||
{
|
||||
public:
|
||||
typedef MemberType ClassType::* pointer_to_member;
|
||||
|
||||
getter_function(pointer_to_member pm)
|
||||
: m_pm(pm) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(MemberType (*)(const ClassType&)).name(); }
|
||||
private:
|
||||
pointer_to_member m_pm;
|
||||
};
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
class setter_function : public function
|
||||
{
|
||||
public:
|
||||
typedef MemberType ClassType::* pointer_to_member;
|
||||
|
||||
setter_function(pointer_to_member pm)
|
||||
: m_pm(pm) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(const ClassType&, const MemberType&)).name(); }
|
||||
private:
|
||||
pointer_to_member m_pm;
|
||||
};
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
PyObject* getter_function<ClassType, MemberType>::do_call(
|
||||
PyObject* args, PyObject* /* keywords */) const
|
||||
{
|
||||
PyObject* self;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
||||
return 0;
|
||||
|
||||
return to_python(
|
||||
from_python(self, type<const ClassType*>())->*m_pm);
|
||||
}
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
PyObject* setter_function<ClassType, MemberType>::do_call(
|
||||
PyObject* args, PyObject* /* keywords */) const
|
||||
{
|
||||
PyObject* self;
|
||||
PyObject* value;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &value))
|
||||
return 0;
|
||||
|
||||
typedef typename boost::call_traits<MemberType>::const_reference extract_type;
|
||||
from_python(self, type<ClassType*>())->*m_pm
|
||||
= from_python(value, type<extract_type>());
|
||||
|
||||
return none();
|
||||
}
|
||||
|
||||
template <class T, class R, class V, class D>
|
||||
PyObject* virtual_function<T,R,V,D>::do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// If the target object is held by pointer, we must call through the virtual
|
||||
// function pointer to the most-derived override.
|
||||
PyObject* target = PyTuple_GetItem(args, 0);
|
||||
if (target != 0)
|
||||
{
|
||||
extension_instance* self = get_extension_instance(target);
|
||||
if (self->wrapped_objects().size() == 1
|
||||
&& !self->wrapped_objects()[0]->held_by_value())
|
||||
{
|
||||
return caller<R>::call(m_virtual_function_ptr, args, keywords);
|
||||
}
|
||||
}
|
||||
return caller<R>::call(m_default_implementation, args, keywords);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // FUNCTIONS_DWA051400_H_
|
||||
507
include/boost/python/detail/init_function.hpp
Normal file
507
include/boost/python/detail/init_function.hpp
Normal file
@@ -0,0 +1,507 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file was generated for %d-argument constructors by gen_init_function.python
|
||||
|
||||
#ifndef INIT_FUNCTION_DWA052000_H_
|
||||
# define INIT_FUNCTION_DWA052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <typeinfo>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// parameter_traits - so far, this is a way to pass a const T& when we can be
|
||||
// sure T is not a reference type, and a raw T otherwise. This should be
|
||||
// rolled into boost::call_traits. Ordinarily, parameter_traits would be
|
||||
// written:
|
||||
//
|
||||
// template <class T> struct parameter_traits
|
||||
// {
|
||||
// typedef const T& const_reference;
|
||||
// };
|
||||
//
|
||||
// template <class T> struct parameter_traits<T&>
|
||||
// {
|
||||
// typedef T& const_reference;
|
||||
// };
|
||||
//
|
||||
// template <> struct parameter_traits<void>
|
||||
// {
|
||||
// typedef void const_reference;
|
||||
// };
|
||||
//
|
||||
// ...but since we can't partially specialize on reference types, we need this
|
||||
// long-winded but equivalent incantation.
|
||||
|
||||
// const_ref_selector -- an implementation detail of parameter_traits (below). This uses
|
||||
// the usual "poor man's partial specialization" hack for MSVC.
|
||||
template <bool is_ref>
|
||||
struct const_ref_selector
|
||||
{
|
||||
template <class T>
|
||||
struct const_ref
|
||||
{
|
||||
typedef const T& type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct const_ref_selector<true>
|
||||
{
|
||||
template <class T>
|
||||
struct const_ref
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4181)
|
||||
# endif // BOOST_MSVC
|
||||
template <class T>
|
||||
struct parameter_traits
|
||||
{
|
||||
private:
|
||||
typedef const_ref_selector<boost::is_reference<T>::value> selector;
|
||||
public:
|
||||
typedef typename selector::template const_ref<T>::type const_reference;
|
||||
};
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
# endif // BOOST_MSVC
|
||||
|
||||
// Full spcialization for void
|
||||
template <>
|
||||
struct parameter_traits<void>
|
||||
{
|
||||
typedef void const_reference;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class reference_parameter
|
||||
{
|
||||
typedef typename parameter_traits<T>::const_reference const_reference;
|
||||
public:
|
||||
reference_parameter(const_reference value)
|
||||
: value(value) {}
|
||||
operator const_reference() { return value; }
|
||||
private:
|
||||
const_reference value;
|
||||
};
|
||||
|
||||
class extension_instance;
|
||||
class instance_holder_base;
|
||||
|
||||
class init;
|
||||
template <class T> struct init0;
|
||||
template <class T, class A1> struct init1;
|
||||
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>
|
||||
struct init_function
|
||||
{
|
||||
static init* create(signature0) {
|
||||
return new init0<T>;
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
static init* create(signature1<A1>) {
|
||||
return new init1<T,
|
||||
detail::parameter_traits<A1>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
static init* create(signature2<A1, A2>) {
|
||||
return new init2<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
static init* create(signature3<A1, A2, A3>) {
|
||||
return new init3<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
static init* create(signature4<A1, A2, A3, A4>) {
|
||||
return new init4<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
static init* create(signature5<A1, A2, A3, A4, A5>) {
|
||||
return new init5<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference>;
|
||||
}
|
||||
|
||||
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,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference>;
|
||||
}
|
||||
|
||||
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,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference>;
|
||||
}
|
||||
|
||||
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,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference>;
|
||||
}
|
||||
|
||||
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,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference,
|
||||
detail::parameter_traits<A9>::const_reference>;
|
||||
}
|
||||
|
||||
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,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference,
|
||||
detail::parameter_traits<A9>::const_reference,
|
||||
detail::parameter_traits<A10>::const_reference>;
|
||||
}
|
||||
};
|
||||
|
||||
class init : public function
|
||||
{
|
||||
private: // override function hook
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
private:
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct init0 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("")))
|
||||
throw argument_error();
|
||||
return new T(self
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1>
|
||||
struct init1 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &a1))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
struct init2 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3>
|
||||
struct init3 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOO"), &a1, &a2, &a3))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4>
|
||||
struct init4 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOO"), &a1, &a2, &a3, &a4))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5>
|
||||
struct init5 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOO"), &a1, &a2, &a3, &a4, &a5))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct init6 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
struct init7 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
struct init8 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
struct init9 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
PyObject* a9;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
|
||||
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9)).name(); }
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
PyObject* a9;
|
||||
PyObject* a10;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
|
||||
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>())),
|
||||
boost::python::detail::reference_parameter<A10>(from_python(a10, type<A10>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)).name(); }
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // INIT_FUNCTION_DWA052000_H_
|
||||
21
include/boost/python/detail/none.hpp
Normal file
21
include/boost/python/detail/none.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef NONE_DWA_052000_H_
|
||||
# define NONE_DWA_052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
inline PyObject* none() { Py_INCREF(Py_None); return Py_None; }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // NONE_DWA_052000_H_
|
||||
251
include/boost/python/detail/signatures.hpp
Normal file
251
include/boost/python/detail/signatures.hpp
Normal file
@@ -0,0 +1,251 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file automatically generated by gen_signatures.python for 10 arguments.
|
||||
#ifndef SIGNATURES_DWA050900_H_
|
||||
# define SIGNATURES_DWA050900_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
// A stand-in for the built-in void. This one can be passed to functions and
|
||||
// (under MSVC, which has a bug, be used as a default template type parameter).
|
||||
struct void_t {};
|
||||
}
|
||||
|
||||
// An envelope in which type information can be delivered for the purposes
|
||||
// of selecting an overloaded from_python() function. This is needed to work
|
||||
// around MSVC's lack of partial specialiation/ordering. Where normally we'd
|
||||
// want to form a function call like void f<const T&>(), We instead pass
|
||||
// type<const T&> as one of the function parameters to select a particular
|
||||
// overload.
|
||||
//
|
||||
// The id typedef helps us deal with the lack of partial ordering by generating
|
||||
// unique types for constructor signatures. In general, type<T>::id is type<T>,
|
||||
// but type<void_t>::id is just void_t.
|
||||
template <class T>
|
||||
struct type
|
||||
{
|
||||
typedef type id;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct type<boost::python::detail::void_t>
|
||||
{
|
||||
typedef boost::python::detail::void_t id;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// These basically encapsulate a chain of types, , used to make the syntax of
|
||||
// add(constructor<T1, ...>()) work. We need to produce a unique type for each number
|
||||
// of non-default parameters to constructor<>. Q: why not use a recursive
|
||||
// formulation for infinite extensibility? A: MSVC6 seems to choke on constructs
|
||||
// that involve recursive template nesting.
|
||||
//
|
||||
// signature chaining
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
|
||||
struct signature10 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
|
||||
struct signature9 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class X>
|
||||
inline signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9> prepend(type<X>, signature9<T1, T2, T3, T4, T5, T6, T7, T8, T9>)
|
||||
{ return signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
struct signature8 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class X>
|
||||
inline signature9<X, T1, T2, T3, T4, T5, T6, T7, T8> prepend(type<X>, signature8<T1, T2, T3, T4, T5, T6, T7, T8>)
|
||||
{ return signature9<X, T1, T2, T3, T4, T5, T6, T7, T8>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
struct signature7 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class X>
|
||||
inline signature8<X, T1, T2, T3, T4, T5, T6, T7> prepend(type<X>, signature7<T1, T2, T3, T4, T5, T6, T7>)
|
||||
{ return signature8<X, T1, T2, T3, T4, T5, T6, T7>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
struct signature6 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class X>
|
||||
inline signature7<X, T1, T2, T3, T4, T5, T6> prepend(type<X>, signature6<T1, T2, T3, T4, T5, T6>)
|
||||
{ return signature7<X, T1, T2, T3, T4, T5, T6>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
struct signature5 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class X>
|
||||
inline signature6<X, T1, T2, T3, T4, T5> prepend(type<X>, signature5<T1, T2, T3, T4, T5>)
|
||||
{ return signature6<X, T1, T2, T3, T4, T5>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
struct signature4 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class X>
|
||||
inline signature5<X, T1, T2, T3, T4> prepend(type<X>, signature4<T1, T2, T3, T4>)
|
||||
{ return signature5<X, T1, T2, T3, T4>(); }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct signature3 {};
|
||||
|
||||
template <class T1, class T2, class T3, class X>
|
||||
inline signature4<X, T1, T2, T3> prepend(type<X>, signature3<T1, T2, T3>)
|
||||
{ return signature4<X, T1, T2, T3>(); }
|
||||
|
||||
template <class T1, class T2>
|
||||
struct signature2 {};
|
||||
|
||||
template <class T1, class T2, class X>
|
||||
inline signature3<X, T1, T2> prepend(type<X>, signature2<T1, T2>)
|
||||
{ return signature3<X, T1, T2>(); }
|
||||
|
||||
template <class T1>
|
||||
struct signature1 {};
|
||||
|
||||
template <class T1, class X>
|
||||
inline signature2<X, T1> prepend(type<X>, signature1<T1>)
|
||||
{ return signature2<X, T1>(); }
|
||||
|
||||
struct signature0 {};
|
||||
|
||||
template <class X>
|
||||
inline signature1<X> prepend(type<X>, signature0)
|
||||
{ return signature1<X>(); }
|
||||
|
||||
|
||||
// This one terminates the chain. Prepending void_t to the head of a void_t
|
||||
// signature results in a void_t signature again.
|
||||
inline signature0 prepend(void_t, signature0) { return signature0(); }
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class A1 = detail::void_t, class A2 = detail::void_t, class A3 = detail::void_t, class A4 = detail::void_t, class A5 = detail::void_t, class A6 = detail::void_t, class A7 = detail::void_t, class A8 = detail::void_t, class A9 = detail::void_t, class A10 = detail::void_t>
|
||||
struct constructor
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// Return value extraction:
|
||||
|
||||
// This is just another little envelope for carrying a typedef (see type,
|
||||
// above). I could have re-used type, but that has a very specific purpose. I
|
||||
// thought this would be clearer.
|
||||
template <class T>
|
||||
struct return_value_select { typedef T type; };
|
||||
|
||||
// free functions
|
||||
template <class R>
|
||||
return_value_select<R> return_value(R (*)()) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1>
|
||||
return_value_select<R> return_value(R (*)(A1)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2>
|
||||
return_value_select<R> return_value(R (*)(A1, A2)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
|
||||
|
||||
// TODO(?): handle 'const void'
|
||||
|
||||
// member functions
|
||||
template <class R, class T>
|
||||
return_value_select<R> return_value(R (T::*)()) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1>
|
||||
return_value_select<R> return_value(R (T::*)(A1)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T>
|
||||
return_value_select<R> return_value(R (T::*)() const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1>
|
||||
return_value_select<R> return_value(R (T::*)(A1) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { return return_value_select<R>(); }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif
|
||||
68
include/boost/python/detail/singleton.hpp
Normal file
68
include/boost/python/detail/singleton.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef SINGLETON_DWA051900_H_
|
||||
# define SINGLETON_DWA051900_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
struct empty {};
|
||||
template <class Derived, class Base = empty>
|
||||
struct singleton : Base
|
||||
{
|
||||
typedef singleton singleton_base; // Convenience type for derived class constructors
|
||||
|
||||
static Derived* instance();
|
||||
|
||||
// Pass-through constructors
|
||||
singleton() : Base() {}
|
||||
|
||||
template <class A1>
|
||||
singleton(const A1& a1) : Base(a1) {}
|
||||
|
||||
template <class A1, class A2>
|
||||
singleton(const A1& a1, const A2& a2) : Base(a1, a2) {}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3) : Base(a1, a2, a3) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4) : Base(a1, a2, a3, a4) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) : Base(a1, a2, a3, a4, a5) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) : Base(a1, a2, a3, a4, a5, a6) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) : Base(a1, a2, a3, a4, a5, a6, a7) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) : Base(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>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9) : Base(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>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) : Base(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
|
||||
};
|
||||
|
||||
template <class Derived, class Base>
|
||||
Derived* singleton<Derived,Base>::instance()
|
||||
{
|
||||
static Derived x;
|
||||
return &x;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif
|
||||
389
include/boost/python/detail/types.hpp
Normal file
389
include/boost/python/detail/types.hpp
Normal file
@@ -0,0 +1,389 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef TYPES_DWA051800_H_
|
||||
# define TYPES_DWA051800_H_
|
||||
|
||||
// Usage:
|
||||
// class X : public
|
||||
// boost::python::callable<
|
||||
// boost::python::getattrable <
|
||||
// boost::python::setattrable<python_object, X> > >
|
||||
// {
|
||||
// public:
|
||||
// ref call(args, kw);
|
||||
// ref getattr(args, kw);
|
||||
// ref setattr(args, kw);
|
||||
// };
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/signatures.hpp> // really just for type<>
|
||||
# include <boost/python/detail/cast.hpp>
|
||||
# include <boost/python/detail/base_object.hpp>
|
||||
# include <typeinfo>
|
||||
# include <vector>
|
||||
# include <cassert>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
class string;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class instance_holder_base;
|
||||
|
||||
class type_object_base : public python_type
|
||||
{
|
||||
public:
|
||||
explicit type_object_base(PyTypeObject* type_type);
|
||||
virtual ~type_object_base();
|
||||
|
||||
public:
|
||||
enum capability {
|
||||
hash, call, str, getattr, setattr, compare, repr,
|
||||
|
||||
mapping_length, mapping_subscript, mapping_ass_subscript,
|
||||
|
||||
sequence_length, sequence_item, sequence_ass_item,
|
||||
sequence_concat, sequence_repeat, sequence_slice, sequence_ass_slice,
|
||||
|
||||
number_add, number_subtract, number_multiply, number_divide,
|
||||
number_remainder, number_divmod, number_power, number_negative,
|
||||
number_positive, number_absolute, number_nonzero, number_invert,
|
||||
number_lshift, number_rshift, number_and, number_xor, number_or,
|
||||
number_coerce, number_int, number_long, number_float, number_oct,
|
||||
number_hex
|
||||
};
|
||||
|
||||
void enable(capability);
|
||||
|
||||
//
|
||||
// type behaviors
|
||||
//
|
||||
public: // Callbacks for basic type functionality.
|
||||
virtual PyObject* instance_repr(PyObject*) const;
|
||||
virtual int instance_compare(PyObject*, PyObject* other) const;
|
||||
virtual PyObject* instance_str(PyObject*) const;
|
||||
virtual long instance_hash(PyObject*) const;
|
||||
virtual PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
|
||||
virtual PyObject* instance_getattr(PyObject* obj, const char* name) const;
|
||||
virtual int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
|
||||
|
||||
// Dealloc is a special case, since every type needs a nonzero tp_dealloc slot.
|
||||
virtual void instance_dealloc(PyObject*) const = 0;
|
||||
|
||||
public: // Callbacks for mapping methods
|
||||
virtual int instance_mapping_length(PyObject*) const;
|
||||
virtual PyObject* instance_mapping_subscript(PyObject*, PyObject*) const ;
|
||||
virtual int instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const;
|
||||
|
||||
public: // Callbacks for sequence methods
|
||||
virtual int instance_sequence_length(PyObject* obj) const;
|
||||
virtual PyObject* instance_sequence_concat(PyObject* obj, PyObject* other) const;
|
||||
virtual PyObject* instance_sequence_repeat(PyObject* obj, int n) const;
|
||||
virtual PyObject* instance_sequence_item(PyObject* obj, int n) const;
|
||||
virtual PyObject* instance_sequence_slice(PyObject* obj, int start, int finish) const;
|
||||
virtual int instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const;
|
||||
virtual int instance_sequence_ass_slice(PyObject* obj, int start, int finish, PyObject* value) const;
|
||||
|
||||
public: // Callbacks for number methods
|
||||
virtual PyObject* instance_number_add(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_subtract(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_multiply(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_divide(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_remainder(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_divmod(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_power(PyObject*, PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_negative(PyObject*) const;
|
||||
virtual PyObject* instance_number_positive(PyObject*) const;
|
||||
virtual PyObject* instance_number_absolute(PyObject*) const;
|
||||
virtual int instance_number_nonzero(PyObject*) const;
|
||||
virtual PyObject* instance_number_invert(PyObject*) const;
|
||||
virtual PyObject* instance_number_lshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_rshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_and(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_xor(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_or(PyObject*, PyObject*) const;
|
||||
virtual int instance_number_coerce(PyObject*, PyObject**, PyObject**) const;
|
||||
virtual PyObject* instance_number_int(PyObject*) const;
|
||||
virtual PyObject* instance_number_long(PyObject*) const;
|
||||
virtual PyObject* instance_number_float(PyObject*) const;
|
||||
virtual PyObject* instance_number_oct(PyObject*) const;
|
||||
virtual PyObject* instance_number_hex(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class type_object : public type_object_base
|
||||
{
|
||||
public:
|
||||
typedef T instance;
|
||||
|
||||
type_object(PyTypeObject* type_type, const char* name)
|
||||
: type_object_base(type_type)
|
||||
{
|
||||
assert(name != 0);
|
||||
this->tp_name = const_cast<char*>(name);
|
||||
}
|
||||
|
||||
type_object(PyTypeObject* type_type)
|
||||
: type_object_base(type_type)
|
||||
{
|
||||
this->tp_name = const_cast<char*>(typeid(instance).name());
|
||||
}
|
||||
|
||||
private: // Overridable behaviors.
|
||||
// Called when the reference count goes to zero. The default implementation
|
||||
// is "delete p". If you have not allocated your object with operator new or
|
||||
// you have other constraints, you'll need to override this
|
||||
virtual void dealloc(T* p) const;
|
||||
|
||||
private: // Implementation of type_object_base hooks. Do not reimplement in derived classes.
|
||||
void instance_dealloc(PyObject*) const;
|
||||
};
|
||||
|
||||
//
|
||||
// type objects
|
||||
//
|
||||
template <class Base>
|
||||
class callable : public Base
|
||||
{
|
||||
public:
|
||||
typedef callable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
callable(PyTypeObject* type_type, const char* name);
|
||||
callable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class getattrable : public Base
|
||||
{
|
||||
public:
|
||||
typedef getattrable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
getattrable(PyTypeObject* type_type, const char* name);
|
||||
getattrable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_getattr(PyObject* obj, const char* name) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class setattrable : public Base
|
||||
{
|
||||
public:
|
||||
typedef setattrable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
setattrable(PyTypeObject* type_type, const char* name);
|
||||
setattrable(PyTypeObject* type_type);
|
||||
private:
|
||||
int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class reprable : public Base
|
||||
{
|
||||
public:
|
||||
typedef reprable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
reprable(PyTypeObject* type_type, const char* name);
|
||||
reprable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_repr(PyObject* obj) const;
|
||||
};
|
||||
|
||||
//
|
||||
// Member function definitions
|
||||
//
|
||||
|
||||
// type_object<>
|
||||
template <class T>
|
||||
void type_object<T>::instance_dealloc(PyObject* obj) const
|
||||
{
|
||||
this->dealloc(downcast<instance>(obj).get());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void type_object<T>::dealloc(T* obj) const
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
|
||||
// callable
|
||||
template <class Base>
|
||||
callable<Base>::callable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(call);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
callable<Base>::callable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(call);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* callable<Base>::instance_call(PyObject* obj, PyObject* args, PyObject* kw) const
|
||||
{
|
||||
return downcast<instance>(obj)->call(args, kw);
|
||||
}
|
||||
|
||||
// getattrable
|
||||
template <class Base>
|
||||
getattrable<Base>::getattrable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(getattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
getattrable<Base>::getattrable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(getattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* getattrable<Base>::instance_getattr(PyObject* obj, const char* name) const
|
||||
{
|
||||
return downcast<instance>(obj)->getattr(name);
|
||||
}
|
||||
|
||||
// setattrable
|
||||
template <class Base>
|
||||
setattrable<Base>::setattrable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(setattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
setattrable<Base>::setattrable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(setattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
int setattrable<Base>::instance_setattr(PyObject* obj, const char* name, PyObject* value) const
|
||||
{
|
||||
return downcast<instance>(obj)->setattr(name, value);
|
||||
}
|
||||
|
||||
// reprable
|
||||
template <class Base>
|
||||
reprable<Base>::reprable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
reprable<Base>::reprable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* reprable<Base>::instance_repr(PyObject* obj) const
|
||||
{
|
||||
return downcast<instance>(obj)->repr();
|
||||
}
|
||||
|
||||
// Helper class for optimized allocation of PODs: If two PODs
|
||||
// happen to contain identical byte patterns, they may share their
|
||||
// memory. Reference counting is used to free unused memory.
|
||||
// This is useful because method tables of related extension classes tend
|
||||
// to be identical, so less memory is needed for them.
|
||||
class shared_pod_manager
|
||||
{
|
||||
typedef std::pair<char*, std::size_t> holder;
|
||||
typedef std::vector<holder> storage;
|
||||
|
||||
public:
|
||||
static shared_pod_manager& obj();
|
||||
~shared_pod_manager();
|
||||
|
||||
// Allocate memory for POD T and fill it with zeros.
|
||||
// This memory is initially not shared.
|
||||
template <class T>
|
||||
static void create(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().create(sizeof(T)));
|
||||
}
|
||||
|
||||
// Decrement the refcount for the memory t points to. If the count
|
||||
// goes to zero, the memory is freed.
|
||||
template <class T>
|
||||
static void dispose(T* t)
|
||||
{
|
||||
obj().dec_ref(t, sizeof(T));
|
||||
}
|
||||
|
||||
// Attempt to share the memory t points to. If memory with the same
|
||||
// contents already exists, t is replaced by a pointer to this memory,
|
||||
// and t's old memory is disposed. Otherwise, t will be registered for
|
||||
// potential future sharing.
|
||||
template <class T>
|
||||
static void replace_if_equal(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().replace_if_equal(t, sizeof(T)));
|
||||
}
|
||||
|
||||
// Create a copy of t's memory that is guaranteed to be private to t.
|
||||
// Afterwards t points to the new memory, unless it was already private, in
|
||||
// which case there is no change (except that t's memory will no longer
|
||||
// be considered for future sharing - see raplade_if_equal())
|
||||
// This function *must* be called before the contents of (*t) can
|
||||
// be overwritten. Otherwise, inconsistencies and crashes may result.
|
||||
template <class T>
|
||||
static void make_unique_copy(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().make_unique_copy(t, sizeof(T)));
|
||||
}
|
||||
|
||||
private:
|
||||
void* replace_if_equal(void* pod, std::size_t size);
|
||||
void* make_unique_copy(void* pod, std::size_t size);
|
||||
void* create(std::size_t size);
|
||||
void dec_ref(void* pod, std::size_t size);
|
||||
void erase_from_list(void* pod);
|
||||
|
||||
struct compare;
|
||||
struct identical;
|
||||
|
||||
private:
|
||||
shared_pod_manager() {} // instance
|
||||
|
||||
#ifdef TYPE_OBJECT_BASE_STANDALONE_TEST
|
||||
public:
|
||||
#endif
|
||||
storage m_storage;
|
||||
};
|
||||
|
||||
|
||||
void add_capability(type_object_base::capability capability,
|
||||
PyTypeObject* dest);
|
||||
|
||||
// This macro gets the length of an array as a compile-time constant, and will
|
||||
// fail to compile if the parameter is a pointer.
|
||||
# define PY_ARRAY_LENGTH(a) \
|
||||
(sizeof(::boost::python::detail::countof_validate(a, &(a))) ? sizeof(a) / sizeof((a)[0]) : 0)
|
||||
|
||||
template<typename T>
|
||||
inline void countof_validate(T* const, T* const*);
|
||||
|
||||
template<typename T>
|
||||
inline int countof_validate(const void*, T);
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // TYPES_DWA051800_H_
|
||||
94
include/boost/python/detail/wrap_python.hpp
Normal file
94
include/boost/python/detail/wrap_python.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
// This file serves as a wrapper around <Python.h> which allows it to be
|
||||
// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC
|
||||
// behavior so that a program may be compiled in debug mode without requiring a
|
||||
// special debugging build of the Python library.
|
||||
|
||||
|
||||
// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the
|
||||
// compiler command-line.
|
||||
|
||||
// Revision History:
|
||||
// 05 Mar 01 Suppress warnings under Cygwin with Python 2.0 (Dave Abrahams)
|
||||
// 04 Mar 01 Rolled in some changes from the Dragon fork (Dave Abrahams)
|
||||
// 01 Mar 01 define PyObject_INIT() for Python 1.x (Dave Abrahams)
|
||||
|
||||
|
||||
#include <patchlevel.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
# ifndef BOOST_DEBUG_PYTHON
|
||||
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
|
||||
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Some things we need in order to get Python.h to work with compilers other
|
||||
// than MSVC on Win32
|
||||
//
|
||||
#if defined(_WIN32)
|
||||
# ifdef __GNUC__
|
||||
|
||||
typedef int pid_t;
|
||||
# define WORD_BIT 32
|
||||
# define hypot _hypot
|
||||
# include <stdio.h>
|
||||
# if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||
# define HAVE_CLOCK
|
||||
# define HAVE_STRFTIME
|
||||
# define HAVE_STRERROR
|
||||
# endif
|
||||
# define NT_THREADS
|
||||
# define WITH_THREAD
|
||||
# ifndef NETSCAPE_PI
|
||||
# define USE_SOCKET
|
||||
# endif
|
||||
|
||||
# ifdef USE_DL_IMPORT
|
||||
# define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE
|
||||
# endif
|
||||
|
||||
# ifdef USE_DL_EXPORT
|
||||
# define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE
|
||||
# define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
|
||||
# endif
|
||||
|
||||
# define HAVE_LONG_LONG 1
|
||||
# define LONG_LONG long long
|
||||
|
||||
# elif defined(__MWERKS__)
|
||||
|
||||
# ifndef _MSC_VER
|
||||
# define PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H 1
|
||||
# define _MSC_VER 900
|
||||
# endif
|
||||
|
||||
# elif defined(_MSC_VER)
|
||||
# include <limits> // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX
|
||||
# endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H
|
||||
# undef _MSC_VER
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# define _DEBUG
|
||||
#endif
|
||||
|
||||
#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||
# define PyObject_INIT(op, typeobj) \
|
||||
( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
|
||||
#endif
|
||||
30
include/boost/python/errors.hpp
Normal file
30
include/boost/python/errors.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef ERRORS_DWA052500_H_
|
||||
# define ERRORS_DWA052500_H_
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
struct error_already_set {};
|
||||
struct argument_error : error_already_set {};
|
||||
|
||||
// Handles exceptions caught just before returning to Python code.
|
||||
void handle_exception();
|
||||
|
||||
template <class T>
|
||||
T* expect_non_null(T* x)
|
||||
{
|
||||
if (x == 0)
|
||||
throw error_already_set();
|
||||
return x;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // ERRORS_DWA052500_H_
|
||||
68
include/boost/python/module_builder.hpp
Normal file
68
include/boost/python/module_builder.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef MODULE_DWA051000_H_
|
||||
# define MODULE_DWA051000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/objects.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
class module_builder
|
||||
{
|
||||
public:
|
||||
// Create a module. REQUIRES: only one module_builder is created per module.
|
||||
module_builder(const char* name);
|
||||
~module_builder();
|
||||
|
||||
// Add elements to the module
|
||||
void add(detail::function* x, const char* name);
|
||||
void add(PyTypeObject* x, const char* name = 0);
|
||||
void add(ref x, const char*name);
|
||||
|
||||
template <class Fn>
|
||||
void def_raw(Fn fn, const char* name)
|
||||
{
|
||||
add(detail::new_raw_arguments_function(fn), name);
|
||||
}
|
||||
|
||||
template <class Fn>
|
||||
void def(Fn fn, const char* name)
|
||||
{
|
||||
add(detail::new_wrapped_function(fn), name);
|
||||
}
|
||||
|
||||
// Return true iff a module is currently being built.
|
||||
static bool initializing();
|
||||
|
||||
// Return the name of the module currently being built.
|
||||
// REQUIRES: initializing() == true
|
||||
static string name();
|
||||
|
||||
// Return a pointer to the Python module object being built
|
||||
PyObject* module() const;
|
||||
|
||||
private:
|
||||
PyObject* m_module;
|
||||
static PyMethodDef initial_methods[1];
|
||||
};
|
||||
|
||||
//
|
||||
// inline implementations
|
||||
//
|
||||
inline PyObject* module_builder::module() const
|
||||
{
|
||||
return m_module;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif
|
||||
334
include/boost/python/objects.hpp
Normal file
334
include/boost/python/objects.hpp
Normal file
@@ -0,0 +1,334 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef OBJECTS_DWA051100_H_
|
||||
# define OBJECTS_DWA051100_H_
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include "boost/operators.hpp"
|
||||
# include <utility>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
class object
|
||||
{
|
||||
public:
|
||||
explicit object(ref p);
|
||||
|
||||
// Return a reference to the held object
|
||||
ref reference() const;
|
||||
|
||||
// Return a raw pointer to the held object
|
||||
PyObject* get() const;
|
||||
|
||||
private:
|
||||
ref m_p;
|
||||
};
|
||||
|
||||
class tuple : public object
|
||||
{
|
||||
public:
|
||||
explicit tuple(std::size_t n = 0);
|
||||
explicit tuple(ref p);
|
||||
|
||||
template <class First, class Second>
|
||||
tuple(const std::pair<First,Second>& x)
|
||||
: object(ref(PyTuple_New(2)))
|
||||
{
|
||||
set_item(0, x.first);
|
||||
set_item(1, x.second);
|
||||
}
|
||||
|
||||
template <class First, class Second>
|
||||
tuple(const First& first, const Second& second)
|
||||
: object(ref(PyTuple_New(2)))
|
||||
{
|
||||
set_item(0, first);
|
||||
set_item(1, second);
|
||||
}
|
||||
|
||||
template <class First, class Second, class Third>
|
||||
tuple(const First& first, const Second& second, const Third& third)
|
||||
: object(ref(PyTuple_New(3)))
|
||||
{
|
||||
set_item(0, first);
|
||||
set_item(1, second);
|
||||
set_item(2, third);
|
||||
}
|
||||
|
||||
template <class First, class Second, class Third, class Fourth>
|
||||
tuple(const First& first, const Second& second, const Third& third, const Fourth& fourth)
|
||||
: object(ref(PyTuple_New(4)))
|
||||
{
|
||||
set_item(0, first);
|
||||
set_item(1, second);
|
||||
set_item(2, third);
|
||||
set_item(3, fourth);
|
||||
}
|
||||
|
||||
static PyTypeObject* type_obj();
|
||||
static bool accepts(ref p);
|
||||
std::size_t size() const;
|
||||
ref operator[](std::size_t pos) const;
|
||||
|
||||
template <class T>
|
||||
void set_item(std::size_t pos, const T& rhs)
|
||||
{
|
||||
this->set_item(pos, make_ref(rhs));
|
||||
}
|
||||
|
||||
void set_item(std::size_t pos, const ref& rhs);
|
||||
|
||||
tuple slice(int low, int high) const;
|
||||
|
||||
friend tuple operator+(const tuple&, const tuple&);
|
||||
tuple& operator+=(const tuple& rhs);
|
||||
};
|
||||
|
||||
class list : public object
|
||||
{
|
||||
struct proxy;
|
||||
struct slice_proxy;
|
||||
public:
|
||||
explicit list(ref p);
|
||||
explicit list(std::size_t sz = 0);
|
||||
static PyTypeObject* type_obj();
|
||||
static bool accepts(ref p);
|
||||
std::size_t size();
|
||||
ref operator[](std::size_t pos) const;
|
||||
proxy operator[](std::size_t pos);
|
||||
ref get_item(std::size_t pos) const;
|
||||
|
||||
template <class T>
|
||||
void set_item(std::size_t pos, const T& x)
|
||||
{ this->set_item(pos, make_ref(x)); }
|
||||
void set_item(std::size_t pos, const ref& );
|
||||
|
||||
// void set_item(std::size_t pos, const object& );
|
||||
|
||||
template <class T>
|
||||
void insert(std::size_t index, const T& x)
|
||||
{ this->insert(index, make_ref(x)); }
|
||||
void insert(std::size_t index, const ref& item);
|
||||
|
||||
template <class T>
|
||||
void push_back(const T& item)
|
||||
{ this->push_back(make_ref(item)); }
|
||||
void push_back(const ref& item);
|
||||
|
||||
template <class T>
|
||||
void append(const T& item)
|
||||
{ this->append(make_ref(item)); }
|
||||
void append(const ref& item);
|
||||
|
||||
list slice(int low, int high) const;
|
||||
slice_proxy slice(int low, int high);
|
||||
void sort();
|
||||
void reverse();
|
||||
tuple as_tuple() const;
|
||||
};
|
||||
|
||||
class string
|
||||
: public object, public boost::multipliable2<string, unsigned int>
|
||||
{
|
||||
public:
|
||||
// Construct from an owned PyObject*.
|
||||
// Precondition: p must point to a python string.
|
||||
explicit string(ref p);
|
||||
explicit string(const char* s);
|
||||
string(const char* s, std::size_t length);
|
||||
string(const string& rhs);
|
||||
|
||||
enum interned_t { interned };
|
||||
string(const char* s, interned_t);
|
||||
|
||||
// Get the type object for Strings
|
||||
static PyTypeObject* type_obj();
|
||||
|
||||
// Return true if the given object is a python string
|
||||
static bool accepts(ref o);
|
||||
|
||||
// Return the length of the string.
|
||||
std::size_t size() const;
|
||||
|
||||
// Returns a null-terminated representation of the contents of string.
|
||||
// The pointer refers to the internal buffer of string, not a copy.
|
||||
// The data must not be modified in any way. It must not be de-allocated.
|
||||
const char* c_str() const;
|
||||
|
||||
string& operator*=(unsigned int repeat_count);
|
||||
string& operator+=(const string& rhs);
|
||||
friend string operator+(string x, string y);
|
||||
string& operator+=(const char* rhs);
|
||||
friend string operator+(string x, const char* y);
|
||||
friend string operator+(const char* x, string y);
|
||||
|
||||
void intern();
|
||||
|
||||
friend string operator%(const string& format, const tuple& args);
|
||||
};
|
||||
|
||||
class dictionary : public object
|
||||
{
|
||||
private:
|
||||
struct proxy;
|
||||
|
||||
public:
|
||||
explicit dictionary(ref p);
|
||||
dictionary();
|
||||
void clear();
|
||||
|
||||
static PyTypeObject* type_obj();
|
||||
static bool accepts(ref p);
|
||||
|
||||
public:
|
||||
template <class Key>
|
||||
proxy operator[](const Key& key)
|
||||
{ return this->operator[](make_ref(key)); }
|
||||
proxy operator[](ref key);
|
||||
|
||||
template <class Key>
|
||||
ref operator[](const Key& key) const
|
||||
{ return this->operator[](make_ref(key)); }
|
||||
ref operator[](ref key) const;
|
||||
|
||||
template <class Key>
|
||||
ref get_item(const Key& key) const
|
||||
{ return this->get_item(make_ref(key)); }
|
||||
ref get_item(const ref& key) const;
|
||||
|
||||
template <class Key, class Default>
|
||||
ref get_item(const Key& key, const Default& default_) const
|
||||
{ return this->get_item(make_ref(key), make_ref(default_)); }
|
||||
ref get_item(const ref& key, const ref& default_) const;
|
||||
|
||||
template <class Key, class Value>
|
||||
void set_item(const Key& key, const Value& value)
|
||||
{ this->set_item(make_ref(key), make_ref(value)); }
|
||||
void set_item(const ref& key, const ref& value);
|
||||
|
||||
template <class Key>
|
||||
void erase(const Key& key)
|
||||
{ this->erase(make_ref(key)); }
|
||||
void erase(ref key);
|
||||
|
||||
// proxy operator[](const object& key);
|
||||
// ref operator[](const object& key) const;
|
||||
|
||||
// ref get_item(const object& key, ref default_ = ref()) const;
|
||||
// void set_item(const object& key, const ref& value);
|
||||
|
||||
// void erase(const object& key);
|
||||
|
||||
list items() const;
|
||||
list keys() const;
|
||||
list values() const;
|
||||
|
||||
std::size_t size() const;
|
||||
// TODO: iterator support
|
||||
};
|
||||
|
||||
struct dictionary::proxy
|
||||
{
|
||||
template <class T>
|
||||
const ref& operator=(const T& rhs)
|
||||
{ return (*this) = make_ref(rhs); }
|
||||
const ref& operator=(const ref& rhs);
|
||||
|
||||
operator ref() const;
|
||||
private:
|
||||
friend class dictionary;
|
||||
proxy(const ref& dict, const ref& key);
|
||||
|
||||
// This is needed to work around the very strange MSVC error report that the
|
||||
// return type of the built-in operator= differs from that of the ones
|
||||
// defined above. Couldn't hurt to make these un-assignable anyway, though.
|
||||
const ref& operator=(const proxy&); // Not actually implemented
|
||||
private:
|
||||
ref m_dict;
|
||||
ref m_key;
|
||||
};
|
||||
|
||||
struct list::proxy
|
||||
{
|
||||
template <class T>
|
||||
const ref& operator=(const T& rhs)
|
||||
{ return (*this) = make_ref(rhs); }
|
||||
const ref& operator=(const ref& rhs);
|
||||
|
||||
operator ref() const;
|
||||
|
||||
private:
|
||||
friend class list;
|
||||
proxy(const ref& list, std::size_t index);
|
||||
|
||||
// This is needed to work around the very strange MSVC error report that the
|
||||
// return type of the built-in operator= differs from that of the ones
|
||||
// defined above. Couldn't hurt to make these un-assignable anyway, though.
|
||||
const ref& operator=(const proxy&); // Not actually implemented
|
||||
private:
|
||||
list m_list;
|
||||
std::size_t m_index;
|
||||
};
|
||||
|
||||
struct list::slice_proxy
|
||||
{
|
||||
const list& operator=(const list& rhs);
|
||||
operator ref() const;
|
||||
operator list() const;
|
||||
std::size_t size();
|
||||
ref operator[](std::size_t pos) const;
|
||||
private:
|
||||
friend class list;
|
||||
slice_proxy(const ref& list, int low, int high);
|
||||
private:
|
||||
ref m_list;
|
||||
int m_low, m_high;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
PyObject* to_python(const boost::python::tuple&);
|
||||
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple>);
|
||||
|
||||
inline boost::python::tuple from_python(PyObject* p, boost::python::type<const boost::python::tuple&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<boost::python::tuple>());
|
||||
}
|
||||
|
||||
PyObject* to_python(const boost::python::list&);
|
||||
boost::python::list from_python(PyObject* p, boost::python::type<boost::python::list>);
|
||||
|
||||
inline boost::python::list from_python(PyObject* p, boost::python::type<const boost::python::list&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<boost::python::list>());
|
||||
}
|
||||
|
||||
PyObject* to_python(const boost::python::string&);
|
||||
boost::python::string from_python(PyObject* p, boost::python::type<boost::python::string>);
|
||||
|
||||
inline boost::python::string from_python(PyObject* p, boost::python::type<const boost::python::string&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<boost::python::string>());
|
||||
}
|
||||
|
||||
PyObject* to_python(const boost::python::dictionary&);
|
||||
boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::python::dictionary>);
|
||||
|
||||
inline boost::python::dictionary from_python(PyObject* p, boost::python::type<const boost::python::dictionary&>)
|
||||
{
|
||||
return from_python(p, boost::python::type<boost::python::dictionary>());
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
#endif // OBJECTS_DWA051100_H_
|
||||
537
include/boost/python/operators.hpp
Normal file
537
include/boost/python/operators.hpp
Normal file
@@ -0,0 +1,537 @@
|
||||
// (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_
|
||||
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
|
||||
// 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) ? 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>
|
||||
# endif
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
tuple standard_coerce(ref l, ref r);
|
||||
|
||||
namespace detail {
|
||||
|
||||
// helper class for automatic operand type detection
|
||||
// during operator wrapping.
|
||||
struct auto_operand {};
|
||||
}
|
||||
|
||||
// Define operator ids that can be or'ed together
|
||||
// (boost::python::op_add | boost::python::op_sub | boost::python::op_mul).
|
||||
// This allows to wrap several operators in one line.
|
||||
enum operator_id
|
||||
{
|
||||
op_add = 0x1,
|
||||
op_sub = 0x2,
|
||||
op_mul = 0x4,
|
||||
op_div = 0x8,
|
||||
op_mod = 0x10,
|
||||
op_divmod =0x20,
|
||||
op_pow = 0x40,
|
||||
op_lshift = 0x80,
|
||||
op_rshift = 0x100,
|
||||
op_and = 0x200,
|
||||
op_xor = 0x400,
|
||||
op_or = 0x800,
|
||||
op_neg = 0x1000,
|
||||
op_pos = 0x2000,
|
||||
op_abs = 0x4000,
|
||||
op_invert = 0x8000,
|
||||
op_int = 0x10000,
|
||||
op_long = 0x20000,
|
||||
op_float = 0x40000,
|
||||
op_str = 0x80000,
|
||||
op_cmp = 0x100000
|
||||
};
|
||||
|
||||
// Wrap the operators given by "which". Usage:
|
||||
// foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>());
|
||||
template <long which, class operand = boost::python::detail::auto_operand>
|
||||
struct operators {};
|
||||
|
||||
// Wrap heterogeneous operators with given left operand type. Usage:
|
||||
// foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
|
||||
// boost::python::left_operand<int>());
|
||||
template <class T>
|
||||
struct left_operand {};
|
||||
|
||||
// Wrap heterogeneous operators with given right operand type. Usage:
|
||||
// foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
|
||||
// boost::python::right_operand<int>());
|
||||
template <class T>
|
||||
struct right_operand {};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Specified>
|
||||
struct operand_select
|
||||
{
|
||||
template <class wrapped_type>
|
||||
struct wrapped
|
||||
{
|
||||
typedef Specified type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct operand_select<auto_operand>
|
||||
{
|
||||
template <class wrapped_type>
|
||||
struct wrapped
|
||||
{
|
||||
typedef const wrapped_type& type;
|
||||
};
|
||||
};
|
||||
|
||||
template <long> struct define_operator;
|
||||
|
||||
// Base class which grants access to extension_class_base::add_method() to its derived classes
|
||||
struct add_operator_base
|
||||
{
|
||||
protected:
|
||||
static inline void add_method(extension_class_base* target, function* method, const char* name)
|
||||
{ target->add_method(method, name); }
|
||||
};
|
||||
|
||||
//
|
||||
// choose_op, choose_unary_op, and choose_rop
|
||||
//
|
||||
// These templates use "poor man's partial specialization" to generate the
|
||||
// appropriate add_method() call (if any) for a given operator and argument set.
|
||||
//
|
||||
// Usage:
|
||||
// choose_op<(which & op_add)>::template args<left_t,right_t>::add(ext_class);
|
||||
//
|
||||
// (see extension_class<>::def_operators() for more examples).
|
||||
//
|
||||
template <long op_selector>
|
||||
struct choose_op
|
||||
{
|
||||
template <class Left, class Right = Left>
|
||||
struct args : add_operator_base
|
||||
{
|
||||
static inline void add(extension_class_base* target)
|
||||
{
|
||||
typedef define_operator<op_selector> def_op;
|
||||
add_method(target,
|
||||
new typename def_op::template operator_function<Left, Right>(),
|
||||
def_op::name());
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// specialization for 0 has no effect
|
||||
template <>
|
||||
struct choose_op<0>
|
||||
{
|
||||
template <class Left, class Right = Left>
|
||||
struct args
|
||||
{
|
||||
static inline void add(extension_class_base*)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
template <long op_selector>
|
||||
struct choose_unary_op
|
||||
{
|
||||
template <class Operand>
|
||||
struct args : add_operator_base
|
||||
{
|
||||
static inline void add(extension_class_base* target)
|
||||
{
|
||||
typedef define_operator<op_selector> def_op;
|
||||
add_method(target,
|
||||
new typename def_op::template operator_function<Operand>(),
|
||||
def_op::name());
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// specialization for 0 has no effect
|
||||
template <>
|
||||
struct choose_unary_op<0>
|
||||
{
|
||||
template <class Operand>
|
||||
struct args
|
||||
{
|
||||
static inline void add(extension_class_base*)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
template <long op_selector>
|
||||
struct choose_rop
|
||||
{
|
||||
template <class Left, class Right = Left>
|
||||
struct args : add_operator_base
|
||||
{
|
||||
static inline void add(extension_class_base* target)
|
||||
{
|
||||
typedef define_operator<op_selector> def_op;
|
||||
add_method(target,
|
||||
new typename def_op::template roperator_function<Right, Left>(),
|
||||
def_op::rname());
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// specialization for 0 has no effect
|
||||
template <>
|
||||
struct choose_rop<0>
|
||||
{
|
||||
template <class Left, class Right = Left>
|
||||
struct args
|
||||
{
|
||||
static inline void add(extension_class_base*)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Fully specialize define_operator for all operators defined in operator_id above.
|
||||
// Every specialization defines one function object for normal operator calls and one
|
||||
// for operator calls with operands reversed ("__r*__" function variants).
|
||||
// Specializations for most operators follow a standard pattern: execute the expression
|
||||
// that uses the operator in question. This standard pattern is realized by the following
|
||||
// macros so that the actual specialization can be done by just calling a macro.
|
||||
#define PY_DEFINE_BINARY_OPERATORS(id, oper) \
|
||||
template <> \
|
||||
struct define_operator<op_##id> \
|
||||
{ \
|
||||
template <class Left, class Right = Left> \
|
||||
struct operator_function : function \
|
||||
{ \
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
||||
{ \
|
||||
tuple args(ref(arguments, ref::increment_count)); \
|
||||
\
|
||||
return BOOST_PYTHON_CONVERSION::to_python( \
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) oper \
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())); \
|
||||
} \
|
||||
\
|
||||
const char* description() const \
|
||||
{ return "__" #id "__"; } \
|
||||
}; \
|
||||
\
|
||||
template <class Right, class Left> \
|
||||
struct roperator_function : function \
|
||||
{ \
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
||||
{ \
|
||||
tuple args(ref(arguments, ref::increment_count)); \
|
||||
\
|
||||
return BOOST_PYTHON_CONVERSION::to_python( \
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) oper \
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())); \
|
||||
} \
|
||||
\
|
||||
const char* description() const \
|
||||
{ return "__r" #id "__"; } \
|
||||
\
|
||||
}; \
|
||||
\
|
||||
static const char * name() { return "__" #id "__"; } \
|
||||
static const char * rname() { return "__r" #id "__"; } \
|
||||
}
|
||||
|
||||
#define PY_DEFINE_UNARY_OPERATORS(id, oper) \
|
||||
template <> \
|
||||
struct define_operator<op_##id> \
|
||||
{ \
|
||||
template <class operand> \
|
||||
struct operator_function : function \
|
||||
{ \
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
||||
{ \
|
||||
tuple args(ref(arguments, ref::increment_count)); \
|
||||
\
|
||||
return BOOST_PYTHON_CONVERSION::to_python( \
|
||||
oper(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()))); \
|
||||
} \
|
||||
\
|
||||
const char* description() const \
|
||||
{ return "__" #id "__"; } \
|
||||
}; \
|
||||
\
|
||||
static const char * name() { return "__" #id "__"; } \
|
||||
}
|
||||
|
||||
PY_DEFINE_BINARY_OPERATORS(add, +);
|
||||
PY_DEFINE_BINARY_OPERATORS(sub, -);
|
||||
PY_DEFINE_BINARY_OPERATORS(mul, *);
|
||||
PY_DEFINE_BINARY_OPERATORS(div, /);
|
||||
PY_DEFINE_BINARY_OPERATORS(mod, %);
|
||||
PY_DEFINE_BINARY_OPERATORS(lshift, <<);
|
||||
PY_DEFINE_BINARY_OPERATORS(rshift, >>);
|
||||
PY_DEFINE_BINARY_OPERATORS(and, &);
|
||||
PY_DEFINE_BINARY_OPERATORS(xor, ^);
|
||||
PY_DEFINE_BINARY_OPERATORS(or, |);
|
||||
|
||||
PY_DEFINE_UNARY_OPERATORS(neg, -);
|
||||
PY_DEFINE_UNARY_OPERATORS(pos, +);
|
||||
PY_DEFINE_UNARY_OPERATORS(abs, abs);
|
||||
PY_DEFINE_UNARY_OPERATORS(invert, ~);
|
||||
PY_DEFINE_UNARY_OPERATORS(int, long);
|
||||
PY_DEFINE_UNARY_OPERATORS(long, PyLong_FromLong);
|
||||
PY_DEFINE_UNARY_OPERATORS(float, double);
|
||||
|
||||
#undef PY_DEFINE_BINARY_OPERATORS
|
||||
#undef PY_DEFINE_UNARY_OPERATORS
|
||||
|
||||
// Some operators need special treatment, e.g. because there is no corresponding
|
||||
// expression in C++. These are specialized manually.
|
||||
|
||||
// pow(): Manual specialization needed because an error message is required if this
|
||||
// function is called with three arguments. The "power modulo" operator is not
|
||||
// supported by define_operator, but can be wrapped manually (see special.html).
|
||||
template <>
|
||||
struct define_operator<op_pow>
|
||||
{
|
||||
template <class Left, class Right = Left>
|
||||
struct operator_function : function
|
||||
{
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const
|
||||
{
|
||||
tuple args(ref(arguments, ref::increment_count));
|
||||
|
||||
if (args.size() == 3 && args[2]->ob_type != Py_None->ob_type)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "expected 2 arguments, got 3");
|
||||
throw argument_error();
|
||||
}
|
||||
|
||||
return BOOST_PYTHON_CONVERSION::to_python(
|
||||
pow(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()),
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())));
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return "__pow__"; }
|
||||
|
||||
};
|
||||
|
||||
template <class Right, class Left>
|
||||
struct roperator_function : function
|
||||
{
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const
|
||||
{
|
||||
tuple args(ref(arguments, ref::increment_count));
|
||||
|
||||
if (args.size() == 3 && args[2]->ob_type != Py_None->ob_type)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()");
|
||||
throw argument_error();
|
||||
}
|
||||
|
||||
return BOOST_PYTHON_CONVERSION::to_python(
|
||||
pow(BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()),
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())));
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return "__rpow__"; }
|
||||
|
||||
};
|
||||
|
||||
static const char * name() { return "__pow__"; }
|
||||
static const char * rname() { return "__rpow__"; }
|
||||
};
|
||||
|
||||
// divmod(): Manual specialization needed because we must actually call two operators and
|
||||
// return a tuple containing both results
|
||||
template <>
|
||||
struct define_operator<op_divmod>
|
||||
{
|
||||
template <class Left, class Right = Left>
|
||||
struct operator_function : function
|
||||
{
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const
|
||||
{
|
||||
tuple args(ref(arguments, ref::increment_count));
|
||||
PyObject * res = PyTuple_New(2);
|
||||
|
||||
PyTuple_SET_ITEM(res, 0,
|
||||
BOOST_PYTHON_CONVERSION::to_python(
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) /
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())));
|
||||
PyTuple_SET_ITEM(res, 1,
|
||||
BOOST_PYTHON_CONVERSION::to_python(
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) %
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return "__divmod__"; }
|
||||
|
||||
};
|
||||
|
||||
template <class Right, class Left>
|
||||
struct roperator_function : function
|
||||
{
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const
|
||||
{
|
||||
tuple args(ref(arguments, ref::increment_count));
|
||||
PyObject * res = PyTuple_New(2);
|
||||
|
||||
PyTuple_SET_ITEM(res, 0,
|
||||
BOOST_PYTHON_CONVERSION::to_python(
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) /
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())));
|
||||
PyTuple_SET_ITEM(res, 1,
|
||||
BOOST_PYTHON_CONVERSION::to_python(
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) %
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return "__rdivmod__"; }
|
||||
|
||||
};
|
||||
|
||||
static const char * name() { return "__divmod__"; }
|
||||
static const char * rname() { return "__rdivmod__"; }
|
||||
};
|
||||
|
||||
// cmp(): Manual specialization needed because there is no three-way compare in C++.
|
||||
// It is implemented by two one-way comparisons with operators reversed in the second.
|
||||
template <>
|
||||
struct define_operator<op_cmp>
|
||||
{
|
||||
template <class Left, class Right = Left>
|
||||
struct operator_function : function
|
||||
{
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const
|
||||
{
|
||||
tuple args(ref(arguments, ref::increment_count));
|
||||
|
||||
return BOOST_PYTHON_CONVERSION::to_python(
|
||||
(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) <
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())) ?
|
||||
- 1 :
|
||||
(BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>()) <
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>())) ?
|
||||
1 :
|
||||
0) ;
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return "__cmp__"; }
|
||||
|
||||
};
|
||||
|
||||
template <class Right, class Left>
|
||||
struct roperator_function : function
|
||||
{
|
||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const
|
||||
{
|
||||
tuple args(ref(arguments, ref::increment_count));
|
||||
|
||||
return BOOST_PYTHON_CONVERSION::to_python(
|
||||
(BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) <
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())) ?
|
||||
- 1 :
|
||||
(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>()) <
|
||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>())) ?
|
||||
1 :
|
||||
0) ;
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return "__rcmp__"; }
|
||||
|
||||
};
|
||||
|
||||
static const char * name() { return "__cmp__"; }
|
||||
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 <>
|
||||
struct define_operator<op_str>
|
||||
{
|
||||
template <class operand>
|
||||
struct operator_function : function
|
||||
{
|
||||
PyObject* do_call(PyObject* arguments, PyObject*) const
|
||||
{
|
||||
tuple args(ref(arguments, ref::increment_count));
|
||||
|
||||
// When STLport is used with native streams, _STL::ostringstream().str() is not
|
||||
// _STL::string, but std::string.
|
||||
# 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
|
||||
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
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return "__str__"; }
|
||||
|
||||
};
|
||||
|
||||
static const char * name() { return "__str__"; }
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# undef BOOST_PYTHON_USE_SSTREAM
|
||||
#endif /* OPERATORS_UK112000_H_ */
|
||||
173
include/boost/python/reference.hpp
Normal file
173
include/boost/python/reference.hpp
Normal file
@@ -0,0 +1,173 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef PYPTR_DWA050400_H_
|
||||
# define PYPTR_DWA050400_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/operators.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/cast.hpp>
|
||||
# include <cassert>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
# include <boost/python/conversions.hpp>
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
template <class T, class Value, class Base>
|
||||
struct py_ptr_conversions : Base
|
||||
{
|
||||
inline friend T from_python(PyObject* x, boost::python::type<const T&>)
|
||||
{ return T(boost::python::downcast<Value>(x).get(), T::increment_count); }
|
||||
|
||||
inline friend T from_python(PyObject* x, boost::python::type<T>)
|
||||
{ return T(boost::python::downcast<Value>(x).get(), T::increment_count); }
|
||||
|
||||
inline friend PyObject* to_python(T x)
|
||||
{ return boost::python::as_object(x.release()); }
|
||||
|
||||
};
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
BOOST_PYTHON_IMPORT_CONVERSION(py_ptr_conversions);
|
||||
|
||||
template <class T>
|
||||
class reference
|
||||
: public py_ptr_conversions<reference<T>, T,
|
||||
boost::dereferenceable<reference<T>, T*> > // supplies op->
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
reference(const reference& rhs)
|
||||
: m_p(rhs.m_p)
|
||||
{
|
||||
Py_XINCREF(object());
|
||||
}
|
||||
|
||||
#if !defined(BOOST_MSVC6_OR_EARLIER)
|
||||
template <class T2>
|
||||
reference(const reference<T2>& rhs)
|
||||
: m_p(rhs.object())
|
||||
{
|
||||
Py_XINCREF(object());
|
||||
}
|
||||
#endif
|
||||
|
||||
reference() : m_p(0) {}
|
||||
|
||||
// These are two ways of spelling the same thing, that we need to increment
|
||||
// the reference count on the pointer when we're initialized.
|
||||
enum increment_count_t { increment_count };
|
||||
|
||||
enum allow_null { null_ok };
|
||||
|
||||
template <class T2>
|
||||
explicit reference(T2* x)
|
||||
: m_p(expect_non_null(x)) {}
|
||||
|
||||
template <class T2>
|
||||
reference(T2* x, increment_count_t)
|
||||
: m_p(expect_non_null(x)) { Py_INCREF(object()); }
|
||||
|
||||
template <class T2>
|
||||
reference(T2* x, allow_null)
|
||||
: m_p(x) {}
|
||||
|
||||
template <class T2>
|
||||
reference(T2* x, allow_null, increment_count_t)
|
||||
: m_p(x) { Py_XINCREF(object()); }
|
||||
|
||||
template <class T2>
|
||||
reference(T2* x, increment_count_t, allow_null)
|
||||
: m_p(x) { Py_XINCREF(object()); }
|
||||
|
||||
#if !defined(BOOST_MSVC6_OR_EARLIER)
|
||||
template <class T2>
|
||||
reference& operator=(const reference<T2>& rhs)
|
||||
{
|
||||
Py_XDECREF(object());
|
||||
m_p = rhs.m_p;
|
||||
Py_XINCREF(object());
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
reference& operator=(const reference& rhs)
|
||||
{
|
||||
Py_XINCREF(static_cast<PyObject*>(rhs.m_p));
|
||||
Py_XDECREF(object());
|
||||
m_p = rhs.m_p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~reference()
|
||||
{
|
||||
Py_XDECREF(m_p);
|
||||
}
|
||||
|
||||
T& operator*() const { return *m_p; }
|
||||
|
||||
T* get() const { return m_p; }
|
||||
|
||||
T* release()
|
||||
{
|
||||
T* p = m_p;
|
||||
m_p = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{ Py_XDECREF(m_p); m_p = 0; }
|
||||
|
||||
template <class T2>
|
||||
void reset(T2* x)
|
||||
{ Py_XDECREF(m_p); m_p = expect_non_null(x);}
|
||||
|
||||
template <class T2>
|
||||
void reset(T2* x, increment_count_t)
|
||||
{ Py_XDECREF(m_p); m_p = expect_non_null(x); Py_INCREF(object()); }
|
||||
|
||||
template <class T2>
|
||||
void reset(T2* x, allow_null)
|
||||
{ Py_XDECREF(m_p); m_p = x;}
|
||||
|
||||
template <class T2>
|
||||
void reset(T2* x, allow_null, increment_count_t)
|
||||
{ Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); }
|
||||
|
||||
template <class T2>
|
||||
void reset(T2* x, increment_count_t, allow_null)
|
||||
{ Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); }
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
private:
|
||||
template<typename Y> friend class shared_ptr;
|
||||
#endif
|
||||
|
||||
inline PyObject* object() const
|
||||
{ return as_object(m_p); }
|
||||
|
||||
T* m_p;
|
||||
};
|
||||
|
||||
typedef reference<PyObject> ref;
|
||||
|
||||
template <class T>
|
||||
ref make_ref(const T& x)
|
||||
{
|
||||
return ref(to_python(x));
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // PYPTR_DWA050400_H_
|
||||
@@ -1,15 +0,0 @@
|
||||
all: lib test
|
||||
|
||||
|
||||
lib::
|
||||
@cd src ; $(MAKE) lib ; cd ..
|
||||
|
||||
test::
|
||||
@cd test ; $(MAKE) test ; cd ..
|
||||
|
||||
install: all
|
||||
@cd src ; $(MAKE) install ; cd ..
|
||||
|
||||
clean:
|
||||
@cd src ; $(MAKE) clean ; cd ..
|
||||
@cd test ; $(MAKE) clean ; cd ..
|
||||
@@ -1,53 +0,0 @@
|
||||
To build using g++:
|
||||
===================
|
||||
|
||||
> setenv CXX g++
|
||||
>
|
||||
> ./configure \
|
||||
--with-pythoninc=/usr/local/include/python1.5 \
|
||||
--with-extra-includes=/usr/local/STLport
|
||||
>
|
||||
> make install
|
||||
|
||||
where
|
||||
--with-pythoninc: the directory where 'Python.h' lives
|
||||
--with-extra-includes: the directory where STLport includes
|
||||
or the 'limits' header are
|
||||
|
||||
|
||||
To build using another compiler:
|
||||
================================
|
||||
|
||||
> setenv CXX CC # your compiler
|
||||
>
|
||||
> ./configure \
|
||||
--with-pythoninc=/usr/local/include/python1.5 \
|
||||
--with-shared-cxx-linker="$CXX -G" \
|
||||
--with-position-independent-code-flag=-pic
|
||||
>
|
||||
> make install
|
||||
|
||||
where
|
||||
--with-pythoninc: as above
|
||||
--with-shared-cxx-linker: command to build a shared library from C++
|
||||
object files (needed for Python modules)
|
||||
--with-position-independent-code-flag: flag that tells the compiler
|
||||
to create position independent code (needed for shared linking)
|
||||
|
||||
|
||||
more options:
|
||||
=============
|
||||
|
||||
> ./configure --help
|
||||
|
||||
of particular interest are:
|
||||
|
||||
--libdir: the install directory for 'libboostpython.a'
|
||||
--with-shared-library-extension: the file extension for shared libraries
|
||||
--with-extra-libs: link modules against these extra libs
|
||||
(on CYGWIN, you need to link against python15.lib)
|
||||
|
||||
For most options, configure provides reasonable defaults, given in brackets.
|
||||
In particular, it is able to guess the right settings for shared library
|
||||
creation and linking on some common systems. Likewise, it tries to find Python
|
||||
in some standard directories if you don't specify a path explicitly.
|
||||
@@ -1,22 +0,0 @@
|
||||
CXXINCLUDES = @CXXINCLUDES@
|
||||
SCXXFLAGS = @SCXXFLAGS@
|
||||
CXX = @CXX@
|
||||
CXX_SHARED_LINKER = @CXX_SHARED_LINKER@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
TARGET_LIBDIR = @libdir@
|
||||
TARGET_LIBNAME = boostpython
|
||||
TARGET_LIBFILENAME = lib$(TARGET_LIBNAME).a
|
||||
MODULE_EXTENSION = @shared_library_extension@
|
||||
LIBS = @LIBS@
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(SCXXFLAGS) $(CXXINCLUDES) -c $*.cpp
|
||||
|
||||
%.d: %.cpp
|
||||
@echo creating $@
|
||||
@set -e; $(CXX) -M $(SCXXFLAGS) $(CXXINCLUDES) -c $*.cpp \
|
||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
Binary file not shown.
1012
libs/python/build/config.guess
vendored
1012
libs/python/build/config.guess
vendored
File diff suppressed because it is too large
Load Diff
1238
libs/python/build/config.sub
vendored
1238
libs/python/build/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
BOOST_INLUDES = /local/boost/boost
|
||||
PYTHON_INCLUDES = /local/python/include/python1.5
|
||||
USER_INCLUDES = /local/include
|
||||
LIBDIR = ../../../lib
|
||||
|
||||
|
||||
LIBSRC = \
|
||||
classes.cpp \
|
||||
conversions.cpp \
|
||||
extension_class.cpp \
|
||||
functions.cpp \
|
||||
init_function.cpp \
|
||||
module_builder.cpp \
|
||||
objects.cpp \
|
||||
types.cpp
|
||||
|
||||
LIBOBJ = $(LIBSRC:.cpp=.o)
|
||||
OBJ = $(LIBOBJ)
|
||||
|
||||
ifeq "$(OS)" "Windows_NT"
|
||||
PYTHON_LIB=c:/tools/python/libs/python15.lib
|
||||
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -Ic:/tools/python/include
|
||||
MODULE_EXTENSION=dll
|
||||
else
|
||||
INC = -I$(USER_INCLUDES) -I$(BOOST_INLUDES) -I$(PYTHON_INCLUDES)
|
||||
MODULE_EXTENSION=so
|
||||
endif
|
||||
|
||||
%.o: ../src/%.cpp
|
||||
g++ -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
%.d: ../src/%.cpp
|
||||
@echo creating $@
|
||||
@set -e; g++ -M $(INC) -c $< \
|
||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
example1: example1.o libpycpp.a
|
||||
g++ -shared -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lpycpp
|
||||
python ../example/test_example1.py
|
||||
|
||||
example1.o: ../example/example1.cpp
|
||||
g++ -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
@@ -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
|
||||
1495
libs/python/configure
vendored
1495
libs/python/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,308 +0,0 @@
|
||||
AC_INIT(src/extension_class.cpp)
|
||||
|
||||
AC_PREFIX_DEFAULT([`pwd | sed 's?/libs/python$??'`])
|
||||
|
||||
AC_CONFIG_AUX_DIR(build)
|
||||
AC_CANONICAL_SYSTEM
|
||||
|
||||
AC_CYGWIN
|
||||
AC_MINGW32
|
||||
|
||||
CCFLAGS=-O
|
||||
CXXFLAGS=-O
|
||||
dnl AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
|
||||
AC_DEFUN(AC_SHARED_LINKING,
|
||||
[
|
||||
dnl AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_PROG_CXX])
|
||||
AC_REQUIRE([AC_CYGWIN])
|
||||
AC_REQUIRE([AC_MINGW32])
|
||||
|
||||
# try to guess the right configurations
|
||||
if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
|
||||
shared_library_extension=".dll"
|
||||
else
|
||||
shared_library_extension=".so"
|
||||
fi
|
||||
|
||||
cxx_tmp="dummy $CXX dummy"
|
||||
if test "$GXX" = "yes"; then # g++
|
||||
shared_cxx_linker="g++ -shared"
|
||||
position_independent_code_flag="-fPIC"
|
||||
elif test "$cxx_tmp[2]" = "como"; then # Comeau C++
|
||||
shared_cxx_linker="como-dyn-link"
|
||||
position_independent_code_flag="--pic"
|
||||
elif test "$cxx_tmp[2]" = "cxx"; then # Compaq C++
|
||||
case "$target" in
|
||||
*dec*) shared_cxx_linker="cxx -shared -expect_unresolved '*'"
|
||||
position_independent_code_flag="";;
|
||||
esac
|
||||
elif test "$cxx_tmp[2]" = "CC"; then # native compilers
|
||||
case "$target" in
|
||||
*solaris*) shared_cxx_linker="CC -G"
|
||||
position_independent_code_flag="-pic";;
|
||||
*irix*) shared_cxx_linker="CC -shared"
|
||||
position_independent_code_flag="";;
|
||||
*hpux*) shared_cxx_linker="ld -b"
|
||||
position_independent_code_flag="+z";;
|
||||
esac
|
||||
else
|
||||
shared_c_linker=""
|
||||
shared_cxx_linker=""
|
||||
position_independent_code_flag=""
|
||||
fi
|
||||
|
||||
ifelse( $1, "", [
|
||||
AC_ARG_ENABLE(shared,
|
||||
[ --enable-shared: build shared libraries. This activates default settings for
|
||||
shared linking and position independent code generation (see below).],
|
||||
, )], [enable_shared=$1])
|
||||
|
||||
if test "$enable_shared" != "no" ; then
|
||||
AC_MSG_CHECKING(for shared library extension )
|
||||
AC_ARG_WITH(shared-library-extension,
|
||||
[ --with-shared-library-extension: file extension for shared libraries
|
||||
(including the dot) [UNIX: .so | Win32: .dll] ],, )
|
||||
if test "${with_shared_library_extension:+X}" != ""; then
|
||||
shared_library_extension=$with_shared_library_extension
|
||||
fi
|
||||
AC_MSG_RESULT([$shared_library_extension])
|
||||
AC_SUBST(shared_library_extension)
|
||||
|
||||
dnl AC_MSG_CHECKING(for shared linker for C objects )
|
||||
dnl AC_ARG_WITH(shared-c-linker,
|
||||
dnl [ --with-shared-c-linker: command for creating a shared library from C objects.
|
||||
dnl [ gcc: $(CC) -shared
|
||||
dnl SUN cc: $(CC) -G
|
||||
dnl IRIX cc: $(CC) -shared ] ],
|
||||
dnl , )
|
||||
dnl if test "${with_shared_c_linker:+X}" != ""; then
|
||||
dnl shared_c_linker=$with_shared_c_linker
|
||||
dnl fi
|
||||
dnl AC_MSG_RESULT([$shared_c_linker])
|
||||
dnl CC_SHARED_LINKER="$shared_c_linker"
|
||||
dnl AC_SUBST(CC_SHARED_LINKER)
|
||||
|
||||
AC_MSG_CHECKING(for shared linker for C++ objects )
|
||||
AC_ARG_WITH(shared-cxx-linker,
|
||||
[ --with-shared-cxx-linker: command for creating a shared library from C++ objects.
|
||||
[ g++: $CXX -shared
|
||||
Comeau C++: como-dyn-link
|
||||
Compaq C++: $CXX -shared -expect_unresolved '*'
|
||||
SUN CC: $CXX -G
|
||||
IRIX CC: $CXX -shared
|
||||
HP-UX aCC: ld -b ] ],
|
||||
, )
|
||||
if test "${with_shared_cxx_linker:+X}" != ""; then
|
||||
shared_cxx_linker=$with_shared_cxx_linker
|
||||
fi
|
||||
AC_MSG_RESULT([$shared_cxx_linker])
|
||||
CXX_SHARED_LINKER="$shared_cxx_linker"
|
||||
AC_SUBST(CXX_SHARED_LINKER)
|
||||
|
||||
AC_MSG_CHECKING(for flag to create position independent code )
|
||||
AC_ARG_WITH(position-independent-code-flag,
|
||||
[ --with-position-independent-code-flag: flag that tells the compiler to generate
|
||||
position independent code
|
||||
[ gcc/g++: -fPIC
|
||||
Comeau C++: --pic
|
||||
Compaq C++: <empty>
|
||||
SUN CC: $CXX -pic
|
||||
IRIX CC: <empty>
|
||||
HP-UX aCC: +z ] ],
|
||||
, )
|
||||
if test "${with_position_independent_code_flag:+X}" != ""; then
|
||||
position_independent_code_flag=$with_position_independent_code_flag
|
||||
fi
|
||||
AC_MSG_RESULT([$position_independent_code_flag])
|
||||
SCCFLAGS="$CCFLAGS $position_independent_code_flag"
|
||||
SCXXFLAGS="$CXXFLAGS $position_independent_code_flag"
|
||||
AC_SUBST(SCCFLAGS)
|
||||
AC_SUBST(SCXXFLAGS)
|
||||
fi
|
||||
])
|
||||
|
||||
#########################################################
|
||||
|
||||
AC_DEFUN([AC_WITH_EXTRA_INCLUDES],
|
||||
[
|
||||
AC_ARG_WITH(extra-includes,
|
||||
[ --with-extra-includes=\"dir1 dir2 ...\" : look in these directories for include files],,)
|
||||
|
||||
for i in $with_extra_includes; do
|
||||
CINCLUDES="$CINCLUDES -I"$i
|
||||
CXXINCLUDES="$CXXINCLUDES -I"$i
|
||||
done
|
||||
])
|
||||
|
||||
#########################################################
|
||||
|
||||
AC_DEFUN([AC_WITH_EXTRA_LIBS],
|
||||
[
|
||||
AC_ARG_WITH(extra-libs,
|
||||
[ --with-extra-libs=\"-Ldir1 -llib1 -Ldir2 -llib2 ...\" : link against these libraries ],,)
|
||||
|
||||
LIBS="$CINCLUDES "$with_extra_libs
|
||||
])
|
||||
|
||||
#########################################################
|
||||
|
||||
dnl AC_EXTRACT_REGEX(list, regEx)
|
||||
dnl variable $regExResult returns the first entry in 'list' that matches the
|
||||
dnl regular expression 'regEx', using the 'expr' utility
|
||||
dnl $regExResult = "" if nothing is found
|
||||
AC_DEFUN(AC_EXTRACT_REGEX,
|
||||
[
|
||||
regExResult=""
|
||||
if test "$1" != ""; then
|
||||
for i in $1; do
|
||||
regExResult=`expr "$i" : "$2"`
|
||||
if test "$regExResult" != ""; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
|
||||
#########################################################
|
||||
|
||||
dnl AC_FIND_PACKAGE(packageName, packageLib, packageInc, packageComment, default)
|
||||
dnl defines with_packageName=yes/no
|
||||
dnl packageNamelib=<path>/not found
|
||||
dnl packageNameinclude=<path>/not found
|
||||
dnl and adds the paths to $LIBS, $CINCLUDES, and $CXXINCLUDES
|
||||
dnl example:
|
||||
dnl AC_FIND_PACKAGE(tiff, tiff, tiff.h, support import/export of tiff images, yes)
|
||||
AC_DEFUN([AC_FIND_PACKAGE],
|
||||
[
|
||||
ifelse($5, "yes",
|
||||
[AC_ARG_WITH([$1], [ --with-$1=dir : $4.
|
||||
if dir=yes: $1 package files will be searched for
|
||||
in some standard directories.
|
||||
if dir is a directory: $1 package files will be searched for
|
||||
using 'find' below dir.
|
||||
alternatively, you can specify:], ,)],
|
||||
[AC_ARG_WITH([$1], [ --with-$1=dir : $4.
|
||||
if dir=yes (default): $1 package files will be searched for
|
||||
in some standard directories.
|
||||
if dir is a directory: $1 package files will be searched for
|
||||
using 'find' below dir.
|
||||
alternatively, you can specify:], ,)])
|
||||
|
||||
ifelse($2, "", ,[AC_ARG_WITH([$1lib], [ --with-$1lib=dir : the $1 package's lib directory], ,)])
|
||||
ifelse($3, "", ,[AC_ARG_WITH([$1inc], [ --with-$1inc=dir : the $1 package's include directory], ,)])
|
||||
|
||||
[$1]lib="not found"
|
||||
[$1]include="not found"
|
||||
|
||||
if test ${with_[$1]:-""} = "" -a ${with_[$1]lib:-""} = "" -a ${with_[$1]inc:-""} = ""; then
|
||||
if test "[$5]" = ""; then
|
||||
with_[$1]="no"
|
||||
else
|
||||
with_[$1]=[$5]
|
||||
fi
|
||||
fi
|
||||
|
||||
if test ${with_[$1]:-""} != "no"; then
|
||||
if test ! [$2] = "" ; then # check for library
|
||||
AC_MSG_CHECKING([for lib$2 ])
|
||||
dirs=""
|
||||
if test -f ${with_[$1]lib:-""}/lib[$2].so; then
|
||||
dirs=${with_[$1]lib:-""}/lib[$2].so
|
||||
elif test -f ${with_[$1]lib:-""}/lib[$2].a; then
|
||||
dirs=${with_[$1]lib:-""}/lib[$2].a
|
||||
elif test -d ${with_[$1]:-""}; then
|
||||
dirs=`find $with_[$1] -name "lib[$2].so" -print; find $with_[$1] -name "lib[$2].a" -print`
|
||||
elif test ${with_[$1]:-""} = "yes"; then
|
||||
for i in /usr/local/lib /usr/local/gnu/lib /usr/local/[$1] /opt/lib /opt/gnu/lib /opt/[$1]; do
|
||||
if test -d $i; then
|
||||
dirs="$dirs "`find $i -name "lib[$2].so" -print; find $i -name "lib[$2].a" -print`
|
||||
fi
|
||||
done
|
||||
fi
|
||||
AC_EXTRACT_REGEX($dirs, \(.*lib\)/lib$2\.so)
|
||||
if test "$regExResult" = ""; then
|
||||
AC_EXTRACT_REGEX($dirs, \(.*lib\)/lib$2\.a)
|
||||
fi
|
||||
if test "$regExResult" = ""; then
|
||||
AC_EXTRACT_REGEX($dirs, \(.*\)/lib$2\.so)
|
||||
fi
|
||||
if test "$regExResult" = ""; then
|
||||
AC_EXTRACT_REGEX($dirs, \(.*\)/lib$2\.a)
|
||||
fi
|
||||
[$1]lib=${regExResult:-"not found"}
|
||||
AC_MSG_RESULT($[$1]lib)
|
||||
else
|
||||
[$1]lib=""
|
||||
fi
|
||||
|
||||
if test ! [$3] = "" ; then # check for header
|
||||
AC_MSG_CHECKING([for $3 ])
|
||||
if test -f ${with_[$1]inc:-""}/[$3]; then
|
||||
dirs=$with_[$1]inc/[$3]
|
||||
elif test -d ${with_[$1]:-""}; then
|
||||
dirs=`find $with_[$1] -name patsubst([$3], .*/, ) -print`
|
||||
elif test ${with_[$1]:-""} = "yes"; then
|
||||
for i in /usr/local/include /usr/local/gnu/include /usr/local/[$1] \
|
||||
/opt/include /opt/gnu/include /opt/[$1]; do
|
||||
if test -d $i; then
|
||||
dirs="$dirs "`find $i -name patsubst([$3], .*/, ) -print`
|
||||
fi
|
||||
done
|
||||
fi
|
||||
AC_EXTRACT_REGEX($dirs, \(.*include\)/patsubst([$3], \., \\.))
|
||||
if test "$regExResult" = ""; then
|
||||
AC_EXTRACT_REGEX($dirs, \(.*\)/patsubst([$3], \., \\.))
|
||||
fi
|
||||
[$1]include=${regExResult:-"not found"}
|
||||
AC_MSG_RESULT($[$1]include)
|
||||
else
|
||||
[$1]include=""
|
||||
fi
|
||||
|
||||
if test "$[$1]lib" = "not found" -o "$[$1]include" = "not found"; then
|
||||
with_[$1]="no"
|
||||
AC_MSG_WARN( Configuring without [$1] support)
|
||||
else
|
||||
with_[$1]="yes"
|
||||
if test ! [$2] = "" ; then
|
||||
LIBS="$LIBS -L$[$1]lib -l[$2]"
|
||||
fi
|
||||
if test ! [$3] = "" ; then
|
||||
CINCLUDES="$CINCLUDES -I$[$1]include"
|
||||
CXXINCLUDES="$CXXINCLUDES -I$[$1]include"
|
||||
AC_SUBST(CXXINCLUDES)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
#########################################################
|
||||
|
||||
AC_WITH_EXTRA_INCLUDES
|
||||
AC_WITH_EXTRA_LIBS
|
||||
AC_SHARED_LINKING(yes)
|
||||
|
||||
#########################################################
|
||||
|
||||
AC_CHECK_PROG(python_prog, python, [yes], [not found])
|
||||
if test "$python_prog" = "yes"; then
|
||||
AC_FIND_PACKAGE(python, "", Python.h, Python includes (required!), yes)
|
||||
else
|
||||
with_python="no"
|
||||
fi
|
||||
if test "$with_python" = "no"; then
|
||||
AC_MSG_ERROR(Python support required to install BPL)
|
||||
fi
|
||||
|
||||
#########################################################
|
||||
|
||||
boost_includes=[-I`pwd | sed 's?/libs/python$??'`]
|
||||
CXXINCLUDES="$CXXINCLUDES $boost_includes"
|
||||
|
||||
#########################################################
|
||||
|
||||
AC_OUTPUT(build/Makefile)
|
||||
@@ -1,116 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Building an Extension Module
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Building an Extension Module
|
||||
</h1>
|
||||
<p>
|
||||
Right now, the only supported configuration is one in which the BPL
|
||||
source files are statically linked with the source for your extension
|
||||
module. BPL comes with a standard build process that compiles the
|
||||
BPL sources, builds the library <code>'libboostpython.a'</code>,
|
||||
runs a comprehensive test suite and (upon success)
|
||||
copies the library into an installation directory specified by the
|
||||
user. To involke this build process, you need to do the following:
|
||||
|
||||
<h4>Compilation with GNU g++:</h4>
|
||||
|
||||
<blockquote><pre>
|
||||
> cd <boost_root>/libs/python
|
||||
> setenv CXX g++ # use g++
|
||||
>
|
||||
> ./configure \
|
||||
--with-pythoninc=/usr/local/include/python1.5 \
|
||||
--with-extra-includes=/usr/local/STLport
|
||||
>
|
||||
> make install
|
||||
</pre></blockquote>
|
||||
|
||||
where
|
||||
<blockquote><pre>
|
||||
--with-pythoninc: the directory where 'Python.h' lives
|
||||
--with-extra-includes: the directory where STLport includes
|
||||
or the 'limits' header are
|
||||
</pre></blockquote>
|
||||
|
||||
<h4>Compilation with another compiler:</h4>
|
||||
|
||||
<blockquote><pre>
|
||||
> cd <boost_root>/libs/python
|
||||
> setenv CXX CC # your compiler
|
||||
>
|
||||
> ./configure \
|
||||
--with-pythoninc=/usr/local/include/python1.5 \
|
||||
--with-shared-cxx-linker="$CXX -G" \
|
||||
--with-position-independent-code-flag=-pic
|
||||
>
|
||||
> make install
|
||||
</pre></blockquote>
|
||||
|
||||
where
|
||||
<blockquote><pre>
|
||||
--with-pythoninc: as above
|
||||
--with-shared-cxx-linker: command to build a shared library from C++
|
||||
object files (needed for Python modules)
|
||||
--with-position-independent-code-flag: flag that tells the compiler
|
||||
to create position independent code (needed for shared linking)
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>configure</code> provides additional options that are listed
|
||||
after invoking
|
||||
|
||||
<blockquote><pre>
|
||||
> ./configure --help
|
||||
</pre></blockquote>
|
||||
|
||||
Of particular interest are the following options:
|
||||
|
||||
<blockquote><pre>
|
||||
--libdir: the install directory for 'libboostpython.a'
|
||||
--enable-shared-library-extension: the file extension for shared libraries
|
||||
</pre></blockquote>
|
||||
|
||||
For most options, configure provides reasonable defaults, given in
|
||||
brackets. In particular, it is able to guess the right settings for
|
||||
shared library creation and linking on some common systems. Likewise,
|
||||
it tries to find Python in some standard directories if you don't
|
||||
specify a path explicitly.
|
||||
<p>
|
||||
If this build process doesn't work for you, you must compile the
|
||||
source files manually. The BPL source files are:
|
||||
<blockquote>
|
||||
<pre>
|
||||
<a href="../../../libs/python/src/extension_class.cpp">extclass.cpp</a>
|
||||
<a href="../../../libs/python/src/functions.cpp">functions.cpp</a>
|
||||
<a href="../../../libs/python/src/init_function.cpp">init_function.cpp</a>
|
||||
<a href="../../../libs/python/src/module_builder.cpp">module.cpp</a>
|
||||
<a href="../../../libs/python/src/types.cpp">newtypes.cpp</a>
|
||||
<a href="../../../libs/python/src/objects.cpp">objects.cpp</a>
|
||||
<a href="../../../libs/python/src/conversions.cpp">py.cpp</a>
|
||||
<a href="../../../libs/python/src/classes.cpp">subclass.cpp</a>
|
||||
</pre>
|
||||
</blockquote>
|
||||
You may first build them into a library and link it with your
|
||||
extension module source, but the effect is the same as compiling all
|
||||
the source files together. Some users have successfully built the
|
||||
sources into a shared library, and support for a shared library
|
||||
build is planned, but not yet implemented.
|
||||
<p>
|
||||
Next: <a href="enums.html">Enums</a>
|
||||
Previous: <a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
</div>
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
A Simple Example
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
||||
"c++boost.gif (8819 bytes)">
|
||||
</h1>
|
||||
<h1>
|
||||
A Simple Example
|
||||
</h1>
|
||||
<p>
|
||||
Suppose we have the following C++ API which we want to expose in
|
||||
Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <string>
|
||||
|
||||
namespace hello {
|
||||
class world
|
||||
{
|
||||
public:
|
||||
world(int);
|
||||
~world();
|
||||
std::string greet() const { return "hi, world"; }
|
||||
...
|
||||
};
|
||||
std::size_t length(const world& x) { return std::strlen(x.greet()); }
|
||||
}
|
||||
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Here is the C++ code for a python module called <code>hello</code>
|
||||
which exposes the API using:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#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 m("hello");
|
||||
// Create the Python type object for our extension class
|
||||
boost::python::class_builder<hello::world> world_class(m, "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
|
||||
m.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
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
That's it! If we build this shared library and put it on our <code>
|
||||
PYTHONPATH</code> we can now access our C++ class and function from
|
||||
Python.
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> import hello
|
||||
>>> hi_world = hello.world(3)
|
||||
>>> hi_world.greet()
|
||||
'hi, world'
|
||||
>>> hello.length(hi_world)
|
||||
9
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
We can even make a subclass of <code>hello.world</code>:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> class my_subclass(hello.world):
|
||||
... def greet(self):
|
||||
... return 'hello, world'
|
||||
...
|
||||
>>> y = my_subclass(4)
|
||||
>>> y.greet()
|
||||
'hello, world'
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> hello.length(y)
|
||||
9
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
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 <code>length()</code> of <code>12</code>? If so, <a href=
|
||||
"overriding.html">read on</a>...
|
||||
<p>
|
||||
Next: <a href="overriding.html">Overridable virtual functions</a>
|
||||
Previous: <a href="comparisons.html">Comparisons with other systems</a> Up:
|
||||
<a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
</div>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
include ../build/Makefile
|
||||
|
||||
LIBSRC = \
|
||||
classes.cpp \
|
||||
conversions.cpp \
|
||||
extension_class.cpp \
|
||||
functions.cpp \
|
||||
init_function.cpp \
|
||||
module_builder.cpp \
|
||||
objects.cpp \
|
||||
types.cpp
|
||||
|
||||
LIBOBJ = $(LIBSRC:.cpp=.o)
|
||||
|
||||
lib: $(TARGET_LIBFILENAME)
|
||||
|
||||
install: lib
|
||||
@if [ ! -d $(TARGET_LIBDIR) ] ; then mkdir -p $(TARGET_LIBDIR) ; fi
|
||||
cp $(TARGET_LIBFILENAME) $(TARGET_LIBDIR)
|
||||
|
||||
$(TARGET_LIBFILENAME): $(LIBOBJ)
|
||||
rm -f $(TARGET_LIBFILENAME)
|
||||
ar cq $(TARGET_LIBFILENAME) $(LIBOBJ)
|
||||
|
||||
clean:
|
||||
rm -rf *.o *$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
from gen_callback import *
|
||||
from gen_caller import *
|
||||
from gen_init_function import *
|
||||
from gen_signatures import *
|
||||
from gen_singleton import *
|
||||
from gen_extclass import *
|
||||
|
||||
def gen_all(args):
|
||||
open('callback.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))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
args = 10
|
||||
else:
|
||||
args = int(sys.argv[1])
|
||||
|
||||
print gen_all(args)
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
include ../build/Makefile
|
||||
|
||||
LIBBPL = ../src/$(TARGET_LIBFILENAME)
|
||||
|
||||
test: test_result
|
||||
@if [ ! -f test_result -o -s test_result ] ; then \
|
||||
echo "tests failed:" ; cat test_result ; exit 1; \
|
||||
else echo "tests OK" ; fi
|
||||
|
||||
test_result: testmodule$(MODULE_EXTENSION) comprehensive.py
|
||||
@rm -f test_result
|
||||
python comprehensive.py > test_result
|
||||
|
||||
testmodule$(MODULE_EXTENSION): $(LIBBPL) comprehensive.o
|
||||
$(CXX_SHARED_LINKER) -o testmodule$(MODULE_EXTENSION) comprehensive.o $(LIBBPL) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -rf *.o *$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out test_result
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 04 Mar 01 Rolled in const_cast from Dragon fork (Dave Abrahams)
|
||||
// 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve)
|
||||
// 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function)
|
||||
|
||||
#include <boost/python/classes.hpp>
|
||||
#include <boost/python/detail/functions.hpp>
|
||||
@@ -67,8 +72,7 @@ namespace {
|
||||
|
||||
ref global_class_reduce()
|
||||
{
|
||||
static ref result(detail::new_wrapped_function(class_reduce));
|
||||
return result;
|
||||
return ref(detail::new_wrapped_function(class_reduce));
|
||||
}
|
||||
|
||||
|
||||
@@ -93,17 +97,41 @@ namespace {
|
||||
ref getstate(PyObject_GetAttrString(obj, const_cast<char*>("__getstate__")),
|
||||
ref::null_ok);
|
||||
PyErr_Clear();
|
||||
|
||||
ref dict(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
|
||||
PyErr_Clear();
|
||||
|
||||
if (getstate.get() != 0)
|
||||
{
|
||||
if (dict.get() != 0 && dictionary(dict).size() > 0)
|
||||
{
|
||||
ref getstate_manages_dict(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__getstate_manages_dict__")), ref::null_ok);
|
||||
PyErr_Clear();
|
||||
if (getstate_manages_dict.get() == 0)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__getstate_manages_dict__ not set)");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
ref state = ref(PyEval_CallObject(getstate.get(), NULL));
|
||||
return tuple(instance_class, initargs, state);
|
||||
}
|
||||
|
||||
ref state(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
|
||||
PyErr_Clear();
|
||||
if (state.get() != 0 && dictionary(state).size() > 0)
|
||||
if (getinitargs.get() == 0)
|
||||
{
|
||||
return tuple(instance_class, initargs, state);
|
||||
ref dict_defines_state(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__dict_defines_state__")), ref::null_ok);
|
||||
PyErr_Clear();
|
||||
if (dict_defines_state.get() == 0)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__dict_defines_state__ not set)");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
if (dict.get() != 0 && dictionary(dict).size() > 0)
|
||||
{
|
||||
return tuple(instance_class, initargs, dict);
|
||||
}
|
||||
|
||||
return tuple(instance_class, initargs);
|
||||
@@ -111,8 +139,7 @@ namespace {
|
||||
|
||||
ref global_instance_reduce()
|
||||
{
|
||||
static ref result(detail::new_wrapped_function(instance_reduce));
|
||||
return result;
|
||||
return ref(detail::new_wrapped_function(instance_reduce));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +204,7 @@ namespace detail {
|
||||
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
|
||||
{
|
||||
ref target(as_object(this), ref::increment_count);
|
||||
return new bound_function(target, global_class_reduce());
|
||||
return bound_function::create(target, global_class_reduce());
|
||||
}
|
||||
|
||||
ref local_attribute = m_name_space.get_item(string(name).reference());
|
||||
@@ -348,7 +375,7 @@ PyObject* instance::getattr(const char* name, bool use_special_function)
|
||||
|
||||
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
|
||||
{
|
||||
return new detail::bound_function(ref(this, ref::increment_count), global_instance_reduce());
|
||||
return detail::bound_function::create(ref(this, ref::increment_count), global_instance_reduce());
|
||||
}
|
||||
|
||||
ref local_attribute = m_name_space.get_item(string(name).reference());
|
||||
@@ -855,7 +882,7 @@ namespace {
|
||||
PyObject *globals = PyEval_GetGlobals();
|
||||
if (globals != NULL)
|
||||
{
|
||||
PyObject *module_name = PyDict_GetItemString(globals, "__name__");
|
||||
PyObject *module_name = PyDict_GetItemString(globals, const_cast<char*>("__name__"));
|
||||
if (module_name != NULL)
|
||||
name_space.set_item(module_key, module_name);
|
||||
}
|
||||
@@ -5,6 +5,10 @@
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams)
|
||||
// 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve)
|
||||
|
||||
#include <boost/python/conversions.hpp>
|
||||
#include <typeinfo>
|
||||
@@ -44,6 +48,19 @@ void handle_exception()
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
void expect_complex(PyObject* p)
|
||||
{
|
||||
if (!PyComplex_Check(p))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "expected a complex number");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace boost::python::detail
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
@@ -160,6 +177,24 @@ unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(char c)
|
||||
{
|
||||
if (c == '\0') return PyString_FromString("");
|
||||
return PyString_FromStringAndSize(&c, 1);
|
||||
}
|
||||
|
||||
char from_python(PyObject* p, boost::python::type<char>)
|
||||
{
|
||||
int l = -1;
|
||||
if (PyString_Check(p)) l = PyString_Size(p);
|
||||
if (l < 0 || l > 1) {
|
||||
PyErr_SetString(PyExc_TypeError, "expected string of length 0 or 1");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
if (l == 0) return '\0';
|
||||
return PyString_AsString(p)[0];
|
||||
}
|
||||
|
||||
PyObject* to_python(unsigned char i)
|
||||
{
|
||||
return integer_to_python(i);
|
||||
@@ -5,6 +5,9 @@
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||
|
||||
#include <boost/python/detail/extension_class.hpp>
|
||||
#include <cstring>
|
||||
@@ -446,8 +449,8 @@ operator_dispatcher::operator_dispatcher(const ref& o, const ref& s)
|
||||
: m_object(o), m_self(s), m_free_list_link(0)
|
||||
|
||||
{
|
||||
ob_refcnt = 1;
|
||||
ob_type = &type_obj;
|
||||
PyObject* self = this;
|
||||
PyObject_INIT(self, &type_obj);
|
||||
}
|
||||
|
||||
operator_dispatcher*
|
||||
@@ -460,7 +463,9 @@ operator_dispatcher::create(const ref& object, const ref& self)
|
||||
free_list = result->m_free_list_link;
|
||||
result->m_object = object;
|
||||
result->m_self = self;
|
||||
Py_INCREF(result);
|
||||
|
||||
PyObject* result_as_pyobject = result;
|
||||
PyObject_INIT(result_as_pyobject, &type_obj);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||
|
||||
#include <boost/python/detail/functions.hpp>
|
||||
#include <boost/python/detail/types.hpp>
|
||||
@@ -97,19 +100,6 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
bound_function* bound_function::create(const ref& target, const ref& fn)
|
||||
{
|
||||
bound_function* const result = free_list;
|
||||
if (result == 0)
|
||||
return new bound_function(target, fn);
|
||||
|
||||
free_list = result->m_free_list_link;
|
||||
result->m_target = target;
|
||||
result->m_unbound_function = fn;
|
||||
Py_INCREF(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// The instance class whose obj represents the type of bound_function
|
||||
// objects in Python. bound_functions must be GetAttrable so the __doc__
|
||||
// attribute of built-in Python functions can be accessed when bound.
|
||||
@@ -123,6 +113,21 @@ private: // type_object<bound_function> hook override
|
||||
void dealloc(bound_function*) const;
|
||||
};
|
||||
|
||||
bound_function* bound_function::create(const ref& target, const ref& fn)
|
||||
{
|
||||
bound_function* const result = free_list;
|
||||
if (result == 0)
|
||||
return new bound_function(target, fn);
|
||||
|
||||
free_list = result->m_free_list_link;
|
||||
result->m_target = target;
|
||||
result->m_unbound_function = fn;
|
||||
|
||||
PyObject* self = result;
|
||||
PyObject_INIT(self, type_object::instance());
|
||||
return result;
|
||||
}
|
||||
|
||||
bound_function::bound_function(const ref& target, const ref& fn)
|
||||
: python_object(type_object::instance()),
|
||||
m_target(target),
|
||||
26
src/gen_all.py
Normal file
26
src/gen_all.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from gen_callback import *
|
||||
from gen_caller import *
|
||||
from gen_init_function import *
|
||||
from gen_signatures import *
|
||||
from gen_singleton import *
|
||||
from gen_extclass import *
|
||||
|
||||
def gen_all(args):
|
||||
open('callback.hpp', 'w').write(gen_callback(args))
|
||||
open('caller.hpp', 'w').write(gen_caller(args))
|
||||
open('init_function.hpp', 'w').write(gen_init_function(args))
|
||||
open('signatures.hpp', 'w').write(gen_signatures(args))
|
||||
open('singleton.hpp', 'w').write(gen_singleton(args))
|
||||
open('extension_class.hpp', 'w').write(gen_extclass(args))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
args = 10
|
||||
else:
|
||||
args = int(sys.argv[1])
|
||||
|
||||
print gen_all(args)
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ def gen_extclass(args):
|
||||
// This file automatically generated for %d-argument constructors by
|
||||
// gen_extclass.python
|
||||
|
||||
// Revision History:
|
||||
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
|
||||
// to_python (Dave Abrahams)
|
||||
|
||||
#ifndef EXTENSION_CLASS_DWA052000_H_
|
||||
# define EXTENSION_CLASS_DWA052000_H_
|
||||
|
||||
@@ -27,6 +31,7 @@ def gen_extclass(args):
|
||||
# include <boost/python/detail/init_function.hpp>
|
||||
# include <typeinfo>
|
||||
# include <boost/smart_ptr.hpp>
|
||||
# include <boost/type_traits.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -66,7 +71,7 @@ T* check_non_null(T* p)
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class T> class held_instance;
|
||||
template <class Held> class held_instance;
|
||||
|
||||
typedef void* (*conversion_function_ptr)(void*);
|
||||
|
||||
@@ -138,6 +143,26 @@ class class_registry
|
||||
static std::vector<derived_class_info> static_derived_class_info;
|
||||
};
|
||||
|
||||
template <bool is_pointer>
|
||||
struct is_null_helper
|
||||
{
|
||||
template <class Ptr>
|
||||
static bool test(Ptr x) { return x == 0; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_null_helper<false>
|
||||
{
|
||||
template <class Ptr>
|
||||
static bool test(const Ptr& x) { return x.get() == 0; }
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
bool is_null(const Ptr& x)
|
||||
{
|
||||
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
@@ -183,9 +208,9 @@ class python_extension_class_converters
|
||||
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
|
||||
return result.release();
|
||||
}
|
||||
|
||||
// Convert to T*
|
||||
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
||||
|
||||
friend
|
||||
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
|
||||
{
|
||||
// downcast to an extension_instance, then find the actual T
|
||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||
@@ -206,9 +231,18 @@ class python_extension_class_converters
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
|
||||
// Convert to PtrType, where PtrType can be dereferenced to obtain a T.
|
||||
// Convert to T*
|
||||
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
||||
{
|
||||
if (obj == Py_None)
|
||||
return 0;
|
||||
else
|
||||
return non_null_from_python(obj, boost::python::type<T*>());
|
||||
}
|
||||
|
||||
// Extract from obj a mutable reference to the PtrType object which is holding a T.
|
||||
template <class PtrType>
|
||||
static PtrType& ptr_from_python(PyObject* obj, boost::python::type<PtrType>)
|
||||
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
|
||||
{
|
||||
// downcast to an extension_instance, then find the actual T
|
||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||
@@ -225,9 +259,29 @@ class python_extension_class_converters
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
|
||||
// Extract from obj a reference to the PtrType object which is holding a
|
||||
// T. If it weren't for auto_ptr, it would be a constant reference. Do not
|
||||
// modify the referent except by copying an auto_ptr! If obj is None, the
|
||||
// reference denotes a default-constructed PtrType
|
||||
template <class PtrType>
|
||||
static PyObject* ptr_to_python(PtrType x)
|
||||
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
|
||||
{
|
||||
if (obj == Py_None)
|
||||
{
|
||||
static PtrType null_ptr;
|
||||
return null_ptr;
|
||||
}
|
||||
return smart_ptr_reference(obj, boost::python::type<PtrType>());
|
||||
}
|
||||
|
||||
template <class PtrType>
|
||||
static PyObject* smart_ptr_to_python(PtrType x)
|
||||
{
|
||||
if (boost::python::detail::is_null(x))
|
||||
{
|
||||
return boost::python::detail::none();
|
||||
}
|
||||
|
||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||
result->add_implementation(
|
||||
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
||||
@@ -259,7 +313,7 @@ class python_extension_class_converters
|
||||
|
||||
// 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*>())); }
|
||||
{ return *boost::python::detail::check_non_null(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&>)
|
||||
@@ -270,28 +324,28 @@ class python_extension_class_converters
|
||||
{ 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 ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
{ return smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
||||
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
|
||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(std::auto_ptr<T> x)
|
||||
{ return ptr_to_python(x); }
|
||||
{ return smart_ptr_to_python(x); }
|
||||
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
{ return smart_ptr_reference(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
||||
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
|
||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(boost::shared_ptr<T> x)
|
||||
{ return ptr_to_python(x); }
|
||||
{ return smart_ptr_to_python(x); }
|
||||
};
|
||||
|
||||
// Convert T to_python, instantiated on demand and only if there isn't a
|
||||
@@ -613,15 +667,15 @@ 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.
|
||||
// any virtual functions in Held.
|
||||
public:"""
|
||||
+ gen_functions("""%{
|
||||
template <%(class A%n%:, %)>%}
|
||||
held_instance(PyObject*%(, A%n% a%n%)) : T(%(a%n%:, %)) {}""", args)
|
||||
held_instance(PyObject*%(, A%n% a%n%)) : Held(%(a%n%:, %)) {}""", args)
|
||||
+ """
|
||||
};
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
// Revision History:
|
||||
// 04 Mar 01 Changed name of extension module so it would work with DebugPython,
|
||||
// eliminated useless test that aggravated MSVC (David Abrahams)
|
||||
#include "comprehensive.hpp"
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <stdio.h> // used for portability on broken compilers
|
||||
@@ -238,6 +242,23 @@ boost::shared_ptr<Foo> Baz::create_foo()
|
||||
return boost::shared_ptr<Foo>(new DerivedFromFoo(0));
|
||||
}
|
||||
|
||||
// Used to check conversion to None
|
||||
boost::shared_ptr<Foo> foo_factory(bool create)
|
||||
{
|
||||
return boost::shared_ptr<Foo>(create ? new DerivedFromFoo(0) : 0);
|
||||
}
|
||||
|
||||
// Used to check conversion from None
|
||||
bool foo_ptr_is_null(Foo* p)
|
||||
{
|
||||
return p == 0;
|
||||
}
|
||||
|
||||
bool foo_shared_ptr_is_null(boost::shared_ptr<Foo> p)
|
||||
{
|
||||
return p.get() == 0;
|
||||
}
|
||||
|
||||
// We can accept smart pointer parameters
|
||||
int Baz::get_foo_value(boost::shared_ptr<Foo> foo)
|
||||
{
|
||||
@@ -404,7 +425,7 @@ static int testUpcast(Base* b)
|
||||
|
||||
static std::auto_ptr<Base> derived1Factory(int i)
|
||||
{
|
||||
return std::auto_ptr<Base>(new Derived1(i));
|
||||
return std::auto_ptr<Base>(i < 0 ? 0 : new Derived1(i));
|
||||
}
|
||||
|
||||
static std::auto_ptr<Base> derived2Factory(int i)
|
||||
@@ -815,6 +836,32 @@ namespace bpl_test {
|
||||
w.set_secret_number(number);
|
||||
}
|
||||
|
||||
// Test plain char converters.
|
||||
char get_plain_char() { return 'x'; }
|
||||
std::string use_plain_char(char c) { return std::string(3, c); }
|
||||
|
||||
// This doesn't test anything but the compiler, since it has the same signature as the above.
|
||||
// Since MSVC is broken and gets the signature wrong, we'll skip it.
|
||||
std::string use_const_plain_char(
|
||||
#ifndef BOOST_MSVC6_OR_EARLIER
|
||||
const
|
||||
#endif
|
||||
char c) { return std::string(5, c); }
|
||||
|
||||
// Test std::complex<double> converters.
|
||||
std::complex<double> dpolar(double rho, double theta) {
|
||||
return std::polar(rho, theta);
|
||||
}
|
||||
double dreal(const std::complex<double>& c) { return c.real(); }
|
||||
double dimag(std::complex<double> c) { return c.imag(); }
|
||||
|
||||
// Test std::complex<float> converters.
|
||||
std::complex<float> fpolar(float rho, float theta) {
|
||||
return std::polar(rho, theta);
|
||||
}
|
||||
double freal(const std::complex<float>& c) { return c.real(); }
|
||||
double fimag(std::complex<float> c) { return c.imag(); }
|
||||
|
||||
/************************************************************/
|
||||
/* */
|
||||
/* init the module */
|
||||
@@ -1036,6 +1083,26 @@ void init_module(boost::python::module_builder& m)
|
||||
world_class.def(world_getinitargs, "__getinitargs__");
|
||||
world_class.def(world_getstate, "__getstate__");
|
||||
world_class.def(world_setstate, "__setstate__");
|
||||
|
||||
// Test plain char converters.
|
||||
m.def(get_plain_char, "get_plain_char");
|
||||
m.def(use_plain_char, "use_plain_char");
|
||||
m.def(use_const_plain_char, "use_const_plain_char");
|
||||
|
||||
// Test std::complex<double> converters.
|
||||
m.def(dpolar, "dpolar");
|
||||
m.def(dreal, "dreal");
|
||||
m.def(dimag, "dimag");
|
||||
|
||||
// Test std::complex<float> converters.
|
||||
m.def(fpolar, "fpolar");
|
||||
m.def(freal, "freal");
|
||||
m.def(fimag, "fimag");
|
||||
|
||||
// Test new null-pointer<->None conversions
|
||||
m.def(foo_factory, "foo_factory");
|
||||
m.def(foo_ptr_is_null, "foo_ptr_is_null");
|
||||
m.def(foo_shared_ptr_is_null, "foo_shared_ptr_is_null");
|
||||
}
|
||||
|
||||
PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary& keywords)
|
||||
@@ -1057,18 +1124,14 @@ PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary&
|
||||
|
||||
void init_module()
|
||||
{
|
||||
boost::python::module_builder test("test");
|
||||
init_module(test);
|
||||
boost::python::module_builder boost_python_test("boost_python_test");
|
||||
init_module(boost_python_test);
|
||||
|
||||
// Just for giggles, add a raw metaclass.
|
||||
test.add(new boost::python::meta_class<boost::python::instance>);
|
||||
boost_python_test.add(new boost::python::meta_class<boost::python::instance>);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void inittest()
|
||||
BOOST_PYTHON_MODULE_INIT(boost_python_test)
|
||||
{
|
||||
try {
|
||||
bpl_test::init_module();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user