2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Dave Abrahams
480aaf6400 gcc-3.0.x needs to use typeid(x).name() instead of type_info directly for cross-shared-lib RTTI.
[SVN r12126]
2001-12-19 22:23:39 +00:00
Dave Abrahams
26b15fe373 initial checkin
[SVN r12123]
2001-12-19 16:06:31 +00:00
Dave Abrahams
eadcc79089 workaround for missing 'C' standard headers
[SVN r12104]
2001-12-18 14:10:06 +00:00
Dave Abrahams
35fd3dfaa1 Integrated Scott Snyder's nested class patch
[SVN r12080]
2001-12-17 05:49:24 +00:00
Dave Abrahams
3505ac2516 initial checkin
[SVN r12077]
2001-12-16 18:38:05 +00:00
Dave Abrahams
946ed17ae1 initial checkin
[SVN r12075]
2001-12-16 18:18:58 +00:00
Dave Abrahams
a4747eb10a *** empty log message ***
[SVN r12074]
2001-12-16 18:09:42 +00:00
nobody
4d6772dac2 This commit was manufactured by cvs2svn to create branch 'newbpl'.
[SVN r8341]
2000-11-27 08:04:06 +00:00
115 changed files with 5182 additions and 19412 deletions

57
Jamfile Normal file
View File

@@ -0,0 +1,57 @@
subproject libs/python ;
# bring in the rules for python
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
include <module@>python.jam ;
PYTHON_PROPERTIES
+= <metrowerks><*><cxxflags>"-inline deferred"
<cxx><*><include>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers
;
local export-bpl ;
if $(NT)
{
# Stick this in the property set to deal with gcc
export-bpl = export-bpl-logic ;
rule export-bpl-logic ( toolset variant : properties * )
{
if $(toolset) != gcc
{
properties += <define>BOOST_PYTHON_EXPORT=__declspec(dllexport) ;
}
else
{
properties += <define>BOOST_PYTHON_EXPORT= ;
}
return $(properties) ;
}
}
dll bpl
:
src/converter/body.cpp
src/converter/handle.cpp
src/converter/registry.cpp
src/converter/wrapper.cpp
src/converter/unwrap.cpp
src/converter/unwrapper.cpp
src/converter/type_id.cpp
src/object/class.cpp
src/object/function.cpp
:
$(PYTHON_PROPERTIES)
$(export-bpl)
# <define>BOOST_PYTHON_TRACE
;
extension m1 : test/m1.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
: <gcc><*><define>BOOST_PYTHON_EXPORT=
: debug-python ;
extension m2 : test/m2.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
: <gcc><*><define>BOOST_PYTHON_EXPORT=
: debug-python ;
boost-python-runtest try : test/newtest.py <lib>m1 <lib>m2 : : debug-python ;

View File

@@ -1,216 +0,0 @@
# Microsoft Developer Studio Project File - Name="bpl_static" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=bpl_static - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "bpl_static.mak".
!MESSAGE
!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
!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
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "bpl_static - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W4 /WX /GR /GX /O2 /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
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 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# 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 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
!ENDIF
# Begin Target
# Name "bpl_static - Win32 Release"
# Name "bpl_static - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\src\classes.cpp
# ADD CPP /W3
# End Source File
# Begin Source File
SOURCE=..\src\conversions.cpp
# ADD CPP /W3
# End Source File
# Begin Source File
SOURCE=..\src\extension_class.cpp
# ADD CPP /W3
# End Source File
# Begin Source File
SOURCE=..\src\functions.cpp
# ADD CPP /W3
# End Source File
# Begin Source File
SOURCE=..\src\init_function.cpp
# ADD CPP /W3
# End Source File
# Begin Source File
SOURCE=..\src\module_builder.cpp
# ADD CPP /W3
# End Source File
# Begin Source File
SOURCE=..\src\objects.cpp
# ADD CPP /W3
# End Source File
# Begin Source File
SOURCE=..\src\types.cpp
# ADD CPP /W3
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\..\boost\python\detail\base_object.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\callback.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\caller.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\cast.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\class_builder.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\classes.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\config.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\conversions.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\errors.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\extension_class.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\functions.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\init_function.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\module_builder.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\none.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\objects.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\operators.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\reference.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\signatures.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\singleton.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\types.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\boost\python\detail\wrap_python.hpp
# End Source File
# End Group
# End Target
# End Project

View File

@@ -1,74 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "bpl_static"=.\bpl_static.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "example1"=.\example1\example1.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name bpl_static
End Project Dependency
}}}
###############################################################################
Project: "rwgk1"=.\rwgk1\rwgk1.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name bpl_static
End Project Dependency
}}}
###############################################################################
Project: "test"=.\test\test.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name bpl_static
End Project Dependency
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

Binary file not shown.

View File

@@ -1,107 +0,0 @@
# Microsoft Developer Studio Project File - Name="example1" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=example1 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "example1.mak".
!MESSAGE
!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
!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
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "example1 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
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 /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 /out:"Release/hello.dll" /libpath:"c:\tools\python\libs"
!ELSEIF "$(CFG)" == "example1 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# 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 "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"
# 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 /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"
!ENDIF
# Begin Target
# Name "example1 - Win32 Release"
# Name "example1 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\example\example1.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -1,48 +0,0 @@
LIBSRC = \
extclass.cpp \
init_function.cpp \
py.cpp \
module.cpp \
subclass.cpp \
functions.cpp \
newtypes.cpp \
objects.cpp
LIBOBJ = $(LIBSRC:.cpp=.o)
OBJ = $(LIBOBJ) extclass_demo.o
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/home/koethe/include -I/home/koethe/C++/boost -I/home/koethe/python/include/python1.5
MODULE_EXTENSION=so
endif
%.o: %.cpp
g++ -fPIC $(INC) -c $*.cpp
%.d: %.cpp
@echo creating $@
@set -e; g++ -M $(INC) -c $*.cpp \
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
[ -s $@ ] || rm -f $@
demo: extclass_demo.o libpycpp.a
g++ -shared -o demomodule.$(MODULE_EXTENSION) $(PYTHON_LIB) extclass_demo.o -L. -lpycpp
python test_extclass.py
clean:
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
libpycpp.a: $(LIBOBJ)
rm -f libpycpp.a
ar cq libpycpp.a $(LIBOBJ)
DEP = $(OBJ:.o=.d)
ifneq "$(MAKECMDGOALS)" "clean"
include $(DEP)
endif

View File

@@ -1,105 +0,0 @@
# Microsoft Developer Studio Project File - Name="rwgk1" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=rwgk1 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "rwgk1.mak".
!MESSAGE
!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
!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
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "rwgk1 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
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 /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"
!ELSEIF "$(CFG)" == "rwgk1 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# 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 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 /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"
!ENDIF
# Begin Target
# Name "rwgk1 - Win32 Release"
# Name "rwgk1 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\example\rwgk1.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -1,112 +0,0 @@
# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=test - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "test.mak".
!MESSAGE
!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
!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
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "test - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# 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
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
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 /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"
!ELSEIF "$(CFG)" == "test - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# 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 "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 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 /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"
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "test - Win32 Release"
# Name "test - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\test\comprehensive.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\test\comprehensive.hpp
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -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

View File

@@ -1,44 +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. 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. 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>
<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>
&copy; 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 &ldquo;as
is&rdquo; without express or implied warranty, and with no claim as to
its suitability for any purpose.
<p>
Updated: Nov 26, 2000
</div>

View File

