2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-22 05:22:45 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
nobody
cec9964b08 This commit was manufactured by cvs2svn to create tag
'Version_1_19_0'.

[SVN r8447]
2000-12-10 15:53:47 +00:00
Dave Abrahams
54ec2a41b2 initial import
[SVN r8331]
2000-11-27 06:57:31 +00:00
44 changed files with 3218 additions and 584 deletions

216
build/bpl_static.dsp Normal file
View File

@@ -0,0 +1,216 @@
# 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

74
build/build.dsw Normal file
View File

@@ -0,0 +1,74 @@
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>
{{{
}}}
###############################################################################

BIN
build/build.opt Normal file

Binary file not shown.

51
build/como.mak Normal file
View File

@@ -0,0 +1,51 @@
LIBSRC = \
classes.cpp \
conversions.cpp \
extension_class.cpp \
functions.cpp \
init_function.cpp \
module_builder.cpp \
objects.cpp \
types.cpp
LIBOBJ = $(LIBSRC:.cpp=.o)
OBJ = $(LIBOBJ)
ifeq "$(OS)" "Windows_NT"
PYTHON_LIB=c:/tools/python/libs/python15.lib
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -Ic:/tools/python/include
MODULE_EXTENSION=dll
else
INC = -I/usr/local/include/python1.5
MODULE_EXTENSION=so
endif
%.o: ../src/%.cpp
como --pic $(INC) -o $*.o -c $<
%.d: ../src/%.cpp
@echo creating $@
@set -e; como -M $(INC) -c $< \
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
[ -s $@ ] || rm -f $@
example1: example1.o libpycpp.a
como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lpycpp
python ../example/test_example1.py
example1.o: ../example/example1.cpp
como --pic $(INC) -o $*.o -c $<
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

107
build/example1/example1.dsp Normal file
View File

@@ -0,0 +1,107 @@
# 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

53
build/gcc.mak Normal file
View File

@@ -0,0 +1,53 @@
LIBSRC = \
classes.cpp \
conversions.cpp \
extension_class.cpp \
functions.cpp \
init_function.cpp \
module_builder.cpp \
objects.cpp \
types.cpp
LIBOBJ = $(LIBSRC:.cpp=.o)
OBJ = $(LIBOBJ)
ifeq "$(OS)" "Windows_NT"
PYTHON_LIB=c:/tools/python/libs/python15.lib
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -Ic:/tools/python/include
MODULE_EXTENSION=dll
else
INC = -I/usr/local/include/python1.5
MODULE_EXTENSION=so
endif
%.o: ../src/%.cpp
g++ -fPIC -Wall -W $(INC) -o $*.o -c $<
%.d: ../src/%.cpp
@echo creating $@
@set -e; g++ -M $(INC) -c $< \
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
[ -s $@ ] || rm -f $@
example1: example1.o libpycpp.a
g++ -shared -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lpycpp
python ../example/test_example1.py
example1.o: ../example/example1.cpp
g++ -fPIC -Wall -W $(INC) -o $*.o -c $<
clean:
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
libpycpp.a: $(LIBOBJ)
rm -f libpycpp.a
ar cq libpycpp.a $(LIBOBJ)
DEP = $(OBJ:.o=.d)
ifneq "$(MAKECMDGOALS)" "clean"
include $(DEP)
endif

105
build/rwgk1/rwgk1.dsp Normal file
View File

@@ -0,0 +1,105 @@
# 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

112
build/test/test.dsp Normal file
View File

@@ -0,0 +1,112 @@
# 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

51
build/tru64.mak Normal file
View File

@@ -0,0 +1,51 @@
#
# 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,212 +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>
py_cpp Python/C++ binding documentation
</title>
<h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
align="center" height="86"> py_cpp<a href="#naming_contest">*</a>
</h1>
<p>
The source code for py_cpp, including a MSVC demo project is available <a
href="py_cpp_20001106.zip">here</a>.
<h2>Synopsis</h2>
<p>
py_cpp is a system for quickly and easily interfacing C++ code with <a
href="http:www.python.org">Python</a> such that the Python interface is
very similar to the C++ interface. It is designed to be minimally
intrusive on your C++ design. In most cases, you should not have to alter
your C++ classes in any way in order to use them with py_cpp. The system
<em>should</em> simply &ldquo;reflect&rdquo; your C++ classes and functions into
Python. The major features of py_cpp 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>py_cpp 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 py_cpp)
</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>
<p>Py_cpp requires the <a href="http://www.boost.org">boost</a> libraries, and is
has been accepted for inclusion into the boost libraries pending &ldquo;boostification&ldquo;
(completion of the documentation, change in some naming conventions and
resolution of some namespace issues).
<h2>Credits</h2>
<ul>
<li><a href="mailto:abrahams@mediaone.net">David Abrahams</a> originated
and wrote py_cpp.
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
had independently developed a similar system. When he discovered py_cpp,
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, Prabhu Ramachandran, and Barry Scott took
the brave step of trying to use py_cpp while it was still in early stages
of development.
<li>The development of py_cpp 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 py_cpp and other
systems for extending Python</a>
<li><a href="example1.html">A Simple Example Using py_cpp</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 Py_cpp</a>
<li>Advanced Topics
<ol>
<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>
More sophisticated examples are given in
<code>extclass_demo.cpp</code>, <code> extclass_demo.h</code>, and <code>
test_extclass.py</code> in the <a href="py_cpp.tgz">source code
archive</a>. There's much more here, and much more documentation to
come...
<p>
Questions should be directed to <a href=
"http://www.egroups.com/list/boost">the boost mailing list</a>.
<h2>Naming Contest</h2>
<p>
Yes, I know py_cpp is a lousy name. Problem is, the best names my puny
imagination can muster (IDLE and GRAIL) are taken, so I'm holding a
naming contest. First prize? You get to pick the name&lt;0.2wink&gt; and
you will be credited in the documentation. Names that have been suggested
so far include:
<ul>
<li>
Py++
<li>
Python++
<li>
Coil
<li>
SnakeSkin
<li>
CCCP - <b>C</b>onvert <b>C</b>++ <b>
C</b>lasses to <b>P</b>ython
<li>
C<sup>3</sup>PO - <b>C</b>onvert <b>C</b>++
<b>C</b>lasses to <b>P</b>ython <b>
O</b>bjects
<li>
PALIN - <b>P</b>ython <b>
A</b>ugmented-<b>L</b>anguage <b>
IN</b>tegration
<li>
CLEESE - <b>C</b>++ <b>L</b>anguage <b>E</b>xtension <b>E</b>nvironment
<b>S</b>upremely <b>E</b>asy
<li>
JONES - <b>J</b>ust <b>O</b>bscenely <b>N</b>eat <b>E</b>xtension
<b>S</b>ystem
<li>
C-thru
<li>
SeamlessC
<li>
BorderCrossing
<li>
Perseus (because he solved a hairy problem involving snakes by using
reflection and was invisible most of the time).
</ul>
Please <a href="http://www.egroups.com/list/boost">post</a> or send <a
href="http:mailto:abrahams@mediaone.net">me</a> your suggestions!<br>
<br>
<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,21 +1,21 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd"> "http://www.w3.org/TR/REC-html40/strict.dtd">
<title> <title>
Building a Module with Py_cpp Building an Extension Module
</title> </title>
<div> <div>
<h1> <h1>
<img width="277" height="86" id="_x0000_i1025" align="center" <img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Building a Module with Py_cpp src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Building an Extension Module
</h1> </h1>
<p> <p>
Right now, the only supported configuration is one in which the py_cpp Right now, the only supported configuration is one in which the BPL
source files are statically linked with the source for your extension 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 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 extension module source, but the effect is the same as compiling all
the source files together. Some users have successfully built the the source files together. Some users have successfully built the
py_cpp sources into a shared library, and support for a shared library sources into a shared library, and support for a shared library
build is planned, but not yet implemented. The py_cpp source files are: build is planned, but not yet implemented. The BPL source files are:
<blockquote> <blockquote>
<pre> <pre>
<a href="../../../libs/python/src/extension_class.cpp">extclass.cpp</a> <a href="../../../libs/python/src/extension_class.cpp">extclass.cpp</a>
@@ -29,13 +29,14 @@
</pre> </pre>
</blockquote> </blockquote>
<p> <p>
Next: <a href="enums.html">Enums</a>
Previous: <a href="under-the-hood.html">A Peek Under the Hood</a> Previous: <a href="under-the-hood.html">A Peek Under the Hood</a>
Up: <a href="index.html">Top</a> Up: <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &ldquo;as notice appears in all copies. This document is provided ``as
is&rdquo; without express or implied warranty, and with no claim as to is'' without express or implied warranty, and with no claim as to
its suitability for any purpose. its suitability for any purpose.
<p> <p>
Updated: Nov 26, 2000 Updated: Nov 26, 2000

View File

@@ -12,14 +12,16 @@
<h2>CXX</h2> <h2>CXX</h2>
<p> <p>
Like py_cpp, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to Like BPL, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
provide a C++-oriented interface to Python. In most cases, like py_cpp, provide a C++-oriented interface to Python. In most cases, as with the
it relieves the user from worrying about reference-counts. As far as I boost library, it relieves the user from worrying about
can tell, there is no support for subclassing C++ extension types in reference-counts. Both libraries automatically convert thrown C++
Python. An even more-significant difference is that a user's C++ code is exceptions into Python exceptions. As far as I can tell, CXX has no
still basically &ldquo;dealing with Python objects&rdquo;, though they are wrapped support for subclassing C++ extension types in Python. An even
in C++ classes. This means such jobs as argument parsing and conversion more significant difference is that a user's C++ code is still basically
are still left to be done explicitly by the user. ``dealing with Python objects'', 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> <p>
CXX claims to interoperate well with the C++ Standard Library CXX claims to interoperate well with the C++ Standard Library
@@ -38,11 +40,9 @@
<p> <p>
As far as I can tell, CXX enables one to write what is essentially As far as I can tell, CXX enables one to write what is essentially
idiomatic Python code in C++, manipulating Python objects through the idiomatic Python code in C++, manipulating Python objects through the
same fully-generic interfaces we use in Python. I think it would be fair same fully-generic interfaces we use in Python. While you're hardly programming directly to the ``bare
to say that while you're not programming directly to the &ldquo;bare metal'' with CXX, it basically presents a ``C++-ized''
metal&rdquo; with CXX, in comparison to py_cpp, it presents a low-level version of the Python 'C' API.
interface to Python. That use is also supported by the py_cpp object
wrappers.
<p> <p>
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original <a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
@@ -51,11 +51,11 @@
fill in the other half. Here is his response to the commentary above: fill in the other half. Here is his response to the commentary above:
<blockquote> <blockquote>
&ldquo;My intention with CXX was not to do what you are doing. It was to enable a ``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 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 the wrapping business covered. I thought maybe CXX would provide an easier
target language for those making wrappers, but I never explored target language for those making wrappers, but I never explored
that.&rdquo;<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i> that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
</blockquote> </blockquote>
<h2>SWIG</h2> <h2>SWIG</h2>
@@ -65,28 +65,28 @@ that.&rdquo;<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
languages. Swig relies on a parser to read your source code and produce 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 additional source code files which can be compiled into a Python (or
Perl or Tcl) extension module. It has been successfully used to create Perl or Tcl) extension module. It has been successfully used to create
many Python extension modules. Like py_cpp, SWIG is trying to allow an 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 interface to be wrapped with little or no change to the
existing code. The documentation says &ldquo;SWIG parses a form of ANSI C existing code. The documentation says ``SWIG parses a form of ANSI C
syntax that has been extended with a number of special directives. As a syntax that has been extended with a number of special directives. As a
result, interfaces are usually built by grabbing a header file and result, interfaces are usually built by grabbing a header file and
tweaking it a little bit.&rdquo; For C++ interfaces, the tweaking has often tweaking it a little bit.'' For C++ interfaces, the tweaking has often
proven to amount to more than just a little bit. One user proven to amount to more than just a little bit. One user
writes: writes:
<blockquote> &ldquo;The problem with swig (when I used it) is that it <blockquote> ``The problem with swig (when I used it) is that it
couldnt handle templates, didnt do func overloading properly etc. For couldnt handle templates, didnt do func overloading properly etc. For
ANSI C libraries this was fine. But for usual C++ code this was a ANSI C libraries this was fine. But for usual C++ code this was a
problem. Simple things work. But for anything very complicated (or problem. Simple things work. But for anything very complicated (or
realistic), one had to write code by hand. I believe py_cpp doesn't have 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 this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
wrap correctly.&rdquo;<br><i>-Prabhu Ramachandran</i> wrap correctly.''<br><i>-Prabhu Ramachandran</i>
</blockquote> </blockquote>
<p> <p>
By contrast, py_cpp doesn't attempt to parse C++ - the problem is simply 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 too complex to do correctly. <a name="sic">Technically</a>, one does
write code by hand to use py_cpp. The goal, however, has been to make 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 that code nearly as simple as listing the names of the classes and
member functions you want to expose in Python. member functions you want to expose in Python.
@@ -95,7 +95,7 @@ that.&rdquo;<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
<a <a
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a> href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
is a system similar to SWIG, though seemingly more is a system similar to SWIG, though seemingly more
C++-oriented. The author says that like py_cpp, SIP supports overriding C++-oriented. The author says that like BPL, SIP supports overriding
extension class member functions in Python subclasses. It appears to extension class member functions in Python subclasses. It appears to
have been designed specifically to directly support some features of have been designed specifically to directly support some features of
PyQt/PyKDE, which is its primary client. Documentation is almost PyQt/PyKDE, which is its primary client. Documentation is almost
@@ -113,7 +113,7 @@ that.&rdquo;<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
to a wide range of computer languages, including Common Lisp, C++, C, 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 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 header file describing the interface, of which the user is expected to
provide an implementation. Unlike py_cpp, this means that the system provide an implementation. Unlike BPL, this means that the system
imposes implementation details on your C++ code at the deepest level. It 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 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 to be reserved to the C++ implementation. It is unclear from the
@@ -124,7 +124,7 @@ that.&rdquo;<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
<a <a
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</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 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 interfaces written in ``legacy languages'', among which C++ is the first one
implemented. Like SWIG, it aims to parse source code and automatically implemented. Like SWIG, it aims to parse source code and automatically
generate wrappers, though it appears to take a more sophisticated approach 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 to parsing in general and C++ in particular, so it should do a much better
@@ -148,70 +148,70 @@ an inheritance relationship?
<h2>Zope ExtensionClasses</h2> <h2>Zope ExtensionClasses</h2>
<p> <p>
<a href="http:http://www.digicool.com/releases/ExtensionClass"> <a href="http:http://www.digicool.com/releases/ExtensionClass">
ExtensionClasses in Zope</a> use the same underlying mechanism as py_cpp ExtensionClasses in Zope</a> use the same underlying mechanism as BPL
to support subclassing of extension types in Python, including to support subclassing of extension types in Python, including
multiple-inheritance. Both systems support pickling/unpickling of multiple-inheritance. Both systems support pickling/unpickling of
extension class instances in very similar ways. Both systems rely on the extension class instances in very similar ways. Both systems rely on the
same &ldquo;<a same ``<a
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
Beaudry Hack</a>&rdquo; that also inspired Don's MESS System. Beaudry Hack</a>'' that also inspired Don's MESS System.
<p> <p>
The major differences are: The major differences are:
<ul> <ul>
<li> <li>
py_cpp lifts the burden on the user to parse and convert function BPL lifts the burden on the user to parse and convert function
argument types. Zope provides no such facility. argument types. Zope provides no such facility.
<li> <li>
py_cpp lifts the burden on the user to maintain Python BPL lifts the burden on the user to maintain Python
reference-counts. reference-counts.
<li> <li>
py_cpp supports function overloading; Zope does not. BPL supports function overloading; Zope does not.
<li> <li>
py_cpp supplies a simple mechanism for exposing read-only and BPL supplies a simple mechanism for exposing read-only and
read/write access to data members of the wrapped C++ type as Python read/write access to data members of the wrapped C++ type as Python
attributes. attributes.
<li> <li>
Writing a Zope ExtensionClass is significantly more complex than Writing a Zope ExtensionClass is significantly more complex than
exposing a C++ class to python using py_cpp (mostly a summary of the exposing a C++ class to python using BPL (mostly a summary of the
previous 4 items). <a href= previous 4 items). <a href=
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A "http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
Zope Example</a> illustrates the differences. Zope Example</a> illustrates the differences.
<li> <li>
Zope's ExtensionClasses are specifically motivated by &ldquo;the need for a Zope's ExtensionClasses are specifically motivated by ``the need for a
C-based persistence mechanism&rdquo;. Py_cpp's are motivated by the desire C-based persistence mechanism''. BPL's are motivated by the desire
to simply reflect a C++ API into Python with as little modification as to simply reflect a C++ API into Python with as little modification as
possible. possible.
<li> <li>
The following Zope restriction does not apply to py_cpp: &ldquo;At most one The following Zope restriction does not apply to BPL: ``At most one
base extension direct or indirect super class may define C data base extension direct or indirect super class may define C data
members. If an extension subclass inherits from multiple base members. If an extension subclass inherits from multiple base
extension classes, then all but one must be mix-in classes that extension classes, then all but one must be mix-in classes that
provide extension methods but no data.&rdquo; provide extension methods but no data.''
<li> <li>
Zope requires use of the somewhat funky inheritedAttribute (search for Zope requires use of the somewhat funky inheritedAttribute (search for
&ldquo;inheritedAttribute&rdquo; on <a ``inheritedAttribute'' on <a
href="http://www.digicool.com/releases/ExtensionClass">this page</a>) href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
method to access base class methods. In py_cpp, base class methods can method to access base class methods. In BPL, base class methods can
be accessed in the usual way by writing be accessed in the usual way by writing
&ldquo;<code>BaseClass.method</code>&rdquo;. ``<code>BaseClass.method</code>''.
<li> <li>
Zope supplies some creative but esoteric idioms such as <a href= Zope supplies some creative but esoteric idioms such as <a href=
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html"> "http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
Acquisition</a>. No specific support for this is built into py_cpp. Acquisition</a>. No specific support for this is built into BPL.
<li> <li>
Zope's ComputedAttribute support is designed to be used from Python. Zope's ComputedAttribute support is designed to be used from Python.
<a href="special.html#getter_setter">The analogous feature of <a href="special.html#getter_setter">The analogous feature of
py_cpp</a> can be used from C++ or Python. The feature is arguably BPL</a> can be used from C++ or Python. The feature is arguably
easier to use in py_cpp. easier to use in BPL.
</ul> </ul>
<p> <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> Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
Next: <a href="example1.html">A Simple Example Using py_cpp</a>
Up: <a href="index.html">Top</a> Up: <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &ldquo;as is&rdquo; without notice appears in all copies. This document is provided ``as is'' without
express or implied warranty, and with no claim as to its suitability express or implied warranty, and with no claim as to its suitability
for any purpose. for any purpose.
<p> <p>

192
doc/data_structures.txt Normal file
View File

@@ -0,0 +1,192 @@
Given a real Python class 'A', a wrapped C++ class 'B', and this definition:
class C(A, B):
def __init__(self):
B.__init__(self)
self.x = 1
...
c = C()
this diagram describes the internal structure of an instance of 'C', including
its inheritance relationships. Note that ExtensionClass<B> is derived from
Class<ExtensionInstance>, and is in fact identical for all intents and purposes.
MetaClass<ExtensionInstance>
+---------+ +---------+
types.ClassType: | | | |
| | | |
| | | |
+---------+ +---------+
^ ^ ^
PyClassObject | ExtensionClass<B> | |
A: +------------+ | B: +------------+ | |
| ob_type -+-+ | ob_type -+-----+ |
| | ()<--+- __bases__ | |
| | | __dict__ -+->{...} |
| | 'B'<-+- __name__ | |
+------------+ +------------+ |
^ ^ |
| | |
+-----+ +-------------+ |
| | |
| | Class<ExtensionInstance> |
| | C: +------------+ |
| | | ob_type -+------------+
tuple:(*, *)<--+- __bases__ |
| __dict__ -+->{__module__, <methods, etc.>}
'C' <-+- __name__ |
+------------+
^ (in case of inheritance from more than one
| extension class, this vector would contain
+---------------+ a pointer to an instance holder for the data
| of each corresponding C++ class)
| ExtensionInstance
| c: +---------------------+ std::vector<InstanceHolderBase>
+----+- __class__ | +---+--
| m_wrapped_objects -+->| * | ...
{'x': 1}<-+- __dict__ | +-|-+--
+---------------------+ | InstanceValueHolder<B>
| +--------------------------------+
+-->| (contains a C++ instance of B) |
+--------------------------------+
In our inheritance test cases in extclass_demo.cpp/test_extclass.py, we have the
following C++ inheritance hierarchy:
+-----+ +----+
| A1 | | A2 |
+-----+ +----+
^ ^ ^ ^ ^
| | | | |
+-----+ | +---------+-----+
| | | |
| +---+----------+
.......!...... | |
: A_callback : +-+--+ +-+--+
:............: | B1 | | B2 |
+----+ +----+
^
|
+-------+---------+
| |
+-+-+ ......!.......
| C | : B_callback :
+---+ :............:
A_callback and B_callback are used as part of the wrapping mechanism but not
represented in Python. C is also not represented in Python but is delivered
there polymorphically through a smart pointer.
This is the data structure in Python.
ExtensionClass<A1>
A1: +------------+
()<--+- __bases__ |
| __dict__ -+->{...}
+------------+
^
| ExtensionInstance
| a1: +---------------------+ vec InstanceValueHolder<A1,A_callback>
+---------+- __class__ | +---+ +---------------------+
| | m_wrapped_objects -+->| *-+-->| contains A_callback |
| +---------------------+ +---+ +---------------------+
|
| ExtensionInstance
| pa1_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
+---------+- __class__ | +---+ +---+
| | m_wrapped_objects -+->| *-+-->| *-+-+ A1
| +---------------------+ +---+ +---+ | +---+
| +->| |
| ExtensionInstance +---+
| pb1_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
+---------+- __class__ | +---+ +---+
| | m_wrapped_objects -+->| *-+-->| *-+-+ B1
| +---------------------+ +---+ +---+ | +---+
| +->| |
| ExtensionInstance +---+
| pb2_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
+---------+- __class__ | +---+ +---+
| | m_wrapped_objects -+->| *-+-->| *-+-+ B2
| +---------------------+ +---+ +---+ | +---+
| +->| |
| +---+
| ExtensionClass<A1>
| A2: +------------+
| ()<--+- __bases__ |
| | __dict__ -+->{...}
| +------------+
| ^
| | ExtensionInstance
| a2: | +---------------------+ vec InstanceValueHolder<A2>
| +-+- __class__ | +---+ +-------------+
| | | m_wrapped_objects -+->| *-+-->| contains A2 |
| | +---------------------+ +---+ +-------------+
| |
| | ExtensionInstance
| pa2_a2: | +---------------------+ vec InstancePtrHolder<auto_ptr<A2>,A2>
| +-+- __class__ | +---+ +---+
| | | m_wrapped_objects -+->| *-+-->| *-+-+ A2
| | +---------------------+ +---+ +---+ | +---+
| | +->| |
| | ExtensionInstance +---+
| pb1_a2: | +---------------------+ vec InstancePtrHolder<auto_ptr<A2>,A2>
| +-+- __class__ | +---+ +---+
| | | m_wrapped_objects -+->| *-+-->| *-+-+ B1
| | +---------------------+ +---+ +---+ | +---+
| | +->| |
| | +---+
| |
| +---------------+------------------------------+
| | |
+------+-------------------------+-|----------------------------+ |
| | | | |
| Class<ExtensionInstance> | | ExtensionClass<B1> | | ExtensionClass<B1>
| DA1: +------------+ | | B1: +------------+ | | B2: +------------+
(*,)<---+- __bases__ | (*,*)<---+- __bases__ | (*,*)<---+- __bases__ |
| __dict__ -+->{...} | __dict__ -+->{...} | __dict__ -+->{...}
+------------+ +------------+ +------------+
^ ^ ^
| ExtensionInstance | |
| da1: +---------------------+ | vec InstanceValueHolder<A1,A_callback>
+-------+- __class__ | | +---+ +---------------------+ |
| m_wrapped_objects -+--|-->| *-+-->| contains A_callback | |
+---------------------+ | +---+ +---------------------+ |
+--------------------------------------+ |
| ExtensionInstance |
b1: | +---------------------+ vec InstanceValueHolder<B1,B_callback> |
+-+- __class__ | +---+ +---------------------+ |
| | m_wrapped_objects -+->| *-+-->| contains B_callback | |
| +---------------------+ +---+ +---------------------+ |
| |
| ExtensionInstance |
pb1_b1: | +---------------------+ vec InstancePtrHolder<auto_ptr<B1>,B1> |
+-+- __class__ | +---+ +---+ |
| | m_wrapped_objects -+->| *-+-->| *-+-+ B1 |
| +---------------------+ +---+ +---+ | +---+ |
| +->| | |
| ExtensionInstance +---+ |
pc_b1: | +---------------------+ vec InstancePtrHolder<auto_ptr<B1>,B1> |
+-+- __class__ | +---+ +---+ |
| | m_wrapped_objects -+->| *-+-->| *-+-+ C |
| +---------------------+ +---+ +---+ | +---+ |
| +->| | |
| +---+ |
| |
| Class<ExtensionInstance> +---------------------------------------+
| DB1: +------------+ | ExtensionInstance
(*,)<---+- __bases__ | a2: | +---------------------+ vec InstanceValueHolder<A2>
| __dict__ -+->{...} +-+- __class__ | +---+ +-------------+
+------------+ | m_wrapped_objects -+->| *-+-->| contains A2 |
^ +---------------------+ +---+ +-------------+
| ExtensionInstance
db1: | +---------------------+ vec InstanceValueHolder<B1,B_callback>
+-+- __class__ | +---+ +----------------------+
| m_wrapped_objects -+-->| *-+-->| contains B1_callback |
+---------------------+ +---+ +----------------------+

View File

@@ -8,31 +8,36 @@
<img width="277" height="86" id="_x0000_i1025" align="center" <img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Wrapping enums src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Wrapping enums
</h1> </h1>
<p>Because there is in general no way to deduce that a value of arbitrary type T <p>Because there is in general no way to deduce that a value of arbitrary type T
is an enumeration constant, py_cpp cannot automatically convert enum values to is an enumeration constant, the Boost Python Library cannot automatically
and from Python. To handle this case, you need to decide how you want the enum convert enum values to and from Python. To handle this case, you need to decide
to show up in Python (since Python doesn't have enums). Once you have done that, how you want the enum to show up in Python (since Python doesn't have
you can write some simple <code>from_python()</code> and enums). Once you have done that, you can write some simple
<code>to_python()</code> functions. <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 <p>If you are satisfied with a Python int as a way to represent your enum
values, py_cpp provides a shorthand for these functions. You just need to 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 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: <code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
<ol> <ol>
<li><blockquote> <li><blockquote>
<pre> <pre>
...
} // close my_namespace
// drop into namespace python and explicitly instantiate // drop into namespace python and explicitly instantiate
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround 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>; template class enum_as_int_converters<extclass_demo::EnumOwner::enum_type>;
BOOST_PYTHON_END_CONVERSION_NAMESPACE BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace my_namespace { // re-open my_namespace
...
</pre> </pre>
</blockquote> </blockquote>
<li><blockquote><pre> <li><blockquote><pre>
// instantiate as base class in any namespace // instantiate as base class in any namespace
struct EnumTypeConverters struct EnumTypeConverters
: boost::python::py_enum_as_int_converters<EnumType> : boost::python::enum_as_int_converters&lt;EnumType&gt;
{ {
}; };
</blockquote></pre> </blockquote></pre>
@@ -82,11 +87,15 @@ my_class.add(boost::python::to_python(enum_value_1), "enum_value_1");
my_class.add(boost::python::to_python(enum_value_2), "enum_value_2"); my_class.add(boost::python::to_python(enum_value_2), "enum_value_2");
... ...
</pre></blockquote> </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> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &ldquo;as notice appears in all copies. This document is provided ``as
is&rdquo; without express or implied warranty, and with no claim as to is'' without express or implied warranty, and with no claim as to
its suitability for any purpose. its suitability for any purpose.
<p> <p>
Updated: Nov 26, 2000 Updated: Nov 26, 2000

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd"> "http://www.w3.org/TR/REC-html40/strict.dtd">
<title> <title>
A Simple Example Using py_cpp A Simple Example
</title> </title>
<div> <div>
<h1> <h1>
@@ -9,7 +9,7 @@
"c++boost.gif (8819 bytes)"> "c++boost.gif (8819 bytes)">
</h1> </h1>
<h1> <h1>
A Simple Example Using py_cpp A Simple Example
</h1> </h1>
<p> <p>
Suppose we have the following C++ API which we want to expose in Suppose we have the following C++ API which we want to expose in
@@ -24,20 +24,20 @@ namespace hello {
   public:    public:
      world(int);       world(int);
      ~world();       ~world();
      std::string get() const { return "hi, world"; }       std::string greet() const { return "hi, world"; }
    ...     ...
  };   };
  std::size_t length(const world&amp; x) { return std::strlen(x.get()); }   std::size_t length(const world&amp; x) { return std::strlen(x.greet()); }
} }
</pre> </pre>
</blockquote> </blockquote>
<p> <p>
Here is the C++ code for a python module called <code>hello</code> Here is the C++ code for a python module called <code>hello</code>
which exposes the API using py_cpp: which exposes the API using:
<blockquote> <blockquote>
<pre> <pre>
#include <boost/python/class_builder.hpp> #include &lt;boost/python/class_builder.hpp&gt;
// Python requires an exported function called init&lt;module-name&gt; in every // Python requires an exported function called init&lt;module-name&gt; in every
// extension module. This is where we build the module contents. // extension module. This is where we build the module contents.
extern "C" extern "C"
@@ -49,15 +49,15 @@ void inithello()
    try     try
    {     {
       // create an object representing this extension module        // create an object representing this extension module
       boost::python::module_builder hello("hello");        boost::python::module_builder m("hello");
       // Create the Python type object for our extension class        // Create the Python type object for our extension class
       boost::python::class_builder&lt;hello::world&gt; world_class(hello, "world");        boost::python::class_builder&lt;hello::world&gt; world_class(m, "world");
       // Add the __init__ function        // Add the __init__ function
       world_class.def(boost::python::constructor&lt;int&gt;());        world_class.def(boost::python::constructor&lt;int&gt;());
       // Add a regular member function        // Add a regular member function
       world_class.def(&amp;hello::world::get, "get");        world_class.def(&amp;hello::world::get, "get");
       // Add a regular function to the module        // Add a regular function to the module
       hello.def(hello::length, "length");        m.def(hello::length, "length");
    }     }
    catch(...)     catch(...)
    {     {
@@ -82,7 +82,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
<pre> <pre>
&gt;&gt;&gt; import hello &gt;&gt;&gt; import hello
&gt;&gt;&gt; hi_world = hello.world(3) &gt;&gt;&gt; hi_world = hello.world(3)
&gt;&gt;&gt; hi_world.get() &gt;&gt;&gt; hi_world.greet()
'hi, world' 'hi, world'
&gt;&gt;&gt; hello.length(hi_world) &gt;&gt;&gt; hello.length(hi_world)
9 9
@@ -93,11 +93,11 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
<blockquote> <blockquote>
<pre> <pre>
&gt;&gt;&gt; class my_subclass(hello.world): &gt;&gt;&gt; class my_subclass(hello.world):
...     def get(self): ...     def greet(self):
...         return 'hello, world' ...         return 'hello, world'
... ...
&gt;&gt;&gt; y = my_subclass(4) &gt;&gt;&gt; y = my_subclass(4)
&gt;&gt;&gt; y.get() &gt;&gt;&gt; y.greet()
'hello, world' 'hello, world'
</pre> </pre>
</blockquote> </blockquote>
@@ -115,7 +115,8 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
to have a <code>length()</code> of <code>12</code>? If so, <a href= to have a <code>length()</code> of <code>12</code>? If so, <a href=
"overriding.html">read on</a>... "overriding.html">read on</a>...
<p> <p>
Previous: <a href="comparisons.html">Comparisons with other systems</a> Next: <a href="overriding.html">Overridable virtual functions</a> Up: 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> <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,

View File

@@ -38,11 +38,11 @@
</ul> </ul>
This last item typically occupies a great deal of code in an extension This last item typically occupies a great deal of code in an extension
module. Remember that Python is a completely dynamic language. A callable 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 object receives its arguments in a tuple; it is up to that object to extract
extract those arguments from the tuple, check their types, and raise those arguments from the tuple, check their types, and raise appropriate
appropriate exceptions. There are numerous other tedious details that need exceptions. There are numerous other tedious details that need to be
to be managed; too many to mention here. Py_cpp is designed to lift most of managed; too many to mention here. The Boost Python Library is designed to
that burden.<br> lift most of that burden.<br>
<br> <br>
<p> <p>
@@ -56,10 +56,10 @@
sublcassing the extension type. Aside from being tedious, it's not really 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 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 override a method of the extension type which is called from the
extension module. Py_cpp solves this problem by taking advantage of <a extension module. BPL solves this problem by taking advantage of <a
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
feature</a> to provide objects which look, walk, and hiss almost exactly feature</a> to provide objects which look, walk, and hiss almost exactly
like regular Python classes. Py_cpp classes are actually cleaner than like regular Python classes. BPL classes are actually cleaner than
Python classes in some subtle ways; a more detailed discussion will Python classes in some subtle ways; a more detailed discussion will
follow (someday).</p> follow (someday).</p>
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a <p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a

View File

@@ -2,28 +2,24 @@
"http://www.w3.org/TR/REC-html40/strict.dtd"> "http://www.w3.org/TR/REC-html40/strict.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title> <title>
py_cpp Python/C++ binding documentation The Boost Python Library (BPL)
</title> </title>
<h1> <h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" <img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
align="center" height="86"> py_cpp<a href="#naming_contest">*</a> align="center" height="86">The Boost Python Library (BPL)
</h1> </h1>
<p>
The source code for py_cpp, including a MSVC demo project is available <a
href="py_cpp_20001106.zip">here</a>.
<h2>Synopsis</h2> <h2>Synopsis</h2>
<p> <p>
py_cpp is a system for quickly and easily interfacing C++ code with <a Use the Boost Python Library to quickly and easily export a C++ library to <a
href="http:www.python.org">Python</a> such that the Python interface is 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 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 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 py_cpp. The system 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 <em>should</em> simply ``reflect'' your C++ classes and functions into
Python. The major features of py_cpp include support for: Python. The major features of BPL include support for:
<ul> <ul>
<li><a href="inheritance.hml">Subclassing extension types in Python</a> <li><a href="inheritance.html">Subclassing extension types in Python</a>
<li><a href="overriding.html">Overriding virtual functions in Python</a> <li><a href="overriding.html">Overriding virtual functions in Python</a>
<li><a href="overloading.html">[Member] function Overloading</a> <li><a href="overloading.html">[Member] function Overloading</a>
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a> <li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
@@ -32,7 +28,7 @@ among others.
<h2>Supported Platforms</h2> <h2>Supported Platforms</h2>
<p>py_cpp has been tested in the following configurations: <p>BPL has been tested in the following configurations:
<ul> <ul>
<li>Against Python 1.5.2 using the following compiler/library: <li>Against Python 1.5.2 using the following compiler/library:
@@ -56,7 +52,7 @@ among others.
href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve</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 <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 py_cpp) Pro6 for Windows</a> (the first release has a bug that's fatal to BPL)
</ul> </ul>
<br> <br>
<li>Against Python 2.0 using the following compiler/library combinations: <li>Against Python 2.0 using the following compiler/library combinations:
@@ -67,18 +63,13 @@ among others.
</ul> </ul>
</ul> </ul>
<p>Py_cpp requires the <a href="http://www.boost.org">boost</a> libraries, and is
has been accepted for inclusion into the boost libraries pending &ldquo;boostification&ldquo;
(completion of the documentation, change in some naming conventions and
resolution of some namespace issues).
<h2>Credits</h2> <h2>Credits</h2>
<ul> <ul>
<li><a href="mailto:abrahams@mediaone.net">David Abrahams</a> originated <li><a href="../../../people/dave_abrahams.htm">David Abrahams</a> originated
and wrote py_cpp. and wrote the library.
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a> <li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
had independently developed a similar system. When he discovered py_cpp, had independently developed a similar system. When he discovered BPL,
he generously contributed countless hours of coding and much insight into 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 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 href="overloading.html">function overloading</a> and wrote the support for
@@ -88,13 +79,13 @@ among others.
exposing <a href="special.html#numeric">numeric operators</a>, including exposing <a href="special.html#numeric">numeric operators</a>, including
a way to avoid explicit coercion by means of overloading. a way to avoid explicit coercion by means of overloading.
<li>The members of the boost mailing list and the Python community supplied <li>The members of the boost mailing list and the Python community
invaluable early feedback. In particular, Ron Clarke, Mark Evans, Anton supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans,
Gluck, Ralf W. Grosse-Kunstleve, Prabhu Ramachandran, and Barry Scott took Anton Gluck, Ralf W. Grosse-Kunstleve, Chuck Ingold, Prabhu Ramachandran,
the brave step of trying to use py_cpp while it was still in early stages and Barry Scott took the brave step of trying to use BPL while it was
of development. still in early stages of development.
<li>The development of py_cpp wouldn't have been <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 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. Hauspie, Inc</a> who supported its development as an open-source project.
</ul> </ul>
@@ -105,10 +96,10 @@ among others.
<li><a href="extending.html">A Brief Introduction to writing Python <li><a href="extending.html">A Brief Introduction to writing Python
extension modules</a> extension modules</a>
<li><a href="comparisons.html">Comparisons between py_cpp and other <li><a href="comparisons.html">Comparisons between BPL and other
systems for extending Python</a> systems for extending Python</a>
<li><a href="example1.html">A Simple Example Using py_cpp</a> <li><a href="example1.html">A Simple Example</a>
<li><a href="overriding.html">Overridable Virtual Functions</a> <li><a href="overriding.html">Overridable Virtual Functions</a>
@@ -120,11 +111,13 @@ among others.
<li><a href="under-the-hood.html">A Peek Under the Hood</a> <li><a href="under-the-hood.html">A Peek Under the Hood</a>
<li><a href="building.html">Building a Module with Py_cpp</a> <li><a href="building.html">Building an Extension Module</a>
<li>Advanced Topics <li>Advanced Topics
<ol> <ol>
<li>Pickling
<li>class_builder&lt;&gt; <li>class_builder&lt;&gt;
<li><a href="enums.html">enums</a> <li><a href="enums.html">enums</a>
@@ -138,72 +131,28 @@ among others.
<li>Other Extension Types <li>Other Extension Types
<li>Templates <li>Templates
<li><a href="data_structures.txt">Internal Data Structures</a>
</ol> </ol>
</ol> </ol>
<p> <p>
More sophisticated examples are given in Documentation is a major ongoing project; assistance is greatly
<code>extclass_demo.cpp</code>, <code> extclass_demo.h</code>, and <code> appreciated! In the meantime, useful examples of every BPL feature should
test_extclass.py</code> in the <a href="py_cpp.tgz">source code be evident in the regression test files <code>test/comprehensive.[<a
archive</a>. There's much more here, and much more documentation to href="../test/comprehensive.py">py</a>/<a
come... href="../test/comprehensive.hpp">hpp</a>/<a
href="../test/comprehensive.cpp">cpp</a>]</code>
<p> <p>
Questions should be directed to <a href= Questions should be directed to <a href=
"http://www.egroups.com/list/boost">the boost mailing list</a>. "http://www.egroups.com/list/boost">the boost mailing list</a>.
<h2>Naming Contest</h2>
<p>
Yes, I know py_cpp is a lousy name. Problem is, the best names my puny
imagination can muster (IDLE and GRAIL) are taken, so I'm holding a
naming contest. First prize? You get to pick the name&lt;0.2wink&gt; and
you will be credited in the documentation. Names that have been suggested
so far include:
<ul>
<li>
Py++
<li>
Python++
<li>
Coil
<li>
SnakeSkin
<li>
CCCP - <b>C</b>onvert <b>C</b>++ <b>
C</b>lasses to <b>P</b>ython
<li>
C<sup>3</sup>PO - <b>C</b>onvert <b>C</b>++
<b>C</b>lasses to <b>P</b>ython <b>
O</b>bjects
<li>
PALIN - <b>P</b>ython <b>
A</b>ugmented-<b>L</b>anguage <b>
IN</b>tegration
<li>
CLEESE - <b>C</b>++ <b>L</b>anguage <b>E</b>xtension <b>E</b>nvironment
<b>S</b>upremely <b>E</b>asy
<li>
JONES - <b>J</b>ust <b>O</b>bscenely <b>N</b>eat <b>E</b>xtension
<b>S</b>ystem
<li>
C-thru
<li>
SeamlessC
<li>
BorderCrossing
<li>
Perseus (because he solved a hairy problem involving snakes by using
reflection and was invisible most of the time).
</ul>
Please <a href="http://www.egroups.com/list/boost">post</a> or send <a
href="http:mailto:abrahams@mediaone.net">me</a> your suggestions!<br>
<br>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &ldquo;as is&rdquo; without 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 express or implied warranty, and with no claim as to its suitability for
any purpose. any purpose.
<p> <p>

View File

@@ -12,11 +12,11 @@
<h2>Inheritance in Python</h2> <h2>Inheritance in Python</h2>
<p> <p>
Py_cpp extension classes support single and multiple-inheritance in BPL extension classes support single and multiple-inheritance in
Python, just like regular Python classes. You can mix built-in Python Python, just like regular Python classes. You can arbitrarily mix
classes with py_cpp extension classes in a derived class' tuple of built-in Python classes with extension classes in a derived class'
bases. Whenever a py_cpp extension class is among the bases for a new tuple of bases. Whenever a BPL extension class is among the bases for a
class in Python, the result is an extension class: new class in Python, the result is an extension class:
<blockquote> <blockquote>
<pre> <pre>
&gt;&gt;&gt; class MyPythonClass: &gt;&gt;&gt; class MyPythonClass:
@@ -37,7 +37,7 @@
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2> <h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
<p> <p>
Py_cpp also allows us to represent C++ inheritance relationships so that BPL also allows us to represent C++ inheritance relationships so that
wrapped derived classes may be passed where values, pointers, or wrapped derived classes may be passed where values, pointers, or
references to a base class are expected as arguments. The references to a base class are expected as arguments. The
<code>declare_base</code> member function of <code>declare_base</code> member function of
@@ -71,7 +71,11 @@ int get_derived_x(const Derived& d) {
return d.x; return d.x;
} }
<hr> <hr>
#include <boost/python/class_builder.hpp> #include &lt;boost/python/class_builder.hpp&gt;
// namespace alias for code brevity
namespace python = boost::python;
extern "C" extern "C"
#ifdef _WIN32 #ifdef _WIN32
__declspec(dllexport) __declspec(dllexport)
@@ -80,13 +84,13 @@ void initmy_module()
{ {
    try     try
    {     {
       boost::python::module_builder my_module("my_module");        python::module_builder my_module("my_module");
       boost::python::class_builder&lt;Base&gt; base_class(my_module, "Base");        python::class_builder&lt;Base&gt; base_class(my_module, "Base");
       base_class.def(boost::python::constructor&lt;void&gt;());        base_class.def(python::constructor&lt;void&gt;());
       boost::python::class_builder&lt;Derived&gt; derived_class(my_module, "Derived");        python::class_builder&lt;Derived&gt; derived_class(my_module, "Derived");
       derived_class.def(boost::python::constructor&lt;void&gt;());        derived_class.def(python::constructor&lt;void&gt;());
<b>// Establish the inheritance relationship between Base and Derived <b>// Establish the inheritance relationship between Base and Derived
derived_class.declare_base(base_class);</b> derived_class.declare_base(base_class);</b>
@@ -96,7 +100,7 @@ void initmy_module()
    }     }
    catch(...)     catch(...)
    {     {
       boost::python::handle_exception();    // Deal with the exception for Python        python::handle_exception();    // Deal with the exception for Python
    }     }
} }
</pre> </pre>
@@ -135,12 +139,12 @@ struct Base2 {};
struct Derived2 { int f(); }; struct Derived2 { int f(); };
<hr> <hr>
... ...
   boost::python::class_builder&lt;Base&gt; base2_class(my_module, "Base2");    python::class_builder&lt;Base&gt; base2_class(my_module, "Base2");
   base2_class.def(boost::python::constructor&lt;void&gt;());    base2_class.def(python::constructor&lt;void&gt;());
   boost::python::class_builder&lt;Derived2&gt; derived2_class(my_module, "Derived2");    python::class_builder&lt;Derived2&gt; derived2_class(my_module, "Derived2");
   derived2_class.def(boost::python::constructor&lt;void&gt;());    derived2_class.def(python::constructor&lt;void&gt;());
derived_class.declare_base(base_class, <b>boost::python::without_downcast</b>); derived_class.declare_base(base_class, <b>python::without_downcast</b>);
</pre> </pre>
</blockquote> </blockquote>
@@ -150,8 +154,8 @@ struct Derived2 { int f(); };
references, or values. references, or values.
<p> <p>
Next: <a href="special.html">Special Method and Operator Support</a>
Previous: <a href="overloading.html">Function Overloading</a> Previous: <a href="overloading.html">Function Overloading</a>
Next: <a href="special.html">Special Method Names</a>
Up: <a href="index.html">Top</a> Up: <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,

View File

@@ -113,8 +113,7 @@ namespace scope as Python member functions.
<h2>Overload Resolution</h2> <h2>Overload Resolution</h2>
<p> <p>
The function overload resolution mechanism in py_cpp works as The function overload resolution mechanism works as follows:
follows:
<ul> <ul>
@@ -124,7 +123,7 @@ namespace scope as Python member functions.
class is found which has a matching attribute, only functions overloaded class is found which has a matching attribute, only functions overloaded
in the context of that class are candidates for overload resolution. In in the context of that class are candidates for overload resolution. In
this sense, overload resolution mirrors the C++ mechanism, where a name 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 in a derived class ``hides'' all functions with the same name from a base
class. class.
<p> <p>
@@ -133,22 +132,22 @@ namespace scope as Python member functions.
<code>def()</code>ed. The first function whose signature can be made to <code>def()</code>ed. The first function whose signature can be made to
match each argument passed is the one which is ultimately called. match each argument passed is the one which is ultimately called.
This means in particular that you cannot overload the same function on 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 both ``<code>int</code>'' and ``<code>float</code>'' because Python
automatically converts either of the two types into the other one. 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 If the ``<code>float</code>'' overload is found first, it is used
also used for arguments of type &ldquo;<code>int</code>&rdquo; as well, and the also used for arguments of type ``<code>int</code>'' as well, and the
&ldquo;<code>int</code>&rdquo; version of the function is never invoked. ``<code>int</code>'' version of the function is never invoked.
</ul> </ul>
<p> <p>
Prev: <a href="overriding.html">Overridable Virtual Functions</a> Next: <a href="inheritance.html">Inheritance</a>
Next: <a href="inheritance.html">Special Method Names</a> Previous: <a href="overriding.html">Overridable Virtual Functions</a>
Up: <a href="index.html">Top</a> Up: <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &ldquo;as notice appears in all copies. This document is provided ``as
is&rdquo; without express or implied warranty, and with no claim as to is'' without express or implied warranty, and with no claim as to
its suitability for any purpose. its suitability for any purpose.
<p> <p>
Updated: Nov 26, 2000 Updated: Nov 26, 2000

View File

@@ -17,7 +17,7 @@
<h2><a name="overriding_example">Example</a></h2> <h2><a name="overriding_example">Example</a></h2>
<p>In this example, it is assumed that <code>world::get()</code> is a virtual <p>In this example, it is assumed that <code>world::greet()</code> is a virtual
member function: member function:
<blockquote><pre> <blockquote><pre>
@@ -26,7 +26,7 @@ class world
public: public:
   world(int);    world(int);
    virtual ~world();     virtual ~world();
    <b>virtual</b> std::string get() const { return "hi, world"; }     <b>virtual</b> std::string greet() const { return "hi, world"; }
}; };
</pre></blockquote> </pre></blockquote>
@@ -65,11 +65,11 @@ struct world_callback : world
: world(x), : world(x),
m_self(self) {} m_self(self) {}
std::string get() const // <a href="#derived_3">3</a> std::string greet() const // <a href="#derived_3">3</a>
{ return boost::python::callback&lt;std::string&gt;::call_method(m_self, "get"); } { 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> static std::string <a name= "default_implementation">default_get</a>(const hello::world& self) const // <a href="#derived_4">4</a>
{ return self.world::get(); } { return self.world::greet(); }
private: private:
PyObject* m_self; // <a href="#derived_1">1</a> PyObject* m_self; // <a href="#derived_1">1</a>
}; };
@@ -94,7 +94,7 @@ world_class.def(&amp;world::get, "get", &amp;<b>world_callback::default_get</b>)
<blockquote><pre> <blockquote><pre>
&gt;&gt;&gt; class my_subclass(hello.world): &gt;&gt;&gt; class my_subclass(hello.world):
... def get(self): ... def greet(self):
... return 'hello, world' ... return 'hello, world'
... ...
&gt;&gt;&gt; hello.length(my_subclass()) &gt;&gt;&gt; hello.length(my_subclass())
@@ -181,9 +181,9 @@ break the <a
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>). href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
<p> <p>
Prev: <a href="example1.html">A Simple Example Using py_cpp</a> Next: <a Next: <a href="overloading.html">Function Overloading</a>
href="overloading.html">Function Overloading</a> Up: <a href= Previous: <a href="example1.html">A Simple Example Using py_cpp</a>
"index.html">Top</a> Up: <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright

View File

@@ -13,7 +13,7 @@
<p> <p>
In general, raw pointers passed to or returned from functions are problematic In general, raw pointers passed to or returned from functions are problematic
for py_cpp because pointers have too many potential meanings. Is it an iterator? 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 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 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 really just a reference? If the latter, what happens to Python references to the
@@ -34,12 +34,10 @@ converted from/to Python strings.
<h3>Can you avoid the problem?</h3> <h3>Can you avoid the problem?</h3>
<p>My first piece of advice to anyone with a case not covered above is <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 ``find a way to avoid the problem.'' For example, if you have just one
or two functions returning a pointer to a single (not an array of) <code>const or two functions that return a pointer to an individual <code>const
T*</code> for some wrapped <code>T</code>, you may be able to write a &ldquo;thin T</code>, and <code>T</code> is a wrapped class, you may be able to write a ``thin
converting wrapper&rdquo; over those two functions as follows (Since py_cpp converting wrapper'' over those two functions as follows:
converts <code>const T&</code> values <code>to_python</code> by copying the T
into a new extension instance, Foo must have a public copy constructor):
<blockquote><pre> <blockquote><pre>
const Foo* f(); // original function const Foo* f(); // original function
@@ -47,6 +45,10 @@ const Foo& f_wrapper() { return *f(); }
... ...
my_module.def(f_wrapper, "f"); my_module.def(f_wrapper, "f");
</pre></blockquote> </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> <h2>Dealing with the problem</h2>
@@ -118,7 +120,7 @@ return value. You can handle this case by returning a Python tuple:
typedef unsigned ErrorCode; typedef unsigned ErrorCode;
const char* f(int* in_out_x); // original function const char* f(int* in_out_x); // original function
... ...
#include <boost/python/objects.hpp> #include &lt;boost/python/objects.hpp&gt;
const boost::python::tuple f_wrapper(int in_x) { const boost::python::tuple f_wrapper(int in_x) {
const char* s = f(in_x); const char* s = f(in_x);
return boost::python::tuple(s, in_x); return boost::python::tuple(s, in_x);
@@ -131,8 +133,9 @@ my_module.def(f_wrapper, "f");
&gt;&gt;&gt; str,out_x = f(3) &gt;&gt;&gt; str,out_x = f(3)
</pre></blockquote> </pre></blockquote>
<p>
Previous: <a href="enums.html">Enums</a>
Up: <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright

View File

@@ -1,11 +1,10 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN" <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title> <title>
Special Method and Operator Support Special Method and Operator Support
</title> </title>
<div> <div>
<h1> <h1>
<img width="277" height="86" id="_x0000_i1025" align="center" src= <img width="277" height="86" id="_x0000_i1025" align="middle" src=
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Special Method and "../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Special Method and
Operator Support Operator Support
</h1> </h1>
@@ -13,7 +12,7 @@
Overview Overview
</h2> </h2>
<p> <p>
Py_cpp supports all of the standard <a href= BPL supports all of the standard <a href=
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html"> "http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
special method names</a> supported by real Python class instances <em> special method names</a> supported by real Python class instances <em>
except</em> <code>__complex__</code> (more on the reasons <a href= except</em> <code>__complex__</code> (more on the reasons <a href=
@@ -41,12 +40,17 @@
<b><tt class='method'>__init__</tt></b>(<i>self</i>) <b><tt class='method'>__init__</tt></b>(<i>self</i>)
<dd> <dd>
Initialize the class instance. For extension classes not subclassed in Initialize the class instance. For extension classes not subclassed in
Python, this is provided by the Python, <code> __init__</code> is defined by
<code>boost::python::constructor<...>()</code> construct and should <i>not</i> be explicitly <code>def</code>ed.
<pre> my_class.def(boost::python::constructor<...>())</pre>
(see section <a href="example1.html">"A Simple Example Using BPL"</a>).<p>
<dt> <dt>
<b><tt class='method'>__del__</tt></b>(<i>self</i>) <b><tt class='method'>__del__</tt></b>(<i>self</i>)
<dd> <dd>
Called when the extension instance is about to be destroyed. Called when the extension instance is about to be destroyed. For extension classes
not subclassed in Python, <code> __del__</code> is always defined automatically by
means of the class' destructor.
<dt> <dt>
<b><tt class='method'>__repr__</tt></b>(<i>self</i>) <b><tt class='method'>__repr__</tt></b>(<i>self</i>)
<dd> <dd>
@@ -78,7 +82,7 @@
<dt> <dt>
<b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>) <b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>)
<dd> <dd>
Called when the instance is &ldquo;called&rdquo; as a function; if this method Called when the instance is ``called'' as a function; if this method
is defined, <code><var>x</var>(arg1, arg2, ...)</code> is a shorthand for is defined, <code><var>x</var>(arg1, arg2, ...)</code> is a shorthand for
<code><var>x</var>.__call__(arg1, arg2, ...)</code>. <code><var>x</var>.__call__(arg1, arg2, ...)</code>.
</dl> </dl>
@@ -100,7 +104,7 @@ std::string to_string(Foo const&amp; f)
boost::python::class_builder&lt;Foo&gt; foo_class(my_module, "Foo"); boost::python::class_builder&lt;Foo&gt; foo_class(my_module, "Foo");
foo_class.def(&amp;to_string, "__str__"); foo_class.def(&amp;to_string, "__str__");
</pre></blockquote> </pre></blockquote>
Note that py_cpp also supports <em>automatic wrapping</em> of Note that BPL also supports <em>automatic wrapping</em> of
<code>__str__</code> and <code>__cmp__</code>. This is explained in the <a <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 href="#numeric">next section</a> and the <a href="#numeric_table">Table of
Automatically Wrapped Methods</a>. Automatically Wrapped Methods</a>.
@@ -111,9 +115,9 @@ foo_class.def(&amp;to_string, "__str__");
Numeric operators can be exposed manually, by <code>def</code>ing C++ Numeric operators can be exposed manually, by <code>def</code>ing C++
[member] functions that support the standard Python <a [member] functions that support the standard Python <a
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/numeric-types.html">numeric href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/numeric-types.html">numeric
protocols</a>. This is the basic same technique used to expose protocols</a>. This is the same basic technique used to expose
<code>to_string()</code> as <code>__str__()</code> above, and is <a <code>to_string()</code> as <code>__str__()</code> above, and is <a
href="#numeric_manual">covered in detail below</a>. Py_cpp also supports href="#numeric_manual">covered in detail below</a>. BPL also supports
<i>automatic wrapping</i> of numeric operators whenever they have already <i>automatic wrapping</i> of numeric operators whenever they have already
been defined in C++. been defined in C++.
@@ -121,7 +125,7 @@ foo_class.def(&amp;to_string, "__str__");
<p> <p>
Supose we wanted to expose a C++ class Supose we wanted to expose a C++ class
<code>BigNum</code> which supports addition, so that we can write (in C++): <code>BigNum</code> which supports addition. That is, in C++ we can write:
<blockquote><pre> <blockquote><pre>
BigNum a, b, c; BigNum a, b, c;
... ...
@@ -143,7 +147,7 @@ bignum_class.def(boost::python::operators&lt;boost::python::op_add&gt;());
Since BigNum also supports subtraction, multiplication, and division, we Since BigNum also supports subtraction, multiplication, and division, we
want to export those also. This can be done in a single command by 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 ``or''ing the operator identifiers together (a complete list of these
identifiers and the corresponding operators can be found in the <a href= identifiers and the corresponding operators can be found in the <a href=
"#numeric_table">Table of Automatically Wrapped Methods</a>): "#numeric_table">Table of Automatically Wrapped Methods</a>):
<blockquote><pre> <blockquote><pre>
@@ -170,7 +174,7 @@ a = i + b;
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::right_operand&lt;int&gt;());
bignum_class.def(boost::python::operators&lt;boost::python::op_add&gt;(), boost::python::left_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> </pre></blockquote>
Py_cpp uses overloading to register several variants of the same BPL uses overloading to register several variants of the same
operation (more on this in the context of <a href="#coercion"> operation (more on this in the context of <a href="#coercion">
coercion</a>). Again, several operators can be exported at once: coercion</a>). Again, several operators can be exported at once:
<blockquote><pre> <blockquote><pre>
@@ -181,7 +185,7 @@ bignum_class.def(boost::python::operators&lt;(boost::python::op_sub | boost::pyt
</pre></blockquote> </pre></blockquote>
The type of the operand not mentioned is taken from the class being wrapped. In 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 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 other operand's type is ``<code>BigNum const&amp;</code>''. You can override
this default by explicitly specifying a type in the <code> this default by explicitly specifying a type in the <code>
operators</code> template: operators</code> template:
<blockquote><pre> <blockquote><pre>
@@ -189,15 +193,18 @@ bignum_class.def(boost::python::operators&lt;boost::python::op_add, BigNum&gt;()
</pre></blockquote> </pre></blockquote>
<p> <p>
Note that automatic wrapping uses the <em>expression</em> Note that automatic wrapping uses the <em>expression</em>
&ldquo;<code>left + right</code>&rdquo; and can be used uniformly ``<code>left + right</code>'' and can be used uniformly
regardless of whether the C++ operators are supplied as free functions regardless of whether the C++ operators are supplied as free functions
<blockquote><pre>
<blockquote><pre>
BigNum operator+(BigNum, BigNum) BigNum operator+(BigNum, BigNum)
</pre></blockquote> </pre></blockquote>
or as member
functions <blockquote><pre> or as member functions
<blockquote><pre>
BigNum::operator+(BigNum). BigNum::operator+(BigNum).
</blockquote></pre> </pre></blockquote>
<p> <p>
For the Python built-in functions <code>pow()</code> and For the Python built-in functions <code>pow()</code> and
@@ -218,8 +225,7 @@ namespace boost { namespace python {
<p> <p>
In some cases, automatic wrapping of operators may be impossible or In some cases, automatic wrapping of operators may be impossible or
undesirable. Suppose, for example, that the modulo operation for BigNums undesirable. Suppose, for example, that the modulo operation for BigNums
is defined by a set of functions <code>mod()</code> (for automatic is defined by a set of functions called <code>mod()</code>:
wrapping, we would need <code>operator%()</code>):
<blockquote><pre> <blockquote><pre>
BigNum mod(BigNum const&amp; left, BigNum const&amp; right); BigNum mod(BigNum const&amp; left, BigNum const&amp; right);
@@ -228,8 +234,9 @@ BigNum mod(int left, BigNum const&amp; right);
</pre></blockquote> </pre></blockquote>
<p> <p>
In order to create the Python operator "__mod__" from these functions, we For automatic wrapping of the modulo function, <code>operator%()</code> would be needed.
have to wrap them manually: Therefore, the <code>mod()</code>-functions must be wrapped manually. That is, we have
to export them explicitly with the Python special name "__mod__":
<blockquote><pre> <blockquote><pre>
bignum_class.def((BigNum (*)(BigNum const&amp;, BigNum const&amp;))&amp;mod, "__mod__"); bignum_class.def((BigNum (*)(BigNum const&amp;, BigNum const&amp;))&amp;mod, "__mod__");
@@ -237,8 +244,8 @@ bignum_class.def((BigNum (*)(BigNum const&amp;, int))&amp;mod, "__mod__");
</pre></blockquote> </pre></blockquote>
<p> <p>
The third form (with <code>int</code> as left operand) cannot be wrapped The third form of <code>mod()</code> (with <code>int</code> as left operand) cannot
this way. We must first create a function <code>rmod()</code> with the be wrapped directly. We must first create a function <code>rmod()</code> with the
operands reversed: operands reversed:
<blockquote><pre> <blockquote><pre>
@@ -248,7 +255,7 @@ BigNum rmod(BigNum const&amp; right, int left)
} }
</pre></blockquote> </pre></blockquote>
This function must be wrapped under the name "__rmod__": This function must be wrapped under the name "__rmod__" (standing for "reverse mod"):
<blockquote><pre> <blockquote><pre>
bignum_class.def(&amp;rmod, "__rmod__"); bignum_class.def(&amp;rmod, "__rmod__");
@@ -261,9 +268,9 @@ bignum_class.def(&amp;rmod, "__rmod__");
<p> <p>
Automatic and manual wrapping can be mixed arbitrarily. Note that you Automatic and manual wrapping can be mixed arbitrarily. Note that you
cannot overload the same operator for a given extension class on both 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 ``<code>int</code>'' and ``<code>float</code>'', because Python implicitly
converts these types into each other. Thus, the overloaded variant 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 found first (be it ``<code>int</code>`` or ``<code>float</code>'') will be
used for either of the two types. used for either of the two types.
<h3><a name="coercion">Coercion</a></h3> <h3><a name="coercion">Coercion</a></h3>
@@ -271,18 +278,18 @@ bignum_class.def(&amp;rmod, "__rmod__");
Plain Python can only execute operators with identical types on the left 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 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 the left and right operand differ, it tries to coerce these types to a
common type before invoking the actual operator. Implementing good common type before invoking the actual operator. Implementing good
coercion functions can be difficult if many type combinations must be coercion functions can be difficult if many type combinations must be
supported. supported.
<p> <p>
Py_cpp solves this problem the same way that C++ does: with <em><a BPL solves this problem the same way that C++ does: with <em><a
href="overloading.html">overloading</a></em>. This technique drastically href="overloading.html">overloading</a></em>. This technique drastically
simplifies the code neccessary to support operators: you just register simplifies the code neccessary to support operators: you just register
operators for all desired type combinations, and py_cpp automatically operators for all desired type combinations, and BPL automatically
ensures that the correct function is called in each case; there is no ensures that the correct function is called in each case; there is no
need for user-defined coercion functions. To enable operator need for user-defined coercion functions. To enable operator
overloading, py_cpp provides a standard coercion which is <em>implicitly overloading, BPL provides a standard coercion which is <em>implicitly
registered</em> whenever automatic operator wrapping is used. registered</em> whenever automatic operator wrapping is used.
<p> <p>
If you wrap all operator functions manually, but still want to use If you wrap all operator functions manually, but still want to use
@@ -295,7 +302,7 @@ bignum_class.def_standard_coerce();
</pre></blockquote> </pre></blockquote>
If you encounter a situation where you absolutely need a customized If you encounter a situation where you absolutely need a customized
coercion, you can overload the "__coerce__" operator itself. The signature coercion, you can still define the "__coerce__" operator manually. The signature
of a coercion function should look like one of the following (the first is of a coercion function should look like one of the following (the first is
the safest): the safest):
@@ -310,13 +317,22 @@ PyObject* custom_coerce(PyObject* left, PyObject* right);
converted to the same type. Such a function is wrapped as usual: converted to the same type. Such a function is wrapped as usual:
<blockquote><pre> <blockquote><pre>
// this must be called before any use of automatic operator
// wrapping or a call to some_class.def_standard_coerce()
some_class.def(&amp;custom_coerce, "__coerce__"); some_class.def(&amp;custom_coerce, "__coerce__");
</pre></blockquote> </pre></blockquote>
Note that the later use of automatic operator wrapping on a Note that the standard coercion (defined by use of automatic
<code>class_builder</code> or a call to operator wrapping on a <code>class_builder</code> or a call to
&ldquo;<code>some_class.def_standard_coerce()</code>&rdquo; will cause any <code>class_builder::def_standard_coerce()</code>) will never be applied if
custom coercion function to be replaced by the standard one. a custom coercion function has been registered. Therefore, in
your coercion function you should call
<blockquote><pre>
boost::python::standard_coerce(left, right);
</pre></blockquote>
for all cases that you don't want to handle yourself.
<h3><a name="ternary_pow">The Ternary <code>pow()</code> Operator</a></h3> <h3><a name="ternary_pow">The Ternary <code>pow()</code> Operator</a></h3>
@@ -330,7 +346,7 @@ some_class.def(&amp;custom_coerce, "__coerce__");
this is done as usual: this is done as usual:
<blockquote><pre> <blockquote><pre>
BigNum power(BigNum const&amp; first, BigNum const&amp; second, BigNum const&amp; module); BigNum power(BigNum const&amp; first, BigNum const&amp; second, BigNum const&amp; modulus);
typedef BigNum (ternary_function1)(const BigNum&amp;, const BigNum&amp;, const BigNum&amp;); typedef BigNum (ternary_function1)(const BigNum&amp;, const BigNum&amp;, const BigNum&amp;);
... ...
bignum_class.def((ternary_function1)&amp;power, "__pow__"); bignum_class.def((ternary_function1)&amp;power, "__pow__");
@@ -353,19 +369,19 @@ bignum_class.def((ternary_function2)&amp;power, "__pow__");
</pre></blockquote> </pre></blockquote>
In the second variant, however, <code>BigNum</code> appears only as second 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 argument, and in the last one it's the third argument. These functions
must be presented to py_cpp such that that the <code>BigNum</code> must be presented to BPL such that that the <code>BigNum</code>
argument appears in first position: argument appears in first position:
<blockquote><pre> <blockquote><pre>
BigNum rpower(BigNum const&amp; second, int first, int modulus) BigNum rpower(BigNum const&amp; second, int first, int modulus)
{ {
return power(first, second, third); return power(first, second, modulus);
} }
BigNum rrpower(BigNum const&amp; third, int first, int second) BigNum rrpower(BigNum const&amp; modulus, int first, int second)
{ {
return power(first, second, third); return power(first, second, modulus);
} }
</pre></blockquote> </pre></blockquote>
@@ -381,7 +397,7 @@ Note that "__rrpow__" is an extension not present in plain Python.
<h2><a name="numeric_table">Table of Automatically Wrapped Methods</a></h2> <h2><a name="numeric_table">Table of Automatically Wrapped Methods</a></h2>
<p> <p>
Py_cpp can automatically wrap the following <a href= BPL can automatically wrap the following <a href=
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html"> "http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
special methods</a>: special methods</a>:
@@ -630,15 +646,16 @@ Note that "__rrpow__" is an extension not present in plain Python.
to Python's iteration and access protocols. These protocols differ to Python's iteration and access protocols. These protocols differ
considerably from the ones found in C++. For example, Python's typical considerably from the ones found in C++. For example, Python's typical
iteration idiom looks like iteration idiom looks like
<blockquote><pre> <blockquote><pre>
for i in S: for i in S:
</blockquote></pre> </pre></blockquote>
while in C++ one writes while in C++ one writes
<blockquote><pre> <blockquote><pre>
for (iterator i = S.begin(), end = S.end(); i != end) for (iterator i = S.begin(), end = S.end(); i != end; ++i)
</blockquote></pre> </pre></blockquote>
<p>One could try to wrap C++ iterators in order to carry the C++ idiom into <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 Python. However, this does not work very well because
@@ -689,7 +706,7 @@ void throw_key_error_if_end(
// Define some simple wrapper functions which match the Python protocol // Define some simple wrapper functions which match the Python protocol
// for __getitem__, __setitem__, and __delitem__. Just as in Python, a // for __getitem__, __setitem__, and __delitem__. Just as in Python, a
// free function with a &ldquo;self&rdquo; first parameter makes a fine class method. // free function with a ``self'' first parameter makes a fine class method.
const std::string&amp; get_item(const StringMap&amp; self, std::size_t key) const std::string&amp; get_item(const StringMap&amp; self, std::size_t key)
{ {
@@ -755,13 +772,13 @@ KeyError: 2
<h2><a name="getter_setter">Customized Attribute Access</a></h2> <h2><a name="getter_setter">Customized Attribute Access</a></h2>
<p> <p>
Just like built-in Python classes, py_cpp extension classes support <a Just like built-in Python classes, BPL extension classes support <a
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/attribute-access.html">special href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/attribute-access.html">special
the usual attribute access methods</a> <code>__getattr__</code>, the usual attribute access methods</a> <code>__getattr__</code>,
<code>__setattr__</code>, and <code>__delattr__</code>. <code>__setattr__</code>, and <code>__delattr__</code>.
Because writing these functions can Because writing these functions can
be tedious in the common case where the attributes being accessed are be tedious in the common case where the attributes being accessed are
known statically, py_cpp checks the special names known statically, BPL checks the special names
<ul> <ul>
<li> <li>
@@ -774,10 +791,10 @@ KeyError: 2
to provide functional access to the attribute <em>&lt;name&gt;</em>. This 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 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: following shows how we can implement a ``computed attribute'' in Python:
<blockquote> <blockquote>
<pre> <pre>
&gt;&gt;&gt; class Range(AnyPy_cppExtensionClass): &gt;&gt;&gt; class Range(AnyBPLExtensionClass):
... def __init__(self, start, end): ... def __init__(self, start, end):
... self.start = start ... self.start = start
... self.end = end ... self.end = end
@@ -793,7 +810,7 @@ KeyError: 2
Direct Access to Data Members Direct Access to Data Members
</h4> </h4>
<p> <p>
Py_cpp uses the special <code> BPL uses the special <code>
__xxxattr__<em>&lt;name&gt;</em>__</code> functionality described above __xxxattr__<em>&lt;name&gt;</em>__</code> functionality described above
to allow direct access to data members through the following special to allow direct access to data members through the following special
functions on <code>class_builder&lt;&gt;</code> and <code> functions on <code>class_builder&lt;&gt;</code> and <code>
@@ -873,14 +890,14 @@ if (PyInstance_Check(r)) { ...
</pre> </pre>
</blockquote> </blockquote>
<p> <p>
Previous: <a href="inheritance.html">Inheritance</a> Next: <a href= Next: <a href="under-the-hood.html">A Peek Under the Hood</a>
"under-the-hood.html">A Peek Under the Hood</a> Up: <a href= Previous: <a href="inheritance.html">Inheritance</a>
"index.html">Top</a> Up: <a href= "index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams and Ullrich K&ouml;the 2000. &copy; Copyright David Abrahams and Ullrich K&ouml;the 2000.
Permission to copy, use, modify, sell and distribute this document is Permission to copy, use, modify, sell and distribute this document is
granted provided this copyright notice appears in all copies. This granted provided this copyright notice appears in all copies. This
document is provided &ldquo;as is&rdquo; without express or implied document is provided ``as is'' without express or implied
warranty, and with no claim as to its suitability for any purpose. warranty, and with no claim as to its suitability for any purpose.
<p> <p>
Updated: Nov 26, 2000 Updated: Nov 26, 2000

View File

@@ -22,7 +22,7 @@
"example1.html#add_world_class">add it to the module</a> it goes into the "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". module's dictionary to be looked up under the name "world".
<p> <p>
Py_cpp uses C++'s template argument deduction mechanism to determine the BPL uses C++'s template argument deduction mechanism to determine the
types of arguments to functions (except constructors, for which we must types of arguments to functions (except constructors, for which we must
<a href="example1.html#Constructor_example">provide an argument list</a> <a href="example1.html#Constructor_example">provide an argument list</a>
because they can't be named in C++). Then, it calls the appropriate because they can't be named in C++). Then, it calls the appropriate
@@ -48,8 +48,8 @@
the top of your module's init function, then <code>def</code> the member the top of your module's init function, then <code>def</code> the member
functions later to avoid problems with inter-class dependencies. functions later to avoid problems with inter-class dependencies.
<p> <p>
Previous: <a href="overriding.html">Function Overloading</a> Next: <a href="building.html">Building a Module with BPL</a>
Next: <a href="building.html">Building a Module with Py_cpp</a> Previous: <a href="special.html">Special Method and Operator Support</a>
Up: <a href="index.html">Top</a> Up: <a href="index.html">Top</a>
<p> <p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify, &copy; Copyright David Abrahams 2000. Permission to copy, use, modify,

41
example/rwgk1.cpp Normal file
View File

@@ -0,0 +1,41 @@
#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
void 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

17
example/test_rwgk1.py Normal file
View File

@@ -0,0 +1,17 @@
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

@@ -27,8 +27,8 @@ class class_builder
// define constructors // define constructors
template <class signature> template <class signature>
void def(const signature& signature) void def(const signature& s)
{ m_class->def(signature); } { m_class->def(s); }
// export heterogeneous reverse-argument operators // export heterogeneous reverse-argument operators
// (type of lhs: 'left', of rhs: 'right') // (type of lhs: 'left', of rhs: 'right')

View File

@@ -21,7 +21,7 @@
# else # else
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python { # define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python # define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
# define BOOST_PYTHON_CONVERSION python # define BOOST_PYTHON_CONVERSION boost::python
# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';' # define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';'
# endif # endif

View File

@@ -6,7 +6,7 @@
// The author gratefully acknowleges the support of Dragon Systems, Inc., in // The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work. // producing this work.
// //
// This file automatically generated for 5-argument constructors by // This file automatically generated for 10-argument constructors by
// gen_extclass.python // gen_extclass.python
#ifndef EXTENSION_CLASS_DWA052000_H_ #ifndef EXTENSION_CLASS_DWA052000_H_
@@ -363,8 +363,8 @@ class extension_class
~extension_class(); ~extension_class();
// define constructors // define constructors
template <class A1, class A2, class A3, class A4, class A5> template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
inline void def(constructor<A1, A2, A3, A4, A5>) inline void def(constructor<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>)
// The following incantation builds a signature1, signature2,... object. It // The following incantation builds a signature1, signature2,... object. It
// should _all_ get optimized away. // should _all_ get optimized away.
{ add_constructor( { add_constructor(
@@ -373,7 +373,12 @@ class extension_class
prepend(type<A3>::id(), prepend(type<A3>::id(),
prepend(type<A4>::id(), prepend(type<A4>::id(),
prepend(type<A5>::id(), prepend(type<A5>::id(),
signature0())))))); prepend(type<A6>::id(),
prepend(type<A7>::id(),
prepend(type<A8>::id(),
prepend(type<A9>::id(),
prepend(type<A10>::id(),
signature0())))))))))));
} }
@@ -625,6 +630,16 @@ public:
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {} held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5> template <class A1, class A2, class A3, class A4, class A5>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {} held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : T(a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : T(a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : T(a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : T(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
}; };
// Abstract base class for all obj holders. Base for template class // Abstract base class for all obj holders. Base for template class
@@ -676,6 +691,21 @@ public:
template <class A1, class A2, class A3, class A4, class A5> 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) : instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
m_held(p, a1, a2, a3, a4, a5) {} m_held(p, a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
m_held(p, a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
m_held(p, a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
public: // implementation of instance_holder_base required interface public: // implementation of instance_holder_base required interface
bool held_by_value() { return true; } bool held_by_value() { return true; }
@@ -721,8 +751,6 @@ class extension_instance : public instance
// Template function implementations // Template function implementations
// //
tuple extension_class_coerce(ref l, ref r);
template <class T, class U> template <class T, class U>
extension_class<T, U>::extension_class() extension_class<T, U>::extension_class()
: extension_class_base(typeid(T).name()) : extension_class_base(typeid(T).name())
@@ -743,7 +771,7 @@ void extension_class<T, U>::def_standard_coerce()
ref coerce_fct = dict().get_item(string("__coerce__")); ref coerce_fct = dict().get_item(string("__coerce__"));
if(coerce_fct.get() == 0) // not yet defined if(coerce_fct.get() == 0) // not yet defined
this->def(&extension_class_coerce, "__coerce__"); this->def(&standard_coerce, "__coerce__");
} }
template <class T, class U> template <class T, class U>
@@ -831,4 +859,3 @@ std::vector<derived_class_info> class_registry<T>::static_derived_class_info;
}}} // namespace boost::python::detail }}} // namespace boost::python::detail
#endif // EXTENSION_CLASS_DWA052000_H_ #endif // EXTENSION_CLASS_DWA052000_H_

View File

@@ -110,11 +110,11 @@ template <class T, class A1, class A2> struct init2;
template <class T, class A1, class A2, class A3> struct init3; template <class T, class A1, class A2, class A3> 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> 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> 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> 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> 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> 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> struct init9;
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct Init10; template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct init10;
template <class T> template <class T>
struct init_function struct init_function
@@ -165,7 +165,7 @@ struct init_function
template <class A1, class A2, class A3, class A4, class A5, class A6> template <class A1, class A2, class A3, class A4, class A5, class A6>
static init* create(signature6<A1, A2, A3, A4, A5, A6>) { static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
return new Init6<T, return new init6<T,
detail::parameter_traits<A1>::const_reference, detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference, detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference, detail::parameter_traits<A3>::const_reference,
@@ -176,7 +176,7 @@ struct init_function
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7> 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>) { static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
return new Init7<T, return new init7<T,
detail::parameter_traits<A1>::const_reference, detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference, detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference, detail::parameter_traits<A3>::const_reference,
@@ -188,7 +188,7 @@ struct init_function
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> 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>) { static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
return new Init8<T, return new init8<T,
detail::parameter_traits<A1>::const_reference, detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference, detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference, detail::parameter_traits<A3>::const_reference,
@@ -201,7 +201,7 @@ struct init_function
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> 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>) { static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
return new Init9<T, return new init9<T,
detail::parameter_traits<A1>::const_reference, detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference, detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference, detail::parameter_traits<A3>::const_reference,
@@ -215,7 +215,7 @@ struct init_function
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> 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>) { static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
return new Init10<T, return new init10<T,
detail::parameter_traits<A1>::const_reference, detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference, detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference, detail::parameter_traits<A3>::const_reference,
@@ -353,7 +353,7 @@ struct init5 : init
}; };
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
struct Init6 : init struct init6 : init
{ {
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{ {
@@ -379,7 +379,7 @@ struct Init6 : init
}; };
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
struct Init7 : init struct init7 : init
{ {
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{ {
@@ -407,7 +407,7 @@ struct Init7 : init
}; };
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
struct Init8 : init struct init8 : init
{ {
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{ {
@@ -437,7 +437,7 @@ struct Init8 : init
}; };
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
struct Init9 : init struct init9 : init
{ {
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{ {
@@ -469,7 +469,7 @@ struct Init9 : init
}; };
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
struct Init10 : init struct init10 : init
{ {
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{ {

View File

@@ -1,5 +1,22 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
// This file serves as a wrapper around <Python.h> which allows it to be
// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC
// behavior so that a program may be compiled in debug mode without requiring a
// special debugging build of the Python library.
// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the
// compiler command-line.
#ifdef _DEBUG #ifdef _DEBUG
# ifndef DEBUG_PYTHON # ifndef BOOST_DEBUG_PYTHON
# undef _DEBUG // Don't let Python force the debug library just because we're debugging. # undef _DEBUG // Don't let Python force the debug library just because we're debugging.
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H # define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# endif # endif

View File

@@ -18,11 +18,10 @@ namespace boost { namespace python {
class module_builder class module_builder
{ {
typedef PyObject * (*raw_function_ptr)(boost::python::tuple const &, boost::python::dictionary const &);
public: public:
// Create a module. REQUIRES: only one module_builder is created per module. // Create a module. REQUIRES: only one module_builder is created per module.
module_builder(const char* name); module_builder(const char* name);
~module_builder();
// Add elements to the module // Add elements to the module
void add(detail::function* x, const char* name); void add(detail::function* x, const char* name);
@@ -41,13 +40,29 @@ class module_builder
add(detail::new_wrapped_function(fn), name); add(detail::new_wrapped_function(fn), name);
} }
static string name(); // Return true iff a module is currently being built.
static bool initializing();
// Return the name of the module currently being built.
// REQUIRES: initializing() == true
static string name();
// Return a pointer to the Python module object being built
PyObject* module() const;
private: private:
PyObject* m_module; PyObject* m_module;
static PyMethodDef initial_methods[1]; static PyMethodDef initial_methods[1];
}; };
//
// inline implementations
//
inline PyObject* module_builder::module() const
{
return m_module;
}
}} // namespace boost::python }} // namespace boost::python
#endif #endif

View File

@@ -1,15 +1,22 @@
#ifndef OPERATORS_UK112000_H_ #ifndef OPERATORS_UK112000_H_
#define OPERATORS_UK112000_H_ #define OPERATORS_UK112000_H_
#include <boost/python/detail/functions.hpp> # include <boost/python/reference.hpp>
#if !defined(__GNUC__) || defined(__SGI_STL_PORT) # include <boost/python/detail/functions.hpp>
# include <sstream>
#else // When STLport is used with native streams, _STL::ostringstream().str() is not
# include <strstream> // _STL::string, but std::string. This confuses to_python(), so we'll use
#endif // strstream instead. Also, GCC 2.95.2 doesn't have sstream.
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
# include <sstream>
# else
# include <strstream>
# endif
namespace boost { namespace python { namespace boost { namespace python {
tuple standard_coerce(ref l, ref r);
namespace detail { namespace detail {
// helper class for automatic operand type detection // helper class for automatic operand type detection
@@ -473,17 +480,15 @@ namespace detail
{ {
tuple args(ref(arguments, ref::increment_count)); tuple args(ref(arguments, ref::increment_count));
#if !defined(__GNUC__) || defined(__SGI_STL_PORT) // When STLport is used with native streams, _STL::ostringstream().str() is not
// _STL::string, but std::string.
#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
std::ostringstream s; std::ostringstream s;
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()); s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>());
return BOOST_PYTHON_CONVERSION::to_python(s.str());
#else #else
std::ostrstream s; std::ostrstream s;
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()) << char(); 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())); return BOOST_PYTHON_CONVERSION::to_python(const_cast<char const *>(s.str()));
#endif #endif
} }

217
release_notes.txt Normal file
View File

@@ -0,0 +1,217 @@
2000-11-22 10:00
Ullrich fixed bug in operator_dispatcher<op_long>.
2000-11-21 10:00
Changed all class and function names into lower_case.
Ullrich updated documentation for operator wrapping.
2000-11-20 10:00
Ullrich renamed ExtensionClass:register_coerce() into
ExtensionClass:def_standard_coerce() and made it public
Ullrich improved shared_pod_manager.
2000-11-17 15:04
Changed allocation strategy of shared_pod_manager to make it portable.
Added pickling support + tests thanks to "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Added a specialization of Callback<const char*> to prevent unsafe usage.
Fixed Ullrich's operator_dispatcher refcount bug
Removed const char* return values from virtual functions in tests; that
usage was unsafe.
Ullrich changed Module::add() so that it steals a reference (fix of refcount bug)
Ullrich added operator_dispatcher::create() optimization
Ullrich changed design and implementation of TypeObjectBase::enable() (to eliminate low-level
code) and added shared_pod_manager optimization.
2000-11-15 12:01
Fixed refcount bugs in operator calls.
Added callback_adjust_refcount(PyObject*, Type<T>) to account for different ownership
semantics of Callback's return types and Caller's arguments (which both use from_python())
This bug caused refcount errors during operator calls.
Moved operator_dispatcher into extclass.cpp
Gave it shared ownership of the objects it wraps
Introduced sequence points in extension_class_coerce for exception-safety
UPPER_CASE_MACRO_NAMES
MixedCase template type argument names
Changed internal error reporting to use Python exceptions so we don't force the
user to link in iostreams code
Changed error return value of call_cmp to -1
Moved unwrap_* functions out of operator_dispatcher. This was transitional: when
I realized they didn't need to be declared in extclass.h I moved them out, but
now that operator_dispatcher itself is in extclass.cpp they could go back in.
Numerous formatting tweaks
Updated the BoundFunction::create() optimization and enabled it so it could actually be used!
2000-11-15 00:26
Made Ullrich's operators support work with MSVC
Cleaned up operators.h such that invalid define_operator<0> is no longer needed.
Ullrich created operators.h to support wrapping of C++ operators (including the "__r*__" forms).
He added several auxiliary classes to extclass.h and extclass.cpp (most importantly,
py::detail::operator_dispatcher and py::operators)
2000-11-13 22:29
removed obsolete ExtensionClassFromPython for good.
removed unused class ExtensionType forward declaration
2000-11-12 13:08
Added enum_as_int_converters for easier enum wrapping
Introduced new conversion namespace macros:
PY_BEGIN_CONVERSION_NAMESPACE,
PY_END_CONVERSION_NAMESPACE,
PY_CONVERSION
callback.h, gen_callback.py:
Added call() function so that a regular python function (as opposed to
method or other function-as-attribute) can be called.
Added newlines for readability.
class_wrapper.h:
Fixed a bug in add(), which allows non-method class attributes
Ullrich has added def_raw for simple varargs and keyword support.
Fixed version number check for __MWERKS__
Added tests for enums and non-method class attributes
objects.h/objects.cpp:
Added py::String operator*= and operator* for repetition
Change Dict::items(), keys(), and values() to return a List
Added template versions of set_item, etc., methods so that users can optionally
use C++ types that have to_python() functions as parameters.
Changed various Ptr by-value parameters to const Ptr&
======= Release =======
2000-11-06 0:22
Lots of documentation updates
added 4-argument template constructor to py::Tuple
added "add" member function to ClassWrapper<> to allow arbitrary Python
objects to be added to an extension class.
gen_all.py now generates support for n argument member functions and n+1
argument member functions at the suggestion of "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Added regression tests and re-ordered declare_base calls to verify that the
phantom base class issue is resolved.
2000-11-04 17:35
Integrated Ullrich Koethe's brilliant from_python_experiment for better
error-reporting in many cases.
extclass.h, gen_extclass.py:
removed special-case MSVC code
added much commentary
removed unused py_copy_to_new_value_holder
init_function.h, gen_init_function.py:
added missing 'template' keyword on type-dependent template member usage
removed special-case MSVC code
added much commentary
2000-11-04 0:36
Removed the need for the phantom base class that screwed up inheritance
hierarchies, introduced error-prone ordering dependencies, and complexified
logic in many places!
extclass.h: Added some explanatory comments, removed wasteful m_self member
of HeldInstance
extclass_demo.cpp: Added #pragmas which allow compilation in ansi strict
mode under Metrowerks
functions.h: Added virtual_function as part of phantom base class removal;
expanded commentary
pyptr.h: Added some missing 'typename's and a GCC workaround fix
subclass.cpp: Added missing string literal const_cast<>s.
2000-11-03 10:58
Fix friend function instantiation bug caught by Metrowerks (thanks
Metrowerks!)
Add proof-of-concept for one technique of wrapping function that return a
pointer
Worked around MSVC optimizer bug by writing to_python(double) and
to_python(float) out-of-line
2000-11-02 23:25
Add /Zm200 option to vc6_prj to deal with MSVC resource limitations
Remove conflicting /Ot option from vc6_prj release build
======= Release =======
2000-11-02 17:42
Added a fix for interactions between default virtual function
implementations and declare_base(). You still need to write your
declare_base() /after/ all member functions have been def()d for the two
classes concerned. Many, many thanks to Ullrich Koethe
<koethe@informatik.uni-hamburg.de> for all his work on this.
Added missing conversions:
to_python(float)
from_python(const char* const&)
from_python(const double&)
from_python(const float&)
Added a Regression test for a reference-counting bug thanks to Mark Evans
(<mark.evans@clarisay.com>)
const-ify ClassBase::getattr()
Add repr() function to Class<T>
Add to_python/from_python conversions for PyPtr<T>
Standardize set_item/get_item interfaces (instead of proxies) for Dict and List
Add Reprable<> template to newtypes.h
Fix a bug wherein the __module__ attribute would be lost for classes that have a
default virtual function implementation.
Remove extra ';' in module.cpp thanks to "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Fix a bug in the code of example1.html

View File

@@ -840,7 +840,27 @@ namespace {
void add_current_module_name(dictionary& name_space) void add_current_module_name(dictionary& name_space)
{ {
static string module_key("__module__", string::interned); static string module_key("__module__", string::interned);
name_space.set_item(module_key, module_builder::name());
// If the user didn't specify a __module__ attribute already
if (name_space.get_item(module_key).get() == 0)
{
if (module_builder::initializing())
{
// The global __name__ is not properly set in this case
name_space.set_item(module_key, module_builder::name());
}
else
{
// Get the module name from the global __name__
PyObject *globals = PyEval_GetGlobals();
if (globals != NULL)
{
PyObject *module_name = PyDict_GetItemString(globals, "__name__");
if (module_name != NULL)
name_space.set_item(module_key, module_name);
}
}
}
} }
} }

View File

@@ -46,24 +46,19 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python { namespace boost { namespace python {
namespace detail { tuple standard_coerce(ref l, ref r)
{
// Introduced sequence points for exception-safety.
ref first(detail::operator_dispatcher::create(l, l));
ref second(r->ob_type == &detail::operator_dispatcher::type_obj
? r
: ref(detail::operator_dispatcher::create(r, ref())));
tuple extension_class_coerce(ref l, ref r) return tuple(first, second);
{ }
// Introduced sequence points for exception-safety.
ref first(operator_dispatcher::create(l, l)); namespace detail {
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 }; enum { unwrap_exception_code = -1000 };

View File

@@ -6,12 +6,12 @@ from gen_singleton import *
from gen_extclass import * from gen_extclass import *
def gen_all(args): def gen_all(args):
open('callback.h', 'w').write(gen_callback(args)) open('callback.hpp', 'w').write(gen_callback(args))
open('caller.h', 'w').write(gen_caller(args)) open('caller.hpp', 'w').write(gen_caller(args))
open('init_function.h', 'w').write(gen_init_function(args)) open('init_function.hpp', 'w').write(gen_init_function(args))
open('signatures.h', 'w').write(gen_signatures(args)) open('signatures.hpp', 'w').write(gen_signatures(args))
open('instance.h', 'w').write(gen_singleton(args)) open('instance.hpp', 'w').write(gen_singleton(args))
open('extclass.h', 'w').write(gen_extclass(args)) open('extension_class.hpp', 'w').write(gen_extclass(args))
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys

View File

@@ -707,8 +707,6 @@ class extension_instance : public instance
// Template function implementations // Template function implementations
// //
tuple extension_class_coerce(ref l, ref r);
template <class T, class U> template <class T, class U>
extension_class<T, U>::extension_class() extension_class<T, U>::extension_class()
: extension_class_base(typeid(T).name()) : extension_class_base(typeid(T).name())
@@ -729,7 +727,7 @@ void extension_class<T, U>::def_standard_coerce()
ref coerce_fct = dict().get_item(string("__coerce__")); ref coerce_fct = dict().get_item(string("__coerce__"));
if(coerce_fct.get() == 0) // not yet defined if(coerce_fct.get() == 0) // not yet defined
this->def(&extension_class_coerce, "__coerce__"); this->def(&standard_coerce, "__coerce__");
} }
template <class T, class U> template <class T, class U>

View File

@@ -14,10 +14,15 @@ namespace {
ref name_holder; ref name_holder;
} }
bool module_builder::initializing()
{
return name_holder.get() != 0;
}
string module_builder::name() string module_builder::name()
{ {
// If this fails, you haven't created a module_builder object // If this fails, you haven't created a module_builder object
assert(name_holder.get() != 0); assert(initializing());
return string(name_holder); return string(name_holder);
} }
@@ -29,6 +34,11 @@ module_builder::module_builder(const char* name)
name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__"))); name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__")));
} }
module_builder::~module_builder()
{
name_holder.reset();
}
void void
module_builder::add(detail::function* x, const char* name) module_builder::add(detail::function* x, const char* name)
{ {

View File

@@ -11,7 +11,7 @@
#include <math.h> // for pow() #include <math.h> // for pow()
#include <boost/rational.hpp> #include <boost/rational.hpp>
namespace extclass_demo { namespace bpl_test {
FooCallback::FooCallback(PyObject* self, int x) FooCallback::FooCallback(PyObject* self, int x)
: Foo(x), m_self(self) : Foo(x), m_self(self)
@@ -714,12 +714,14 @@ const Record* get_record()
return &v; return &v;
} }
template class boost::python::class_builder<Record>; // explicitly instantiate } // namespace bpl_test
} // namespace extclass_demo namespace boost { namespace python {
template class class_builder<bpl_test::Record>; // explicitly instantiate
}} // namespace boost::python
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
inline PyObject* to_python(const extclass_demo::Record* p) inline PyObject* to_python(const bpl_test::Record* p)
{ {
return to_python(*p); return to_python(*p);
} }
@@ -731,7 +733,7 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
/* */ /* */
/************************************************************/ /************************************************************/
namespace extclass_demo { namespace bpl_test {
struct EnumOwner struct EnumOwner
{ {
@@ -753,8 +755,8 @@ struct EnumOwner
} }
namespace boost { namespace python { namespace boost { namespace python {
template class enum_as_int_converters<extclass_demo::EnumOwner::enum_type>; template class enum_as_int_converters<bpl_test::EnumOwner::enum_type>;
using extclass_demo::pow; using bpl_test::pow;
}} // namespace boost::python }} // namespace boost::python
// This is just a way of getting the converters instantiated // This is just a way of getting the converters instantiated
@@ -763,7 +765,7 @@ namespace boost { namespace python {
//{ //{
//}; //};
namespace extclass_demo { namespace bpl_test {
/************************************************************/ /************************************************************/
/* */ /* */
@@ -1036,7 +1038,7 @@ void init_module(boost::python::module_builder& m)
world_class.def(world_setstate, "__setstate__"); world_class.def(world_setstate, "__setstate__");
} }
PyObject* raw(boost::python::tuple const& args, boost::python::dictionary const& keywords) PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary& keywords)
{ {
if(args.size() != 2 || keywords.size() != 2) if(args.size() != 2 || keywords.size() != 2)
{ {
@@ -1055,21 +1057,21 @@ PyObject* raw(boost::python::tuple const& args, boost::python::dictionary const&
void init_module() void init_module()
{ {
boost::python::module_builder demo("demo"); boost::python::module_builder test("test");
init_module(demo); init_module(test);
// Just for giggles, add a raw metaclass. // Just for giggles, add a raw metaclass.
demo.add(new boost::python::meta_class<boost::python::instance>); test.add(new boost::python::meta_class<boost::python::instance>);
} }
extern "C" extern "C"
#ifdef _WIN32 #ifdef _WIN32
__declspec(dllexport) __declspec(dllexport)
#endif #endif
void initdemo() void inittest()
{ {
try { try {
extclass_demo::init_module(); bpl_test::init_module();
} }
catch(...) { catch(...) {
boost::python::handle_exception(); boost::python::handle_exception();
@@ -1083,7 +1085,7 @@ CompareIntPairPythonClass::CompareIntPairPythonClass(boost::python::module_build
def(&CompareIntPair::operator(), "__call__"); def(&CompareIntPair::operator(), "__call__");
} }
} // namespace extclass_demo } // namespace bpl_test
#if defined(_WIN32) #if defined(_WIN32)
@@ -1124,7 +1126,7 @@ BOOL WINAPI DllMain(
switch(fdwReason) switch(fdwReason)
{ {
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
assert(extclass_demo::total_Ints == 0); assert(bpl_test::total_Ints == 0);
} }
#endif #endif

View File

@@ -6,8 +6,8 @@
// The author gratefully acknowleges the support of Dragon Systems, Inc., in // The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work. // producing this work.
#ifndef EXTCLASS_DEMO_DWA052200_H_ #ifndef BPL_TEST_DWA052200_H_
# define EXTCLASS_DEMO_DWA052200_H_ # define BPL_TEST_DWA052200_H_
// //
// Example code demonstrating extension class usage // Example code demonstrating extension class usage
// //
@@ -21,7 +21,7 @@
# include <string> # include <string>
# include <map> # include <map>
namespace extclass_demo { namespace bpl_test {
// //
// example: Foo, Bar, and Baz are C++ classes we want to wrap. // example: Foo, Bar, and Baz are C++ classes we want to wrap.
@@ -226,6 +226,6 @@ struct CompareIntPairPythonClass
CompareIntPairPythonClass(boost::python::module_builder&); CompareIntPairPythonClass(boost::python::module_builder&);
}; };
} // namespace extclass_demo } // namespace bpl_test
#endif // EXTCLASS_DEMO_DWA052200_H_ #endif // BPL_TEST_DWA052200_H_

View File

@@ -209,7 +209,7 @@ Polymorphism also works:
Pickling tests: Pickling tests:
>>> world.__module__ >>> world.__module__
'demo' 'test'
>>> world.__safe_for_unpickling__ >>> world.__safe_for_unpickling__
1 1
>>> world.__reduce__() >>> world.__reduce__()
@@ -1072,7 +1072,7 @@ test methodologies for wrapping functions that return a pointer
1 1
''' '''
from demo import * from test import *
import string import string
import re import re
import sys import sys
@@ -1080,8 +1080,8 @@ import sys
def run(args = None): def run(args = None):
if args is not None: if args is not None:
sys.argv = args sys.argv = args
import doctest, test_extclass import doctest, comprehensive
doctest.testmod(test_extclass) doctest.testmod(comprehensive)
if __name__ == '__main__': if __name__ == '__main__':
run() run()

1112
test/doctest.py Normal file

File diff suppressed because it is too large Load Diff

426
todo.txt Normal file
View File

@@ -0,0 +1,426 @@
Check for const reference parameters in all from_python functions in py.h, including implementations.
Better python and C++ exception handling/error reporting.
long long support
use Python generic numeric coercion in from_python() for C++ numeric types
Rename PyPtr to Reference.
Report Cygwin linker memory issues
__init__ stuff
Make abstract classes non-instantiable (?)
Call default __init__ functions automatically where applicable (?)
Support for Python LONG types in Objects.h
Throw TypeError after asserting when objects from objects.cpp detect a type mismatch.
Figure out how to package everything as a shared library.
Unicode string support
Add read-only wrapper for __dict__ attribute
Objects.h support for generic objects, Sequence objects, etc.
empty() member functions for objects.hpp
Testing
Python 2.0
object revival in __del__
More thorough tests of objects.h/cpp classes
Better reference-count checking
Optimizations
Remove one level of indirection on type objects (no vtbl?).
Specializations of Caller<> for commmon combinations of argument types (?)
Replace uses of XXXable classes
Don't allocate instance __dict__ unless used.
Documentation:
differences between Python classes and ExtensionClasses
additional capabilities of ExtensionClasses
slice adjustment
Why special attributes other than __doc__ and __name__ are immutable.
An example of the problems with the built-in Python classes.
>>> class A:
... def __getattr__(self, name):
... return 'A.__getattr__'
...
>>> class B(A): pass
...
>>> class C(B): pass
...
>>> C().x
'A.__getattr__'
>>> B.__bases__ = ()
>>> C().x
'A.__getattr__'
Smart pointers
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
namespace py {
#endif
template <class T>
struct VtkConverters
{
typedef py::PyExtensionClassConverters<T> Converters;
friend vtk_ptr<T>& from_python(PyObject* p, py::Type<vtk_ptr<T>&>)
{ return Converters::ptr_from_python(p, py::Type<vtk_ptr<T> >()); }
friend vtk_ptr<T>& from_python(PyObject* p, py::Type<vtk_ptr<T> >)
{ return Converters::ptr_from_python(p, py::Type<vtk_ptr<T> >()); }
friend const vtk_ptr<T>& from_python(PyObject* p, py::Type<const vtk_ptr<T>&>)
{ return Converters::ptr_from_python(p, py::Type<vtk_ptr<T> >()); }
friend PyObject* to_python(vtk_ptr<T> x)
{ return Converters::ptr_to_python(x); }
};
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
}
#endif
template <class T>
struct VtkWrapper : py::ClassWrapper<T>, py::VtkConverters<T>
{
typedef py::ClassWrapper<T> Base;
VtkWrapper(Module& module, const char* name)
: Base(module, name) {}
};
exception handling
Advanced Topics:
Advanced Type Conversion
adding conversions for fundamental types
generic conversions for template types (with partial spec).
Interacting with built-in Python objects and types from C++
dealing with non-const reference/pointer parameters
extending multiple-argument support using gen_all.py
Fancy wrapping tricks
templates
Yes. If you look at the examples in extclass_demo.cpp you'll see that I have
exposed several template instantiations (e.g. std::pair<int,int>) in Python.
Keep in mind, however, that you can only expose a template instantiation,
not a template. In other words, MyTemplate<Foo> can be exposed. MyTemplate
itself cannot.
Well, that's not strictly true. Wow, this is more complicated to explain
than I thought.
You can't make an ExtensionClass<MyTemplate>, since after all MyTemplate is
not a type. You can only expose a concrete type to Python.
What you *can* do (if your compiler supports partial ordering of function
templates - MSVC is broken and does not) is to write appropriate
from_python() and to_python() functions for converting a whole class of
template instantiations to/from Python. That won't let you create an
instance of MyTemplate<SomePythonType> from Python, but it will let you
pass/return arbitrary MyTemplate<SomeCplusplusType> instances to/from your
wrapped C++ functions.
template <class T>
MyTemplate<T> from_python(PyObject* x, py::Type<MyTemplate<T> >)
{
// code to convert x into a MyTemplate<T>... that part is up to you
}
template <class T>
PyObject* from_python(const MyTemplate<T>&)
{
// code to convert MyTemplate<T> into a PyObject*... that part is up to
you
}
For example, you could use this to convert Python lists to/from
std::vector<T> automatically.
Pointer return values
Case 1:
> I am now also able to wrap the problematic TextRecordIterator for Python.
> However, one of its function compiles with this warning:
>
> d:\py_cpp/caller.h(33) : warning C4800: 'const class Record *const '
> : forcing value to bool 'true' or 'false' (performance warning)
> d:\py_cpp/functions.h(54) : see reference to function template
> instantiation 'struct _object *__cdecl py::Caller::call(const class Record
> *const (__thiscall TextRecordIterator::*)(void),struct _object *,struct
> _object *)' being compiled
>
> If you look at the offending code, you'll see that we really do need to
> get back that pointer:
>
> const Record* const TextRecordIterator::Next() {
> if (fStatus != RecordIterator::SUCCESS) {
> return 0;
> } else {
> return &fData;
> }
> }
>
> The point of the TextRecordIterator is to hand over one reord after
> another. A bool wouldn't do us much good here :-)
>
> Do you have any suggestions for fixing this?
In general, py_cpp doesn't automatically convert pointer return values
to_python because pointers have too many potential meanings. Is it an
iterator? A pointer to a single element? An array? Is ownership being passed
to Python or is the pointer really just a reference? If the latter, what
happens when some C++ code deletes the referent. The only exception to this
rule is const char*, since it has a generally accepted interpretation (could
be trouble with some generic code, though!)
If you have wrapped the Record class, you could add this to namespace py:
PyObject* to_python(const Record* p) {
return to_python(*p);
}
Of course, this will cause the Record class to be copied. If you can't live
with that (Record would have to be /really/ heavyweight to make this
worthwhile), you can follow one of these dangerous approaches:
1. Use the technique I described with dangerous_array in
http://www.egroups.com/message/boost/6196. You do not have to expose Record
explicitly in this case. Instead the class you expose will be more of a
Record_proxy
2. Wrap Record in the usual way, then add the following to namespace py:
PyObject* to_python(const Record* p)
{
return ExtensionClass<Record>::ptr_to_python(const_cast<Record*>(p));
}
This will cause the Record* 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 const-correctness issue: Const-correctness is completely
lost to Python anyway!
3. As above, but instead wrap const Record rather than plain Record. Then
you can avoid the const_cast, but you obviously can't def() any non-const
member functions of Record.
Case 2:
> I have yet another question. This is more a general wrapper question.
> Let me say that there is a function that returns a float* which most
> probably is an array. Similarly if I have a function that takes a
> float* as an argument, what is the best way of wrapping this?
I think you have correctly perceived that it doesn't make sense for me to
automatically convert all pointers, since the ownership semantics are so
blurry.
> 1) If the array is small it makes sense to convert it to either a
> tuple or list. What is the easiest way to do this?? I am looking
> for a way that makes one write the least code. :)
How can you tell the length of the array from a single pointer?
Once you've answered that question, you can expose a wrapper function which
returns an instance of the py::Tuple or py::List class from objects.h. If
you are using a List, for example, you could write something like this:
py::List wrap_f()
{
T* start = f();
py::List x;
for (T* p = start; p != start + length_constant; ++p)
x.push_back(py::to_python(*p));
return x;
}
> 2) If the array is large it may not make sense to use a list/tuple
> esp. if the values are used for computationally intense programs.
In this case you can do one of several somewhat dangerous things. Why
dangerous? Because python can not control the lifetime of the data, so the
data in the array may be destroyed or become invalid before the last
reference to it disappears. The basic approach is to make a small C++ class
which contains the pointer, and expose that:
// UNTESTED
template <class T>
struct dangerous_array
{
dangerous_array(T* start, T* end)
: m_start(start), m_end(end) {}
// exposed as "__len__"
std::size_t length() {
return m_end - m_start;
}
// exposed as "__getitem__"
T get_item(std::size_t n) {
check_range(n);
return start[n];
}
// exposed as "__setitem__" if the array is mutable
void set_item(std::size_t n, const T& x) {
check_range(n);
start[n] = x;
}
private:
void check_range(std::size_t n) {
if (n >= m_end - m_start) {
PyErr_SetString(PyExc_IndexError, "array index out of range");
throw py::ErrorAlreadySet;
}
}
T* m_start;
T* m_end;
};
A reasonably safe approach would be to make a wrapper function for each
function that returns a T*, and expose that instead. If you're too lazy and
you really like to live on the edge, though, you can write to_python(T*) in
terms of to_python(const dangerous_array<T>&), and you'll automatically
convert all T* return values to a wrapped dangerous_array.
> 3) For an arbitrary class "class_A", say, can py_cpp handle
> references to class_A &instance, or class_A *instance?? i.e. will it
> wrap function calls to such objects? This question is obviously
> related to the earlier questions.
Yes, iff class_A has been exposed to python with a ClassWrapper<class_A>.
See http://people.ne.mediaone.net/abrahams/downloads/under-the-hood.html for
a few details.
raw C++ arrays
You could expose a function like this one to get the desired effect:
#include <py_cpp/objects.h>
void set_len(UnitCell& x, py::Tuple tuple)
{
double len[3];
for (std::size_t i =0; i < 3; ++i)
len[i] = py::from_python(tuple[i].get(), py::Type<double>());
x.set_len(len);
}
Types that are already wrapped by other libraries
It's not documented yet, but you should be able to use a raw PyObject* or a
py::Ptr as one parameter to your C++ function. Then you can manipulate it as
any other generic Python object.
Alternatively, If the NTL gives you a C/C++ interface, you can also write
your own converter function:
some_ntl_type& from_python(PyObject* p, py::Type<some_NTL_type&>)
{
// an Example implementation. Basically, you need
// to extract the NTL type from the PyObject*.
if (p->ob_type != NTL_long_type) {
PyErr_SetString(PyExc_TypeErr, "NTL long required");
throw py::ArgumentError();
}
return *static_cast<some_NTL_type*>(p);
}
then the C++ functions you're wrapping can take a some_NTL_type& parameter
directly.
"Thin converting wrappers" for constructors
hijack some of the functionality
described in the section on Overridable Virtual Functions (even though you
don't have any virtual functions). I suggest this workaround:
struct UnitCellWrapper : UnitCell
{
UnitCellWrapper(PyObject* self, py::Tuple x, py::Tuple y)
: UnitCell(from_python(x[1], py::Type<double>()),
from_python(x[2], py::Type<double>()),
from_python(x[3], py::Type<double>()),
from_python(y[1], py::Type<double>()),
from_python(y[2], py::Type<double>()),
from_python(y[3], py::Type<double>()))
{}
}
py::ClassWrapper<UnitCell, UnitCellWrapper> unit_cell_class;
unit_cell_class.def(py::Constructor<py::Tuple, py::Tuple>());
...
returning references to wrapped objects
the importance of declaration order of ClassWrappers/ExtensionInstances
out parameters and non-const pointers
Calling back into Python:
// caveat: UNTESTED!
#include <py_cpp/pyptr.h>
#include <py_cpp/callback.h>
#include <py_cpp/py.h>
#include <Python.h>
int main()
{
try {
py::Ptr module(PyImport_ImportModule("weapons"));
const int strength = 10;
const char* manufacturer = "Vordon Empire";
py::Ptr a_blaster(py::Callback<py::Ptr>::call_method(
module.get(), "Blaster", strength, manufacturer));
py::Callback<void>::call_method(a_blaster.get(), "Fire");
int old_strength = py::Callback<int>::call_method(a_blaster.get(), "get_strength");
py::Callback<void>::call_method(a_blaster.get(), "set_strength", 5);
}
catch(...)
{
}
}
Miscellaneous
About the vc6 project and the debug build
About doctest.py
Boost remarks:
> > One of us is completely nuts ;->. How can I move the test
> > (is_prefix(enablers[i].name + 2, name + 2)) outside the loop if it
depends
> > on the loop index, i?
> >
> name += 2;
> for()
> {
> if (is_prefix(enablers[i].name + 2, name))
> }
I see now. I guess I should stop pussyfooting and either go for optimization
or clarity here, eh?
------
> Re: Dict
> Why abbreviate this? Code is read 5 or 6 times for every time its
> written. The few extra characters don't affect compile time or program
> speed. It's part of my personal goal of write what you mean, name them
what
> they are.
I completely agree. Abbrevs rub me the wrong way, 2 ;->
-------
Later:
keyword and varargs?
Put explicit Type<> arguments at the beginnings of overloads, to make them look more like template instance specifications.
Known bugs
can't handle 'const void' return values
Who returns 'const void'? I did it once, by mistake ;)