@@ -1,220 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Comparisons with Other Systems
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Comparisons with
Other Systems
</h1>
<h2>CXX</h2>
<p>
Like BPL, <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++
exceptions into Python exceptions. As far as I can tell, CXX has no
support for subclassing C++ extension types in Python. An even
more significant difference is that a user's C++ code is still basically
&ldquo;dealing with Python objects&rdquo;, though they are wrapped in
C++ classes. This means such jobs as argument parsing and conversion are
still left to be done explicitly by the user.
<p>
CXX claims to interoperate well with the C++ Standard Library
(a.k.a. STL) by providing iterators into Python Lists and Dictionaries,
but the claim is unfortunately unsupportable. The problem is that in
general, access to Python sequence and mapping elements through
iterators requires the use of proxy objects as the return value of
iterator dereference operations. This usage conflicts with the basic
ForwardIterator requirements in <a
href="http://anubis.dkuug.dk/jtc1/sc22/open/n2356/lib-iterators.html#lib.forward.iterators">
section 24.1.3 of the standard</a> (dereferencing must produce a
reference). Although you may be able to use these iterators with some
operations in some standard library implementations, it is neither
guaranteed to work nor portable.
<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 &ldquo;bare
metal&rdquo; with CXX, it basically presents a &ldquo;C++-ized&rdquo;
version of the Python 'C' API.
<p>
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
author of CXX, has told me that what I've described is only half of the
picture with CXX, but I never understood his explanation well-enough to
fill in the other half. Here is his response to the commentary above:
<blockquote>
&ldquo;My intention with CXX was not to do what you are doing. It was to enable a
person to write an extension directly in C++ rather than C. I figured others had
the wrapping business covered. I thought maybe CXX would provide an easier
target language for those making wrappers, but I never explored
that.&rdquo;<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
</blockquote>
<h2>SWIG</h2>
<p>
<a href= "http://www.swig.org/">SWIG</a> is an impressively mature tool
for exporting an existing ANSI 'C' interface into various scripting
languages. Swig relies on a parser to read your source code and produce
additional source code files which can be compiled into a Python (or
Perl or Tcl) extension module. It has been successfully used to create
many Python extension modules. Like BPL, SWIG is trying to allow an
existing interface to be wrapped with little or no change to the
existing code. The documentation says &ldquo;SWIG parses a form of ANSI C
syntax that has been extended with a number of special directives. As a
result, interfaces are usually built by grabbing a header file and
tweaking it a little bit.&rdquo; For C++ interfaces, the tweaking has often
proven to amount to more than just a little bit. One user
writes:
<blockquote> &ldquo;The problem with swig (when I used it) is that it
couldnt handle templates, didnt do func overloading properly etc. For
ANSI C libraries this was fine. But for usual C++ code this was a
problem. Simple things work. But for anything very complicated (or
realistic), one had to write code by hand. I believe BPL doesn't have
this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
wrap correctly.&rdquo;<br><i>-Prabhu Ramachandran</i>
</blockquote>
<p>
By contrast, BPL 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
that code nearly as simple as listing the names of the classes and
member functions you want to expose in Python.
<h2>SIP</h2>
<p>
<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
extension class member functions in Python subclasses. It appears to
have been designed specifically to directly support some features of
PyQt/PyKDE, which is its primary client. Documentation is almost
entirely missing at the time of this writing, so a detailed comparison
is difficult.
<h2>ILU</h2>
<p>
<a
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual">ILU</a>
is a very ambitious project which tries to describe a module's interface
(types and functions) in terms of an <a
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual/manual_2.html">Interface
Specification Language</a> (ISL) so that it can be uniformly interfaced
to a wide range of computer languages, including Common Lisp, C++, C,
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
header file describing the interface, of which the user is expected to
provide an implementation. Unlike BPL, this means that the system
imposes implementation details on your C++ code at the deepest level. It
is worth noting that some of the C++ names generated by ILU are supposed
to be reserved to the C++ implementation. It is unclear from the
documentation whether ILU supports overriding C++ virtual functions in Python.
<h2>GRAD</h2>
<p>
<a
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</a>
is another very ambitious project aimed at generating Python wrappers for
interfaces written in &ldquo;legacy languages&rdquo;, among which C++ is the first one
implemented. Like SWIG, it aims to parse source code and automatically
generate wrappers, though it appears to take a more sophisticated approach
to parsing in general and C++ in particular, so it should do a much better
job with C++. It appears to support function overloading. The
documentation is missing a lot of information I'd like to see, so it is
difficult to give an accurate and fair assessment. I am left with the
following questions:
<ul>
<li>Does it support overriding of virtual functions?
<li>What about overriding private or protected virtual functions (the documentation indicates
that only public interfaces are supported)?
<li>Which C++ language constructs are supportd?
<li>Does it support implicit conversions between wrapped C++ classes that have
an inheritance relationship?
<li>Does it support smart pointers?
</ul>
<p>
Anyone in the possession of the answers to these questions will earn my
gratitude for a write-up <code>;-)</code>
<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
to support subclassing of extension types in Python, including
multiple-inheritance. Both systems support pickling/unpickling of
extension class instances in very similar ways. Both systems rely on the
same &ldquo;<a
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
Beaudry Hack</a>&rdquo; that also inspired Don's MESS System.
<p>
The major differences are:
<ul>
<li>
BPL 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
reference-counts.
<li>
BPL supports function overloading; Zope does not.
<li>
BPL 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
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 &ldquo;the need for a
C-based persistence mechanism&rdquo;. BPL'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: &ldquo;At most one
base extension direct or indirect super class may define C data
members. If an extension subclass inherits from multiple base
extension classes, then all but one must be mix-in classes that
provide extension methods but no data.&rdquo;
<li>
Zope requires use of the somewhat funky inheritedAttribute (search for
&ldquo;inheritedAttribute&rdquo; on <a
href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
method to access base class methods. In BPL, base class methods can
be accessed in the usual way by writing
&ldquo;<code>BaseClass.method</code>&rdquo;.
<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.
<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.
</ul>
<p>
Next: <a href="example1.html">A Simple Example Using BPL</a>
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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 &ldquo;as is&rdquo; without
express or implied warranty, and with no claim as to its suitability
for any purpose.
<p>
Updated: Nov 26, 2000
</div>

View File

@@ -1,103 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Wrapping enums
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Wrapping enums
</h1>
<p>Because there is in general no way to deduce that a value of arbitrary type T
is an enumeration constant, the Boost Python Library cannot automatically
convert enum values to and from Python. To handle this case, you need to decide
how you want the enum to show up in Python (since Python doesn't have
enums). Once you have done that, you can write some simple
<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&lt;EnumType&gt;</code> where
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
<ol>
<li><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 my_namespace { // re-open my_namespace
...
</pre>
</blockquote>
<li><blockquote><pre>
// instantiate as base class in any namespace
struct EnumTypeConverters
: boost::python::enum_as_int_converters&lt;EnumType&gt;
{
};
</blockquote></pre>
</ol>
<p>Either of the above is equivalent to the following declarations:
<blockquote><pre>
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
MyEnumType from_python(PyObject* x, boost::python::type&lt;MyEnumType&gt;)
{
return static_cast&lt;MyEnum&gt;(
from_python(x, boost::python::type&lt;long&gt;()));
}
MyEnumType from_python(PyObject* x, boost::python::type&lt;const MyEnumType&amp;&gt;)
{
return static_cast&lt;MyEnum&gt;(
from_python(x, boost::python::type&lt;long&gt;()));
}
PyObject* to_python(MyEnumType x)
{
return to_python(static_cast&lt;long&gt;(x));
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
</pre></blockquote>
<p>This technique defines the conversions of
<code>MyEnumType</code> in terms of the conversions for the built-in
<code>long</code> type.
You may also want to add a bunch of lines like this to your module
initialization:
<blockquote><pre>
mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
...
</pre></blockquote>
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");
...
</pre></blockquote>
<p>
Next: <a href="pointers.html">Pointers</a>
Previous: <a href="building.html">Building an Extension Module</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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 &ldquo;as
is&rdquo; without express or implied warranty, and with no claim as to
its suitability for any purpose.
<p>
Updated: Nov 26, 2000
</div>

View File

@@ -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 Using BPL
</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 Using BPL
</h1>
<p>
Suppose we have the following C++ API which we want to expose in
Python:
<blockquote>
<pre>
#include &lt;string&gt;
namespace hello {
  class world
  {
   public:
      world(int);
      ~world();
      std::string greet() const { return "hi, world"; }
    ...
  };
  std::size_t length(const world&amp; 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 BPL:
<blockquote>
<pre>
#include &lt;boost/python/class_builder.hpp&gt;
// Python requires an exported function called init&lt;module-name&gt; 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&lt;hello::world&gt; world_class(m, "world");
       // Add the __init__ function
       world_class.def(boost::python::constructor&lt;int&gt;());
       // Add a regular member function
       world_class.def(&amp;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 &lt;windows.h&gt;
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>
&gt;&gt;&gt; import hello
&gt;&gt;&gt; hi_world = hello.world(3)
&gt;&gt;&gt; hi_world.greet()
'hi, world'
&gt;&gt;&gt; hello.length(hi_world)
9
</pre>
</blockquote>
<p>
We can even make a subclass of <code>hello.world</code>:
<blockquote>
<pre>
&gt;&gt;&gt; class my_subclass(hello.world):
...     def greet(self):
...         return 'hello, world'
...
&gt;&gt;&gt; y = my_subclass(4)
&gt;&gt;&gt; y.greet()
'hello, world'
</pre>
</blockquote>
<p>
Pretty cool! You can't do that with an ordinary Python extension type!
<blockquote>
<pre>
&gt;&gt;&gt; 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>
&copy; 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>

View File

@@ -1,73 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
A Brief Introduction to writing Python extension modules
</title>
<h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
</h1>
<h1>
A Brief Introduction to writing Python extension modules
</h1>
<p>
Interfacing any language to Python involves building a module which can
be loaded by the Python interpreter, but which isn't written in Python.
This is known as an <em>extension module</em>. Many of the <a href=
"http://www.python.org/doc/current/lib/lib.html">built-in Python
libraries</a> are constructed in 'C' this way; Python even supplies its
<a href="http://www.python.org/doc/current/lib/types.html">fundamental
types</a> using the same mechanism. An extension module can be statically
linked with the Python interpreter, but it more commonly resides in a
shared library or DLL.
<p>
As you can see from <a href=
"http://www.python.org/doc/current/ext/ext.html"> The Python Extending
and Embedding Tutorial</a>, writing an extension module normally means
worrying about
<ul>
<li>
<a href="http://www.python.org/doc/current/ext/refcounts.html">
maintaining reference counts</a>
<li>
<a href="http://www.python.org/doc/current/ext/callingPython.html"> how
to call back into Python</a>
<li>
<a href="http://www.python.org/doc/current/ext/parseTuple.html">
function argument parsing and typechecking</a>
</ul>
This last item typically occupies a great deal of code in an extension
module. Remember that Python is a completely dynamic language. A callable
object receives its arguments in a tuple; it is up to that object to extract
those arguments from the tuple, check their types, and raise appropriate
exceptions. There are numerous other tedious details that need to be
managed; too many to mention here. The Boost Python Library is designed to
lift most of that burden.<br>
<br>
<p>
Another obstacle that most people run into eventually when extending
Python is that there's no way to make a true Python class in an extension
module. The typical solution is to create a new Python type in the
extension module, and then write an additional module in 100% Python. The
Python module defines a Python class which dispatches to an instance of
the extension type, which it contains. This allows users to write
subclasses of the class in the Python module, almost as though they were
sublcassing the extension type. Aside from being tedious, it's not really
the same as having a true class, because there's no way for the user to
override a method of the extension type which is called from the
extension module. BPL 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
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
href="index.html">Top</a> </p>
<p>
&copy; 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>

View File

@@ -1,158 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"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)
</title>
<h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
align="center" height="86">The Boost Python Library (BPL)
</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
very similar to the C++ interface. It is designed to be minimally
intrusive on your C++ design. In most cases, you should not have to alter
your C++ classes in any way in order to use them with BPL. The system
<em>should</em> simply &ldquo;reflect&rdquo; your C++ classes and functions into
Python. The major features of BPL include support for:
<ul>
<li><a href="inheritance.hml">Subclassing extension types in Python</a>
<li><a href="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>
</ul>
among others.
<h2>Supported Platforms</h2>
<p>BPL has been tested in the following configurations:
<ul>
<li>Against Python 1.5.2 using the following compiler/library:
<ul>
<li><a
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
<li><a
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>/<a
href="http://www.stlport.org">STLport 4.0</a>
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a> [by <a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich
Koethe</a>]
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a>/<a href="http://www.stlport.org">STLport 4.0</a>
<li>Compaq C++ V6.2-024 for Digital UNIX V5.0 Rev. 910 (an <a
href="http://www.edg.com/">EDG</a>-based compiler) with <a
href="http://www.stlport.org/beta.html">STLport-4.1b3</a> [by <a
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)
</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.
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
had independently developed a similar system. When he discovered BPL,
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
<a href="inheritance.html#implicit_conversion">reflecting C++ inheritance
relationships</a>. He has helped to improve error-reporting from both
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>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.
<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.
</ul>
<h2>Table of Contents</h2>
<ol>
<li><a href="extending.html">A Brief Introduction to writing Python
extension modules</a>
<li><a href="comparisons.html">Comparisons between BPL and other
systems for extending Python</a>
<li><a href="example1.html">A Simple Example Using BPL</a>
<li><a href="overriding.html">Overridable Virtual Functions</a>
<li><a href="overloading.html">Function Overloading</a>
<li><a href="inheritance.html">Inheritance</a>
<li><a href="special.html">Special Method and Operator Support</a>
<li><a href="under-the-hood.html">A Peek Under the Hood</a>
<li><a href="building.html">Building a Module with BPL</a>
<li>Advanced Topics
<ol>
<li>Pickling
<li>class_builder&lt;&gt;
<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
</ol>
</ol>
<p>
Documentation is a major ongoing project; assistance is greatly
appreciated! In the meantime, useful examples of every BPL 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
href="../test/comprehensive.cpp">cpp</a>]</code>
<p>
Questions should be directed to <a href=
"http://www.egroups.com/list/boost">the boost mailing list</a>.
<p>
&copy; 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 &ldquo;as is&rdquo; without
express or implied warranty, and with no claim as to its suitability for
any purpose.
<p>
Updated: Nov 26, 2000

View File

@@ -1,169 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Inheritance
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Inheritance
</h1>
<h2>Inheritance in Python</h2>
<p>
BPL 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
new class in Python, the result is an extension class:
<blockquote>
<pre>
&gt;&gt;&gt; class MyPythonClass:
... def f(): return 'MyPythonClass.f()'
...
&gt;&gt;&gt; import my_extension_module
&gt;&gt;&gt; class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
... '''This is an extension class'''
... pass
...
&gt;&gt;&gt; x = Derived()
&gt;&gt;&gt; x.f()
'MyPythonClass.f()'
&gt;&gt;&gt; x.g()
'MyExtensionClass.g()'
</pre>
</blockquote>
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
<p>
BPL 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
<code>class_builder&lt;&gt;</code> is used to establish the relationship
between base and derived classes:
<blockquote>
<pre>
#include &lt;memory&gt; // for std::auto_ptr&lt;&gt;
struct Base {
virtual ~Base() {}
virtual const char* name() const { return "Base"; }
};
struct Derived : Base {
Derived() : x(-1) {}
virtual const char* name() const { return "Derived"; }
int x;
};
std::auto_ptr&lt;Base&gt; derived_as_base() {
return std::auto_ptr&lt;Base&gt;(new Derived);
}
const char* get_name(const Base& b) {
return b.name();
}
int get_derived_x(const Derived& d) {
return d.x;
}
<hr>
#include &lt;boost/python/class_builder.hpp&gt;
// namespace alias for code brevity
namespace python = boost::python;
extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
void initmy_module()
{
    try
    {
       python::module_builder my_module("my_module");
       python::class_builder&lt;Base&gt; base_class(my_module, "Base");
       base_class.def(python::constructor&lt;void&gt;());
       python::class_builder&lt;Derived&gt; derived_class(my_module, "Derived");
       derived_class.def(python::constructor&lt;void&gt;());
<b>// Establish the inheritance relationship between Base and Derived
derived_class.declare_base(base_class);</b>
my_module.def(derived_as_base, "derived_as_base");
my_module.def(get_name, "get_name");
my_module.def(get_derived_x, "get_derived_x");
    }
    catch(...)
    {
       python::handle_exception();    // Deal with the exception for Python
    }
}
</pre>
</blockquote>
<p>
Then, in Python:
<blockquote>
<pre>
&gt;&gt;&gt; from my_module import *
&gt;&gt;&gt; base = Base()
&gt;&gt;&gt; derived = Derived()
&gt;&gt;&gt; get_name(base)
'Base'
</pre><i>objects of wrapped class Derived may be passed where Base is expected</i><pre>
&gt;&gt;&gt; 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>
&gt;&gt;&gt; get_derived_x(derived_as_base())
-1
</pre>
</blockquote>
<h2>Inheritance Without Virtual Functions</h2>
<p>
If for some reason your base class has no virtual functions but you still want
to represent the inheritance relationship between base and derived classes,
pass the special symbol <code>boost::python::without_downcast</code> as the 2nd parameter
to <code>declare_base</code>:
<blockquote>
<pre>
struct Base2 {};
struct Derived2 { int f(); };
<hr>
...
   python::class_builder&lt;Base&gt; base2_class(my_module, "Base2");
   base2_class.def(python::constructor&lt;void&gt;());
   python::class_builder&lt;Derived2&gt; derived2_class(my_module, "Derived2");
   derived2_class.def(python::constructor&lt;void&gt;());
derived_class.declare_base(base_class, <b>python::without_downcast</b>);
</pre>
</blockquote>
<p>This approach will allow <code>Derived2</code> objects to be passed where
<code>Base2</code> is expected, but does not attempt to implicitly convert (downcast)
smart-pointers to <code>Base2</code> into <code>Derived2</code> pointers,
references, or values.
<p>
Next: <a href="special.html">Special Method and Operator Support</a>
Previous: <a href="overloading.html">Function Overloading</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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>

308
doc/new-conversions.html Normal file
View File

@@ -0,0 +1,308 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>A New Type Conversion Mechanism for Boost.Python</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p><img border="0" src="../../../c++boost.gif" width="277" height="86"
alt="boost logo"></p>
<h1>A New Type Conversion Mechanism for Boost.Python</h1>
<p>By <a href="../../../people/dave_abrahams.htm">David Abrahams</a>.
<h2>Introduction</h2>
This document describes a redesign of the mechanism for automatically
converting objects between C++ and Python. The current implementation
uses two functions for any type <tt>T</tt>:
<blockquote><pre>
U from_python(PyObject*, type&lt;T&gt;);
void to_python(V);
</pre></blockquote>
where U is convertible to T and T is convertible to V. These functions
are at the heart of C++/Python interoperability in Boost.Python, so
why would we want to change them? There are many reasons:
<h3>Bugs</h3>
<p>Firstly, the current mechanism relies on a common C++ compiler
bug. This is not just embarrassing: as compilers get to be more
conformant, the library stops working. The issue, in detail, is the
use of inline friend functions in templates to generate
conversions. It is a very powerful, and legal technique as long as
it's used correctly:
<blockquote><pre>
template &lt;class Derived&gt;
struct add_some_functions
{
friend <i>return-type</i> some_function1(..., Derived <i>cv-*-&amp;-opt</i>, ...);
friend <i>return-type</i> some_function2(..., Derived <i>cv-*-&amp;-opt</i>, ...);
};
template &lt;class T&gt;
struct some_template : add_some_functions&lt;some_template&lt;T&gt; &gt;
{
};
</pre></blockquote>
The <tt>add_some_functions</tt> template generates free functions
which operate on <tt>Derived</tt>, or on related types. Strictly
speaking the related types are not just cv-qualified <tt>Derived</tt>
values, pointers and/or references. Section 3.4.2 in the standard
describes exactly which types you must use as parameters to these
functions if you want the functions to be found
(there is also a less-technical description in section 11.5.1 of
C++PL3 <a href="#ref_1">[1]</a>). Suffice it to say that
with the current design, the <tt>from_python</tt> and
<tt>to_python</tt> functions are not supposed to be callable under any
conditions!
<h3>Compilation and Linking Time</h3>
The conversion functions generated for each wrapped class using the
above technique are not function templates, but regular functions. The
upshot is that they must <i>all</i> be generated regardless of whether
they are actually used. Generating all of those functions can slow
down module compilation, and resolving the references can slow down
linking.
<h3>Efficiency</h3>
The conversion functions are primarily used in (member) function
wrappers to convert the arguments and return values. Being functions,
converters have no interface which allows us to ask &quot;will the
conversion succeed?&quot; without calling the function. Since the
return value of the function must be the object to be passed as an
argument, Boost.Python currently uses C++ exception-handling to detect
an unsuccessful conversion. It's not a particularly good use of
exception-handling, since the failure is not handled very far from
where it occurred. More importantly, it means that C++ exceptions are
thrown during overload resolution as we seek an overload that matches
the arguments passed. Depending on the implementation, this approach
can result in significant slowdowns.
<p>It is also unclear that the current library generates a minimal
amount of code for any type conversion. Many of the conversion
functions are nontrivial, and partly because of compiler limitations,
they are declared <tt>inline</tt>. Also, we could have done a better
job separating the type-specific conversion code from the code which
is type-independent.
<h3>Cross-module Support</h3>
The current strategy requires every module to contain the definition
of conversions it uses. In general, a new module can never supply
conversion code which is used by another module. Ralf Grosse-Kunstleve
designed a clever system which imports conversions directly from one
library into another using some explicit declarations, but it has some
disadvantages also:
<ol>
<li>The system Ullrich Koethe designed for implicit conversion between
wrapped classes related through inheritance does not currently work if
the classes are defined in separate modules.
<li>The writer of the importing module is required to know the name of
the module supplying the imported conversions.
<li>There can be only one way to extract any given C++ type from a
Python object in a given module.
</ol>
The first item might be addressed by moving Boost.Python into a shared
library, but the other two cannot. Ralf turned the limitation in item
two into a feature: the required module is loaded implicitly when a
conversion it defines is invoked. We will probably want to provide
that functionality anyway, but it's not clear that we should require
the declaration of all such conversions. The final item is a more
serious limitation. If, for example, new numeric types are defined in
separate modules, and these types can all be converted to
<tt>double</tt>s, we have to choose just one conversion method.
<h3>Ease-of-use</h3>
One persistent source of confusion for users of Boost.Python has been
the fact that conversions for a class are not be visible at
compile-time until the declaration of that class has been seen. When
the user tries to expose a (member) function operating on or returning
an instance of the class in question, compilation fails...even though
the user goes on to expose the class in the same translation unit!
<p>
The new system lifts all compile-time checks for the existence of
particular type conversions and replaces them with runtime checks, in
true Pythonic style. While this might seem cavalier, the compile-time
checks are actually not much use in the current system if many classes
are wrapped in separate modules, since the checks are based only on
the user's declaration that the conversions exist.
<h2>The New Design</h2>
<h3>Motivation</h3>
The new design was heavily influenced by a desire to generate as
little code as possible in extension modules. Some of Boost.Python's
clients are enormous projects where link time is proportional to the
amount of object code, and there are many Python extension modules. As
such, we try to keep type-specific conversion code out of modules
other than the one the converters are defined in, and rely as much as
possible on centralized control through a shared library.
<h3>The Basics</h3>
The library contains a <tt>registry</tt> which maps runtime type
identifiers (actually an extension of <tt>std::type_info</tt> which
preserves references and constness) to entries containing type
converters. An <tt>entry</tt> can contain only one converter from C++ to Python
(<tt>wrapper</tt>), but many converters from Python to C++
(<tt>unwrapper</tt>s). <font color="#ff0000">What should happen if
multiple modules try to register wrappers for the same type?</font>. Wrappers
and unwrappers are known as <tt>body</tt> objects, and are accessed
by the user and the library (in its function-wrapping code) through
corresponding <tt>handle</tt> (<tt>wrap&lt;T&gt;</tt> and
<tt>unwrap&lt;T&gt;</tt>) objects. The <tt>handle</tt> objects are
extremely lightweight, and delegate <i>all</i> of their operations to
the corresponding <tt>body</tt>.
<p>
When a <tt>handle</tt> object is constructed, it accesses the
registry to find a corresponding <tt>body</tt> that can convert the
handle's constructor argument. Actually the registry record for any
type
<tt>T</tt>used in a module is looked up only once and stored in a
static <tt>registration&lt;T&gt;</tt> object for efficiency. For
example, if the handle is an <tt>unwrap&lt;Foo&amp;&gt;</tt> object,
the <tt>entry</tt> for <tt>Foo&amp;</tt> is looked up in the
<tt>registry</tt>, and each <tt>unwrapper</tt> it contains is queried
to determine if it can convert the
<tt>PyObject*</tt> with which the <tt>unwrap</tt> was constructed. If
a body object which can perform the conversion is found, a pointer to
it is stored in the handle. A body object may at any point store
additional data in the handle to speed up the conversion process.
<p>
Now that the handle has been constructed, the user can ask it whether
the conversion can be performed. All handles can be tested as though
they were convertible to <tt>bool</tt>; a <tt>true</tt> value
indicates success. If the user forges ahead and tries to do the
conversion without checking when no conversion is possible, an
exception will be thrown as usual. The conversion itself is performed
by the body object.
<h3>Handling complex conversions</h3>
<p>Some conversions may require a dynamic allocation. For example,
when a Python tuple is converted to a <tt>std::vector&lt;double&gt;
const&amp;</tt>, we need some storage into which to construct the
vector so that a reference to it can be formed. Furthermore, multiple
conversions of the same type may need to be &quot;active&quot;
simultaneously, so we can't keep a single copy of the storage
anywhere. We could keep the storage in the <tt>body</tt> object, and
have the body clone itself in case the storage is used, but in that
case the storage in the body which lives in the registry is never
used. If the storage was actually an object of the target type (the
safest way in C++), we'd have to find a way to construct one for the
body in the registry, since it may not have a default constructor.
<p>
The most obvious way out of this quagmire is to allocate the object using a
<i>new-expression</i>, and store a pointer to it in the handle. Since
the <tt>body</tt> object knows everything about the data it needs to
allocate (if any), it is also given responsibility for destroying that
data. When the <tt>handle</tt> is destroyed it asks the <tt>body</tt>
object to tear down any data it may have stored there. In many ways,
you can think of the <tt>body</tt> as a &quot;dynamically-determined
vtable&quot; for the handle.
<h3>Eliminating Redundancy</h3>
If you look at the current Boost.Python code, you'll see that there
are an enormous number of conversion functions generated for each
wrapped class. For a given class <tt>T</tt>, functions are generated
to extract the following types <tt>from_python</tt>:
<blockquote><pre>
T*
T const*
T const* const&amp;
T* const&amp;
T&amp;
T const&amp;
T
std::auto_ptr&lt;T&gt;&amp;
std::auto_ptr&lt;T&gt;
std::auto_ptr&lt;T&gt; const&amp;
boost::shared_ptr&lt;T&gt;&amp;
boost::shared_ptr&lt;T&gt;
boost::shared_ptr&lt;T&gt; const&amp;
</pre></blockquote>
Most of these are implemented in terms of just a few conversions, and
<t>if you're lucky</t>, they will be inlined and cause no extra
overhead. In the new system, however, a significant amount of data
will be associated with each type that needs to be converted. We
certainly don't want to register a separate unwrapper object for all
of the above types.
<p>Fortunately, much of the redundancy can be eliminated. For example,
if we generate an unwrapper for <tt>T&</tt>, we don't need an
unwrapper for <tt>T const&</tt> or <tt>T</tt>. Accordingly, the user's
request to wrap/unwrap a given type is translated at compile-time into
a request which helps to eliminate redundancy. The rules used to
<tt>unwrap</tt> a type are:
<ol>
<li> Treat built-in types specially: when unwrapping a value or
constant reference to one of these, use a value for the target
type. It will bind to a const reference if neccessary, and more
importantly, avoids having to dynamically allocate room for
an lvalue of types which can be cheaply copied.
<li>
Reduce everything else to a reference to an un-cv-qualified type
where possible. Since cv-qualification is lost on Python
anyway, there's no point in trying to convert to a
<tt>const&amp;</tt>. <font color="#ff0000">What about conversions
to values like the tuple-&gt;vector example above? It seems to me
that we don't want to make a <tt>vector&lt;double&gt;&amp;</tt>
(non-const) converter available for that case. We may need to
rethink this slightly.</font>
</ol>
<h3>Efficient Argument Conversion</h3>
Since type conversions are primarily used in function wrappers, an
optimization is provided for the case where a group of conversions are
used together. Each <tt>handle</tt> class has a corresponding
&quot;<tt>_more</tt>&quot; class which does the same job, but has a
trivial destructor. Instead of asking each &quot;<tt>_more</tt>&quot;
handle to destroy its own body, it is linked into an endogenous list
managed by the first (ordinary) handle. The <tt>wrap</tt> and
<tt>unwrap</tt> destructors are responsible for traversing that list
and asking each <tt>body</tt> class to tear down its
<tt>handle</tt>. This mechanism is also used to determine if all of
the argument/return-value conversions can succeed with a single
function call in the function wrapping code. <font color="#ff0000">We
might need to handle return values in a separate step for Python
callbacks, since the availablility of a conversion won't be known
until the result object is retrieved.</font>
<br>
<hr>
<h2>References</h2>
<p><a name="ref_1">[1]</a>B. Stroustrup, The C++ Programming Language
Special Edition Addison-Wesley, ISBN 0-201-70073-5.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->19 December 2001<!--webbot bot="Timestamp" endspan i-checksum="31283" --></p>
<p>© Copyright David Abrahams, 2001</p>
</body>
</html>

111
doc/new-conversions.txt Normal file
View File

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

View File

@@ -1,155 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Function Overloading
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Function Overloading
</h1>
<h2>An Example</h2>
<p>
To expose overloaded functions in Python, simply <code>def()</code> each
one with the same Python name:
<blockquote>
<pre>
inline int f1() { return 3; }
inline int f2(int x) { return x + 1; }
class X {
public:
X() : m_value(0) {}
X(int n) : m_value(n) {}
int value() const { return m_value; }
void value(int v) { m_value = v; }
private:
int m_value;
};
...
void initoverload_demo()
{
    try
    {
boost::python::module_builder overload_demo("overload_demo");
// Overloaded functions at module scope
overload_demo.def(f1, "f");
overload_demo.def(f2, "f");
boost::python::class_builder&lt;X&gt; x_class(overload_demo, "X");
// Overloaded constructors
x_class.def(boost::python::constructor&lt;&gt;());
x_class.def(boost::python::constructor&lt;int&gt;());
// Overloaded member functions
x_class.def((int (X::*)() const)&amp;X::value, "value");
x_class.def((void (X::*)(int))&amp;X::value, "value");
...
</pre>
</blockquote>
<p>
Now in Python:
<blockquote>
<pre>
>>> from overload_demo import *
>>> x0 = X()
>>> x1 = X(1)
>>> x0.value()
0
>>> x1.value()
1
>>> x0.value(3)
>>> x0.value()
3
>>> X('hello')
TypeError: No overloaded functions match (X, string). Candidates are:
void (*)()
void (*)(int)
>>> f()
3
>>> f(4)
5
</pre>
</blockquote>
<h2>Discussion</h2>
<p>
Notice that overloading in the Python module was produced three ways:<ol>
<li>by combining the non-overloaded C++ functions <code>int f1()</code>
and <code>int f2(int)</code> and exposing them as <code>f</code> in Python.
<li>by exposing the overloaded constructors of <code>class X</code>
<li>by exposing the overloaded member functions <code>X::value</code>.
</ol>
<p>
Techniques 1. and 3. above are really alternatives. In case 3, you need
to form a pointer to each of the overloaded functions. The casting
syntax shown above is one way to do that in C++. Case 1 does not require
complicated-looking casts, but may not be viable if you can't change
your C++ interface. N.B. There's really nothing unsafe about casting an
overloaded (member) function address this way: the compiler won't let
you write it at all unless you get it right.
<h2>An Alternative to Casting</h2>
<p>
This approach is not neccessarily better, but may be preferable for some
people who have trouble writing out the types of (member) function
pointers or simply prefer to avoid all casts as a matter of principle:
<blockquote>
<pre>
// Forwarding functions for X::value
inline void set_x_value(X&amp; self, int v) { self.value(v); }
inline int get_x_value(X&amp; self) { return self.value(); }
...
// Overloaded member functions
x_class.def(set_x_value, "value");
x_class.def(get_x_value, "value");
</pre>
</blockquote>
<p>Here we are taking advantage of the ability to expose C++ functions at
namespace scope as Python member functions.
<h2>Overload Resolution</h2>
<p>
The function overload resolution mechanism works as follows:
<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
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
this sense, overload resolution mirrors the C++ mechanism, where a name
in a derived class &ldquo;hides&rdquo; all functions with the same name from a base
class.
<p>
<li>Within a name-space context (extension class or module), overloaded
functions are tried in the same order they were
<code>def()</code>ed. The first function whose signature can be made to
match each argument passed is the one which is ultimately called.
This means in particular that you cannot overload the same function on
both &ldquo;<code>int</code>&rdquo; and &ldquo;<code>float</code>&rdquo; because Python
automatically converts either of the two types into the other one.
If the &ldquo;<code>float</code>&rdquo; overload is found first, it is used
also used for arguments of type &ldquo;<code>int</code>&rdquo; as well, and the
&ldquo;<code>int</code>&rdquo; version of the function is never invoked.
</ul>
<p>
Next: <a href="inheritance.html">Inheritance</a>
Previous: <a href="overriding.html">Overridable Virtual Functions</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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 &ldquo;as
is&rdquo; without express or implied warranty, and with no claim as to
its suitability for any purpose.
<p>
Updated: Nov 26, 2000
</div>

View File

@@ -1,195 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Overridable Virtual Functions</title>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
<h1>Overridable Virtual Functions</h1>
<p>
In the <a href="example1.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>.
<h2><a name="overriding_example">Example</a></h2>
<p>In this example, it is assumed that <code>world::greet()</code> is a virtual
member function:
<blockquote><pre>
class world
{
public:
   world(int);
    virtual ~world();
    <b>virtual</b> std::string greet() const { return "hi, world"; }
};
</pre></blockquote>
<p>
We'll need a derived class<a href="#why_derived">*</a> to help us
dispatch the call to Python. In our derived class, we need the following
elements:
<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_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_3">An</a> implementation of each virtual function you may
wish to override in Python which uses
<code>boost::python::callback&lt<i>return-type</i>&gt;::call_method()</code> 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
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.
</ol>
<blockquote><pre>
struct world_callback : world
{
world_callback(PyObject* self, int x) // <a href="#derived_2">2</a>
: world(x),
m_self(self) {}
std::string greet() const // <a href="#derived_3">3</a>
{ return boost::python::callback&lt;std::string&gt;::call_method(m_self, "get"); }
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(); }
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&lt;&gt;</code> declaration in our module initialization
function, and when we define the function, we must tell py_cpp about the default
implementation:
<blockquote><pre>
// Create the <a name=
"world_class">Python type object</a> for our extension class
boost::python::class_builder&lt;hello::world<strong>,world_callback&gt;</strong> world_class(hello, "world");
// Add a virtual member function
world_class.def(&amp;world::get, "get", &amp;<b>world_callback::default_get</b>);
</pre></blockquote>
<p>
Now our subclass of <code>hello.world</code> behaves as expected:
<blockquote><pre>
&gt;&gt;&gt; class my_subclass(hello.world):
... def greet(self):
... return 'hello, world'
...
&gt;&gt;&gt; hello.length(my_subclass())
12
</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
minimally intrusive on an existing C++ design. In principle, it should be
possible to expose the interface for a 3rd party library without changing
it. To unintrusively hook into the virtual functions so that a Python
override may be called, we must use a derived class.
<h2>Pure Virtual Functions</h2>
<p>
A pure virtual function with no implementation is actually a lot easier to
deal with than a virtual function with a default implementation. First of
all, you obviously don't need to <a href="#default_implementation"> supply
a default implementation</a>. Secondly, you don't need to call
<code>def()</code> on the <code>extension_class&lt;&gt;</code> 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,
indicating that it should have been implemented. For example:
<blockquote>
<pre>
struct baz {
<strong>virtual</strong> int pure(int) = 0;
};
struct baz_callback {
int pure(int x) { boost::python::callback&lt;int&gt;::call_method(m_self, "pure", x); }
};
extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
initfoobar()
{
try
{
boost::python::module_builder foobar("foobar");
boost::python::class_builder&lt;baz,baz_callback&gt; baz_class("baz");
baz_class.def(&amp;baz::pure, "pure");
}
catch(...)
{
boost::python::handle_exception(); // Deal with the exception for Python
}
}
</pre>
</blockquote>
<p>
Now in Python:
<blockquote>
<pre>
&gt;&gt;&gt; from foobar import baz
&gt;&gt;&gt; x = baz()
&gt;&gt;&gt; x.pure(1)
Traceback (innermost last):
File "&lt;stdin&gt;", line 1, in ?
AttributeError: pure
&gt;&gt;&gt; class mumble(baz):
... def pure(self, x): return x + 1
...
&gt;&gt;&gt; y = mumble()
&gt;&gt;&gt; y.pure(99)
100
</pre></blockquote>
<a name="private"><h2>Private Non-Pure Virtual Functions</h2></a>
<p>This is one area where some minor intrusiveness on the wrapped library is
required. Once it has been overridden, the only way to call the base class
implementation of a private virtual function is to make the derived class a
friend of the base class. You didn't hear it from me, but most C++
implementations will allow you to change the declaration of the base class in
this limited way without breaking binary compatibility (though it will certainly
break the <a
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
<p>
Next: <a href="overloading.html">Function Overloading</a>
Previous: <a href="example1.html">A Simple Example Using py_cpp</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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

View File

@@ -1,148 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Pointers
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Pointers
</h1>
<h2><a name="problem">The Problem With Pointers</a></h2>
<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?
A pointer to a single element? An array? When used as a return value, is the
caller expected to manage (delete) the pointed-to object or is the pointer
really just a reference? If the latter, what happens to Python references to the
referent when some C++ code deletes it?
<p>
There are a few cases in which pointers are converted automatically:
<ul>
<li>Both const- and non-const pointers to wrapped class instances can be passed
<i>to</i> C++ functions.
<li>Values of type <code>const char*</code> are interpreted as
null-terminated 'C' strings and when passed to or returned from C++ functions are
converted from/to Python strings.
</ul>
<h3>Can you avoid the problem?</h3>
<p>My first piece of advice to anyone with a case not covered above is
&ldquo;find a way to avoid the problem.&rdquo; For example, if you have just one
or two functions that return a pointer to an individual <code>const
T</code>, and <code>T</code> is a wrapped class, you may be able to write a &ldquo;thin
converting wrapper&rdquo; over those two functions as follows:
<blockquote><pre>
const Foo* f(); // original function
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
converts <code>const T&</code> values <code>to_python</code> by copying the <code>T</code>
value into a new extension instance.
<h2>Dealing with the problem</h2>
<p>The first step in handling the remaining cases is to figure out what the pointer
means. Several potential solutions are provided in the examples that follow:
<h3>Returning a pointer to a wrapped type</h3>
<h4>Returning a const pointer</h4>
<p>If you have lots of functions returning a <code>const T*</code> for some
wrapped <code>T</code>, you may want to provide an automatic
<code>to_python</code> conversion function so you don't have to write lots of
thin wrappers. You can do this simply as follows:
<blockquote><pre>
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
PyObject* to_python(const Foo* p) {
return to_python(*p); // convert const Foo* in terms of const Foo&
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
</pre></blockquote>
<h4>If you can't (afford to) copy the referent, or the pointer is non-const</h4>
<p>If the wrapped type doesn't have a public copy constructor, if copying is
<i>extremely</i> costly (remember, we're dealing with Python here), or if the
pointer is non-const and you really need to be able to modify the referent from
Python, you can use the following dangerous trick. Why dangerous? Because python
can not control the lifetime of the referent, so it may be destroyed by your C++
code before the last Python reference to it disappears:
<blockquote><pre>
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);
}
PyObject* to_python(const Foo* p)
{
return to_python(const_cast<Foo*>(p));
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
</pre></blockquote>
This will cause the Foo* to be treated as though it were an owning smart
pointer, even though it's not. Be sure you don't use the reference for anything
from Python once the pointer becomes invalid, though. Don't worry too much about
the <code>const_cast&lt;&gt;</code> above: Const-correctness is completely lost
to Python anyway!
<h3>[In/]Out Parameters and Immutable Types</h3>
<p>If you have an interface that uses non-const pointers (or references) as
in/out parameters to types which in Python are immutable (e.g. int, string),
there simply is <i>no way</i> to get the same interface in Python. You must
resort to transforming your interface with simple thin wrappers as shown below:
<blockquote><pre>
const void f(int* in_out_x); // original function
const int f_wrapper(int in_x) { f(in_x); return in_x; }
...
my_module.def(f_wrapper, "f");
</pre></blockquote>
<p>Of course, [in/]out parameters commonly occur only when there is already a
return value. You can handle this case by returning a Python tuple:
<blockquote><pre>
typedef unsigned ErrorCode;
const char* f(int* in_out_x); // original function
...
#include &lt;boost/python/objects.hpp&gt;
const boost::python::tuple f_wrapper(int in_x) {
const char* s = f(in_x);
return boost::python::tuple(s, in_x);
}
...
my_module.def(f_wrapper, "f");
</pre></blockquote>
<p>Now, in Python:
<blockquote><pre>
&gt;&gt;&gt; str,out_x = f(3)
</pre></blockquote>
<p>
Previous: <a href="enums.html">Enums</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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>

View File

@@ -1,888 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Special Method and Operator Support
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center" src=
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Special Method and
Operator Support
</h1>
<h2>
Overview
</h2>
<p>
BPL supports all of the standard <a href=
"http://www.pythonlabs.com/pub/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
suitable C++ functions and operators as Python operators. The following
categories of special method names are supported:
<ul>
<li><a href="#general">Basic Customization</a>
<li><a href="#numeric">Numeric Operators</a>
<li><a href="#sequence_and_mapping">Sequence and Mapping protocols</a>
<li><a href="#getter_setter">Attribute Getters and Setters</a>
</ul>
<h2><a name="general">Basic Customization</a></h2>
<p>
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>.
<dl>
<dt>
<b><tt class='method'>__init__</tt></b>(<i>self</i>)
<dd>
Initialize the class instance. For extension classes not subclassed in
Python, this is provided by the
<code>boost::python::constructor<...>()</code> construct and should <i>not</i> be explicitly <code>def</code>ed.
<dt>
<b><tt class='method'>__del__</tt></b>(<i>self</i>)
<dd>
Called when the extension instance is about to be destroyed.
<dt>
<b><tt class='method'>__repr__</tt></b>(<i>self</i>)
<dd>
Create a string representation from which the object can be
reconstructed.
<dt>
<b><tt class='method'>__str__</tt></b>(<i>self</i>)
<dd>
Create a string representation which is suitable for printing.
<dt>
<b><tt class='method'>__cmp__</tt></b>(<i>self, other</i>)
<dd>
Three-way compare function, used to implement comparison operators
(&lt; etc.) Should return a negative integer if <code> self < other
</code> , zero if <code> self == other </code> , a positive integer if
<code> self > other </code>.
<dt>
<b><tt class='method'>__hash__</tt></b>(<i>self</i>)
<dd>
Called for the key object for dictionary operations, and by the
built-in function hash(). Should return a 32-bit integer usable as a
hash value for dictionary operations (only allowed if __cmp__ is also
defined)
<dt>
<b><tt class='method'>__nonzero__</tt></b>(<i>self</i>)
<dd>
called if the object is used as a truth value (e.g. in an if
statement)
<dt>
<b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>)
<dd>
Called when the instance is &ldquo;called&rdquo; as a function; if this method
is defined, <code><var>x</var>(arg1, arg2, ...)</code> is a shorthand for
<code><var>x</var>.__call__(arg1, arg2, ...)</code>.
</dl>
If we have a suitable C++ function that supports any of these features,
we can export it like any other function, using its Python special name.
For example, suppose that class <code>Foo</code> provides a string
conversion function:
<blockquote><pre>
std::string to_string(Foo const&amp; f)
{
std::ostringstream s;
s &lt;&lt; f;
return s.str();
}
</pre></blockquote>
This function would be wrapped like this:
<blockquote><pre>
boost::python::class_builder&lt;Foo&gt; foo_class(my_module, "Foo");
foo_class.def(&amp;to_string, "__str__");
</pre></blockquote>
Note that BPL 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>.
<h2><a name="numeric">Numeric Operators</a></h2>
<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
protocols</a>. This is the basic same 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
<i>automatic wrapping</i> of numeric operators whenever they have already
been defined in C++.
<h3><a name="numeric_auto">Exposing C++ Operators Automatically</a></h3>
<p>
Supose we wanted to expose a C++ class
<code>BigNum</code> which supports addition, so that we can write (in C++):
<blockquote><pre>
BigNum a, b, c;
...
c = a + b;
</pre></blockquote>
<p>
To enable the same functionality in Python, we first wrap the <code>
BigNum</code> class as usual:
<blockquote><pre>
boost::python::class_builder&lt;BigNum&gt; bignum_class(my_module, "BigNum");
bignum_class.def(boost::python::constructor&lt;&gt;());
...
</pre></blockquote>
Then we export the addition operator like this:
<blockquote><pre>
bignum_class.def(boost::python::operators&lt;boost::python::op_add&gt;());
</pre></blockquote>
Since BigNum also supports subtraction, multiplication, and division, we
want to export those also. This can be done in a single command by
&ldquo;or&rdquo;ing the operator identifiers together (a complete list of these
identifiers and the corresponding operators can be found in the <a href=
"#numeric_table">Table of Automatically Wrapped Methods</a>):
<blockquote><pre>
bignum_class.def(boost::python::operators&lt;(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)&gt;());
</pre></blockquote>
[Note that the or-expression must be enclosed in parentheses.]
<p>This form of operator definition can be used to wrap unary and
homogeneous binary operators (a <i>homogeneous</i> operator has left and
right operands of the same type). Now suppose that our C++ library also
supports addition of BigNums and plain integers:
<blockquote><pre>
BigNum a, b;
int i;
...
a = b + i;
a = i + b;
</pre></blockquote>
To wrap these heterogeneous operators, we need to specify a different type for
one of the operands. This is done using the <code>right_operand</code>
and <code>left_operand</code> templates:
<blockquote><pre>
bignum_class.def(boost::python::operators&lt;boost::python::op_add&gt;(), boost::python::right_operand&lt;int&gt;());
bignum_class.def(boost::python::operators&lt;boost::python::op_add&gt;(), boost::python::left_operand&lt;int&gt;());
</pre></blockquote>
BPL 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>
bignum_class.def(boost::python::operators&lt;(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)&gt;(),
boost::python::right_operand&lt;int&gt;());
bignum_class.def(boost::python::operators&lt;(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)&gt;(),
boost::python::left_operand&lt;int&gt;());
</pre></blockquote>
The type of the operand not mentioned is taken from the class being wrapped. In
our example, the class object is <code>bignum_class</code>, and thus the
other operand's type is &ldquo;<code>BigNum const&amp;</code>&rdquo;. You can override
this default by explicitly specifying a type in the <code>
operators</code> template:
<blockquote><pre>
bignum_class.def(boost::python::operators&lt;boost::python::op_add, BigNum&gt;(), boost::python::right_operand&lt;int&gt;());
</pre></blockquote>
<p>
Note that automatic wrapping uses the <em>expression</em>
&ldquo;<code>left + right</code>&rdquo; and can be used uniformly
regardless of whether the C++ operators are supplied as free functions
<blockquote><pre>
BigNum operator+(BigNum, BigNum)
</pre></blockquote>
or as member
functions <blockquote><pre>
BigNum::operator+(BigNum).
</blockquote></pre>
<p>
For the Python built-in functions <code>pow()</code> and
<code>abs()</code>, there is no corresponding C++ operator. Instead,
automatic wrapping attempts to wrap C++ functions of the same name. This
only works if those functions are known in namespace
<code>python</code>. On some compilers (e.g. MSVC) it might be
necessary to add a using declaration prior to wrapping:
<blockquote><pre>
namespace boost { namespace python {
using my_namespace::pow;
using my_namespace::abs;
}
</pre></blockquote>
<h3><a name="numeric_manual">Wrapping Numeric Operators Manually</a></h3>
<p>
In some cases, automatic wrapping of operators may be impossible or
undesirable. Suppose, for example, that the modulo operation for BigNums
is defined by a set of functions <code>mod()</code> (for automatic
wrapping, we would need <code>operator%()</code>):
<blockquote><pre>
BigNum mod(BigNum const&amp; left, BigNum const&amp; right);
BigNum mod(BigNum const&amp; left, int right);
BigNum mod(int left, BigNum const&amp; right);
</pre></blockquote>
<p>
In order to create the Python operator "__mod__" from these functions, we
have to wrap them manually:
<blockquote><pre>
bignum_class.def((BigNum (*)(BigNum const&amp;, BigNum const&amp;))&amp;mod, "__mod__");
bignum_class.def((BigNum (*)(BigNum const&amp;, int))&amp;mod, "__mod__");
</pre></blockquote>
<p>
The third form (with <code>int</code> as left operand) cannot be wrapped
this way. We must first create a function <code>rmod()</code> with the
operands reversed:
<blockquote><pre>
BigNum rmod(BigNum const&amp; right, int left)
{
return mod(left, right);
}
</pre></blockquote>
This function must be wrapped under the name "__rmod__":
<blockquote><pre>
bignum_class.def(&amp;rmod, "__rmod__");
</pre></blockquote>
Many of the possible operator names can be found in the <a href=
"#numeric_table">Table of Automatically Wrapped Methods</a>. Special treatment is
necessary to export the <a href="#ternary_pow">ternary pow</a> operator.
<p>
Automatic and manual wrapping can be mixed arbitrarily. Note that you
cannot overload the same operator for a given extension class on both
&ldquo;<code>int</code>&rdquo; and &ldquo;<code>float</code>&rdquo;, because Python implicitly
converts these types into each other. Thus, the overloaded variant
found first (be it &ldquo;<code>int</code>&ldquo; or &ldquo;<code>float</code>&rdquo;) will be
used for either of the two types.
<h3><a name="coercion">Coercion</a></h3>
Plain Python can only execute operators with identical types on the left
and right hand side. If it encounters an expression where the types of
the left and right operand differ, it tries to coerce these type to a
common type before invoking the actual operator. Implementing good
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
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
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
registered</em> whenever automatic operator wrapping is used.
<p>
If you wrap all operator functions manually, but still want to use
operator overloading, you have to register the standard coercion
function explicitly:
<blockquote><pre>
// this is not necessary if automatic operator wrapping is used
bignum_class.def_standard_coerce();
</pre></blockquote>
If you encounter a situation where you absolutely need a customized
coercion, you can overload the "__coerce__" operator itself. The signature
of a coercion function should look like one of the following (the first is
the safest):
<blockquote><pre>
boost::python::tuple custom_coerce(boost::python::reference left, boost::python::reference right);
boost::python::tuple custom_coerce(PyObject* left, PyObject* right);
PyObject* custom_coerce(PyObject* left, PyObject* right);
</pre></blockquote>
The resulting <code>tuple</code> must contain two elements which
represent the values of <code>left</code> and <code>right</code>
converted to the same type. Such a function is wrapped as usual:
<blockquote><pre>
some_class.def(&amp;custom_coerce, "__coerce__");
</pre></blockquote>
Note that the later use of automatic operator wrapping on a
<code>class_builder</code> or a call to
&ldquo;<code>some_class.def_standard_coerce()</code>&rdquo; will cause any
custom coercion function to be replaced by the standard one.
<h3><a name="ternary_pow">The Ternary <code>pow()</code> Operator</a></h3>
<p>
In addition to the usual binary <code>pow(x, y)</code> operator (meaning
<i>x<sup>y</sup></i>), Python also provides a ternary variant that implements
<i>x<sup>y</sup> <b>mod</b> z</i>, presumably using a more efficient algorithm than
concatenation of power and modulo operators. Automatic operator wrapping
can only be used with the binary variant. Ternary <code>pow()</code> must
always be wrapped manually. For a homgeneous ternary <code>pow()</code>,
this is done as usual:
<blockquote><pre>
BigNum power(BigNum const&amp; first, BigNum const&amp; second, BigNum const&amp; module);
typedef BigNum (ternary_function1)(const BigNum&amp;, const BigNum&amp;, const BigNum&amp;);
...
bignum_class.def((ternary_function1)&amp;power, "__pow__");
</pre></blockquote>
If you want to support this function with non-uniform argument
types, wrapping is a little more involved. Suppose you have to wrap:
<blockquote><pre>
BigNum power(BigNum const&amp; first, int second, int modulus);
BigNum power(int first, BigNum const&amp; second, int modulus);
BigNum power(int first, int second, BigNum const&amp; modulus);
</pre></blockquote>
The first variant can be wrapped as usual:
<blockquote><pre>
typedef BigNum (ternary_function2)(const BigNum&amp;, int, int);
bignum_class.def((ternary_function2)&amp;power, "__pow__");
</pre></blockquote>
In the second variant, however, <code>BigNum</code> appears only as second
argument, and in the last one it is the third argument. These functions
must be presented to BPL such that that the <code>BigNum</code>
argument appears in first position:
<blockquote><pre>
BigNum rpower(BigNum const&amp; second, int first, int modulus)
{
return power(first, second, third);
}
BigNum rrpower(BigNum const&amp; third, int first, int second)
{
return power(first, second, third);
}
</pre></blockquote>
<p>These functions must be wrapped under the names "__rpow__" and "__rrpow__"
respectively:
<blockquote><pre>
bignum_class.def((ternary_function2)&amp;rpower, "__rpow__");
bignum_class.def((ternary_function2)&amp;rrpower, "__rrpow__");
</pre></blockquote>
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">
special methods</a>:
<p>
<table summary="special numeric methods" cellpadding="5" border="1"
width="100%">
<tr>
<td align="center">
<b>Python Operator Name</b>
<td align="center">
<b>Python Expression</b>
<td align="center">
<b>C++ Operator Id</b>
<td align="center">
<b>C++ Expression Used For Automatic Wrapping</b><br>
with <code>cpp_left = from_python(left,
type&lt;Left&gt;())</code>,<br>
<code>cpp_right = from_python(right,
type&lt;Right&gt;())</code>,<br>
and <code>cpp_oper = from_python(oper, type&lt;Oper&gt;())</code>
<tr>
<td>
<code>__add__, __radd__</code>
<td>
<code>left + right</code>
<td>
<code>op_add</code>
<td>
<code>cpp_left + cpp_right</code>
<tr>
<td>
<code>__sub__, __rsub__</code>
<td>
<code>left - right</code>
<td>
<code>op_sub</code>
<td>
<code>cpp_left - cpp_right</code>
<tr>
<td>
<code>__mul__, __rmul__</code>
<td>
<code>left * right</code>
<td>
<code>op_mul</code>
<td>
<code>cpp_left * cpp_right</code>
<tr>
<td>
<code>__div__, __rdiv__</code>
<td>
<code>left / right</code>
<td>
<code>op_div</code>
<td>
<code>cpp_left / cpp_right</code>
<tr>
<td>
<code>__mod__, __rmod__</code>
<td>
<code>left % right</code>
<td>
<code>op_mod</code>
<td>
<code>cpp_left % cpp_right</code>
<tr>
<td>
<code>__divmod__, __rdivmod__</code>
<td>
<code>(quotient, remainder)<br>
= divmod(left, right)</code>
<td>
<code>op_divmod</code>
<td>
<code>cpp_left / cpp_right</code>
<br><code>cpp_left % cpp_right</code>
<tr>
<td>
<code>__pow__, __rpow__</code>
<td>
<code>pow(left, right)</code><br>
(binary power)
<td>
<code>op_pow</code>
<td>
<code>pow(cpp_left, cpp_right)</code>
<tr>
<td>
<code>__rrpow__</code>
<td>
<code>pow(left, right, modulo)</code><br>
(ternary power modulo)
<td colspan="2">
no automatic wrapping, <a href="#ternary_pow">special treatment</a>
required
<tr>
<td>
<code>__lshift__, __rlshift__</code>
<td>
<code>left &lt;&lt; right</code>
<td>
<code>op_lshift</code>
<td>
<code>cpp_left &lt;&lt; cpp_right</code>
<tr>
<td>
<code>__rshift__, __rrshift__</code>
<td>
<code>left &gt;&gt; right</code>
<td>
<code>op_rshift</code>
<td>
<code>cpp_left &gt;&gt; cpp_right</code>
<tr>
<td>
<code>__and__, __rand__</code>
<td>
<code>left &amp; right</code>
<td>
<code>op_and</code>
<td>
<code>cpp_left &amp; cpp_right</code>
<tr>
<td>
<code>__xor__, __rxor__</code>
<td>
<code>left ^ right</code>
<td>
<code>op_xor</code>
<td>
<code>cpp_left ^ cpp_right</code>
<tr>
<td>
<code>__or__, __ror__</code>
<td>
<code>left | right</code>
<td>
<code>op_or</code>
<td>
<code>cpp_left | cpp_right</code>
<tr>
<td>
<code>__cmp__, __rcmp__</code>
<td>
<code>cmp(left, right)</code><br>
<code>left &lt; right</code><br>
<code>left &lt;= right</code><br>
<code>left &gt; right</code><br>
<code>left &gt;= right</code><br>
<code>left == right</code><br>
<code>left != right</code>
<td>
<code>op_cmp</code>
<td>
<code>cpp_left &lt; cpp_right </code>
<br><code>cpp_right &lt; cpp_left</code>
<tr>
<td>
<code>__neg__</code>
<td>
<code>-oper </code> (unary negation)
<td>
<code>op_neg</code>
<td>
<code>-cpp_oper</code>
<tr>
<td>
<code>__pos__</code>
<td>
<code>+oper </code> (identity)
<td>
<code>op_pos</code>
<td>
<code>+cpp_oper</code>
<tr>
<td>
<code>__abs__</code>
<td>
<code>abs(oper) </code> (absolute value)
<td>
<code>op_abs</code>
<td>
<code>abs(cpp_oper)</code>
<tr>
<td>
<code>__invert__</code>
<td>
<code>~oper </code> (bitwise inversion)
<td>
<code>op_invert</code>
<td>
<code>~cpp_oper</code>
<tr>
<td>
<code>__int__</code>
<td>
<code>int(oper) </code> (integer conversion)
<td>
<code>op_int</code>
<td>
<code>long(cpp_oper)</code>
<tr>
<td>
<code>__long__</code>
<td>
<code>long(oper) </code><br>
(infinite precision integer conversion)
<td>
<code>op_long</code>
<td>
<code>PyLong_FromLong(cpp_oper)</code>
<tr>
<td>
<code>__float__</code>
<td>
<code>float(oper) </code> (float conversion)
<td>
<code>op_float</code>
<td>
<code>double(cpp_oper)</code>
<tr>
<td>
<code>__str__</code>
<td>
<code>str(oper) </code> (string conversion)
<td>
<code>op_str</code>
<td>
<code>std::ostringstream s; s &lt;&lt; oper;</code>
<tr>
<td>
<code>__coerce__</code>
<td>
<code>coerce(left, right)</code>
<td colspan="2">
usually defined automatically, otherwise <a href="#coercion">
special treatment</a> required
</table>
<h2><a name="sequence_and_mapping">Sequence and Mapping Operators</a></h2>
<p>
Sequence and mapping operators let wrapped objects behave in accordance
to Python's iteration and access protocols. These protocols differ
considerably from the ones found in C++. For example, Python's typical
iteration idiom looks like
<blockquote><pre>
for i in S:
</blockquote></pre>
while in C++ one writes
<blockquote><pre>
for (iterator i = S.begin(), end = S.end(); i != end)
</blockquote></pre>
<p>One could try to wrap C++ iterators in order to carry the C++ idiom into
Python. However, this does not work very well because
<ol>
<li>It leads to
non-uniform Python code (wrapped sequences support a usage different from
Python built-in sequences) and
<li>Iterators (e.g. <code>std::vector::iterator</code>) are often implemented as plain C++
pointers which are <a href="pointers.html#problem">problematic</a> for any automatic
wrapping system.
</ol>
<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
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">
container operators</a>. In particular, expose __getitem__, __setitem__
and remember to raise the appropriate Python exceptions
(<code>PyExc_IndexError</code> for sequences,
<code>PyExc_KeyError</code> for mappings) when the requested item is not
present.
<p>
In the following example, we expose <code>std::map&lt;std::size_t,std::string&gt;</code>:
<blockquote>
<pre>
typedef std::map&lt;std::size_t, std::string&gt; StringMap;
// A helper function for dealing with errors. Throw a Python exception
// if p == m.end().
void throw_key_error_if_end(
const StringMap&amp; m,
StringMap::const_iterator p,
std::size_t key)
{
if (p == m.end())
{
PyErr_SetObject(PyExc_KeyError, boost::python::converters::to_python(key));
throw boost::python::error_already_set();
}
}
// Define some simple wrapper functions which match the Python protocol
// for __getitem__, __setitem__, and __delitem__. Just as in Python, a
// free function with a &ldquo;self&rdquo; first parameter makes a fine class method.
const std::string&amp; get_item(const StringMap&amp; self, std::size_t key)
{
const StringMap::const_iterator p = self.find(key);
throw_key_error_if_end(self, p, key);
return p-&gt;second;
}
// Sets the item corresponding to key in the map.
void StringMapPythonClass::set_item(StringMap&amp; self, std::size_t key, const std::string&amp; value)
{
self[key] = value;
}
// Deletes the item corresponding to key from the map.
void StringMapPythonClass::del_item(StringMap&amp; self, std::size_t key)
{
const StringMap::iterator p = self.find(key);
throw_key_error_if_end(self, p, key);
self.erase(p);
}
class_builder&lt;StringMap&gt; string_map(my_module, "StringMap");
string_map.def(boost::python::constructor&lt;&gt;());
string_map.def(&amp;StringMap::size, "__len__");
string_map.def(get_item, "__getitem__");
string_map.def(set_item, "__setitem__");
string_map.def(del_item, "__delitem__");
</pre>
</blockquote>
<p>
Then in Python:
<blockquote>
<pre>
&gt;&gt;&gt; m = StringMap()
&gt;&gt;&gt; m[1]
Traceback (innermost last):
File "&lt;stdin&gt;", line 1, in ?
KeyError: 1
&gt;&gt;&gt; m[1] = 'hello'
&gt;&gt;&gt; m[1]
'hello'
&gt;&gt;&gt; del m[1]
&gt;&gt;&gt; m[1] # prove that it's gone
Traceback (innermost last):
File "&lt;stdin&gt;", line 1, in ?
KeyError: 1
&gt;&gt;&gt; del m[2]
Traceback (innermost last):
File "&lt;stdin&gt;", line 1, in ?
KeyError: 2
&gt;&gt;&gt; len(m)
0
&gt;&gt;&gt; m[0] = 'zero'
&gt;&gt;&gt; m[1] = 'one'
&gt;&gt;&gt; m[2] = 'two'
&gt;&gt;&gt; m[3] = 'three'
&gt;&gt;&gt; len(m)
4
</pre>
</blockquote>
<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
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
<ul>
<li>
<code>__getattr__<em>&lt;name&gt;</em>__</code>
<li>
<code>__setattr__<em>&lt;name&gt;</em>__</code>
<li>
<code>__delattr__<em>&lt;name&gt;</em>__</code>
</ul>
to provide functional access to the attribute <em>&lt;name&gt;</em>. This
facility can be used from C++ or entirely from Python. For example, the
following shows how we can implement a &ldquo;computed attribute&rdquo; in Python:
<blockquote>
<pre>
&gt;&gt;&gt; class Range(AnyBPLExtensionClass):
... def __init__(self, start, end):
... self.start = start
... self.end = end
... def __getattr__length__(self):
... return self.end - self.start
...
&gt;&gt;&gt; x = Range(3, 9)
&gt;&gt;&gt; x.length
6
</pre>
</blockquote>
<h4>
Direct Access to Data Members
</h4>
<p>
BPL uses the special <code>
__xxxattr__<em>&lt;name&gt;</em>__</code> functionality described above
to allow direct access to data members through the following special
functions on <code>class_builder&lt;&gt;</code> and <code>
extension_class&lt;&gt;</code>:
<ul>
<li>
<code>def_getter(<em>pointer-to-member</em>, <em>name</em>)</code> //
read access to the member via attribute <em>name</em>
<li>
<code>def_setter(<em>pointer-to-member</em>, <em>name</em>)</code> //
write access to the member via attribute <em>name</em>
<li>
<code>def_readonly(<em>pointer-to-member</em>, <em>name</em>)</code>
// read-only access to the member via attribute <em>name</em>
<li>
<code>def_read_write(<em>pointer-to-member</em>, <em>
name</em>)</code> // read/write access to the member via attribute
<em>name</em>
</ul>
<p>
Note that the first two functions, used alone, may produce surprising
behavior. For example, when <code>def_getter()</code> is used, the
default functionality for <code>setattr()</code> and <code>
delattr()</code> remains in effect, operating on items in the extension
instance's name-space (i.e., its <code>__dict__</code>). For that
reason, you'll usually want to stick with <code>def_readonly</code> and
<code>def_read_write</code>.
<p>
For example, to expose a <code>std::pair&lt;int,long&gt;</code> we
might write:
<blockquote>
<pre>
typedef std::pair&lt;int,long&gt; Pil;
int first(const Pil&amp; x) { return x.first; }
long second(const Pil&amp; x) { return x.second; }
...
my_module.def(first, "first");
my_module.def(second, "second");
class_builder&lt;Pil&gt; pair_int_long(my_module, "Pair");
pair_int_long.def(boost::python::constructor&lt;&gt;());
pair_int_long.def(boost::python::constructor&lt;int,long&gt;());
pair_int_long.def_read_write(&amp;Pil::first, "first");
pair_int_long.def_read_write(&amp;Pil::second, "second");
</pre>
</blockquote>
<p>
Now your Python class has attributes <code>first</code> and <code>
second</code> which, when accessed, actually modify or reflect the
values of corresponding data members of the underlying C++ object. Now
in Python:
<blockquote>
<pre>
&gt;&gt;&gt; x = Pair(3,5)
&gt;&gt;&gt; x.first
3
&gt;&gt;&gt; x.second
5
&gt;&gt;&gt; x.second = 8
&gt;&gt;&gt; x.second
8
&gt;&gt;&gt; second(x) # Prove that we're not just changing the instance __dict__
8
</pre>
</blockquote>
<h2>
<a name="reasons">And what about <code>__complex__</code>?</a>
</h2>
<p>
That, dear reader, is one problem we don't know how to solve. The
Python source contains the following fragment, indicating the
special-case code really is hardwired:
<blockquote>
<pre>
/* XXX Hack to support classes with __complex__ method */
if (PyInstance_Check(r)) { ...
</pre>
</blockquote>
<p>
Next: <a href="under-the-hood.html">A Peek Under the Hood</a>
Previous: <a href="inheritance.html">Inheritance</a>
Up: <a href= "index.html">Top</a>
<p>
&copy; Copyright David Abrahams and Ullrich K&ouml;the 2000.
Permission to copy, use, modify, sell and distribute this document is
granted provided this copyright notice appears in all copies. This
document is provided &ldquo;as is&rdquo; without express or implied
warranty, and with no claim as to its suitability for any purpose.
<p>
Updated: Nov 26, 2000
</div>

View File

@@ -1,26 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
The Title Of This Page
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">The Title Of This
Page
</h1>
<p>
<p>
Prev: <a href="prev.html">Previous</a>
Next: <a href="next.html">Next</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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>

View File

@@ -1,62 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
A Peek Under the Hood
</title>
<h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
</h1>
<h1>
A Peek Under the Hood
</h1>
<p>
Declaring a <code>class_builder&lt;T&gt;</code> causes the instantiation
of an <code>extension_class&lt;T&gt;</code> to which it forwards all
member function calls and which is doing most of the real work.
<code>extension_class&lt;T&gt;</code> is a subclass of <code>
PyTypeObject</code>, the <code> struct</code> which Python's 'C' API uses
to describe a type. <a href="example1.html#world_class">An instance of the
<code>extension_class&lt;&gt;</code></a> becomes the Python type object
corresponding to <code>hello::world</code>. When we <a href=
"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
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
overloaded functions <code>PyObject*
to_python(</code><em>S</em><code>)</code> and <em>
S'</em><code>from_python(PyObject*,
type&lt;</code><em>S</em><code>&gt;)</code> which convert between any C++
type <em>S</em> and a <code>PyObject*</code>, the type which represents a
reference to any Python object in its 'C' API. The <a href=
"example1.html#world_class"><code>extension_class&lt;T&gt;</code></a>
template defines a whole raft of these conversions (for <code>T, T*,
T&amp;, std::auto_ptr&lt;T&gt;</code>, etc.), using the same inline
friend function technique employed by <a href=
"http://www.boost.org/libs/utility/operators.htm">the boost operators
library</a>.
<p>
Because the <code>to_python</code> and <code>from_python</code> functions
for a user-defined class are defined by <code>
extension_class&lt;T&gt;</code>, it is important that an instantiation of
<code> extension_class&lt;T&gt;</code> is visible to any code which wraps
a C++ function with a <code>T, T*, const T&amp;</code>, etc. parameter or
return value. In particular, you may want to create all of the classes at
the top of your module's init function, then <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>
Previous: <a href="special.html">Special Method and Operator Support</a>
Up: <a href="index.html">Top</a>
<p>
&copy; 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

View File

@@ -1,54 +0,0 @@
#include <string.h>
namespace hello {
class world
{
public:
world(int) {}
~world() {}
const char* get() const { return "hi, world"; }
};
size_t length(const world& x) { return strlen(x.get()); }
}
#include <boost/python/class_builder.hpp>
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
void inithello()
{
try
{
// create an object representing this extension module
boost::python::module_builder hello("hello");
// Create the Python type object for our extension class
boost::python::class_builder<hello::world> world_class(hello, "world");
// Add the __init__ function
world_class.def(boost::python::constructor<int>());
// Add a regular member function
world_class.def(&hello::world::get, "get");
// Add a regular function to the module
hello.def(hello::length, "length");
}
catch(...)
{
boost::python::handle_exception(); // Deal with the exception for Python
}
}
// Win32 DLL boilerplate
#if defined(_WIN32)
#include <windows.h>
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
{
return 1;
}
#endif // _WIN32

View File

@@ -1,41 +0,0 @@
#include <string>
namespace { // Avoid cluttering the global namespace.
// A couple of simple C++ functions that we want to expose to Python.
std::string greet() { return "hello, world"; }
int square(int number) { return number * number; }
}
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
initrwgk1()
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("rwgk1");
// 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
}
}
// Win32 DLL boilerplate
#if defined(_WIN32)
#include <windows.h>
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; }
#endif // _WIN32

View File

@@ -1,50 +0,0 @@
r'''
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
That's it! If we build this shared library and put it on our PYTHONPATH we can
now access our C++ class and function from Python.
>>> import hello
>>> hi_world = hello.world(3)
>>> hi_world.get()
'hi, world'
>>> hello.length(hi_world)
9
We can even make a subclass of hello.world:
>>> class my_subclass(hello.world):
... def get(self):
... return 'hello, world'
...
>>> y = my_subclass(2)
>>> y.get()
'hello, world'
Pretty cool! You can't do that with an ordinary Python extension type!
>>> hello.length(y)
9
Of course, you may now have a slightly empty feeling in the pit of your little
pythonic stomach. Perhaps you feel your subclass deserves to have a length() of
12? If so, read on...
'''
from hello import *
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_example1
doctest.testmod(test_example1)
if __name__ == '__main__':
run()

View File

@@ -1,17 +0,0 @@
r'''>>> import rwgk1
>>> print rwgk1.greet()
hello, world
>>> number = 11
>>> print number, '*', number, '=', rwgk1.square(number)
11 * 11 = 121
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_rwgk1
doctest.testmod(test_rwgk1)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,210 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for 5-argument member functions and 6-argument free
// functions by gen_call.py
#ifndef CALL_DWA20011214_HPP
# define CALL_DWA20011214_HPP
# include <boost/python/detail/returning.hpp>
namespace boost { namespace python {
template <class R>
PyObject* call(R (*f)(), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (*f)(A0), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (*f)(A0, A1), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
// Member functions
template <class R, class A0>
PyObject* call(R (A0::*f)(), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
}} // namespace boost::python
#endif // CALL_DWA20011214_HPP

View File

@@ -1,829 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// 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_

File diff suppressed because it is too large Load Diff

View File

@@ -1,156 +0,0 @@
#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()
{}
// 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_

View File

@@ -1,527 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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

View File

@@ -1,325 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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>
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 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(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&>);
// 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 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_

View File

@@ -0,0 +1,82 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONVERT_DWA20011129_HPP
# define CONVERT_DWA20011129_HPP
# include <boost/python/converter/target.hpp>
# include <boost/python/converter/source.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/unwrap.hpp>
namespace boost { namespace python {
namespace detail
{
template <class T>
struct converter_gen
{
typedef T value_type;
typedef typename converter::source<value_type>::type source;
typedef converter::wrap_<source> wrap;
typedef converter::wrap_more_<source> wrap_more;
typedef typename converter::target<value_type>::type target;
typedef converter::unwrap_<target> unwrap;
typedef converter::unwrap_more_<target> unwrap_more;
};
}
template <class T>
struct wrap : detail::converter_gen<T>::wrap
{
typedef typename detail::converter_gen<T>::wrap base;
};
template <class T>
struct wrap_more : detail::converter_gen<T>::wrap_more
{
typedef typename detail::converter_gen<T>::wrap_more base;
wrap_more(converter::handle& prev);
};
template <class T>
struct unwrap : detail::converter_gen<T>::unwrap
{
typedef typename detail::converter_gen<T>::unwrap base;
unwrap(PyObject*);
};
template <class T>
struct unwrap_more : detail::converter_gen<T>::unwrap_more
{
typedef typename detail::converter_gen<T>::unwrap_more base;
unwrap_more(PyObject*, converter::handle& prev);
};
//
// implementations
//
template <class T>
inline wrap_more<T>::wrap_more(converter::handle& prev)
: base(prev)
{
}
template <class T>
inline unwrap<T>::unwrap(PyObject* source)
: base(source)
{
}
template <class T>
inline unwrap_more<T>::unwrap_more(PyObject* source, converter::handle& prev)
: base(source, prev)
{
}
}} // namespace boost::python
#endif // CONVERT_DWA20011129_HPP

View File

@@ -0,0 +1,46 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef BODY_DWA2001127_HPP
# define BODY_DWA2001127_HPP
# include <boost/config.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT handle;
struct BOOST_PYTHON_EXPORT body
{
public:
body(type_id_t key);
virtual ~body() {}
// default implementation is a no-op
virtual void destroy_handle(handle*) const;
type_id_t key() const;
private:
type_id_t m_key;
};
//
// implementations
//
inline body::body(type_id_t key)
: m_key(key)
{
}
inline type_id_t body::key() const
{
return m_key;
}
}}} // namespace boost::python::converter
#endif // BODY_DWA2001127_HPP

View File

@@ -0,0 +1,56 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CLASS_DWA20011215_HPP
# define CLASS_DWA20011215_HPP
# include <boost/python/object/class.hpp>
# include <boost/python/converter/unwrapper.hpp>
namespace boost { namespace python { namespace converter {
struct class_unwrapper_base
{
class_unwrapper_base(type_id_t sought_type);
void*
};
template <class T>
struct class_unwrapper
{
struct ref_unwrapper : unwrapper<T&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
struct const_ref_unwrapper : unwrapper<T const&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
# endif
};
}}} // namespace boost::python::converter
#endif // CLASS_DWA20011215_HPP

View File

@@ -0,0 +1,91 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef HANDLE_DWA20011130_HPP
# define HANDLE_DWA20011130_HPP
# include <boost/python/export.hpp>
# include <boost/utility.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT body;
// The common base class for unwrap_ and wrap_ handle objects. They
// share a common base so that handles can be linked into a chain
// within a function wrapper which is managed by a single object.
struct BOOST_PYTHON_EXPORT handle : boost::noncopyable
{
public: // member functions
// All constructors take a body* passed from the derived class.
//
// Constructors taking a handle links this into a chain of
// handles, for more efficient management in function wrappers
handle(body* body);
handle(body* body, handle& prev);
// returns true iff all handles in the chain can convert their
// arguments
bool convertible() const;
// safe_bool idiom from Peter Dimov: provides handles to/from
// bool without enabling handles to integer types/void*.
private:
struct dummy { inline void nonnull() {} };
typedef void (dummy::*safe_bool)();
public:
inline operator safe_bool() const;
inline safe_bool operator!() const;
protected: // member functions for derived classes
// Get the body we hold
inline body* get_body() const;
// Release all bodies in the chain, in reverse order of
// initialization. Only actually called for the head of the chain.
void destroy();
private:
// Holds implementation
body* m_body;
// handle for next argument, if any.
handle* m_next;
};
//
// implementations
//
inline handle::handle(body* body, handle& prev)
: m_body(body), m_next(0)
{
prev.m_next = this;
}
inline handle::handle(body* body)
: m_body(body), m_next(0)
{
}
inline handle::operator handle::safe_bool() const
{
return convertible() ? &dummy::nonnull : 0;
}
inline handle::safe_bool handle::operator!() const
{
return convertible() ? 0 : &dummy::nonnull;
}
inline body* handle::get_body() const
{
return m_body;
}
}}} // namespace boost::python::converter
#endif // HANDLE_DWA20011130_HPP

View File

@@ -0,0 +1,83 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef REGISTRATION_DWA20011130_HPP
# define REGISTRATION_DWA20011130_HPP
# include <boost/config.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
struct BOOST_PYTHON_EXPORT unwrapper_base;
// This class is really sort of a "templated namespace". It manages a
// static data member which refers to the registry entry for T. This
// reference is acquired once to reduce the burden of multiple
// dictionary lookups at runtime.
template <class T>
struct registration
{
public: // member functions
// Return a converter which can convert the given Python object to
// T, or 0 if no such converter exists
static unwrapper_base* unwrapper(PyObject*);
// Return a converter which can convert T to a Python object, or 0
// if no such converter exists
static wrapper_base* wrapper();
private: // helper functions
static registry::entry* entry();
static registry::entry* find_entry();
private: // data members
static registry::entry* m_registry_entry;
};
// because this is static POD data it will be initialized to zero
template <class T>
registry::entry* registration<T>::m_registry_entry;
template <class T>
registry::entry* registration<T>::find_entry()
{
return registry::find(type_id<T>());
}
template <class T>
inline registry::entry* registration<T>::entry()
{
if (!m_registry_entry)
m_registry_entry = find_entry();
return m_registry_entry;
}
template <class T>
unwrapper_base* registration<T>::unwrapper(PyObject* p)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "retrieving unwrapper for " << type_id<T>() << std::endl;
# endif
return entry()->unwrapper(p);
}
template <class T>
wrapper_base* registration<T>::wrapper()
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "retrieving wrapper for " << type_id<T>() << std::endl;
# endif
return entry()->wrapper();
}
}}} // namespace boost::python::converter
#endif // REGISTRATION_DWA20011130_HPP

View File

@@ -0,0 +1,74 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef REGISTRY_DWA20011127_HPP
# define REGISTRY_DWA20011127_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
# include <list>
# include <memory>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
struct BOOST_PYTHON_EXPORT unwrapper_base;
// This namespace acts as a sort of singleton
namespace registry
{
// These are the elements stored in the registry
class BOOST_PYTHON_EXPORT entry
{
public: // member functions
entry();
~entry();
// Return a converter appropriate for converting the given
// Python object from_python to the C++ type with which this
// converter is associated in the registry, or 0 if no such
// converter exists.
unwrapper_base* unwrapper(PyObject*) const;
// Return a converter appropriate for converting a C++ object
// whose type this entry is associated with in the registry to a
// Python object, or 0 if no such converter exists.
wrapper_base* wrapper() const;
// Conversion classes use these functions to register
// themselves.
void insert(wrapper_base&);
void remove(wrapper_base&);
void insert(unwrapper_base&);
void remove(unwrapper_base&);
private: // types
typedef std::list<unwrapper_base*> unwrappers;
private: // helper functions
unwrappers::iterator find(unwrapper_base const&);
private: // data members
// The collection of from_python converters for the associated
// C++ type.
unwrappers m_unwrappers;
// The unique to_python converter for the associated C++ type.
converter::wrapper_base* m_wrapper;
};
BOOST_PYTHON_EXPORT entry* find(type_id_t);
BOOST_PYTHON_EXPORT void insert(wrapper_base& x);
BOOST_PYTHON_EXPORT void insert(unwrapper_base& x);
BOOST_PYTHON_EXPORT void remove(wrapper_base& x);
BOOST_PYTHON_EXPORT void remove(unwrapper_base& x);
}
}}} // namespace boost::python::converter
#endif // REGISTRY_DWA20011127_HPP

View File

@@ -0,0 +1,80 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SOURCE_DWA20011119_HPP
# define SOURCE_DWA20011119_HPP
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/mpl/select_type.hpp>
namespace boost { namespace python { namespace converter {
// source --
//
// This type generator (see
// ../../../more/generic_programming.html#type_generator) is used
// to select the argument type to use when converting T to a PyObject*
template <class T> struct source;
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Since for some strange reason temporaries can't be bound to const
// volatile references (8.5.3/5 in the C++ standard), we cannot use a
// const volatile reference as the standard for values and references.
template <class T>
struct source
{
typedef T const& type;
};
// This will handle the following:
// T const volatile& -> T const volatile&
// T volatile& -> T const volatile&
// T const& -> T const&
// T& -> T const&
template <class T>
struct source<T&>
{
typedef T const& type;
};
template <class T>
struct source<T*>
{
typedef T const* type;
};
template <class T>
struct source<T* const>
{
typedef T const* type;
};
// Deal with references to pointers
template <class T>
struct source<T*&>
{
typedef T const* type;
};
template <class T>
struct source<T* const&>
{
typedef T const* type;
};
# else
template <class T>
struct source
{
typedef typename add_reference<
typename add_const<T>::type
>::type type;
};
# endif
}}} // namespace boost::python::converter
#endif // SOURCE_DWA20011119_HPP

View File

@@ -0,0 +1,24 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SOURCE_HOLDER_DWA20011215_HPP
# define SOURCE_HOLDER_DWA20011215_HPP
namespace boost { namespace python { namespace converter {
struct source_holder_base
{
};
template <class T>
struct source_holder : source_holder_base
{
source_holder(T x) : value(x) {}
T value;
};
}}} // namespace boost::python::converter
#endif // SOURCE_HOLDER_DWA20011215_HPP

View File

@@ -0,0 +1,172 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef TARGET_DWA20011119_HPP
# define TARGET_DWA20011119_HPP
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/same_traits.hpp>
namespace boost { namespace python { namespace converter {
// target --
//
// This type generator (see
// ../../../more/generic_programming.html#type_generator) is used
// to select the return type of the appropriate converter for
// unwrapping a given type.
// Strategy:
//
// 1. reduce everything to a common, un-cv-qualified reference
// type where possible. This will save on registering many different
// converter types.
//
// 2. Treat built-in types specially: when unwrapping a value or
// constant reference to one of these, use a value for the target
// type. It will bind to a const reference if neccessary, and more
// importantly, avoids having to dynamically allocate room for
// an lvalue of types which can be cheaply copied.
//
// In the tables below, "cv" stands for the set of all possible
// cv-qualifications.
// Target Source
// int int
// int const& int
// int& int&
// int volatile& int volatile&
// int const volatile& int const volatile&
// On compilers supporting partial specialization:
//
// Target Source
// T T&
// T cv& T&
// T cv* T*
// T cv*const& T*
// T cv*& T*& <- should this be legal?
// T cv*volatile& T*& <- should this be legal?
// T cv*const volatile& T*& <- should this be legal?
// On others:
//
// Target Source
// T T&
// T cv& T cv&
// T cv* T cv*
// T cv*cv& T cv*cv&
// As you can see, in order to handle the same range of types without
// partial specialization, more converters need to be registered.
template <class T>
struct target
{
// Some pointer types are handled in a more sophisticated way on
// compilers supporting partial specialization.
BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_scalar<T>::value));
typedef typename mpl::select_type<
use_identity
, T
, typename add_reference<typename remove_cv<T>::type>::type
>::type type;
};
// When partial specialization is not present, we'll simply need to
// register many more converters.
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct target<T&>
{
typedef typename remove_cv<T>::type& type;
};
template <class T>
struct target<T*>
{
typedef typename remove_cv<T>::type* type;
};
// Handle T*-cv for completeness. Function arguments in a signature
// are never actually cv-qualified, but who knows how this might be
// used, or what compiler bugs may lurk?
template <class T>
struct target<T* const>
{
typedef typename remove_cv<T>::type* type;
};
template <class T>
struct target<T* volatile>
{
typedef typename remove_cv<T>::type* type;
};
template <class T>
struct target<T* const volatile>
{
typedef typename remove_cv<T>::type* type;
};
// non-const references to pointers should be handled by the
// specialization for T&, above.
template <class T>
struct target<T* const&>
{
typedef typename remove_cv<T>::type* type;
};
# endif
// Fortunately, we can handle T const& where T is an arithmetic type
// by explicit specialization. These specializations will cause value
// and const& arguments to be converted to values, rather than to
// references.
# define BOOST_PYTHON_UNWRAP_VALUE(T) \
template <> \
struct target<T> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const> \
{ \
typedef T type; \
}; \
template <> \
struct target<T volatile> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const volatile> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const&> \
{ \
typedef T type; \
}
BOOST_PYTHON_UNWRAP_VALUE(char);
BOOST_PYTHON_UNWRAP_VALUE(unsigned char);
BOOST_PYTHON_UNWRAP_VALUE(signed char);
BOOST_PYTHON_UNWRAP_VALUE(unsigned int);
BOOST_PYTHON_UNWRAP_VALUE(signed int);
BOOST_PYTHON_UNWRAP_VALUE(unsigned short);
BOOST_PYTHON_UNWRAP_VALUE(signed short);
BOOST_PYTHON_UNWRAP_VALUE(unsigned long);
BOOST_PYTHON_UNWRAP_VALUE(signed long);
BOOST_PYTHON_UNWRAP_VALUE(char const*);
}}} // namespace boost::python::converter
#endif // TARGET_DWA20011119_HPP

View File

@@ -0,0 +1,200 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef TYPE_ID_DWA20011127_HPP
# define TYPE_ID_DWA20011127_HPP
# include <boost/config.hpp>
# include <boost/python/export.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/python/export.hpp>
# include <boost/operators.hpp>
# include <typeinfo>
# include <iosfwd>
# include <cstring>
namespace boost { namespace python { namespace converter {
// a portable mechanism for identifying types at runtime across modules.
namespace detail
{
template <class T> class dummy;
}
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so use typeid(x).name() instead. It's not
// yet clear what the best default strategy is.
# if defined(__GNUC__) && __GNUC__ >= 3
# define BOOST_PYTHON_TYPE_ID_NAME
# endif
# if 1
struct type_id_t : totally_ordered<type_id_t>
{
enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 };
# ifdef BOOST_PYTHON_TYPE_ID_NAME
typedef char const* base_id_t;
# else
typedef std::type_info const* base_id_t;
# endif
type_id_t(base_id_t, decoration decoration);
bool operator<(type_id_t const& rhs) const;
bool operator==(type_id_t const& rhs) const;
friend BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&);
private:
decoration m_decoration;
base_id_t m_base_type;
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct is_reference_to_const
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T>
struct is_reference_to_const<T const&>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct is_reference_to_volatile
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T>
struct is_reference_to_volatile<T volatile&>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
# else
template <typename V>
struct is_const_help
{
typedef typename mpl::select_type<
is_const<V>::value
, type_traits::yes_type
, type_traits::no_type
>::type type;
};
template <typename V>
struct is_volatile_help
{
typedef typename mpl::select_type<
is_volatile<V>::value
, type_traits::yes_type
, type_traits::no_type
>::type type;
};
template <typename V>
typename is_const_help<V>::type reference_to_const_helper(V&);
type_traits::no_type
reference_to_const_helper(...);
template <class T>
struct is_reference_to_const
{
static T t;
BOOST_STATIC_CONSTANT(
bool, value
= sizeof(reference_to_const_helper(t)) == sizeof(type_traits::yes_type));
};
template <typename V>
typename is_volatile_help<V>::type reference_to_volatile_helper(V&);
type_traits::no_type reference_to_volatile_helper(...);
template <class T>
struct is_reference_to_volatile
{
static T t;
BOOST_STATIC_CONSTANT(
bool, value
= sizeof(reference_to_volatile_helper(t)) == sizeof(type_traits::yes_type));
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
inline type_id_t type_id(detail::dummy<T>* = 0)
{
return type_id_t(
# ifdef BOOST_PYTHON_TYPE_ID_NAME
typeid(T).name()
# else
&typeid(T)
# endif
, type_id_t::decoration(
(is_const<T>::value || is_reference_to_const<T>::value
? type_id_t::const_ : 0)
| (is_volatile<T>::value || is_reference_to_volatile<T>::value
? type_id_t::volatile_ : 0)
| (is_reference<T>::value ? type_id_t::reference : 0)
)
);
}
inline type_id_t::type_id_t(base_id_t base_t, decoration decoration)
: m_decoration(decoration)
, m_base_type(base_t)
{
}
inline bool type_id_t::operator<(type_id_t const& rhs) const
{
return m_decoration < rhs.m_decoration
|| m_decoration == rhs.m_decoration
# ifdef BOOST_PYTHON_TYPE_ID_NAME
&& std::strcmp(m_base_type, rhs.m_base_type) < 0;
# else
&& m_base_type->before(*rhs.m_base_type);
# endif
}
inline bool type_id_t::operator==(type_id_t const& rhs) const
{
return m_decoration == rhs.m_decoration
# ifdef BOOST_PYTHON_TYPE_ID_NAME
&& !std::strcmp(m_base_type, rhs.m_base_type);
# else
&& *m_base_type == *rhs.m_base_type;
# endif
}
# else
// This is the type which is used to identify a type
typedef char const* type_id_t;
// This is a workaround for a silly MSVC bug
// Converts a compile-time type to its corresponding runtime identifier.
template <class T>
type_id_t type_id(detail::dummy<T>* = 0)
{
return typeid(T).name();
}
# endif
struct BOOST_PYTHON_EXPORT type_id_before
{
bool operator()(type_id_t const& x, type_id_t const& y) const;
};
BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&);
}}} // namespace boost::python::converter
#endif // TYPE_ID_DWA20011127_HPP

View File

@@ -0,0 +1,192 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAP_BASE_DWA20011130_HPP
# define UNWRAP_BASE_DWA20011130_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrapper.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrapper;
struct BOOST_PYTHON_EXPORT body;
struct BOOST_PYTHON_EXPORT unwrap_base : handle
{
public: // member functions
inline unwrap_base(PyObject* source, body*, handle& prev);
inline unwrap_base(PyObject* source, body*);
inline PyObject* source() const;
private: // data members
PyObject* m_source;
};
// These converters will be used by the function wrappers. They don't
// manage any resources, but are instead linked into a chain which is
// managed by an instance of unwrap_ or wrap_.
template <class T>
struct unwrap_more_ : unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev);
// invoke the conversion or throw an exception if unsuccessful
T operator*();
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source);
private: // helper functions
// Return the unwrapper which will convert the given Python object
// to T, or 0 if no such converter exists
static unwrapper_base* lookup(PyObject*);
private:
// unspecified storage which may be allocated by the unwrapper to
// do value conversions.
mutable void* m_storage;
friend class unwrapper<T>;
};
// specialization for PyObject*
template <>
struct unwrap_more_<PyObject*>
: unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, m_unwrapper, prev)
{
}
// invoke the conversion or throw an exception if unsuccessful
PyObject* operator*()
{
return source();
}
bool convertible(PyObject*) const
{
return true;
}
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source)
: unwrap_base(source, m_unwrapper)
{
}
private:
static BOOST_PYTHON_EXPORT unwrapper_base* m_unwrapper;
};
template <class T>
struct unwrap_ : unwrap_more_<T>
{
unwrap_(PyObject* source);
~unwrap_();
};
//
// implementations
//
inline unwrap_base::unwrap_base(PyObject* source, body* body, handle& prev)
: handle(body, prev)
, m_source(source)
{
}
inline unwrap_base::unwrap_base(PyObject* source, body* body)
: handle(body)
, m_source(source)
{
}
inline PyObject* unwrap_base::source() const
{
return m_source;
}
template <class T>
inline unwrapper_base* unwrap_more_<T>::lookup(PyObject* source)
{
// Find the converters registered for T and get a unwrapper
// appropriate for the source object
return registration<T>::unwrapper(source);
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, lookup(source), prev)
, m_storage(0)
{
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source)
: unwrap_base(source, lookup(source))
, m_storage(0)
{
}
# if 0
template <>
inline unwrap_more_<PyObject*>::unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, m_unwrapper, prev)
{
}
template <>
inline unwrap_more_<PyObject*>::unwrap_more_(PyObject* source)
: unwrap_base(source, m_unwrapper)
{
}
template <>
inline PyObject* unwrap_more_<PyObject*>::operator*()
{
return source();
}
template <>
inline bool unwrap_more_<PyObject*>::convertible(PyObject*) const
{
return true;
}
# endif
template <class T>
inline unwrap_<T>::unwrap_(PyObject* source)
: unwrap_more_<T>(source)
{
}
template <class T>
T unwrap_more_<T>::operator*()
{
return static_cast<unwrapper<T>*>(
get_body())->do_conversion(this);
}
template <class T>
unwrap_<T>::~unwrap_()
{
destroy();
}
}}} // namespace boost::python::converter
#endif // UNWRAP_BASE_DWA20011130_HPP

View File

@@ -0,0 +1,53 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAPPER_DWA2001127_HPP
# define UNWRAPPER_DWA2001127_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrap.hpp>
# include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrap_more_;
// Abstract base for all unwrappers of Ts
template <class T>
struct unwrapper : unwrapper_base
{
public:
unwrapper();
T do_conversion(unwrap_more_<T> const* handle) const;
private:
virtual T convert(PyObject*, void*&) const = 0;
private: // body required interface implementation
void destroy_handle(handle*) const {}
};
//
// implementations
//
template <class T>
unwrapper<T>::unwrapper()
: unwrapper_base(type_id<T>())
{
}
// We could think about making this virtual in an effort to get its
// code generated in the module where the unwrapper is defined, but
// it's not clear that it's a good tradeoff.
template <class T>
T unwrapper<T>::do_conversion(unwrap_more_<T> const* handle) const
{
return convert(handle->source(), handle->m_storage);
}
}}} // namespace boost::python::converter
#endif // UNWRAPPER_DWA2001127_HPP

View File

@@ -0,0 +1,25 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAPPER_BASE_DWA20011215_HPP
# define UNWRAPPER_BASE_DWA20011215_HPP
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT unwrapper_base : body
{
public:
unwrapper_base(type_id_t); // registers
~unwrapper_base(); // unregisters
virtual bool convertible(PyObject*) const = 0;
};
}}} // namespace boost::python::converter
#endif // UNWRAPPER_BASE_DWA20011215_HPP

View File

@@ -0,0 +1,145 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef WRAP_DWA2001127_HPP
# define WRAP_DWA2001127_HPP
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/wrapper.hpp>
# include <boost/python/export.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <cassert>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
template <class T> struct wrapper;
struct wrap_base : handle
{
public: // member functions
wrap_base(body*, handle& prev);
wrap_base(body*);
PyObject* release();
public: // accessor, really only for wrappers
PyObject*& target() const;
protected:
void hold_result(PyObject*) const;
private:
mutable PyObject* m_target;
};
template <class T>
struct wrap_more_ : wrap_base
{
protected:
typedef T source_t;
public: // member functions
wrap_more_(handle& prev);
PyObject* operator()(source_t) const;
protected: // constructor for wrap_<T>, below
wrap_more_();
private: // helper functions
static wrapper_base* lookup();
private:
friend class wrapper<T>;
};
template <class T>
struct wrap_ : wrap_more_<T>
{
typedef typename wrap_more_<T>::source_t source_t;
public: // member functions
wrap_();
~wrap_();
};
//
// implementations
//
inline wrap_base::wrap_base(body* body, handle& prev)
: handle(body, prev),
m_target(0)
{
}
inline wrap_base::wrap_base(body* body)
: handle(body),
m_target(0)
{
}
inline PyObject*& wrap_base::target() const
{
return m_target;
}
inline void wrap_base::hold_result(PyObject* p) const
{
assert(m_target == 0);
m_target = p;
}
inline PyObject* wrap_base::release()
{
PyObject* result = m_target;
m_target = 0;
return result;
}
template <class T>
inline wrapper_base* wrap_more_<T>::lookup()
{
// Find the converters registered for T and get a wrapper
// appropriate for the source object
return registration<T>::wrapper();
}
template <class T>
inline wrap_more_<T>::wrap_more_(handle& prev)
: wrap_base(lookup(), prev)
{
}
template <class T>
PyObject* wrap_more_<T>::operator()(source_t x) const
{
return static_cast<wrapper<T>*>(
get_body())->do_conversion(*this, source_holder<T>(x));
}
template <class T>
wrap_more_<T>::wrap_more_()
: wrap_base(lookup())
{
}
template <class T>
wrap_<T>::wrap_()
: wrap_more_<T>()
{
}
template <class T>
wrap_<T>::~wrap_()
{
destroy();
}
}}} // namespace boost::python::converter
#endif // WRAP_DWA2001127_HPP

View File

@@ -0,0 +1,69 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef WRAPPER_DWA2001127_HPP
# define WRAPPER_DWA2001127_HPP
# include <boost/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct source_holder_base;
struct wrap_base;
template <class T> struct wrap_more_;
struct BOOST_PYTHON_EXPORT wrapper_base : body
{
public:
wrapper_base(type_id_t); // registers
~wrapper_base(); // unregisters
virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0;
};
template <class T>
struct wrapper : wrapper_base
{
public:
wrapper();
PyObject* do_conversion(wrap_base const&, source_holder_base const&) const;
// This does the actual conversion
virtual PyObject* convert(T source) const = 0;
};
//
// implementations
//
template <class T>
wrapper<T>::wrapper()
: wrapper_base(type_id<T>())
{
}
template <class T>
PyObject* wrapper<T>::do_conversion(wrap_base const& handle_, source_holder_base const& data_) const
{
// Casting pointers instead of references suppresses a CWPro7 bug.
wrap_more_<T> const& handle = *static_cast<wrap_more_<T> const*>(&handle_);
source_holder<T> const& data = *static_cast<source_holder<T> const*>(&data_);
if (handle.target() == 0)
{
handle.hold_result(convert(data.value));
}
return handle.target();
}
}}} // namespace boost::python::converter
#endif // WRAPPER_DWA2001127_HPP

View File

@@ -0,0 +1,233 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for 5-argument member functions and 6-argument free
// functions by gen_arg_tuple_size.python
#ifndef ARG_TUPLE_SIZE_DWA20011201_HPP
# define ARG_TUPLE_SIZE_DWA20011201_HPP
namespace boost { namespace python { namespace detail {
// Computes (at compile-time) the number of elements that a Python
// argument tuple must have in order to be passed to a wrapped C++
// (member) function of the given type.
template <class F> struct arg_tuple_size;
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__BORLANDC__)
template <class R>
struct arg_tuple_size<R (*)()>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 0);
};
template <class R, class A1>
struct arg_tuple_size<R (*)(A1)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
};
template <class R, class A1, class A2>
struct arg_tuple_size<R (*)(A1, A2)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 2);
};
template <class R, class A1, class A2, class A3>
struct arg_tuple_size<R (*)(A1, A2, A3)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 3);
};
template <class R, class A1, class A2, class A3, class A4>
struct arg_tuple_size<R (*)(A1, A2, A3, A4)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 4);
};
template <class R, class A1, class A2, class A3, class A4, class A5>
struct arg_tuple_size<R (*)(A1, A2, A3, A4, A5)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 5);
};
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
struct arg_tuple_size<R (*)(A1, A2, A3, A4, A5, A6)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 6);
};
template <class R, class A0>
struct arg_tuple_size<R (A0::*)()>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
};
template <class R, class A0, class A1>
struct arg_tuple_size<R (A0::*)(A1)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 2);
};
template <class R, class A0, class A1, class A2>
struct arg_tuple_size<R (A0::*)(A1, A2)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 3);
};
template <class R, class A0, class A1, class A2, class A3>
struct arg_tuple_size<R (A0::*)(A1, A2, A3)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 4);
};
template <class R, class A0, class A1, class A2, class A3, class A4>
struct arg_tuple_size<R (A0::*)(A1, A2, A3, A4)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 5);
};
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
struct arg_tuple_size<R (A0::*)(A1, A2, A3, A4, A5)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 6);
};
# else
// We will use the "sizeof() trick" to work around the lack of
// partial specialization in MSVC6 and its broken-ness in borland.
// See http://opensource.adobe.com or
// http://groups.yahoo.com/group/boost/message/5441 for
// more examples
// This little package is used to transmit the number of arguments
// from the helper functions below to the sizeof() expression below.
// Because we can never have an array of fewer than 1 element, we
// add 1 to n and then subtract 1 from the result of sizeof() below.
template <int n>
struct char_array
{
char elements[n+1];
};
// The following helper functions are never actually called, since
// they are only used within a sizeof() expression, but the type of
// their return value is used to discriminate between various free
// and member function pointers at compile-time.
template <class R>
char_array<0> arg_tuple_size_helper(R (*)());
template <class R, class A1>
char_array<1> arg_tuple_size_helper(R (*)(A1));
template <class R, class A1, class A2>
char_array<2> arg_tuple_size_helper(R (*)(A1, A2));
template <class R, class A1, class A2, class A3>
char_array<3> arg_tuple_size_helper(R (*)(A1, A2, A3));
template <class R, class A1, class A2, class A3, class A4>
char_array<4> arg_tuple_size_helper(R (*)(A1, A2, A3, A4));
template <class R, class A1, class A2, class A3, class A4, class A5>
char_array<5> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5));
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
char_array<6> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5, A6));
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)());
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1));
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2));
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3));
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4));
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5));
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)() const);
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const);
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const);
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const);
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const);
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const);
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)() volatile);
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) volatile);
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) volatile);
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) volatile);
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) volatile);
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) volatile);
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)() const volatile);
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const volatile);
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const volatile);
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const volatile);
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const volatile);
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const volatile);
template <class F>
struct arg_tuple_size
{
// The sizeof() magic happens here
BOOST_STATIC_CONSTANT(std::size_t, value
= sizeof(arg_tuple_size_helper(F(0)).elements) - 1);
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
}}} // namespace boost::python::detail
#endif // ARG_TUPLE_SIZE_DWA20011201_HPP

View File

@@ -1,62 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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));
ob_refcnt = 1;
ob_type = type_obj;
Py_INCREF(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_

View File

@@ -0,0 +1,27 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CALLER_DWA20011214_HPP
# define CALLER_DWA20011214_HPP
# include <boost/python/call.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace detail {
struct caller
{
typedef PyObject* result_type;
template <class F>
PyObject* operator()(F f, PyObject* args, PyObject* keywords)
{
return call(f, args, keywords);
}
};
}}} // namespace boost::python::detail
#endif // CALLER_DWA20011214_HPP

View File

@@ -1,81 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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_

View File

@@ -1,56 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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 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.
# if defined(BOOST_MSVC6_OR_EARLIER) && !defined(__STLPORT)
# define BOOST_CSTD_
# else
# define BOOST_CSTD_ std
# endif
#endif // CONFIG_DWA052200_H_

View File

@@ -1,834 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file automatically generated for 5-argument constructors by
// gen_extclass.python
#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>
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 T> 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;
};
}}} // 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();
}
// Convert to T*
friend T* 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 PtrType, where PtrType can be dereferenced to obtain a T.
template <class PtrType>
static PtrType& ptr_from_python(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();
}
template <class PtrType>
static PyObject* ptr_to_python(PtrType x)
{
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(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 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 ptr_from_python(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> >()); }
friend PyObject* to_python(std::auto_ptr<T> x)
{ return 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> >()); }
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<const boost::shared_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
friend PyObject* to_python(boost::shared_ptr<T> x)
{ return 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>
inline void def(constructor<A1, A2, A3, A4, A5>)
// 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(),
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 T>
class held_instance : public T
{
// There are no member functions: we want to avoid inadvertently overriding
// any virtual functions in T.
public:
held_instance(PyObject*) : T() {}
template <class A1>
held_instance(PyObject*, A1 a1) : T(a1) {}
template <class A1, class A2>
held_instance(PyObject*, A1 a1, A2 a2) : T(a1, a2) {}
template <class A1, class A2, class A3>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {}
};
// 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) {}
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
//
tuple extension_class_coerce(ref l, ref r);
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(&extension_class_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_

View File

@@ -1,306 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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_

View File

@@ -1,507 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// 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_

View File

@@ -1,21 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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_

View File

@@ -0,0 +1,846 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for 5-argument member functions and 6-argument free
// functions by gen_returning.py
#ifndef RETURNING_DWA20011201_HPP
# define RETURNING_DWA20011201_HPP
//# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/config.hpp>
# include <boost/python/convert.hpp>
# include <boost/python/detail/none.hpp>
namespace boost { namespace python { namespace detail {
// Calling C++ from Python
template <class R>
struct returning
{
template <class A0>
static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
template <class A0>
static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
template <class A0>
static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
// missing const volatile type traits
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class A0>
static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ )
{
// find the result converter
wrap<R> r;
return r( (*pf)() );
};
template <class A0>
static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( (*pf)(*c0) );
};
template <class A0, class A1>
static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( (*pf)(*c0, *c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) );
};
};
template <>
struct returning<void>
{
typedef void R;
template <class A0>
static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
template <class A0>
static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
template <class A0>
static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
// missing const volatile type traits
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class A0>
static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ )
{
(*pf)();
return detail::none();
};
template <class A0>
static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
(*pf)(*c0);
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
(*pf)(*c0, *c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2, *c3, *c4, *c5);
return detail::none();
};
};
}}} // namespace boost::python::detail
#endif // RETURNING_DWA20011201_HPP

View File

@@ -1,251 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// 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

View File

@@ -1,68 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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

View File

@@ -1,389 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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_

View File

@@ -1,61 +0,0 @@
#ifdef _DEBUG
# ifndef 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>
# define HAVE_CLOCK
# define HAVE_STRFTIME
# define HAVE_STRERROR
# 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
# 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

View File

@@ -1,30 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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_

View File

@@ -0,0 +1,20 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef EXPORT_DWA20011120_HPP
# define EXPORT_DWA20011120_HPP
# include <boost/config.hpp>
# include <boost/preprocessor/if.hpp>
# include <boost/preprocessor/cat.hpp>
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# ifndef BOOST_PYTHON_EXPORT
# define BOOST_PYTHON_EXPORT __declspec(dllimport)
# endif
# else
# define BOOST_PYTHON_EXPORT
# endif
#endif // EXPORT_DWA20011120_HPP

View File

@@ -0,0 +1,41 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_FUNCTION_DWA20011214_HPP
# define MAKE_FUNCTION_DWA20011214_HPP
# include <boost/bind.hpp>
# include <boost/python/object/function.hpp>
# include <boost/python/object/make_holder.hpp>
# include <boost/python/detail/caller.hpp>
# include <boost/mpl/size.hpp>
namespace boost { namespace python {
template <class F>
PyObject* make_function(F f)
{
return new object::function(
object::py_function(
bind<PyObject*>(detail::caller(), f, _1, _2)));
}
template <class T, class ArgList, class Generator>
PyObject* make_constructor(T* = 0, ArgList* = 0, Generator* = 0)
{
return new object::function(
object::py_function(
bind<PyObject*>(detail::caller()
, object::make_holder<
mpl::size<ArgList>::value
>::template apply<
T, Generator, ArgList
>::execute
, _1, _2)));
}
}} // namespace boost::python
#endif // MAKE_FUNCTION_DWA20011214_HPP

View File

@@ -0,0 +1,37 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MODULE_DWA2001128_HPP
# define MODULE_DWA2001128_HPP
# include <boost/config.hpp>
#if defined(_WIN32) || defined(__CYGWIN__)
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
extern "C" __declspec(dllexport) void init##name() \
{ \
/*boost::python::handle_exception(*/init_module_##name()/*)*/; \
} \
void init_module_##name()
#else
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
extern "C" void init##name() \
{ \
/*boost::python::handle_exception(*/init_module_##name()/*)*/; \
} \
void init_module_##name()
#endif
namespace boost { namespace python {
}} // namespace boost::python
#endif // MODULE_DWA2001128_HPP

View File

@@ -1,53 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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
{
typedef PyObject * (*raw_function_ptr)(boost::python::tuple const &, boost::python::dictionary const &);
public:
// Create a module. REQUIRES: only one module_builder is created per module.
module_builder(const char* name);
// 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);
}
static string name();
private:
PyObject* m_module;
static PyMethodDef initial_methods[1];
};
}} // namespace boost::python
#endif

View File

@@ -0,0 +1,76 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CLASS_DWA20011214_HPP
# define CLASS_DWA20011214_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# include <boost/utility.hpp>
# include <boost/python/converter/type_id.hpp>
namespace boost { namespace python { namespace object {
template <class T> struct holder;
// Base class for all holders
struct BOOST_PYTHON_EXPORT holder_base : noncopyable
{
public:
holder_base(converter::type_id_t id);
virtual ~holder_base();
virtual bool held_by_value() const = 0;
holder_base* next() const;
converter::type_id_t type() const;
void install(PyObject* inst);
private:
converter::type_id_t m_type;
holder_base* m_next;
};
// Abstract base class which holds a Held, somehow. Provides a uniform
// way to get a pointer to the held object
template <class Held>
struct holder : holder_base
{
typedef Held held_type;
holder();
virtual Held* target() = 0;
};
// Each extension instance will be one of these
struct instance
{
PyObject_HEAD
holder_base* objects;
};
extern BOOST_PYTHON_EXPORT PyTypeObject class_metatype;
extern BOOST_PYTHON_EXPORT PyTypeObject class_type;
//
// implementation
//
inline holder_base* holder_base::next() const
{
return m_next;
}
inline converter::type_id_t holder_base::type() const
{
return m_type;
}
template <class Held>
holder<Held>::holder()
: holder_base(converter::type_id<Held>())
{
}
}}} // namespace boost::python::object
#endif // CLASS_DWA20011214_HPP

View File

@@ -0,0 +1,24 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONSTRUCT_DWA20011215_HPP
# define CONSTRUCT_DWA20011215_HPP
namespace boost { namespace python { namespace object {
template <class T, class ArgList>
struct construct
{
static
template <class
void operator()(PyObject* args, PyObject* keywords)
{
}
};
}}} // namespace boost::python::object
#endif // CONSTRUCT_DWA20011215_HPP

View File

@@ -0,0 +1,33 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef FORWARD_DWA20011215_HPP
# define FORWARD_DWA20011215_HPP
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
namespace boost { namespace python { namespace object {
// A little metaprogram which selects the type to pass through an
// intermediate forwarding function when the destination argument type
// is T.
template <class T>
struct forward
{
typedef typename mpl::select_type<
is_scalar<T>::value | is_reference<T>::value
, T
, reference_wrapper<
typename add_const<T>::type
>
>::type type;
};
}}} // namespace boost::python::object
#endif // FORWARD_DWA20011215_HPP

View File

@@ -0,0 +1,36 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef FUNCTION_DWA20011214_HPP
# define FUNCTION_DWA20011214_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# include <boost/function.hpp>
namespace boost { namespace python { namespace object {
// We use boost::function to avoid generating lots of virtual tables
typedef boost::function2<PyObject*, PyObject*, PyObject*> py_function;
struct BOOST_PYTHON_EXPORT function : PyObject
{
function(py_function);
~function();
PyObject* call(PyObject*, PyObject*) const;
private:
py_function m_fn;
};
extern BOOST_PYTHON_EXPORT PyTypeObject function_type;
//
// implementations
//
}}} // namespace boost::python::object
#endif // FUNCTION_DWA20011214_HPP

View File

@@ -0,0 +1,124 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_HOLDER_DWA20011215_HPP
# define MAKE_HOLDER_DWA20011215_HPP
# include <boost/mpl/at.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/python/object/class.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace object {
template <class T> struct undefined;
template <class UnaryMetaFunction, class T>
struct eval
{
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
// based on the (non-conforming) MSVC trick from MPL
template<bool>
struct unarymetafunction_vc : UnaryMetaFunction {};
// illegal C++ which causes VC to admit that unarymetafunction_vc
// can have a nested template:
template<>
struct unarymetafunction_vc<true>
{
template<class> struct apply;
};
typedef typename unarymetafunction_vc<
::boost::mpl::detail::msvc_never_true<UnaryMetaFunction>::value
>::template apply<T>::type type;
# else
typedef typename UnaryMetaFunction::template apply<T>::type type;
# endif
};
template <int nargs> struct make_holder;
template <>
struct make_holder<0>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
static void execute(
PyObject* p)
{
(new holder(p))->install(p);
}
};
};
template <>
struct make_holder<1>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
static void execute(
PyObject* p
, t0 a0)
{
(new holder(p, f0(a0)))->install(p);
}
};
};
template <>
struct make_holder<2>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
typedef typename mpl::at<1,ArgList>::type t1;
typedef typename forward<t1>::type f1;
static void execute(
PyObject* p, t0 a0, t1 a1)
{
(new holder(p, f0(a0), f1(a1)))->install(p);
}
};
};
template <>
struct make_holder<3>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
typedef typename mpl::at<1,ArgList>::type t1;
typedef typename forward<t1>::type f1;
typedef typename mpl::at<2,ArgList>::type t2;
typedef typename forward<t2>::type f2;
static void execute(
PyObject* p, t0 a0, t1 a1, t2 a2)
{
(new holder(p, f0(a0), f1(a1), f2(a2)))->install(p);
}
};
};
}}} // namespace boost::python::object
#endif // MAKE_HOLDER_DWA20011215_HPP

View File

@@ -0,0 +1,80 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef VALUE_HOLDER_DWA20011215_HPP
# define VALUE_HOLDER_DWA20011215_HPP
# include <boost/python/object/class.hpp>
namespace boost { namespace python { namespace object {
template <class Held>
struct value_holder : holder<Held>
{
// Forward construction to the held object
value_holder(PyObject*)
: m_held() {}
template <class A1>
value_holder(PyObject*, A1 a1)
: m_held(a1) {}
template <class A1, class A2>
value_holder(PyObject*, A1 a1, A2 a2)
: m_held(a1, a2) {}
template <class A1, class A2, class A3>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3)
: m_held(a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4)
: m_held(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
: m_held(a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
: m_held(a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
: m_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>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
: m_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>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
: m_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>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
: m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
private: // required holder implementation
Held* target() { return &m_held; }
bool held_by_value() const { return true; }
private: // data members
Held m_held;
};
// A generator metafunction which can be passed to make_holder
struct value_holder_generator
{
template <class Held>
struct apply
{
typedef value_holder<Held> type;
};
};
}}} // namespace boost::python::object
#endif // VALUE_HOLDER_DWA20011215_HPP

View File

@@ -1,334 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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_

View File

@@ -1,504 +0,0 @@
#ifndef OPERATORS_UK112000_H_
#define OPERATORS_UK112000_H_
#include <boost/python/detail/functions.hpp>
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
# include <sstream>
#else
# include <strstream>
#endif
namespace boost { namespace python {
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__"; }
};
// 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));
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
std::ostringstream s;
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>());
#else
std::ostrstream s;
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()) << char();
#endif
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
return BOOST_PYTHON_CONVERSION::to_python(s.str());
#else
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
#endif /* OPERATORS_UK112000_H_ */

View File

@@ -1,173 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#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_

View File

@@ -1,884 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/classes.hpp>
#include <boost/python/detail/functions.hpp>
#include <boost/python/detail/singleton.hpp>
#include <cstddef>
#include <boost/python/callback.hpp>
#include <cstring>
#include <boost/python/module_builder.hpp>
namespace boost { namespace python {
namespace detail {
void enable_named_method(boost::python::detail::class_base* type_obj, const char* name);
}
namespace {
// Add the name of the module currently being loaded to the name_space with the
// key "__module__". If no module is being loaded, or if name_space already has
// a key "__module", has no effect. This is not really a useful public
// interface; it's just used for class_t<>::class_t() below.
void add_current_module_name(dictionary&);
bool is_prefix(const char* s1, const char* s2);
bool is_special_name(const char* name);
void enable_special_methods(boost::python::detail::class_base* derived, const tuple& bases, const dictionary& name_space);
void report_ignored_exception(PyObject* source)
{
// This bit of code copied wholesale from classobject.c in the Python source.
PyObject *f, *t, *v, *tb;
PyErr_Fetch(&t, &v, &tb);
f = PySys_GetObject(const_cast<char*>("stderr"));
if (f != NULL)
{
PyFile_WriteString(const_cast<char*>("Exception "), f);
if (t) {
PyFile_WriteObject(t, f, Py_PRINT_RAW);
if (v && v != Py_None) {
PyFile_WriteString(const_cast<char*>(": "), f);
PyFile_WriteObject(v, f, 0);
}
}
PyFile_WriteString(const_cast<char*>(" in "), f);
PyFile_WriteObject(source, f, 0);
PyFile_WriteString(const_cast<char*>(" ignored\n"), f);
PyErr_Clear(); /* Just in case */
}
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
}
//
// pickle support courtesy of "Ralf W. Grosse-Kunstleve" <rwgk@cci.lbl.gov>
//
PyObject* class_reduce(PyObject* klass)
{
return PyObject_GetAttrString(klass, const_cast<char*>("__name__"));
}
ref global_class_reduce()
{
static ref result(detail::new_wrapped_function(class_reduce));
return result;
}
tuple instance_reduce(PyObject* obj)
{
ref instance_class(PyObject_GetAttrString(obj, const_cast<char*>("__class__")));
ref getinitargs(PyObject_GetAttrString(obj, const_cast<char*>("__getinitargs__")),
ref::null_ok);
PyErr_Clear();
ref initargs;
if (getinitargs.get() != 0)
{
initargs = ref(PyEval_CallObject(getinitargs.get(), NULL));
initargs = ref(PySequence_Tuple(initargs.get()));
}
else
{
initargs = ref(PyTuple_New(0));
}
ref getstate(PyObject_GetAttrString(obj, const_cast<char*>("__getstate__")),
ref::null_ok);
PyErr_Clear();
if (getstate.get() != 0)
{
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)
{
return tuple(instance_class, initargs, state);
}
return tuple(instance_class, initargs);
}
ref global_instance_reduce()
{
static ref result(detail::new_wrapped_function(instance_reduce));
return result;
}
}
namespace detail {
class_base::class_base(PyTypeObject* meta_class_obj, string name, tuple bases, const dictionary& name_space)
: type_object_base(meta_class_obj),
m_name(name),
m_bases(bases),
m_name_space(name_space)
{
this->tp_name = const_cast<char*>(name.c_str());
enable(type_object_base::getattr);
enable(type_object_base::setattr);
add_current_module_name(m_name_space);
static const boost::python::string docstr("__doc__", boost::python::string::interned);
if (PyDict_GetItem(m_name_space.get(), docstr.get())== 0)
{
PyDict_SetItem(m_name_space.get(), docstr.get(), Py_None);
}
enable_special_methods(this, bases, name_space);
}
void class_base::add_base(ref base)
{
tuple new_bases(m_bases.size() + 1);
for (std::size_t i = 0; i < m_bases.size(); ++i)
new_bases.set_item(i, m_bases[i]);
new_bases.set_item(m_bases.size(), base);
m_bases = new_bases;
}
PyObject* class_base::getattr(const char* name)
{
if (!BOOST_CSTD_::strcmp(name, "__dict__"))
{
PyObject* result = m_name_space.get();
Py_INCREF(result);
return result;
}
if (!BOOST_CSTD_::strcmp(name, "__bases__"))
{
PyObject* result = m_bases.get();
Py_INCREF(result);
return result;
}
if (!BOOST_CSTD_::strcmp(name, "__name__"))
{
PyObject* result = m_name.get();
Py_INCREF(result);
return result;
}
// pickle support courtesy of "Ralf W. Grosse-Kunstleve" <rwgk@cci.lbl.gov>
if (!BOOST_CSTD_::strcmp(name, "__safe_for_unpickling__"))
{
return PyInt_FromLong(1);
}
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
{
ref target(as_object(this), ref::increment_count);
return new bound_function(target, global_class_reduce());
}
ref local_attribute = m_name_space.get_item(string(name).reference());
if (local_attribute.get())
return local_attribute.release();
// In case there are no bases...
PyErr_SetString(PyExc_AttributeError, name);
// Check bases
for (std::size_t i = 0; i < m_bases.size(); ++i)
{
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear(); // we're going to try a base class
else if (PyErr_Occurred())
break; // Other errors count, though!
PyObject* base_attribute = PyObject_GetAttrString(m_bases[i].get(), const_cast<char*>(name));
if (base_attribute != 0)
{
// Unwind the actual underlying function from unbound Python class
// methods in case of multiple inheritance from real Python
// classes. Python stubbornly insists that the first argument to a
// method must be a true Python instance object otherwise. Do not
// unwrap bound methods; that would interfere with intended semantics.
if (PyMethod_Check(base_attribute)
&& reinterpret_cast<PyMethodObject*>(base_attribute)->im_self == 0)
{
PyObject* function
= reinterpret_cast<PyMethodObject*>(base_attribute)->im_func;
Py_INCREF(function);
Py_DECREF(base_attribute);
return function;
}
else
{
return base_attribute;
}
}
}
return 0;
}
// Mostly copied wholesale from Python's classobject.c
PyObject* class_base::repr() const
{
PyObject *mod = PyDict_GetItemString(
m_name_space.get(), const_cast<char*>("__module__"));
unsigned long address = reinterpret_cast<unsigned long>(this);
string result = (mod == NULL || !PyString_Check(mod))
? string("<extension class %s at %lx>") % tuple(m_name, address)
: string("<extension class %s.%s at %lx>") % tuple(ref(mod, ref::increment_count), m_name, address);
return result.reference().release();
}
int class_base::setattr(const char* name, PyObject* value)
{
if (is_special_name(name)
&& BOOST_CSTD_::strcmp(name, "__doc__") != 0
&& BOOST_CSTD_::strcmp(name, "__name__") != 0)
{
boost::python::string message("Special attribute names other than '__doc__' and '__name__' are read-only, in particular: ");
PyErr_SetObject(PyExc_TypeError, (message + name).get());
throw error_already_set();
}
if (PyCallable_Check(value))
detail::enable_named_method(this, name);
return PyDict_SetItemString(
m_name_space.reference().get(), const_cast<char*>(name), value);
}
bool class_base::initialize_instance(instance* obj, PyObject* args, PyObject* keywords)
{
// Getting the init function off the obj should result in a
// bound method.
PyObject* const init_function = obj->getattr("__init__", false);
if (init_function == 0)
{
if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear(); // no __init__? That's legal.
}
else {
return false; // Something else? Keep the error
}
}
else
{
// Manage the reference to the bound function
ref init_function_holder(init_function);
// Declare a ref to manage the result of calling __init__ (which should be None).
ref init_result(
PyEval_CallObjectWithKeywords(init_function, args, keywords));
}
return true;
}
void class_base::instance_dealloc(PyObject* obj) const
{
Py_INCREF(obj); // This allows a __del__ function to revive the obj
PyObject* exc_type;
PyObject* exc_value;
PyObject* exc_traceback;
PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
// This scope ensures that the reference held by del_function doesn't release
// the last reference and delete the object recursively (infinitely).
{
ref del_function;
try {
instance* const target = boost::python::downcast<boost::python::instance>(obj);
del_function = ref(target->getattr("__del__", false), ref::null_ok);
}
catch(...) {
}
if (del_function.get() != 0)
{
ref result(PyEval_CallObject(del_function.get(), (PyObject *)NULL), ref::null_ok);
if (result.get() == NULL)
report_ignored_exception(del_function.get());
}
}
PyErr_Restore(exc_type, exc_value, exc_traceback);
if (--obj->ob_refcnt <= 0)
delete_instance(obj);
}
}
instance::instance(PyTypeObject* class_)
: boost::python::detail::base_object<PyObject>(class_)
{
}
instance::~instance()
{
}
PyObject* instance::getattr(const char* name, bool use_special_function)
{
if (!BOOST_CSTD_::strcmp(name, "__dict__"))
{
if (PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError,
"instance.__dict__ not accessible in restricted mode");
return 0;
}
Py_INCREF(m_name_space.get());
return m_name_space.get();
}
if (!BOOST_CSTD_::strcmp(name, "__class__"))
{
Py_INCREF(this->ob_type);
return as_object(this->ob_type);
}
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
{
return new detail::bound_function(ref(this, ref::increment_count), global_instance_reduce());
}
ref local_attribute = m_name_space.get_item(string(name).reference());
if (local_attribute.get())
return local_attribute.release();
// Check its class.
PyObject* function =
PyObject_GetAttrString(as_object(this->ob_type), const_cast<char*>(name));
if (function == 0 && !use_special_function)
{
return 0;
}
ref class_attribute;
if (function != 0)
{
// This will throw if the attribute wasn't found
class_attribute = ref(function);
}
else
{
// Clear the error while we try special methods method (if any).
PyErr_Clear();
// First we try the special method that comes from concatenating
// "__getattr__" and <name> and 2 trailing underscores. This is an
// extension to regular Python class functionality.
const string specific_getattr_name(detail::getattr_string() + name + "__");
PyObject* getattr_method = PyObject_GetAttr(
as_object(this->ob_type), specific_getattr_name.get());
// Use just the first arg to PyEval_CallFunction if found
char* arg_format = const_cast<char*>("(O)");
// Try for the regular __getattr__ method if not found
if (getattr_method == 0)
{
PyErr_Clear();
getattr_method = PyObject_GetAttrString(
as_object(this->ob_type), const_cast<char*>("__getattr__"));
// Use both args to PyEval_CallFunction
arg_format = const_cast<char*>("(Os)");
}
// If there is no such method, throw now.
if (PyErr_Occurred())
{
PyErr_SetString(PyExc_AttributeError, name);
return 0;
}
// Take ownership of the method
ref owner(getattr_method);
// Call it to get the attribute.
return PyEval_CallFunction(getattr_method, arg_format, this, name);
}
if (!PyCallable_Check(class_attribute.get()))
{
PyErr_Clear();
return class_attribute.release();
}
else
{
return detail::bound_function::create(ref(this, ref::increment_count), class_attribute);
}
}
// instance::setattr_dict
//
// Implements setattr() functionality for the "__dict__" attribute
//
int instance::setattr_dict(PyObject* value)
{
if (PyEval_GetRestricted())
{
PyErr_SetString(PyExc_RuntimeError,
"__dict__ not accessible in restricted mode");
return -1;
}
if (value == 0 || !PyDict_Check(value))
{
PyErr_SetString(PyExc_TypeError,
"__dict__ must be set to a dictionary");
return -1;
}
m_name_space = dictionary(ref(value, ref::increment_count));
return 0;
}
// instance::setattr -
//
// Implements the setattr() and delattr() functionality for our own instance
// objects, using the standard Python interface: if value == 0, we are deleting
// the attribute, and returns 0 unless an error occurred.
int instance::setattr(const char* name, PyObject* value)
{
if (BOOST_CSTD_::strcmp(name, "__class__") == 0)
{
PyErr_SetString(PyExc_TypeError, "__class__ attribute is read-only");
throw error_already_set();
}
if (BOOST_CSTD_::strcmp(name, "__dict__") == 0)
return setattr_dict(value);
// Try to find an appropriate "specific" setter or getter method, either
// __setattr__<name>__(value) or __delattr__<name>__(). This is an extension
// to regular Python class functionality.
const string& base_name = value ? detail::setattr_string() : detail::delattr_string();
const string specific_method_name(base_name + name + "__");
ref special_method(
PyObject_GetAttr(as_object(this->ob_type), specific_method_name.get()),
ref::null_ok);
PyObject* result_object = 0;
if (special_method.get() != 0)
{
// The specific function was found; call it now. Note that if value is
// not included in the format string, it is ignored.
char* format_string = const_cast<char*>(value ? "(OO)" : "(O)");
result_object = PyEval_CallFunction(special_method.get(), format_string, this, value);
}
else
{
// If not found, try the usual __setattr__(name, value) or
// __delattr__(name) functions.
PyErr_Clear();
special_method.reset(
PyObject_GetAttr(as_object(this->ob_type), base_name.get()),
ref::null_ok);
if (special_method.get() != 0)
{
// The special function was found; call it now. Note that if value
// is not included in the format string, it is ignored.
char* format_string = const_cast<char*>(value ? "(OsO)" : "(Os)");
result_object = PyEval_CallFunction(
special_method.get(), format_string, this, name, value);
}
}
// If we found an appropriate special method, handle the return value.
if (special_method.get() != 0)
{
ref manage_result(result_object);
return 0;
}
PyErr_Clear(); // Nothing was found; clear the python error state
if (value == 0) // Try to remove the attribute from our name space
{
const int result = PyDict_DelItemString(m_name_space.reference().get(),
const_cast<char*>(name));
if (result < 0)
{
PyErr_Clear();
PyErr_SetString(PyExc_AttributeError, "delete non-existing instance attribute");
}
return result;
}
else // Change the specified item in our name space
{
return PyDict_SetItemString(m_name_space.reference().get(),
const_cast<char*>(name), value);
}
}
PyObject* instance::call(PyObject* args, PyObject* keywords)
{
return PyEval_CallObjectWithKeywords(
ref(getattr("__call__")).get(), // take possession of the result from getattr()
args, keywords);
}
PyObject* instance::repr()
{
return callback<PyObject*>::call_method(this, "__repr__");
}
int instance::compare(PyObject* other)
{
return callback<int>::call_method(this, "__cmp__", other);
}
PyObject* instance::str()
{
return callback<PyObject*>::call_method(this, "__str__");
}
long instance::hash()
{
return callback<long>::call_method(this, "__hash__");
}
int instance::length()
{
return callback<int>::call_method(this, "__len__");
}
PyObject* instance::get_subscript(PyObject* key)
{
return callback<PyObject*>::call_method(this, "__getitem__", key);
}
void instance::set_subscript(PyObject* key, PyObject* value)
{
if (value == 0)
callback<void>::call_method(this, "__delitem__", key);
else
callback<void>::call_method(this, "__setitem__", key, value);
}
PyObject* instance::get_slice(int start, int finish)
{
return callback<PyObject*>::call_method(this, "__getslice__", start, finish);
}
void instance::set_slice(int start, int finish, PyObject* value)
{
if (value == 0)
callback<void>::call_method(this, "__delslice__", start, finish);
else
callback<void>::call_method(this, "__setslice__", start, finish, value);
}
PyObject* instance::add(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__add__", other);
}
PyObject* instance::subtract(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__sub__", other);
}
PyObject* instance::multiply(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__mul__", other);
}
PyObject* instance::divide(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__div__", other);
}
PyObject* instance::remainder(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__mod__", other);
}
PyObject* instance::divmod(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__divmod__", other);
}
PyObject* instance::power(PyObject* exponent, PyObject* modulus)
{
if (as_object(modulus->ob_type) == Py_None)
return callback<PyObject*>::call_method(this, "__pow__", exponent);
else
return callback<PyObject*>::call_method(this, "__pow__", exponent, modulus);
}
PyObject* instance::negative()
{
return callback<PyObject*>::call_method(this, "__neg__");
}
PyObject* instance::positive()
{
return callback<PyObject*>::call_method(this, "__pos__");
}
PyObject* instance::absolute()
{
return callback<PyObject*>::call_method(this, "__abs__");
}
int instance::nonzero()
{
return callback<bool>::call_method(this, "__nonzero__");
}
PyObject* instance::invert()
{
return callback<PyObject*>::call_method(this, "__invert__");
}
PyObject* instance::lshift(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__lshift__", other);
}
PyObject* instance::rshift(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__rshift__", other);
}
PyObject* instance::do_and(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__and__", other);
}
PyObject* instance::do_xor(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__xor__", other);
}
PyObject* instance::do_or(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__or__", other);
}
int instance::coerce(PyObject** x, PyObject** y)
{
assert(this == *x);
// Coerce must return a tuple
tuple result(callback<tuple>::call_method(this, "__coerce__", *y));
*x = result[0].release();
*y = result[1].release();
return 0;
}
PyObject* instance::as_int()
{
return callback<PyObject*>::call_method(this, "__int__");
}
PyObject* instance::as_long()
{
return callback<PyObject*>::call_method(this, "__long__");
}
PyObject* instance::as_float()
{
return callback<PyObject*>::call_method(this, "__float__");
}
PyObject* instance::oct()
{
return callback<PyObject*>::call_method(this, "__oct__");
}
PyObject* instance::hex()
{
return callback<PyObject*>::call_method(this, "__hex__");
}
namespace {
struct named_capability
{
const char* name;
detail::type_object_base::capability capability;
};
const named_capability enablers[] =
{
{ "__hash__", detail::type_object_base::hash },
{ "__cmp__", detail::type_object_base::compare },
{ "__repr__", detail::type_object_base::repr },
{ "__str__", detail::type_object_base::str },
{ "__call__", detail::type_object_base::call },
{ "__getattr__", detail::type_object_base::getattr },
{ "__setattr__", detail::type_object_base::setattr },
{ "__len__", detail::type_object_base::mapping_length },
{ "__len__", detail::type_object_base::sequence_length },
{ "__getitem__", detail::type_object_base::mapping_subscript },
{ "__getitem__", detail::type_object_base::sequence_item },
{ "__setitem__", detail::type_object_base::mapping_ass_subscript },
{ "__setitem__", detail::type_object_base::sequence_ass_item },
{ "__delitem__", detail::type_object_base::mapping_ass_subscript },
{ "__delitem__", detail::type_object_base::sequence_ass_item },
{ "__getslice__", detail::type_object_base::sequence_slice },
{ "__setslice__", detail::type_object_base::sequence_ass_slice },
{ "__delslice__", detail::type_object_base::sequence_ass_slice },
{ "__add__", detail::type_object_base::number_add },
{ "__sub__", detail::type_object_base::number_subtract },
{ "__mul__", detail::type_object_base::number_multiply },
{ "__div__", detail::type_object_base::number_divide },
{ "__mod__", detail::type_object_base::number_remainder },
{ "__divmod__", detail::type_object_base::number_divmod },
{ "__pow__", detail::type_object_base::number_power },
{ "__neg__", detail::type_object_base::number_negative },
{ "__pos__", detail::type_object_base::number_positive },
{ "__abs__", detail::type_object_base::number_absolute },
{ "__nonzero__", detail::type_object_base::number_nonzero },
{ "__invert__", detail::type_object_base::number_invert },
{ "__lshift__", detail::type_object_base::number_lshift },
{ "__rshift__", detail::type_object_base::number_rshift },
{ "__and__", detail::type_object_base::number_and },
{ "__xor__", detail::type_object_base::number_xor },
{ "__or__", detail::type_object_base::number_or },
{ "__coerce__", detail::type_object_base::number_coerce },
{ "__int__", detail::type_object_base::number_int },
{ "__long__", detail::type_object_base::number_long },
{ "__float__", detail::type_object_base::number_float },
{ "__oct__", detail::type_object_base::number_oct },
{ "__hex__", detail::type_object_base::number_hex }
};
bool is_prefix(const char* s1, const char* s2)
{
while (*s1 != 0 && *s2 != 0 && *s1 == *s2)
++s1, ++s2;
return *s1 == 0;
}
bool is_special_name(const char* name)
{
if (name[0] != '_' || name[1] != '_' || name[2] == 0 || name[3] == 0)
return false;
std::size_t name_length = BOOST_CSTD_::strlen(name);
return name[name_length - 1] == '_' && name[name_length - 2] == '_';
}
}
namespace detail {
// Enable the special handler for methods of the given name, if any.
void enable_named_method(boost::python::detail::class_base* type_obj, const char* name)
{
const std::size_t num_enablers = sizeof(enablers) / sizeof(enablers[0]);
// Make sure this ends with "__" since we'll only compare the head of the
// string. This is done to make the __getattr__<name>__/__setattr__<name>__
// extension work.
if (!is_special_name(name))
return;
for (std::size_t i = 0; i < num_enablers; ++i)
{
if (is_prefix(enablers[i].name + 2, name + 2))
{
type_obj->enable(enablers[i].capability);
}
}
}
}
namespace {
// Enable any special methods which are enabled in the base class.
void enable_special_methods(boost::python::detail::class_base* derived, const tuple& bases, const dictionary& name_space)
{
for (std::size_t i = 0; i < bases.size(); ++i)
{
PyObject* base = bases[i].get();
for (std::size_t n = 0; n < PY_ARRAY_LENGTH(enablers); ++n)
{
ref attribute(
PyObject_GetAttrString(base, const_cast<char*>(enablers[n].name)),
ref::null_ok);
PyErr_Clear();
if (attribute.get() != 0 && PyCallable_Check(attribute.get()))
detail::add_capability(enablers[n].capability, derived);
}
}
list keys(name_space.keys());
for (std::size_t j = 0, len = keys.size(); j < len; ++j)
{
string name_obj(keys.get_item(j));
const char* name = name_obj.c_str();
if (!is_special_name(name))
continue;
for (std::size_t i = 0; i < PY_ARRAY_LENGTH(enablers); ++i)
{
if (is_prefix(enablers[i].name + 2, name + 2))
{
detail::add_capability(enablers[i].capability, derived);
}
}
}
}
void add_current_module_name(dictionary& name_space)
{
static string module_key("__module__", string::interned);
name_space.set_item(module_key, module_builder::name());
}
}
void adjust_slice_indices(PyObject* obj, int& start, int& finish)
{
int length = callback<int>::call_method(obj, "__len__");
// This is standard Python class behavior.
if (start < 0)
start += length;
if (finish < 0)
finish += length;
// This is not
if (start < 0)
start = 0;
if (finish < 0)
finish = 0;
}
namespace detail {
const string& setattr_string()
{
static string x("__setattr__", string::interned);
return x;
}
const string& getattr_string()
{
static string x("__getattr__", string::interned);
return x;
}
const string& delattr_string()
{
static string x("__delattr__", string::interned);
return x;
}
}
}} // namespace boost::python

View File

@@ -1,241 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/conversions.hpp>
#include <typeinfo>
#include <exception>
#ifndef BOOST_NO_LIMITS
# include <boost/cast.hpp>
#endif
namespace boost { namespace python {
// IMPORTANT: this function may only be called from within a catch block!
void handle_exception()
{
try {
// re-toss the current exception so we can find out what type it is.
// NOTE: a heinous bug in MSVC6 causes exception objects re-thrown in
// this way to be double-destroyed. Thus, you must only use objects that
// can tolerate double-destruction with that compiler. Metrowerks
// Codewarrior doesn't suffer from this problem.
throw;
}
catch(const boost::python::error_already_set&)
{
// The python error reporting has already been handled.
}
catch(const std::bad_alloc&)
{
PyErr_NoMemory();
}
catch(const std::exception& x)
{
PyErr_SetString(PyExc_RuntimeError, x.what());
}
catch(...)
{
PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception");
}
}
}} // namespace boost::python
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
long from_python(PyObject* p, boost::python::type<long>)
{
// Why am I clearing the error here before trying to convert? I know there's a reason...
long result;
{
result = PyInt_AsLong(p);
if (PyErr_Occurred())
throw boost::python::argument_error();
}
return result;
}
double from_python(PyObject* p, boost::python::type<double>)
{
double result;
{
result = PyFloat_AsDouble(p);
if (PyErr_Occurred())
throw boost::python::argument_error();
}
return result;
}
template <class T>
T integer_from_python(PyObject* p, boost::python::type<T>)
{
const long long_result = from_python(p, boost::python::type<long>());
#ifndef BOOST_NO_LIMITS
try
{
return boost::numeric_cast<T>(long_result);
}
catch(const boost::bad_numeric_cast&)
#else
if (static_cast<T>(long_result) == long_result)
{
return static_cast<T>(long_result);
}
else
#endif
{
char buffer[256];
const char message[] = "%ld out of range for %s";
sprintf(buffer, message, long_result, typeid(T).name());
PyErr_SetString(PyExc_ValueError, buffer);
throw boost::python::argument_error();
}
#if defined(__MWERKS__) && __MWERKS__ <= 0x2400
return 0; // Not smart enough to know that the catch clause always rethrows
#endif
}
template <class T>
PyObject* integer_to_python(T value)
{
long value_as_long;
#ifndef BOOST_NO_LIMITS
try
{
value_as_long = boost::numeric_cast<long>(value);
}
catch(const boost::bad_numeric_cast&)
#else
value_as_long = static_cast<long>(value);
if (value_as_long != value)
#endif
{
const char message[] = "value out of range for Python int";
PyErr_SetString(PyExc_ValueError, message);
throw boost::python::error_already_set();
}
return to_python(value_as_long);
}
int from_python(PyObject* p, boost::python::type<int> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(unsigned int i)
{
return integer_to_python(i);
}
unsigned int from_python(PyObject* p, boost::python::type<unsigned int> type)
{
return integer_from_python(p, type);
}
short from_python(PyObject* p, boost::python::type<short> type)
{
return integer_from_python(p, type);
}
float from_python(PyObject* p, boost::python::type<float>)
{
return static_cast<float>(from_python(p, boost::python::type<double>()));
}
PyObject* to_python(unsigned short i)
{
return integer_to_python(i);
}
unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(unsigned char i)
{
return integer_to_python(i);
}
unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(signed char i)
{
return integer_to_python(i);
}
signed char from_python(PyObject* p, boost::python::type<signed char> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(unsigned long x)
{
return integer_to_python(x);
}
unsigned long from_python(PyObject* p, boost::python::type<unsigned long> type)
{
return integer_from_python(p, type);
}
void from_python(PyObject* p, boost::python::type<void>)
{
if (p != Py_None) {
PyErr_SetString(PyExc_TypeError, "expected argument of type None");
throw boost::python::argument_error();
}
}
const char* from_python(PyObject* p, boost::python::type<const char*>)
{
const char* s = PyString_AsString(p);
if (!s)
throw boost::python::argument_error();
return s;
}
PyObject* to_python(const std::string& s)
{
return PyString_FromString(s.c_str());
}
std::string from_python(PyObject* p, boost::python::type<std::string>)
{
return std::string(from_python(p, boost::python::type<const char*>()));
}
bool from_python(PyObject* p, boost::python::type<bool>)
{
int value = from_python(p, boost::python::type<int>());
if (value == 0)
return false;
return true;
}
#ifdef BOOST_MSVC6_OR_EARLIER
// An optimizer bug prevents these from being inlined.
PyObject* to_python(double d)
{
return PyFloat_FromDouble(d);
}
PyObject* to_python(float f)
{
return PyFloat_FromDouble(f);
}
#endif // BOOST_MSVC6_OR_EARLIER
BOOST_PYTHON_END_CONVERSION_NAMESPACE

18
src/converter/body.cpp Normal file
View File

@@ -0,0 +1,18 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
// default implementation is a no-op. Most handles will not hold any
// data that needs to be managed. Unwrap objects which convert
// by-value are an exception. Fortunately, the concrete body subclass
// has that knowledge.
void body::destroy_handle(handle*) const
{
}
}}} // namespace boost::python::converter

35
src/converter/handle.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/handle.hpp>
#include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
bool handle::convertible() const
{
for (handle const* p = this; p != 0; p = p->m_next)
{
if (p->m_body == 0)
return false;
}
return true;
}
void handle::destroy()
{
// Recurse down the chain releasing from tail to head
if (m_next != 0)
m_next->destroy();
// Our body knows how to destroy us. If we never got a body,
// there's nothing to do.
if (m_body)
m_body->destroy_handle(this);
}
// void handle::dummy::nonnull() {}
}}} // namespace boost::python::converter

170
src/converter/registry.cpp Normal file
View File

@@ -0,0 +1,170 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
# include <boost/python/converter/unwrapper.hpp>
# include <boost/python/converter/wrapper.hpp>
# include <map>
# include <list>
# include <algorithm>
# include <stdexcept>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
namespace boost { namespace python { namespace converter {
namespace // <unnamed>
{
typedef std::map<type_id_t, registry::entry, type_id_before> registry_t;
registry_t& entries()
{
static registry_t registry;
return registry;
}
} // namespace <unnamed>
namespace registry
{
entry* find(type_id_t type)
{
return &entries()[type];
}
entry::entry()
: m_wrapper(0)
{
}
namespace // <unnamed>
{
// A UnaryFunction type which deletes its argument
struct delete_item
{
template <class T>
void operator()(T* x) const
{
delete x;
}
};
// A UnaryFunction type which returns true iff its argument is a
// unwrapper which can convert the given Python object.
struct convertible
{
convertible(PyObject* p)
: m_p(p)
{}
bool operator()(unwrapper_base* converter) const
{
return converter->convertible(m_p);
}
PyObject* m_p;
};
}
entry::~entry()
{
}
unwrapper_base* entry::unwrapper(PyObject* p) const
{
unwrappers::const_iterator q =
std::find_if(m_unwrappers.begin(), m_unwrappers.end(), convertible(p));
return q == m_unwrappers.end() ? 0 : *q;
}
wrapper_base* entry::wrapper() const
{
return m_wrapper;
}
entry::unwrappers::iterator entry::find(unwrapper_base const& x)
{
return std::find(m_unwrappers.begin(), m_unwrappers.end(), &x);
}
void entry::insert(unwrapper_base& x)
{
unwrappers::iterator p = this->find(x);
assert(p == m_unwrappers.end());
if (p != m_unwrappers.end())
{
throw std::runtime_error(
"trying to register unrapper which is already registered");
}
m_unwrappers.push_back(&x);
}
void entry::remove(unwrapper_base& x)
{
unwrappers::iterator p = find(x);
// Be sure we're not removing a converter which hasn't been
// registered.
assert(p != m_unwrappers.end());
if (p == m_unwrappers.end())
{
throw std::runtime_error(
"trying to unregister unwrapper which is not registered");
}
m_unwrappers.erase(p);
}
void entry::insert(wrapper_base& x)
{
assert(m_wrapper == 0); // we have a problem otherwise
if (m_wrapper != 0)
{
throw std::runtime_error(
"trying to register wrapper for a type which already has a registered wrapper");
}
m_wrapper = &x;
}
void entry::remove(wrapper_base& x)
{
assert(m_wrapper == &x);
if (m_wrapper != &x)
{
throw std::runtime_error(
"trying to unregister a wrapper which is not registered");
}
m_wrapper = 0;
}
void insert(wrapper_base& w)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting wrapper for " << w.key() << std::endl;
# endif
find(w.key())->insert(w);
}
void insert(unwrapper_base& u)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting unwrapper for " << u.key() << std::endl;
# endif
find(u.key())->insert(u);
}
void remove(wrapper_base& w)
{
find(w.key())->remove(w);
}
void remove(unwrapper_base& u)
{
find(u.key())->remove(u);
}
} // namespace registry
}}} // namespace boost::python::converter

67
src/converter/type_id.cpp Normal file
View File

@@ -0,0 +1,67 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/type_id.hpp>
#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT
# include <ostream>
#else
# include <ostream.h>
#endif
namespace boost { namespace python { namespace converter {
#if 1
bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const
{
return x < y;
}
BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream& os, type_id_t const& x)
{
# ifdef BOOST_PYTHON_TYPE_ID_NAME
os << x.m_base_type;
# else
os << x.m_base_type->name();
# endif
// VC6 mistakenly distinguishes typeid(X) from typeid(X const)
// from typeid(X&)... so the name is already correct. I have it
// from Jason Shirk that VC7.0 has the same bug but it will be
// fixed in 7.1
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
if (x.m_decoration & type_id_t::const_)
os << " const";
if (x.m_decoration & type_id_t::volatile_)
os << " volatile";
if (x.m_decoration & type_id_t::reference)
os << "&";
# endif
return os;
}
#else
bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const
{
for (;;)
{
if (*y == 0)
{
return 0;
}
else if (*x == 0)
{
return 1;
}
else if (*x != *y)
{
return *x < *y;
}
++x;
++y;
}
}
#endif
}}} // namespace boost::python::converter

35
src/converter/unwrap.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/unwrap.hpp>
namespace boost { namespace python { namespace converter {
namespace
{
struct pyobject_unwrapper : unwrapper_base
{
pyobject_unwrapper();
bool convertible(PyObject*) const;
};
pyobject_unwrapper static_unwrapper;
pyobject_unwrapper::pyobject_unwrapper()
: unwrapper_base(type_id<PyObject*>())
{
}
bool pyobject_unwrapper::convertible(PyObject*) const
{
return true;
}
}
BOOST_PYTHON_EXPORT unwrapper_base*
unwrap_more_<PyObject*>::m_unwrapper = &static_unwrapper;
}}} // namespace boost::python::converter

View File

@@ -0,0 +1,23 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/unwrapper.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/type_traits/same_traits.hpp>
namespace boost { namespace python { namespace converter {
unwrapper_base::unwrapper_base(type_id_t key)
: body(key)
{
registry::insert(*this);
}
unwrapper_base::~unwrapper_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter

29
src/converter/wrapper.cpp Normal file
View File

@@ -0,0 +1,29 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/wrapper.hpp>
namespace boost { namespace python { namespace converter {
wrapper_base::wrapper_base(type_id_t type)
: body(type)
{
// static assertions for target<T>. These would go in a header,
// but Metrowerks only respects BOOST_STATIC_ASSERT if it is in an
// instantiated function
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#else
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
registry::insert(*this);
}
wrapper_base::~wrapper_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter

View File

@@ -1,683 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/detail/extension_class.hpp>
#include <cstring>
#include <boost/utility.hpp>
namespace boost { namespace python {
namespace detail {
struct operator_dispatcher
: public PyObject
{
static PyTypeObject type_obj;
static PyNumberMethods number_methods;
static operator_dispatcher* create(const ref& o, const ref& s);
ref m_object;
ref m_self;
// data members for allocation/deallocation optimization
operator_dispatcher* m_free_list_link;
static operator_dispatcher* free_list;
private:
// only accessible through create()
operator_dispatcher(const ref& o, const ref& s);
};
operator_dispatcher* operator_dispatcher::free_list = 0;
}}} // namespace boost::python::detail
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
inline PyObject* to_python(boost::python::detail::operator_dispatcher* n) { return n; }
BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python {
namespace detail {
tuple extension_class_coerce(ref l, ref r)
{
// Introduced sequence points for exception-safety.
ref first(operator_dispatcher::create(l, l));
ref second;
if(r->ob_type == &operator_dispatcher::type_obj)
{
second = r;
}
else
{
second = ref(operator_dispatcher::create(r, ref()));
}
return boost::python::tuple(first, second);
}
enum { unwrap_exception_code = -1000 };
int unwrap_args(PyObject* left, PyObject* right, PyObject*& self, PyObject*& other)
{
if (left->ob_type != &operator_dispatcher::type_obj ||
right->ob_type != &operator_dispatcher::type_obj)
{
PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_args(): expecting operator_dispatcher arguments only!");
return unwrap_exception_code;
}
typedef reference<operator_dispatcher> DPtr;
DPtr lwrapper(static_cast<operator_dispatcher*>(left), DPtr::increment_count);
DPtr rwrapper(static_cast<operator_dispatcher*>(right), DPtr::increment_count);
if (lwrapper->m_self.get() != 0)
{
self = lwrapper->m_self.get();
other = rwrapper->m_object.get();
return 0;
}
else
{
self = rwrapper->m_self.get();
other = lwrapper->m_object.get();
return 1;
}
}
int unwrap_pow_args(PyObject* left, PyObject* right, PyObject* m,
PyObject*& self, PyObject*& first, PyObject*& second)
{
if (left->ob_type != &operator_dispatcher::type_obj ||
right->ob_type != &operator_dispatcher::type_obj ||
m->ob_type != &operator_dispatcher::type_obj)
{
PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_pow_args(): expecting operator_dispatcher arguments only!");
return unwrap_exception_code;
}
typedef reference<operator_dispatcher> DPtr;
DPtr lwrapper(static_cast<operator_dispatcher*>(left), DPtr::increment_count);
DPtr rwrapper(static_cast<operator_dispatcher*>(right), DPtr::increment_count);
DPtr mwrapper(static_cast<operator_dispatcher*>(m), DPtr::increment_count);
if (lwrapper->m_self.get() != 0)
{
self = lwrapper->m_self.get();
first = rwrapper->m_object.get();
second = mwrapper->m_object.get();
return 0;
}
else if (rwrapper->m_self.get() != 0)
{
self = rwrapper->m_self.get();
first = lwrapper->m_object.get();
second = mwrapper->m_object.get();
return 1;
}
else
{
self = mwrapper->m_self.get();
first = lwrapper->m_object.get();
second = rwrapper->m_object.get();
return 2;
}
}
extension_instance* get_extension_instance(PyObject* p)
{
// The object's type will just be some class_t<extension_instance> object,
// but if its meta-type is right, then it is an extension_instance.
if (p->ob_type->ob_type != extension_meta_class())
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw boost::python::argument_error();
}
return static_cast<extension_instance*>(p);
}
void
extension_instance::add_implementation(std::auto_ptr<instance_holder_base> holder)
{
for (held_objects::const_iterator p = m_wrapped_objects.begin();
p != m_wrapped_objects.end(); ++p)
{
if (typeid(*holder) == typeid(**p))
{
PyErr_SetString(PyExc_RuntimeError, "Base class already initialized");
throw error_already_set();
}
}
m_wrapped_objects.push_back(holder.release());
}
extension_instance::extension_instance(PyTypeObject* class_)
: instance(class_)
{
}
extension_instance::~extension_instance()
{
for (held_objects::const_iterator p = m_wrapped_objects.begin(),
finish = m_wrapped_objects.end();
p != finish; ++p)
{
delete *p;
}
}
meta_class<extension_instance>* extension_meta_class()
{
static meta_class<extension_instance> result;
return &result;
}
typedef class_t<extension_instance> extension_class_t;
bool is_subclass(const extension_class_t* derived,
const PyObject* possible_base)
{
tuple bases = derived->bases();
for (std::size_t i = 0, size = bases.size(); i < size; ++i)
{
const PyObject* base = bases[i].get();
if (base == possible_base)
return true;
if (base->ob_type == extension_meta_class())
{
const extension_class_t* base_class = downcast<const extension_class_t>(base);
if (is_subclass(base_class, possible_base))
return true;
}
}
return false;
}
// Return true iff obj is an obj of target_class
bool is_instance(extension_instance* obj,
class_t<extension_instance>* target_class)
{
if (obj->ob_type == target_class)
return true;
else
{
return is_subclass(
downcast<class_t<extension_instance> >(obj->ob_type).get(),
as_object(target_class));
}
}
void two_string_error(PyObject* exception_object, const char* format, const char* s1, const char* s2)
{
char buffer[256];
std::size_t format_length = BOOST_CSTD_::strlen(format);
std::size_t length1 = BOOST_CSTD_::strlen(s1);
std::size_t length2 = BOOST_CSTD_::strlen(s2);
std::size_t additional_length = length1 + length2;
if (additional_length + format_length > format_length - 1)
{
std::size_t difference = sizeof(buffer) - 1 - additional_length;
length1 -= difference / 2;
additional_length -= difference / 2;
}
sprintf(buffer, format, length1, s1, length2, s2);
PyErr_SetString(exception_object, buffer);
if (exception_object == PyExc_TypeError)
throw argument_error();
else
throw error_already_set();
}
// This is called when an attempt has been made to convert the given obj to
// a C++ type for which it doesn't have any obj data. In that case, either
// the obj was not derived from the target_class, or the appropriate
// __init__ function wasn't called to initialize the obj data of the target class.
void report_missing_instance_data(
extension_instance* obj, // The object being converted
class_t<extension_instance>* target_class, // the extension class of the C++ type
const std::type_info& target_typeid, // The typeid of the C++ type
bool target_is_ptr)
{
char buffer[256];
if (is_instance(obj, target_class))
{
if (target_is_ptr)
{
two_string_error(PyExc_RuntimeError,
"Object of extension class '%.*s' does not wrap <%.*s>.",
obj->ob_type->tp_name, target_typeid.name());
}
else
{
const char message[] = "__init__ function for extension class '%.*s' was never called.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1,
target_class->tp_name);
}
PyErr_SetString(PyExc_RuntimeError, buffer);
}
else if (target_class == 0)
{
const char message[] = "Cannot convert to <%.*s>; its Python class was never created or has been deleted.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, target_typeid.name());
PyErr_SetString(PyExc_RuntimeError, buffer);
}
else
{
two_string_error(PyExc_TypeError, "extension class '%.*s' is not convertible into '%.*s'.",
obj->ob_type->tp_name, target_class->tp_name);
}
}
void report_missing_instance_data(
extension_instance* obj, // The object being converted
class_t<extension_instance>* target_class, // the extension class of the C++ type
const std::type_info& target_typeid) // The typeid of the C++ type
{
report_missing_instance_data(obj, target_class, target_typeid, false);
}
void report_missing_ptr_data(
extension_instance* obj, // The object being converted
class_t<extension_instance>* target_class, // the extension class of the C++ type
const std::type_info& target_typeid) // The typeid of the C++ type
{
report_missing_instance_data(obj, target_class, target_typeid, true);
}
void report_missing_class_object(const std::type_info& info)
{
char buffer[256];
const char message[] = "Cannot convert <%.*s> to python; its Python class was never created or has been deleted.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name());
PyErr_SetString(PyExc_RuntimeError, buffer);
throw error_already_set();
}
void report_released_smart_pointer(const std::type_info& info)
{
char buffer[256];
const char message[] = "Converting from python, pointer or smart pointer to <%.*s> is NULL.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name());
PyErr_SetString(PyExc_RuntimeError, buffer);
throw argument_error();
}
read_only_setattr_function::read_only_setattr_function(const char* name)
: m_name(name)
{
}
PyObject* read_only_setattr_function::do_call(PyObject* /*args*/, PyObject* /*keywords*/) const
{
PyErr_SetObject(PyExc_AttributeError, ("'" + m_name + "' attribute is read-only").get());
return 0;
}
const char* read_only_setattr_function::description() const
{
return "uncallable";
}
extension_class_base::extension_class_base(const char* name)
: class_t<extension_instance>(
extension_meta_class(), string(name), tuple(), dictionary())
{
}
// This function is used in from_python() to convert wrapped classes that are
// related by inheritance. The problem is this: although C++ provides all necessary
// conversion operators, source and target of a conversion must be known at compile
// time. However, in Python we want to convert classes at runtime. The solution is to
// generate conversion functions at compile time, register them within the appropriate
// class objects and call them when a particular runtime conversion is required.
// If functions for any possible conversion have to be stored, their number will grow
// qudratically. To reduce this number, we actually store only conversion functions
// between adjacent levels in the inheritance tree. By traversing the tree recursively,
// we can build any allowed conversion as a concatenation of simple conversions. This
// traversal is done in the functions try_base_class_conversions() and
// try_derived_class_conversions(). If a particular conversion is impossible, all
// conversion functions will return a NULL pointer.
// The function extract_object_from_holder() attempts to actually extract the pointer
// to the contained object from an instance_holder_base (a wrapper class). A conversion
// of the held object to 'T *' is allowed when the conversion
// 'dynamic_cast<instance_holder<T> *>(an_instance_holder_base)' succeeds.
void* extension_class_base::try_class_conversions(instance_holder_base* object) const
{
void* result = try_derived_class_conversions(object);
if (result)
return result;
if (!object->held_by_value())
return try_base_class_conversions(object);
else
return 0;
}
void* extension_class_base::try_base_class_conversions(instance_holder_base* object) const
{
for (std::size_t i = 0; i < base_classes().size(); ++i)
{
if (base_classes()[i].convert == 0)
continue;
void* result1 = base_classes()[i].class_object->extract_object_from_holder(object);
if (result1)
return (*base_classes()[i].convert)(result1);
void* result2 = base_classes()[i].class_object->try_base_class_conversions(object);
if (result2)
return (*base_classes()[i].convert)(result2);
}
return 0;
}
void* extension_class_base::try_derived_class_conversions(instance_holder_base* object) const
{
for (std::size_t i = 0; i < derived_classes().size(); ++i)
{
void* result1 = derived_classes()[i].class_object->extract_object_from_holder(object);
if (result1)
return (*derived_classes()[i].convert)(result1);
void* result2 = derived_classes()[i].class_object->try_derived_class_conversions(object);
if (result2)
return (*derived_classes()[i].convert)(result2);
}
return 0;
}
void extension_class_base::add_method(function* method, const char* name)
{
add_method(reference<function>(method), name);
}
void extension_class_base::add_method(reference<function> method, const char* name)
{
// Add the attribute to the computed target
function::add_to_namespace(method, name, this->dict().get());
// If it is a special member function it should be enabled both here and there.
detail::enable_named_method(this, name);
}
void extension_class_base::add_constructor_object(function* init_fn)
{
add_method(init_fn, "__init__");
}
void extension_class_base::add_setter_method(function* setter_, const char* name)
{
reference<function> setter(setter_);
add_method(setter, (detail::setattr_string() + name + "__").c_str());
}
void extension_class_base::add_getter_method(function* getter_, const char* name)
{
reference<function> getter(getter_);
add_method(getter, (detail::getattr_string() + name + "__").c_str());
}
void extension_class_base::set_attribute(const char* name, PyObject* x_)
{
ref x(x_);
set_attribute(name, x);
}
void extension_class_base::set_attribute(const char* name, ref x)
{
dict().set_item(string(name), x);
if (PyCallable_Check(x.get()))
detail::enable_named_method(this, name);
}
operator_dispatcher::operator_dispatcher(const ref& o, const ref& s)
: m_object(o), m_self(s), m_free_list_link(0)
{
ob_refcnt = 1;
ob_type = &type_obj;
}
operator_dispatcher*
operator_dispatcher::create(const ref& object, const ref& self)
{
operator_dispatcher* const result = free_list;
if (result == 0)
return new operator_dispatcher(object, self);
free_list = result->m_free_list_link;
result->m_object = object;
result->m_self = self;
Py_INCREF(result);
return result;
}
extern "C"
{
void operator_dispatcher_dealloc(PyObject* self)
{
operator_dispatcher* obj = static_cast<operator_dispatcher*>(self);
obj->m_free_list_link = operator_dispatcher::free_list;
operator_dispatcher::free_list = obj;
obj->m_object.reset();
obj->m_self.reset();
}
int operator_dispatcher_coerce(PyObject** l, PyObject** r)
{
Py_INCREF(*l);
try
{
*r = operator_dispatcher::create(ref(*r, ref::increment_count), ref());
}
catch(...)
{
handle_exception();
return -1;
}
return 0;
}
#define PY_DEFINE_OPERATOR(id, symbol) \
PyObject* operator_dispatcher_call_##id(PyObject* left, PyObject* right) \
{ \
/* unwrap the arguments from their OperatorDispatcher */ \
PyObject* self; \
PyObject* other; \
int reverse = unwrap_args(left, right, self, other); \
if (reverse == unwrap_exception_code) \
return 0; \
\
/* call the function */ \
PyObject* result = \
PyEval_CallMethod(self, \
const_cast<char*>(reverse ? "__r" #id "__" : "__" #id "__"), \
const_cast<char*>("(O)"), \
other); \
if (result == 0 && PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)) \
{ \
PyErr_Clear(); \
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for " #symbol); \
} \
return result; \
}
PY_DEFINE_OPERATOR(add, +)
PY_DEFINE_OPERATOR(sub, -)
PY_DEFINE_OPERATOR(mul, *)
PY_DEFINE_OPERATOR(div, /)
PY_DEFINE_OPERATOR(mod, %)
PY_DEFINE_OPERATOR(divmod, divmod)
PY_DEFINE_OPERATOR(lshift, <<)
PY_DEFINE_OPERATOR(rshift, >>)
PY_DEFINE_OPERATOR(and, &)
PY_DEFINE_OPERATOR(xor, ^)
PY_DEFINE_OPERATOR(or, |)
/* coercion rules for heterogeneous pow():
pow(Foo, int): left, right coerced; m: None => reverse = 0
pow(int, Foo): left, right coerced; m: None => reverse = 1
pow(Foo, int, int): left, right, m coerced => reverse = 0
pow(int, Foo, int): left, right, m coerced => reverse = 1
pow(int, int, Foo): left, right, m coerced => reverse = 2
pow(Foo, Foo, int): left, right coerced; m coerced twice => reverse = 0
pow(Foo, int, Foo): left, right, m coerced => reverse = 0
pow(int, Foo, Foo): left, right, m coerced => reverse = 1
*/
PyObject* operator_dispatcher_call_pow(PyObject* left, PyObject* right, PyObject* m)
{
int reverse;
PyObject* self;
PyObject* first;
PyObject* second;
if (m->ob_type == Py_None->ob_type)
{
reverse = unwrap_args(left, right, self, first);
second = m;
}
else
{
reverse = unwrap_pow_args(left, right, m, self, first, second);
}
if (reverse == unwrap_exception_code)
return 0;
// call the function
PyObject* result =
PyEval_CallMethod(self,
const_cast<char*>((reverse == 0)
? "__pow__"
: (reverse == 1)
? "__rpow__"
: "__rrpow__"),
const_cast<char*>("(OO)"),
first, second);
if (result == 0 &&
(PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_TypeError) ||
PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)))
{
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()");
}
return result;
}
int operator_dispatcher_call_cmp(PyObject* left, PyObject* right)
{
// unwrap the arguments from their OperatorDispatcher
PyObject* self;
PyObject* other;
int reverse = unwrap_args(left, right, self, other);
if (reverse == unwrap_exception_code)
return -1;
// call the function
PyObject* result =
PyEval_CallMethod(self,
const_cast<char*>(reverse ? "__rcmp__" : "__cmp__"),
const_cast<char*>("(O)"),
other);
if (result == 0)
{
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for cmp() or <");
return -1;
}
else
{
try
{
return BOOST_PYTHON_CONVERSION::from_python(result, type<int>());
}
catch(...)
{
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "cmp() didn't return int");
return -1;
}
}
}
} // extern "C"
PyTypeObject operator_dispatcher::type_obj =
{
PyObject_HEAD_INIT(&PyType_Type)
0,
const_cast<char*>("operator_dispatcher"),
sizeof(operator_dispatcher),
0,
&operator_dispatcher_dealloc,
0,
0,
0,
&operator_dispatcher_call_cmp,
0,
&operator_dispatcher::number_methods,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
};
PyNumberMethods operator_dispatcher::number_methods =
{
&operator_dispatcher_call_add,
&operator_dispatcher_call_sub,
&operator_dispatcher_call_mul,
&operator_dispatcher_call_div,
&operator_dispatcher_call_mod,
&operator_dispatcher_call_divmod,
&operator_dispatcher_call_pow,
0,
0,
0,
0,
0,
&operator_dispatcher_call_lshift,
&operator_dispatcher_call_rshift,
&operator_dispatcher_call_and,
&operator_dispatcher_call_xor,
&operator_dispatcher_call_or,
&operator_dispatcher_coerce,
0,
0,
0,
0,
0
};
} // namespace detail
}} // namespace boost::python

View File

@@ -1,167 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/detail/functions.hpp>
#include <boost/python/detail/types.hpp>
#include <boost/python/detail/singleton.hpp>
#include <boost/python/objects.hpp>
#include <boost/python/errors.hpp>
namespace boost { namespace python { namespace detail {
struct function::type_object :
singleton<function::type_object, callable<boost::python::detail::type_object<function> > >
{
type_object() : singleton_base(&PyType_Type) {}
};
void function::add_to_namespace(reference<function> new_function, const char* name, PyObject* dict)
{
dictionary d(ref(dict, ref::increment_count));
string key(name);
ref existing_object = d.get_item(key.reference());
if (existing_object.get() == 0)
{
d[key] = ref(new_function.get(), ref::increment_count);
}
else
{
if (existing_object->ob_type == type_object::instance())
{
function* f = static_cast<function*>(existing_object.get());
while (f->m_overloads.get() != 0)
f = f->m_overloads.get();
f->m_overloads = new_function;
}
else
{
PyErr_SetObject(PyExc_RuntimeError,
(string("Attempt to overload ") + name
+ " failed. The existing attribute has type "
+ existing_object->ob_type->tp_name).get());
throw error_already_set();
}
}
}
function::function()
: python_object(type_object::instance())
{
}
PyObject* function::call(PyObject* args, PyObject* keywords) const
{
for (const function* f = this; f != 0; f = f->m_overloads.get())
{
PyErr_Clear();
try
{
PyObject* const result = f->do_call(args, keywords);
if (result != 0)
return result;
}
catch(const argument_error&)
{
}
}
if (m_overloads.get() == 0)
return 0;
PyErr_Clear();
string message("No overloaded functions match (");
tuple arguments(ref(args, ref::increment_count));
for (std::size_t i = 0; i < arguments.size(); ++i)
{
if (i != 0)
message += ", ";
message += arguments[i]->ob_type->tp_name;
}
message += "). Candidates are:\n";
for (const function* f1 = this; f1 != 0; f1 = f1->m_overloads.get())
{
if (f1 != this)
message += "\n";
message += f1->description();
}
PyErr_SetObject(PyExc_TypeError, message.get());
return 0;
}
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.
struct bound_function::type_object :
singleton<bound_function::type_object,
getattrable<callable<boost::python::detail::type_object<bound_function> > > >
{
type_object() : singleton_base(&PyType_Type) {}
private: // type_object<bound_function> hook override
void dealloc(bound_function*) const;
};
bound_function::bound_function(const ref& target, const ref& fn)
: python_object(type_object::instance()),
m_target(target),
m_unbound_function(fn),
m_free_list_link(0)
{
}
PyObject*
bound_function::call(PyObject* args, PyObject* keywords) const
{
// Build a new tuple which prepends the target to the arguments
tuple tail_arguments(ref(args, ref::increment_count));
ref all_arguments(PyTuple_New(tail_arguments.size() + 1));
PyTuple_SET_ITEM(all_arguments.get(), 0, m_target.get());
Py_INCREF(m_target.get());
for (std::size_t i = 0; i < tail_arguments.size(); ++i)
{
PyTuple_SET_ITEM(all_arguments.get(), i + 1, tail_arguments[i].get());
Py_INCREF(tail_arguments[i].get());
}
return PyEval_CallObjectWithKeywords(m_unbound_function.get(), all_arguments.get(), keywords);
}
PyObject* bound_function::getattr(const char* name) const
{
return PyObject_GetAttrString(m_unbound_function.get(), const_cast<char*>(name));
}
void bound_function::type_object::dealloc(bound_function* obj) const
{
obj->m_free_list_link = free_list;
free_list = obj;
obj->m_target.reset();
obj->m_unbound_function.reset();
}
bound_function* bound_function::free_list;
}}} // namespace boost::python::detail

View File

@@ -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)

82
src/gen_call.py Normal file
View File

@@ -0,0 +1,82 @@
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# This work was funded in part by Lawrence Berkeley National Labs
from gen_function import *
import string
header = '''// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for %d-argument member functions and %d-argument free
// functions by gen_call.py
#ifndef CALL_DWA20011214_HPP
# define CALL_DWA20011214_HPP
# include <boost/python/detail/returning.hpp>
namespace boost { namespace python {
'''
_cv_qualifiers = ('', ' const', ' volatile', ' const volatile')
def gen_call(member_function_args, free_function_args = None):
if free_function_args is None:
free_function_args = member_function_args + 1
return (header % (member_function_args, free_function_args)
+ gen_functions(
'''template <class R%(, class A%n%)>
PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
''', free_function_args)
+
'''// Member functions
'''
+ reduce(lambda x,y: x+y
, map(lambda cv:
gen_functions(
'''template <class R, class A0%(, class A%+%)>
PyObject* call(R (A0::*f)(%(A%+%:, %))%1, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
'''
, member_function_args, cv)
, _cv_qualifiers))
+
'''
}} // namespace boost::python
#endif // CALL_DWA20011214_HPP
''')
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
member_function_args = 5
free_function_args = 6
else:
member_function_args = int(sys.argv[1])
if len(sys.argv) > 2:
free_function_args = int(sys.argv[2])
else:
free_function_args = member_function_args
print gen_call(member_function_args, free_function_args)

View File

@@ -1,124 +0,0 @@
from gen_function import *
import string
def gen_callback(args):
return (
"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file was generated for %d-argument python callbacks by gen_callback.python
#ifndef CALLBACK_DWA_052100_H_
# define CALLBACK_DWA_052100_H_
# include <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
{""" % args
+ gen_functions('''
%{ template <%(class A%n%:, %)>
%} static R call_method(PyObject* self, const char* name%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
detail::callback_adjust_refcount(result.get(), type<R>());
return from_python(result.get(), type<R>());
}
%{ template <%(class A%n%:, %)>
%} static R call(PyObject* self%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
detail::callback_adjust_refcount(result.get(), type<R>());
return from_python(result.get(), type<R>());
}
''', args)
+
"""};
// This specialization wouldn't be needed, but MSVC6 doesn't correctly allow the following:
// void g();
// void f() { return g(); }
template <>
struct callback<void>
{
"""
+ gen_functions('''
%{ template <%(class A%n%:, %)>
%} static void call_method(PyObject* self, const char* name%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
}
%{ template <%(class A%n%:, %)>
%} static void call(PyObject* self%(, const A%n& a%n%))
{%(
ref p%n(to_python(a%n));%)
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
p%n.get()%)));
}
''', args)
+
"""};
// Make it a compile-time error to try to return a const char* from a virtual
// function. The standard conversion
//
// from_python(PyObject* string, boost::python::type<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_
""")
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
args = 5
else:
args = int(sys.argv[1])
print gen_callback(args)

View File

@@ -1,138 +0,0 @@
# (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# The author gratefully acknowleges the support of Dragon Systems, Inc., in
# producing this work.
from gen_function import *
import string
header = '''// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file generated for %d-argument member functions and %d-argument free
// functions by gen_caller.python
'''
body_sections = (
'''
#ifndef CALLER_DWA05090_H_
# define CALLER_DWA05090_H_
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/config.hpp>
# include <boost/python/detail/signatures.hpp>
# include <boost/python/detail/none.hpp>
namespace boost { namespace python {
// Calling C++ from Python
template <class R>
struct caller
{
''',
'''
''',
''' // Free functions
''',
'''};
template <>
struct caller<void>
{
''',
'''
''',
'''
// Free functions
''',
'''};
}} // namespace boost::python
#endif
''')
#'
member_function = ''' template <class T%(, class A%n%)>
static PyObject* call(%1 (T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) {
PyObject* self;
%( PyObject* a%n;
%) if (!PyArg_ParseTuple(args, const_cast<char*>("O%(O%)"), &self%(, &a%n%)))
return 0;
T& target = from_python(self, type<T&>());
%3(target.*pmf)(%(from_python(a%n, type<A%n>())%:,
%))%4
}
'''
free_function = '''%{ template <%(class A%n%:, %)>
%} static PyObject* call(%1 (*f)(%(A%n%:, %)), PyObject* args, PyObject* /* keywords */ ) {
%( PyObject* a%n;
%) if (!PyArg_ParseTuple(args, const_cast<char*>("%(O%)")%(, &a%n%)))
return 0;
%2f(%(from_python(a%n, type<A%n>())%:,
%))%3
}
'''
def gen_caller(member_function_args, free_function_args = None):
if free_function_args is None:
free_function_args = member_function_args + 1
return_none = ''';
return detail::none();'''
return (header % (member_function_args, free_function_args)
+ body_sections[0]
+ gen_functions(member_function, member_function_args,
'R', '', 'return to_python(', ');')
+ body_sections[1]
+ gen_functions(member_function, member_function_args,
'R', ' const', 'return to_python(', ');')
+ body_sections[2]
+ gen_functions(free_function, free_function_args,
'R', 'return to_python(', ');')
+ body_sections[3]
# specialized part for void return values begins here
+ gen_functions(member_function, member_function_args,
'void', '', '', return_none)
+ body_sections[4]
+ gen_functions(member_function, member_function_args,
'void', ' const', '', return_none)
+ body_sections[5]
+ gen_functions(free_function, free_function_args,
'void', '', return_none)
+ body_sections[6]
)
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
member_function_args = 5
free_function_args = 6
else:
member_function_args = int(sys.argv[1])
if len(sys.argv) > 2:
free_function_args = int(sys.argv[2])
else:
free_function_args = member_function_args
print gen_caller(member_function_args, free_function_args)

View File

@@ -1,830 +0,0 @@
from gen_function import *
import string
def gen_extclass(args):
return (
"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file automatically generated for %d-argument constructors by
// gen_extclass.python
#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>
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 T> 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;
};
}}} // 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();
}
// Convert to T*
friend T* 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 PtrType, where PtrType can be dereferenced to obtain a T.
template <class PtrType>
static PtrType& ptr_from_python(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();
}
template <class PtrType>
static PyObject* ptr_to_python(PtrType x)
{
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(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 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 ptr_from_python(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> >()); }
friend PyObject* to_python(std::auto_ptr<T> x)
{ return 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> >()); }
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<const boost::shared_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
friend PyObject* to_python(boost::shared_ptr<T> x)
{ return 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
""" % args
+ gen_function(
""" template <%(class A%n%:, %)>
inline void def(constructor<%(A%n%:, %)>)
// The following incantation builds a signature1, signature2,... object. It
// should _all_ get optimized away.
{ add_constructor(
%(prepend(type<A%n>::id(),
%) signature0()%()%));
}
""", args)
+
"""
// export homogeneous operators (type of both lhs and rhs is 'operator')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>());
// export homogeneous operators (type of both lhs and rhs is 'T const&')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>());
template <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 T>
class held_instance : public T
{
// There are no member functions: we want to avoid inadvertently overriding
// any virtual functions in T.
public:"""
+ gen_functions("""%{
template <%(class A%n%:, %)>%}
held_instance(PyObject*%(, A%n% a%n%)) : T(%(a%n%:, %)) {}""", args)
+ """
};
// 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; }
"""
+ gen_functions("""%{
template <%(class A%n%:, %)>%}
instance_value_holder(extension_instance* p%(, A%n a%n%)) :
m_held(p%(, a%n%)) {}""", args)
+ """
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
//
tuple extension_class_coerce(ref l, ref r);
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(&extension_class_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_
""")
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
args = 5
else:
args = int(sys.argv[1])
print gen_extclass(args)

View File

@@ -1,184 +0,0 @@
import string
def _find(s, sub, start=0, end=None):
"""Just like string.find, except it returns end or len(s) when not found.
"""
if end == None:
end = len(s)
pos = string.find(s, sub, start, end)
if pos < 0:
return end
else:
return pos
def _gen_common_key(key, n, args):
if len(key) > 0 and key in '123456789':
return str(args[int(key) - 1])
elif key == 'x':
return str(n)
else:
return key
def _gen_arg(template, n, args, delimiter = '%'):
result = ''
i = 0
while i < len(template): # until the template is consumed
# consume everything up to the first delimiter
delimiter_pos = _find(template, delimiter, i)
result = result + template[i:delimiter_pos]
# The start position of whatever comes after the delimiter+key
start = delimiter_pos + 2
key = template[start - 1 : start] # the key character. If there were no
# delimiters left, key will be empty
if key == 'n':
result = result + `n`
else:
result = result + _gen_common_key(key, n, args)
i = start
return result
def gen_function(template, n, *args, **keywords):
r"""gen_function(template, n, [args...] ) -> string
Generate a function declaration based on the given template.
Sections of the template between '%(', '%)' pairs are repeated n times. If '%:'
appears in the middle, it denotes the beginning of a delimiter.
Sections of the template between '%{', '%}' pairs are ommitted if n == 0.
%n is transformed into the string representation of 1..n for each repetition
of n.
%x, where x is a digit, is transformed into the corresponding additional
argument.
for example,
>>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void')
'void abc(int a1, int a2); // all args are ints'
>>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x')
'x abc();'
>>> template = ''' template <class T%(, class A%n%)>
... static PyObject* call( %1(T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) {
... PyObject* self;
... %( PyObject* a%n;
... %) if (!PyArg_ParseTuple(args, const_cast<char*>("O%(O%)"), &self%(, &a%n%)))
... return 0;
... T& target = from_python(self, type<T&>());
... %3to_python((target.*pmf)(%(
... from_python(a%n, type<A%n>())%:,%)
... ));%4
... }'''
>>> print gen_function(template, 0, 'R ', '', 'return ', '')
template <class T>
static PyObject* call( R (T::*pmf)(), PyObject* args, PyObject* /* keywords */ ) {
PyObject* self;
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
return 0;
T& target = from_python(self, type<T&>());
return to_python((target.*pmf)(
));
}
>>> print gen_function(template, 2, 'R ', '', 'return ', '')
template <class T, class A1, class A2>
static PyObject* call( R (T::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) {
PyObject* self;
PyObject* a1;
PyObject* a2;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOO"), &self, &a1, &a2))
return 0;
T& target = from_python(self, type<T&>());
return to_python((target.*pmf)(
from_python(a1, type<A1>()),
from_python(a2, type<A2>())
));
}
>>> print gen_function(template, 3, 'void ', ' const', '', '\n'+8*' ' + 'return none();')
template <class T, class A1, class A2, class A3>
static PyObject* call( void (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) {
PyObject* self;
PyObject* a1;
PyObject* a2;
PyObject* a3;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOO"), &self, &a1, &a2, &a3))
return 0;
T& target = from_python(self, type<T&>());
to_python((target.*pmf)(
from_python(a1, type<A1>()),
from_python(a2, type<A2>()),
from_python(a3, type<A3>())
));
return none();
}
"""
delimiter = keywords.get('delimiter', '%')
result = ''
i = 0
while i < len(template): # until the template is consumed
# consume everything up to the first delimiter
delimiter_pos = _find(template, delimiter, i)
result = result + template[i:delimiter_pos]
# The start position of whatever comes after the delimiter+key
start = delimiter_pos + 2
key = template[start - 1 : start] # the key character. If there were no
# delimiters left, key will be empty
pairs = { '(':')', '{':'}' }
if key in pairs.keys():
end = string.find(template, delimiter + pairs[key], start)
assert end >= 0, "Matching '" + delimiter + pairs[key] +"' not found!"
delimiter_pos = end
if key == '{':
if n > 0:
result = result + gen_function(template[start:end], n, args, delimiter)
else:
separator_pos = _find(template, delimiter + ':', start, end)
separator = template[separator_pos+2 : end]
for x in range(1, n + 1):
result = result + _gen_arg(template[start:separator_pos], x, args,
delimiter)
if x != n:
result = result + separator
else:
result = result + _gen_common_key(key, n, args)
i = delimiter_pos + 2
return result
def gen_functions(template, n, *args):
r"""gen_functions(template, n, [args...]) -> string
Call gen_function repeatedly with from 0..n and the given optional
arguments.
>>> print gen_functions('%1 abc(%(int a%n%:, %));%{ // all args are ints%}\n', 2, 'void'),
void abc();
void abc(int a1); // all args are ints
void abc(int a1, int a2); // all args are ints
"""
result = ''
for x in range(n + 1):
result = result + apply(gen_function, (template, x) + args)
return result
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@@ -1,166 +0,0 @@
from gen_function import *
import string
def gen_init_function(args):
return (
"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file was generated for %d-argument 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;
"""
+ gen_functions('template <class T%(, class A%n%)> struct init%x;\n', args)
+ """
template <class T>
struct init_function
{
""" + gen_functions("""%{
template <%(class A%n%:, %)>
%} static init* create(signature%x%{<%(A%n%:, %)>%}) {
return new init%x<T%(,
detail::parameter_traits<A%n>::const_reference%)>;
}
""", args)+"""};
class init : public function
{
private: // override function hook
PyObject* do_call(PyObject* args, PyObject* keywords) const;
private:
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0;
};
""" + gen_functions("""
template <class T%(, class A%n%)>
struct init%x : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
%(PyObject* a%n;
%)if (!PyArg_ParseTuple(args, const_cast<char*>("%(O%)")%(, &a%n%)))
throw argument_error();
return new T(self%(,
boost::python::detail::reference_parameter<A%n>(from_python(a%n, type<A%n>()))%)
);
}
const char* description() const
{ return typeid(void (*)(T&%(, A%n%%))).name(); }
};""", args) + """
}}} // namespace boost::python::detail
#endif // INIT_FUNCTION_DWA052000_H_
""")
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
args = 5
else:
args = int(sys.argv[1])
print gen_init_function(args)

191
src/gen_returning.py Normal file
View File

@@ -0,0 +1,191 @@
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# This work was funded in part by Lawrence Berkeley National Labs
from gen_function import *
import string
header = '''// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for %d-argument member functions and %d-argument free
// functions by gen_returning.py
'''
body_sections = (
'''
#ifndef RETURNING_DWA20011201_HPP
# define RETURNING_DWA20011201_HPP
//# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/config.hpp>
# include <boost/python/convert.hpp>
# include <boost/python/detail/none.hpp>
namespace boost { namespace python { namespace detail {
// Calling C++ from Python
template <class R>
struct returning
{
''',
'''
''',
''' // Free functions
''',
'''};
template <>
struct returning<void>
{
typedef void R;
''',
'''
''',
'''
// Free functions
''',
'''};
}}} // namespace boost::python::detail
#endif // RETURNING_DWA20011201_HPP
''')
#'
member_function = ''' template <class A0%(, class A%+%)>
static PyObject* call(R (A0::*pmf)(%(A%+%:, %))%1, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0%1&> c0(PyTuple_GET_ITEM(args, 0));
%( unwrap_more<A%+> c%+(PyTuple_GET_ITEM(args, %+), c%n);
%)
%[r%: // find the result converter
wrap_more<R> r(c%n);
%] if (!c0) return 0;
%[r%:return r( %]((*c0).*pmf)(%(*c%+%:, %))%[r%: )%];%[v%:
return detail::none();%]
};
'''
free_function = '''%{ template <%(class A%n%:, %)>
%} static PyObject* call(R (*pf)(%(A%n%:, %)), PyObject*%{ args%}, PyObject* /* keywords */ )
{%{
// check that each of the arguments is convertible
%}%( unwrap%{_more%}<A%n> c%n(PyTuple_GET_ITEM(args, %n)%{, c%-%});
%)%[r%:
// find the result converter
wrap%{_more%}<R> r%{(c%-)%};%]%{
if (!c0) return 0;%}
%[r%:return r( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%:
return detail::none();%]
};
'''
def _returns_value(key, n, args, value):
if key == 'r':
return value
# pass the value through gen_function again for recursive expansion
# return apply(gen_function, (value, n) + args
# , {'fill': _returns_value})
else:
assert key == 'v'
return ''
def _returns_void(key, n, args, value):
if key == 'v':
return value
else:
assert key == 'r'
# return the empty string, ignoring the value
return ''
_cv_qualifiers = ('', ' const', ' volatile', ' const volatile')
_prefix = {
# ' const': '''
# // missing cv-qualified -> cv-unqualified member pointer conversions
# # if defined(__MWERKS__) && __MWERKS__ <=0x2406 || defined(BOOST_MSVC) && BOOST_MSVC <= 1200 || defined(__BORLANDC__)
# ''',
' const volatile': '''
// missing const volatile type traits
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''};
def gen_returning(member_function_args, free_function_args = None):
if free_function_args is None:
free_function_args = member_function_args + 1
return_none = ''';
return detail::none();'''
return (header % (member_function_args, free_function_args)
+ body_sections[0]
#
# functions returning results
#
+ reduce(lambda x,y: x+y
, map(lambda cv:
_prefix.get(cv,'')
+ gen_functions(member_function,
member_function_args, cv,
fill = _returns_value) + '\n'
, _cv_qualifiers))
+ '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''
## endif // missing cv-qualified -> cv-unqualified member pointer conversions
#'''
# free functions
+ gen_functions(free_function, free_function_args, fill = _returns_value)
+ body_sections[3]
#
# functions returning void
#
+ reduce(lambda x,y: x+y
, map(lambda cv:
_prefix.get(cv,'')
+ gen_functions(member_function,
member_function_args, cv, fill =
_returns_void) + '\n'
, _cv_qualifiers))
+ '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''
## endif // missing cv-qualified -> cv-unqualified member pointer conversions
#'''
# free functions
+ gen_functions(free_function, free_function_args, fill = _returns_void)
+ body_sections[6]
)
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
member_function_args = 5
free_function_args = 6
else:
member_function_args = int(sys.argv[1])
if len(sys.argv) > 2:
free_function_args = int(sys.argv[2])
else:
free_function_args = member_function_args
print gen_returning(member_function_args, free_function_args)

View File

@@ -1,158 +0,0 @@
from gen_function import *
import string
def gen_struct_signatures(args):
result = ''
for n in range(args, -1, -1):
result = (
result + gen_function("""%{template <%(class T%n%:, %)>
%}struct signature%x {};
""", n)
# + ((n == args) and [""] or
# [gen_function("""
# template <class X>
# static inline signature%1<X%(, T%n%)> prepend(type<X>)
# { return signature%1<X%(, T%n%)>(); }""",
# n, (str(n+1),))
# ]
# )[0]
#
# + ((n != 0) and [""] or
# ["""
# // This one terminates the chain. Prepending void_t to the head of a void_t
# // signature results in a void_t signature again.
# static inline signature0 prepend(void_t) { return signature0(); }"""]
# )[0]
# + """
#};
#
#"""
+ ((n == args) and [""] or
[gen_function(
"""template <%(class T%n%, %)class X>
inline signature%1<X%(, T%n%)> prepend(type<X>, signature%x%{<%(T%n%:, %)>%})
{ return signature%1<X%(, T%n%)>(); }
""", n, str(n+1))
]
)[0]
)
return result
def gen_signatures(args):
return (
"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file automatically generated by gen_signatures.python for %d arguments.
#ifndef SIGNATURES_DWA050900_H_
# define SIGNATURES_DWA050900_H_
# include <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
""" % args
+ gen_struct_signatures(args)
+ """
// This one terminates the chain. Prepending void_t to the head of a void_t
// signature results in a void_t signature again.
inline signature0 prepend(void_t, signature0) { return signature0(); }
} // namespace detail
"""
+ gen_function("""
template <%(class A%n% = detail::void_t%:, %)>
struct constructor
{
};
""", args)
+ """
namespace detail {
// Return value extraction:
// This is just another little envelope for carrying a typedef (see type,
// above). I could have re-used type, but that has a very specific purpose. I
// thought this would be clearer.
template <class T>
struct return_value_select { typedef T type; };
// free functions"""
+ gen_functions("""
template <class R%(, class A%n%)>
return_value_select<R> return_value(R (*)(%(A%n%:, %))) { return return_value_select<R>(); }
""", args)
+
"""
// TODO(?): handle 'const void'
// member functions"""
+ gen_functions("""
template <class R, class T%(, class A%n%)>
return_value_select<R> return_value(R (T::*)(%(A%n%:, %))) { return return_value_select<R>(); }
""", args)
+ gen_functions("""
template <class R, class T%(, class A%n%)>
return_value_select<R> return_value(R (T::*)(%(A%n%:, %)) const) { return return_value_select<R>(); }
""", args)
+ """
}}} // namespace boost::python::detail
#endif
""")
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
args = 5
else:
args = int(sys.argv[1])
print gen_signatures(args)

View File

@@ -1,58 +0,0 @@
from gen_function import *
import string
def gen_singleton(args):
return (
"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#ifndef SINGLETON_DWA051900_H_
# define SINGLETON_DWA051900_H_
# include <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
"""
+ gen_functions("""%{
template <%(class A%n%:, %)>
%} singleton(%(const A%n& a%n%:, %)) : Base(%(a%n%:, %)) {}
""", args)
+ """
};
template <class Derived, class Base>
Derived* singleton<Derived,Base>::instance()
{
static Derived x;
return &x;
}
}}} // namespace boost::python::detail
#endif
""")
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
args = 5
else:
args = int(sys.argv[1])
print gen_singleton(args)

View File

@@ -1,36 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/detail/init_function.hpp>
#include <boost/python/objects.hpp>
#include <boost/python/detail/extension_class.hpp>
#include <utility>
namespace boost { namespace python { namespace detail {
PyObject* init::do_call(PyObject* args_, PyObject* keywords) const
{
tuple args(ref(args_, ref::increment_count));
if (args[0]->ob_type->ob_type != extension_meta_class())
{
PyErr_SetString(PyExc_TypeError, "argument 1 to __init__ must be an ExtensionInstance");
return 0;
}
extension_instance *self = static_cast<extension_instance*>(args[0].get());
tuple ctor_args = args.slice(1, args.size());
std::auto_ptr<instance_holder_base> result(
create_holder(self, ctor_args.get(), keywords));
self->add_implementation(result);
return none();
}
}}} // namespace boost::python::detail

View File

@@ -1,52 +0,0 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/module_builder.hpp>
namespace boost { namespace python {
namespace {
ref name_holder;
}
string module_builder::name()
{
// If this fails, you haven't created a module_builder object
assert(name_holder.get() != 0);
return string(name_holder);
}
module_builder::module_builder(const char* name)
: m_module(Py_InitModule(const_cast<char*>(name), initial_methods))
{
// If this fails, you've created more than 1 module_builder object in your module
assert(name_holder.get() == 0);
name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__")));
}
void
module_builder::add(detail::function* x, const char* name)
{
reference<detail::function> f(x); // First take possession of the object.
detail::function::add_to_namespace(f, name, PyModule_GetDict(m_module));
}
void module_builder::add(ref x, const char* name)
{
PyObject* dictionary = PyModule_GetDict(m_module);
PyDict_SetItemString(dictionary, const_cast<char*>(name), x.get());
}
void module_builder::add(PyTypeObject* x, const char* name /*= 0*/)
{
this->add(ref(as_object(x)), name ? name : x->tp_name);
}
PyMethodDef module_builder::initial_methods[] = { { 0, 0, 0, 0 } };
}} // namespace boost::python

Some files were not shown because too many files have changed in this diff Show More