mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
2 Commits
svn-branch
...
boost-1.20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56614b282d | ||
|
|
54ec2a41b2 |
216
build/bpl_static.dsp
Normal file
216
build/bpl_static.dsp
Normal 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 "d:\boost\type_traits" /I "..\..\.." /I "c:\progra~1\python20\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# 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
74
build/build.dsw
Normal 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
BIN
build/build.opt
Normal file
Binary file not shown.
51
build/como.mak
Normal file
51
build/como.mak
Normal 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
107
build/example1/example1.dsp
Normal 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
53
build/gcc.mak
Normal 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
105
build/rwgk1/rwgk1.dsp
Normal 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
112
build/test/test.dsp
Normal 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
51
build/tru64.mak
Normal 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
|
||||
212
doc/#index.html#
212
doc/#index.html#
@@ -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 “reflect” 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 “boostification“
|
||||
(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<>
|
||||
|
||||
<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<0.2wink> 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>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided “as is” without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Building a Module with Py_cpp
|
||||
Building an Extension Module
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Building a Module with Py_cpp
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Building an Extension Module
|
||||
</h1>
|
||||
<p>
|
||||
Right now, the only supported configuration is one in which the 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
|
||||
module. You may first build them into a library and link it with your
|
||||
extension module source, but the effect is the same as compiling all
|
||||
the source files together. Some users have successfully built the
|
||||
py_cpp sources into a shared library, and support for a shared library
|
||||
build is planned, but not yet implemented. The py_cpp source files are:
|
||||
sources into a shared library, and support for a shared library
|
||||
build is planned, but not yet implemented. The BPL source files are:
|
||||
<blockquote>
|
||||
<pre>
|
||||
<a href="../../../libs/python/src/extension_class.cpp">extclass.cpp</a>
|
||||
@@ -29,13 +29,14 @@
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Next: <a href="enums.html">Enums</a>
|
||||
Previous: <a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided “as
|
||||
is” without express or implied warranty, and with no claim as to
|
||||
notice appears in all copies. This document is provided ``as
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
|
||||
@@ -12,14 +12,16 @@
|
||||
|
||||
<h2>CXX</h2>
|
||||
<p>
|
||||
Like py_cpp, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
||||
provide a C++-oriented interface to Python. In most cases, like py_cpp,
|
||||
it relieves the user from worrying about reference-counts. As far as I
|
||||
can tell, there is no support for subclassing C++ extension types in
|
||||
Python. An even more-significant difference is that a user's C++ code is
|
||||
still basically “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.
|
||||
Like BPL, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
||||
provide a C++-oriented interface to Python. In most cases, as with the
|
||||
boost library, it relieves the user from worrying about
|
||||
reference-counts. Both libraries automatically convert thrown C++
|
||||
exceptions into Python exceptions. As far as I can tell, CXX has no
|
||||
support for subclassing C++ extension types in Python. An even
|
||||
more significant difference is that a user's C++ code is still basically
|
||||
``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>
|
||||
CXX claims to interoperate well with the C++ Standard Library
|
||||
@@ -38,11 +40,9 @@
|
||||
<p>
|
||||
As far as I can tell, CXX enables one to write what is essentially
|
||||
idiomatic Python code in C++, manipulating Python objects through the
|
||||
same fully-generic interfaces we use in Python. I think it would be fair
|
||||
to say that while you're not programming directly to the “bare
|
||||
metal” with CXX, in comparison to py_cpp, it presents a low-level
|
||||
interface to Python. That use is also supported by the py_cpp object
|
||||
wrappers.
|
||||
same fully-generic interfaces we use in Python. While you're hardly programming directly to the ``bare
|
||||
metal'' with CXX, it basically presents a ``C++-ized''
|
||||
version of the Python 'C' API.
|
||||
|
||||
<p>
|
||||
<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:
|
||||
|
||||
<blockquote>
|
||||
“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
|
||||
the wrapping business covered. I thought maybe CXX would provide an easier
|
||||
target language for those making wrappers, but I never explored
|
||||
that.”<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>
|
||||
|
||||
<h2>SWIG</h2>
|
||||
@@ -65,28 +65,28 @@ that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
languages. Swig relies on a parser to read your source code and produce
|
||||
additional source code files which can be compiled into a Python (or
|
||||
Perl or Tcl) extension module. It has been successfully used to create
|
||||
many Python extension modules. Like 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 code. The documentation says “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
|
||||
result, interfaces are usually built by grabbing a header file and
|
||||
tweaking it a little bit.” 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
|
||||
writes:
|
||||
|
||||
<blockquote> “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
|
||||
ANSI C libraries this was fine. But for usual C++ code this was a
|
||||
problem. Simple things work. But for anything very complicated (or
|
||||
realistic), one had to write code by hand. I believe 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
|
||||
wrap correctly.”<br><i>-Prabhu Ramachandran</i>
|
||||
wrap correctly.''<br><i>-Prabhu Ramachandran</i>
|
||||
</blockquote>
|
||||
|
||||
<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
|
||||
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
|
||||
member functions you want to expose in Python.
|
||||
|
||||
@@ -95,7 +95,7 @@ that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
<a
|
||||
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
|
||||
is a system similar to SWIG, though seemingly more
|
||||
C++-oriented. The author says that like 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
|
||||
have been designed specifically to directly support some features of
|
||||
PyQt/PyKDE, which is its primary client. Documentation is almost
|
||||
@@ -113,7 +113,7 @@ that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
to a wide range of computer languages, including Common Lisp, C++, C,
|
||||
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
|
||||
header file describing the interface, of which the user is expected to
|
||||
provide an implementation. Unlike 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
|
||||
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
|
||||
@@ -124,7 +124,7 @@ that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
<a
|
||||
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</a>
|
||||
is another very ambitious project aimed at generating Python wrappers for
|
||||
interfaces written in “legacy languages”, 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
|
||||
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
|
||||
@@ -148,70 +148,70 @@ an inheritance relationship?
|
||||
<h2>Zope ExtensionClasses</h2>
|
||||
<p>
|
||||
<a href="http:http://www.digicool.com/releases/ExtensionClass">
|
||||
ExtensionClasses in Zope</a> use the same underlying mechanism as py_cpp
|
||||
ExtensionClasses in Zope</a> use the same underlying mechanism as BPL
|
||||
to support subclassing of extension types in Python, including
|
||||
multiple-inheritance. Both systems support pickling/unpickling of
|
||||
extension class instances in very similar ways. Both systems rely on the
|
||||
same “<a
|
||||
same ``<a
|
||||
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
|
||||
Beaudry Hack</a>” that also inspired Don's MESS System.
|
||||
Beaudry Hack</a>'' that also inspired Don's MESS System.
|
||||
<p>
|
||||
The major differences are:
|
||||
<ul>
|
||||
<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.
|
||||
<li>
|
||||
py_cpp lifts the burden on the user to maintain Python
|
||||
BPL lifts the burden on the user to maintain Python
|
||||
reference-counts.
|
||||
<li>
|
||||
py_cpp supports function overloading; Zope does not.
|
||||
BPL supports function overloading; Zope does not.
|
||||
<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
|
||||
attributes.
|
||||
<li>
|
||||
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=
|
||||
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
|
||||
Zope Example</a> illustrates the differences.
|
||||
<li>
|
||||
Zope's ExtensionClasses are specifically motivated by “the need for a
|
||||
C-based persistence mechanism”. Py_cpp's are motivated by the desire
|
||||
Zope's ExtensionClasses are specifically motivated by ``the need for a
|
||||
C-based persistence mechanism''. BPL's are motivated by the desire
|
||||
to simply reflect a C++ API into Python with as little modification as
|
||||
possible.
|
||||
<li>
|
||||
The following Zope restriction does not apply to py_cpp: “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
|
||||
members. If an extension subclass inherits from multiple base
|
||||
extension classes, then all but one must be mix-in classes that
|
||||
provide extension methods but no data.”
|
||||
provide extension methods but no data.''
|
||||
<li>
|
||||
Zope requires use of the somewhat funky inheritedAttribute (search for
|
||||
“inheritedAttribute” on <a
|
||||
``inheritedAttribute'' on <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
|
||||
“<code>BaseClass.method</code>”.
|
||||
``<code>BaseClass.method</code>''.
|
||||
<li>
|
||||
Zope supplies some creative but esoteric idioms such as <a href=
|
||||
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
|
||||
Acquisition</a>. No specific support for this is built into py_cpp.
|
||||
Acquisition</a>. No specific support for this is built into BPL.
|
||||
<li>
|
||||
Zope's ComputedAttribute support is designed to be used from Python.
|
||||
<a href="special.html#getter_setter">The analogous feature of
|
||||
py_cpp</a> can be used from C++ or Python. The feature is arguably
|
||||
easier to use in py_cpp.
|
||||
BPL</a> can be used from C++ or Python. The feature is arguably
|
||||
easier to use in BPL.
|
||||
</ul>
|
||||
<p>
|
||||
Next: <a href="example1.html">A Simple Example Using BPL</a>
|
||||
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
|
||||
Next: <a href="example1.html">A Simple Example Using py_cpp</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided “as is” without
|
||||
notice appears in all copies. This document is provided ``as is'' without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
|
||||
192
doc/data_structures.txt
Normal file
192
doc/data_structures.txt
Normal 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 |
|
||||
+---------------------+ +---+ +----------------------+
|
||||
@@ -8,31 +8,36 @@
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Wrapping enums
|
||||
</h1>
|
||||
|
||||
<p>Because there is in general no way to deduce that a value of arbitrary type T
|
||||
is an enumeration constant, py_cpp cannot automatically convert enum values to
|
||||
and from Python. To handle this case, you need to decide how you want the enum
|
||||
to show up in Python (since Python doesn't have enums). Once you have done that,
|
||||
you can write some simple <code>from_python()</code> and
|
||||
<code>to_python()</code> functions.
|
||||
is an enumeration constant, the Boost Python Library cannot automatically
|
||||
convert enum values to and from Python. To handle this case, you need to decide
|
||||
how you want the enum to show up in Python (since Python doesn't have
|
||||
enums). Once you have done that, you can write some simple
|
||||
<code>from_python()</code> and <code>to_python()</code> functions.
|
||||
|
||||
<p>If you are satisfied with a Python int as a way to represent your enum
|
||||
values, 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<EnumType></code> where
|
||||
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
|
||||
|
||||
<ol>
|
||||
<li><blockquote>
|
||||
<pre>
|
||||
...
|
||||
} // close my_namespace
|
||||
// drop into namespace python and explicitly instantiate
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
template class enum_as_int_converters<extclass_demo::EnumOwner::enum_type>;
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
namespace my_namespace { // re-open my_namespace
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
<li><blockquote><pre>
|
||||
// instantiate as base class in any namespace
|
||||
struct EnumTypeConverters
|
||||
: boost::python::py_enum_as_int_converters<EnumType>
|
||||
: boost::python::enum_as_int_converters<EnumType>
|
||||
{
|
||||
};
|
||||
</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");
|
||||
...
|
||||
</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>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided “as
|
||||
is” without express or implied warranty, and with no claim as to
|
||||
notice appears in all copies. This document is provided ``as
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
A Simple Example Using py_cpp
|
||||
A Simple Example
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
@@ -9,7 +9,7 @@
|
||||
"c++boost.gif (8819 bytes)">
|
||||
</h1>
|
||||
<h1>
|
||||
A Simple Example Using py_cpp
|
||||
A Simple Example
|
||||
</h1>
|
||||
<p>
|
||||
Suppose we have the following C++ API which we want to expose in
|
||||
@@ -24,20 +24,20 @@ namespace hello {
|
||||
public:
|
||||
world(int);
|
||||
~world();
|
||||
std::string get() const { return "hi, world"; }
|
||||
std::string greet() const { return "hi, world"; }
|
||||
...
|
||||
};
|
||||
std::size_t length(const world& x) { return std::strlen(x.get()); }
|
||||
std::size_t length(const world& x) { return std::strlen(x.greet()); }
|
||||
}
|
||||
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Here is the C++ code for a python module called <code>hello</code>
|
||||
which exposes the API using py_cpp:
|
||||
which exposes the API using:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
// Python requires an exported function called init<module-name> in every
|
||||
// extension module. This is where we build the module contents.
|
||||
extern "C"
|
||||
@@ -49,15 +49,15 @@ void inithello()
|
||||
try
|
||||
{
|
||||
// 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
|
||||
boost::python::class_builder<hello::world> world_class(hello, "world");
|
||||
boost::python::class_builder<hello::world> world_class(m, "world");
|
||||
// Add the __init__ function
|
||||
world_class.def(boost::python::constructor<int>());
|
||||
// Add a regular member function
|
||||
world_class.def(&hello::world::get, "get");
|
||||
// Add a regular function to the module
|
||||
hello.def(hello::length, "length");
|
||||
m.def(hello::length, "length");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -82,7 +82,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
<pre>
|
||||
>>> import hello
|
||||
>>> hi_world = hello.world(3)
|
||||
>>> hi_world.get()
|
||||
>>> hi_world.greet()
|
||||
'hi, world'
|
||||
>>> hello.length(hi_world)
|
||||
9
|
||||
@@ -93,11 +93,11 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> class my_subclass(hello.world):
|
||||
... def get(self):
|
||||
... def greet(self):
|
||||
... return 'hello, world'
|
||||
...
|
||||
>>> y = my_subclass(4)
|
||||
>>> y.get()
|
||||
>>> y.greet()
|
||||
'hello, world'
|
||||
</pre>
|
||||
</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=
|
||||
"overriding.html">read on</a>...
|
||||
<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>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
|
||||
@@ -38,11 +38,11 @@
|
||||
</ul>
|
||||
This last item typically occupies a great deal of code in an extension
|
||||
module. Remember that Python is a completely dynamic language. A callable
|
||||
object receives its arguments in a tuple; it is up to that object to
|
||||
extract those arguments from the tuple, check their types, and raise
|
||||
appropriate exceptions. There are numerous other tedious details that need
|
||||
to be managed; too many to mention here. Py_cpp is designed to lift most of
|
||||
that burden.<br>
|
||||
object receives its arguments in a tuple; it is up to that object to extract
|
||||
those arguments from the tuple, check their types, and raise appropriate
|
||||
exceptions. There are numerous other tedious details that need to be
|
||||
managed; too many to mention here. The Boost Python Library is designed to
|
||||
lift most of that burden.<br>
|
||||
<br>
|
||||
|
||||
<p>
|
||||
@@ -56,10 +56,10 @@
|
||||
sublcassing the extension type. Aside from being tedious, it's not really
|
||||
the same as having a true class, because there's no way for the user to
|
||||
override a method of the extension type which is called from the
|
||||
extension module. 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
|
||||
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
|
||||
follow (someday).</p>
|
||||
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
|
||||
|
||||
119
doc/index.html
119
doc/index.html
@@ -2,28 +2,24 @@
|
||||
"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
|
||||
The Boost Python Library (BPL)
|
||||
</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>
|
||||
align="center" height="86">The Boost Python Library (BPL)
|
||||
</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
|
||||
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
|
||||
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 “reflect” your C++ classes and functions into
|
||||
Python. The major features of py_cpp include support for:
|
||||
your C++ classes in any way in order to use them with BPL. The system
|
||||
<em>should</em> simply ``reflect'' your C++ classes and functions into
|
||||
Python. The major features of BPL include support for:
|
||||
<ul>
|
||||
<li><a href="inheritance.hml">Subclassing extension types in Python</a>
|
||||
<li><a href="inheritance.html">Subclassing extension types in Python</a>
|
||||
<li><a href="overriding.html">Overriding virtual functions in Python</a>
|
||||
<li><a href="overloading.html">[Member] function Overloading</a>
|
||||
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
|
||||
@@ -32,7 +28,7 @@ among others.
|
||||
|
||||
|
||||
<h2>Supported Platforms</h2>
|
||||
<p>py_cpp has been tested in the following configurations:
|
||||
<p>BPL has been tested in the following configurations:
|
||||
|
||||
<ul>
|
||||
<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>]
|
||||
|
||||
<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>
|
||||
<br>
|
||||
<li>Against Python 2.0 using the following compiler/library combinations:
|
||||
@@ -67,18 +63,13 @@ among others.
|
||||
</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 “boostification“
|
||||
(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="../../../people/dave_abrahams.htm">David Abrahams</a> originated
|
||||
and wrote the library.
|
||||
|
||||
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
|
||||
had independently developed a similar system. When he discovered py_cpp,
|
||||
had independently developed a similar system. When he discovered BPL,
|
||||
he generously contributed countless hours of coding and much insight into
|
||||
improving it. He is responsible for an early version of the support for <a
|
||||
href="overloading.html">function overloading</a> and wrote the support for
|
||||
@@ -88,13 +79,13 @@ among others.
|
||||
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 members of the boost mailing list and the Python community
|
||||
supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans,
|
||||
Anton Gluck, Ralf W. Grosse-Kunstleve, Chuck Ingold, Prabhu Ramachandran,
|
||||
and Barry Scott took the brave step of trying to use BPL while it was
|
||||
still in early stages of development.
|
||||
|
||||
<li>The development of 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
|
||||
Hauspie, Inc</a> who supported its development as an open-source project.
|
||||
</ul>
|
||||
@@ -105,10 +96,10 @@ among others.
|
||||
<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
|
||||
<li><a href="comparisons.html">Comparisons between BPL and other
|
||||
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>
|
||||
|
||||
@@ -120,11 +111,13 @@ among others.
|
||||
|
||||
<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
|
||||
|
||||
<ol>
|
||||
<li>Pickling
|
||||
|
||||
<li>class_builder<>
|
||||
|
||||
<li><a href="enums.html">enums</a>
|
||||
@@ -138,72 +131,28 @@ among others.
|
||||
<li>Other Extension Types
|
||||
|
||||
<li>Templates
|
||||
|
||||
<li><a href="data_structures.txt">Internal Data Structures</a>
|
||||
</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...
|
||||
Documentation is a major ongoing project; assistance is greatly
|
||||
appreciated! In the meantime, useful examples of every BPL feature should
|
||||
be evident in the regression test files <code>test/comprehensive.[<a
|
||||
href="../test/comprehensive.py">py</a>/<a
|
||||
href="../test/comprehensive.hpp">hpp</a>/<a
|
||||
href="../test/comprehensive.cpp">cpp</a>]</code>
|
||||
|
||||
<p>
|
||||
Questions should be directed to <a href=
|
||||
"http://www.egroups.com/list/boost">the boost mailing list</a>.
|
||||
|
||||
<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<0.2wink> 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>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided “as is” without
|
||||
notice appears in all copies. This document is provided ``as is'' without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
<p>
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
<h2>Inheritance in Python</h2>
|
||||
|
||||
<p>
|
||||
Py_cpp extension classes support single and multiple-inheritance in
|
||||
Python, just like regular Python classes. You can mix built-in Python
|
||||
classes with py_cpp extension classes in a derived class' tuple of
|
||||
bases. Whenever a py_cpp extension class is among the bases for a new
|
||||
class in Python, the result is an extension class:
|
||||
BPL extension classes support single and multiple-inheritance in
|
||||
Python, just like regular Python classes. You can arbitrarily mix
|
||||
built-in Python classes with extension classes in a derived class'
|
||||
tuple of bases. Whenever a BPL extension class is among the bases for a
|
||||
new class in Python, the result is an extension class:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> class MyPythonClass:
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
||||
<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
|
||||
references to a base class are expected as arguments. The
|
||||
<code>declare_base</code> member function of
|
||||
@@ -71,7 +71,11 @@ int get_derived_x(const Derived& d) {
|
||||
return d.x;
|
||||
}
|
||||
<hr>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
// namespace alias for code brevity
|
||||
namespace python = boost::python;
|
||||
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
@@ -80,13 +84,13 @@ void initmy_module()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::python::module_builder my_module("my_module");
|
||||
python::module_builder my_module("my_module");
|
||||
|
||||
boost::python::class_builder<Base> base_class(my_module, "Base");
|
||||
base_class.def(boost::python::constructor<void>());
|
||||
python::class_builder<Base> base_class(my_module, "Base");
|
||||
base_class.def(python::constructor<void>());
|
||||
|
||||
boost::python::class_builder<Derived> derived_class(my_module, "Derived");
|
||||
derived_class.def(boost::python::constructor<void>());
|
||||
python::class_builder<Derived> derived_class(my_module, "Derived");
|
||||
derived_class.def(python::constructor<void>());
|
||||
<b>// Establish the inheritance relationship between Base and Derived
|
||||
derived_class.declare_base(base_class);</b>
|
||||
|
||||
@@ -96,7 +100,7 @@ void initmy_module()
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
boost::python::handle_exception(); // Deal with the exception for Python
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
@@ -135,12 +139,12 @@ struct Base2 {};
|
||||
struct Derived2 { int f(); };
|
||||
<hr>
|
||||
...
|
||||
boost::python::class_builder<Base> base2_class(my_module, "Base2");
|
||||
base2_class.def(boost::python::constructor<void>());
|
||||
python::class_builder<Base> base2_class(my_module, "Base2");
|
||||
base2_class.def(python::constructor<void>());
|
||||
|
||||
boost::python::class_builder<Derived2> derived2_class(my_module, "Derived2");
|
||||
derived2_class.def(boost::python::constructor<void>());
|
||||
derived_class.declare_base(base_class, <b>boost::python::without_downcast</b>);
|
||||
python::class_builder<Derived2> derived2_class(my_module, "Derived2");
|
||||
derived2_class.def(python::constructor<void>());
|
||||
derived_class.declare_base(base_class, <b>python::without_downcast</b>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@@ -150,8 +154,8 @@ struct Derived2 { int f(); };
|
||||
references, or values.
|
||||
|
||||
<p>
|
||||
Next: <a href="special.html">Special Method and Operator Support</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>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
|
||||
@@ -113,18 +113,17 @@ namespace scope as Python member functions.
|
||||
|
||||
<h2>Overload Resolution</h2>
|
||||
<p>
|
||||
The function overload resolution mechanism in py_cpp works as
|
||||
follows:
|
||||
The function overload resolution mechanism works as follows:
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Attribute lookup for extension classes proceeds in <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/tut/node11.html#SECTION0011510000000000000000">the
|
||||
href="http://www.python.org/doc/current/tut/node11.html#SECTION0011510000000000000000">the
|
||||
usual Python way</a> using a depth-first, left-to-right search. When a
|
||||
class is found which has a matching attribute, only functions overloaded
|
||||
in the context of that class are candidates for overload resolution. In
|
||||
this sense, overload resolution mirrors the C++ mechanism, where a name
|
||||
in a derived class “hides” all functions with the same name from a base
|
||||
in a derived class ``hides'' all functions with the same name from a base
|
||||
class.
|
||||
<p>
|
||||
|
||||
@@ -133,22 +132,22 @@ namespace scope as Python member functions.
|
||||
<code>def()</code>ed. The first function whose signature can be made to
|
||||
match each argument passed is the one which is ultimately called.
|
||||
This means in particular that you cannot overload the same function on
|
||||
both “<code>int</code>” and “<code>float</code>” because Python
|
||||
both ``<code>int</code>'' and ``<code>float</code>'' because Python
|
||||
automatically converts either of the two types into the other one.
|
||||
If the “<code>float</code>” overload is found first, it is used
|
||||
also used for arguments of type “<code>int</code>” as well, and the
|
||||
“<code>int</code>” version of the function is never invoked.
|
||||
If the ``<code>float</code>'' overload is found first, it is used
|
||||
also used for arguments of type ``<code>int</code>'' as well, and the
|
||||
``<code>int</code>'' version of the function is never invoked.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Prev: <a href="overriding.html">Overridable Virtual Functions</a>
|
||||
Next: <a href="inheritance.html">Special Method Names</a>
|
||||
Next: <a href="inheritance.html">Inheritance</a>
|
||||
Previous: <a href="overriding.html">Overridable Virtual Functions</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided “as
|
||||
is” without express or implied warranty, and with no claim as to
|
||||
notice appears in all copies. This document is provided ``as
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<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:
|
||||
|
||||
<blockquote><pre>
|
||||
@@ -26,7 +26,7 @@ class world
|
||||
public:
|
||||
world(int);
|
||||
virtual ~world();
|
||||
<b>virtual</b> std::string get() const { return "hi, world"; }
|
||||
<b>virtual</b> std::string greet() const { return "hi, world"; }
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -65,11 +65,11 @@ struct world_callback : world
|
||||
: world(x),
|
||||
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<std::string>::call_method(m_self, "get"); }
|
||||
|
||||
static std::string <a name= "default_implementation">default_get</a>(const hello::world& self) const // <a href="#derived_4">4</a>
|
||||
{ return self.world::get(); }
|
||||
{ return self.world::greet(); }
|
||||
private:
|
||||
PyObject* m_self; // <a href="#derived_1">1</a>
|
||||
};
|
||||
@@ -94,7 +94,7 @@ world_class.def(&world::get, "get", &<b>world_callback::default_get</b>)
|
||||
|
||||
<blockquote><pre>
|
||||
>>> class my_subclass(hello.world):
|
||||
... def get(self):
|
||||
... def greet(self):
|
||||
... return 'hello, world'
|
||||
...
|
||||
>>> 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>).
|
||||
|
||||
<p>
|
||||
Prev: <a href="example1.html">A Simple Example Using py_cpp</a> Next: <a
|
||||
href="overloading.html">Function Overloading</a> Up: <a href=
|
||||
"index.html">Top</a>
|
||||
Next: <a href="overloading.html">Function Overloading</a>
|
||||
Previous: <a href="example1.html">A Simple Example Using py_cpp</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<p>
|
||||
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
|
||||
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
|
||||
@@ -34,12 +34,10 @@ converted from/to Python strings.
|
||||
<h3>Can you avoid the problem?</h3>
|
||||
|
||||
<p>My first piece of advice to anyone with a case not covered above is
|
||||
“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
|
||||
T*</code> for some wrapped <code>T</code>, you may be able to write a “thin
|
||||
converting wrapper” over those two functions as follows (Since py_cpp
|
||||
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):
|
||||
``find a way to avoid the problem.'' For example, if you have just one
|
||||
or two functions that return a pointer to an individual <code>const
|
||||
T</code>, and <code>T</code> is a wrapped class, you may be able to write a ``thin
|
||||
converting wrapper'' over those two functions as follows:
|
||||
|
||||
<blockquote><pre>
|
||||
const Foo* f(); // original function
|
||||
@@ -47,6 +45,10 @@ const Foo& f_wrapper() { return *f(); }
|
||||
...
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
Foo must have a public copy constructor for this technique to work, since BPL
|
||||
converts <code>const T&</code> values <code>to_python</code> by copying the <code>T</code>
|
||||
value into a new extension instance.
|
||||
|
||||
<h2>Dealing with the problem</h2>
|
||||
|
||||
@@ -118,7 +120,7 @@ return value. You can handle this case by returning a Python tuple:
|
||||
typedef unsigned ErrorCode;
|
||||
const char* f(int* in_out_x); // original function
|
||||
...
|
||||
#include <boost/python/objects.hpp>
|
||||
#include <boost/python/objects.hpp>
|
||||
const boost::python::tuple f_wrapper(int in_x) {
|
||||
const char* s = f(in_x);
|
||||
return boost::python::tuple(s, in_x);
|
||||
@@ -131,8 +133,9 @@ my_module.def(f_wrapper, "f");
|
||||
>>> str,out_x = f(3)
|
||||
</pre></blockquote>
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
Previous: <a href="enums.html">Enums</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
|
||||
149
doc/special.html
149
doc/special.html
@@ -1,11 +1,10 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<title>
|
||||
Special Method and Operator Support
|
||||
</title>
|
||||
<div>
|
||||
<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
|
||||
Operator Support
|
||||
</h1>
|
||||
@@ -13,8 +12,8 @@
|
||||
Overview
|
||||
</h2>
|
||||
<p>
|
||||
Py_cpp supports all of the standard <a href=
|
||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
|
||||
BPL supports all of the standard <a href=
|
||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||
special method names</a> supported by real Python class instances <em>
|
||||
except</em> <code>__complex__</code> (more on the reasons <a href=
|
||||
"#reasons">below</a>). In addition, it can quickly and easily expose
|
||||
@@ -34,19 +33,24 @@
|
||||
Python provides a number of special operators for basic customization of a
|
||||
class. Only a brief description is provided below; more complete
|
||||
documentation can be found <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/customization.html">here</a>.
|
||||
href="http://www.python.org/doc/current/ref/customization.html">here</a>.
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<b><tt class='method'>__init__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
Initialize the class instance. For extension classes not subclassed in
|
||||
Python, this is provided by the
|
||||
<code>boost::python::constructor<...>()</code> construct and should <i>not</i> be explicitly <code>def</code>ed.
|
||||
Python, <code> __init__</code> is defined by
|
||||
|
||||
<pre> my_class.def(boost::python::constructor<...>())</pre>
|
||||
|
||||
(see section <a href="example1.html">"A Simple Example Using BPL"</a>).<p>
|
||||
<dt>
|
||||
<b><tt class='method'>__del__</tt></b>(<i>self</i>)
|
||||
<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>
|
||||
<b><tt class='method'>__repr__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
@@ -78,7 +82,7 @@
|
||||
<dt>
|
||||
<b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>)
|
||||
<dd>
|
||||
Called when the instance is “called” 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
|
||||
<code><var>x</var>.__call__(arg1, arg2, ...)</code>.
|
||||
</dl>
|
||||
@@ -100,7 +104,7 @@ std::string to_string(Foo const& f)
|
||||
boost::python::class_builder<Foo> foo_class(my_module, "Foo");
|
||||
foo_class.def(&to_string, "__str__");
|
||||
</pre></blockquote>
|
||||
Note that 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
|
||||
href="#numeric">next section</a> and the <a href="#numeric_table">Table of
|
||||
Automatically Wrapped Methods</a>.
|
||||
@@ -110,10 +114,10 @@ foo_class.def(&to_string, "__str__");
|
||||
<p>
|
||||
Numeric operators can be exposed manually, by <code>def</code>ing C++
|
||||
[member] functions that support the standard Python <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/numeric-types.html">numeric
|
||||
protocols</a>. This is the basic same technique used to expose
|
||||
href="http://www.python.org/doc/current/ref/numeric-types.html">numeric
|
||||
protocols</a>. This is the same basic technique used to expose
|
||||
<code>to_string()</code> as <code>__str__()</code> above, and is <a
|
||||
href="#numeric_manual">covered in detail below</a>. 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
|
||||
been defined in C++.
|
||||
|
||||
@@ -121,7 +125,7 @@ foo_class.def(&to_string, "__str__");
|
||||
|
||||
<p>
|
||||
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>
|
||||
BigNum a, b, c;
|
||||
...
|
||||
@@ -143,7 +147,7 @@ bignum_class.def(boost::python::operators<boost::python::op_add>());
|
||||
|
||||
Since BigNum also supports subtraction, multiplication, and division, we
|
||||
want to export those also. This can be done in a single command by
|
||||
“or”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=
|
||||
"#numeric_table">Table of Automatically Wrapped Methods</a>):
|
||||
<blockquote><pre>
|
||||
@@ -170,7 +174,7 @@ a = i + b;
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>());
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>());
|
||||
</pre></blockquote>
|
||||
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">
|
||||
coercion</a>). Again, several operators can be exported at once:
|
||||
<blockquote><pre>
|
||||
@@ -181,7 +185,7 @@ bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::pyt
|
||||
</pre></blockquote>
|
||||
The type of the operand not mentioned is taken from the class being wrapped. In
|
||||
our example, the class object is <code>bignum_class</code>, and thus the
|
||||
other operand's type is “<code>BigNum const&</code>”. You can override
|
||||
other operand's type is ``<code>BigNum const&</code>''. You can override
|
||||
this default by explicitly specifying a type in the <code>
|
||||
operators</code> template:
|
||||
<blockquote><pre>
|
||||
@@ -189,15 +193,18 @@ bignum_class.def(boost::python::operators<boost::python::op_add, BigNum>()
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
Note that automatic wrapping uses the <em>expression</em>
|
||||
“<code>left + right</code>” 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
|
||||
<blockquote><pre>
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum operator+(BigNum, BigNum)
|
||||
</pre></blockquote>
|
||||
or as member
|
||||
functions <blockquote><pre>
|
||||
|
||||
or as member functions
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum::operator+(BigNum).
|
||||
</blockquote></pre>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
For the Python built-in functions <code>pow()</code> and
|
||||
@@ -218,8 +225,7 @@ namespace boost { namespace python {
|
||||
<p>
|
||||
In some cases, automatic wrapping of operators may be impossible or
|
||||
undesirable. Suppose, for example, that the modulo operation for BigNums
|
||||
is defined by a set of functions <code>mod()</code> (for automatic
|
||||
wrapping, we would need <code>operator%()</code>):
|
||||
is defined by a set of functions called <code>mod()</code>:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum mod(BigNum const& left, BigNum const& right);
|
||||
@@ -228,8 +234,9 @@ BigNum mod(int left, BigNum const& right);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
In order to create the Python operator "__mod__" from these functions, we
|
||||
have to wrap them manually:
|
||||
For automatic wrapping of the modulo function, <code>operator%()</code> would be needed.
|
||||
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>
|
||||
bignum_class.def((BigNum (*)(BigNum const&, BigNum const&))&mod, "__mod__");
|
||||
@@ -237,8 +244,8 @@ bignum_class.def((BigNum (*)(BigNum const&, int))&mod, "__mod__");
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The third form (with <code>int</code> as left operand) cannot be wrapped
|
||||
this way. We must first create a function <code>rmod()</code> with the
|
||||
The third form of <code>mod()</code> (with <code>int</code> as left operand) cannot
|
||||
be wrapped directly. We must first create a function <code>rmod()</code> with the
|
||||
operands reversed:
|
||||
|
||||
<blockquote><pre>
|
||||
@@ -248,7 +255,7 @@ BigNum rmod(BigNum const& right, int left)
|
||||
}
|
||||
</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>
|
||||
bignum_class.def(&rmod, "__rmod__");
|
||||
@@ -261,9 +268,9 @@ bignum_class.def(&rmod, "__rmod__");
|
||||
<p>
|
||||
Automatic and manual wrapping can be mixed arbitrarily. Note that you
|
||||
cannot overload the same operator for a given extension class on both
|
||||
“<code>int</code>” and “<code>float</code>”, because Python implicitly
|
||||
``<code>int</code>'' and ``<code>float</code>'', because Python implicitly
|
||||
converts these types into each other. Thus, the overloaded variant
|
||||
found first (be it “<code>int</code>“ or “<code>float</code>”) will be
|
||||
found first (be it ``<code>int</code>`` or ``<code>float</code>'') will be
|
||||
used for either of the two types.
|
||||
|
||||
<h3><a name="coercion">Coercion</a></h3>
|
||||
@@ -271,18 +278,18 @@ bignum_class.def(&rmod, "__rmod__");
|
||||
|
||||
Plain Python can only execute operators with identical types on the left
|
||||
and right hand side. If it encounters an expression where the types of
|
||||
the left and right operand differ, it tries to coerce these type to a
|
||||
the left and right operand differ, it tries to coerce these types to a
|
||||
common type before invoking the actual operator. Implementing good
|
||||
coercion functions can be difficult if many type combinations must be
|
||||
supported.
|
||||
<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
|
||||
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
|
||||
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.
|
||||
<p>
|
||||
If you wrap all operator functions manually, but still want to use
|
||||
@@ -295,7 +302,7 @@ bignum_class.def_standard_coerce();
|
||||
</pre></blockquote>
|
||||
|
||||
If you encounter a situation where you absolutely need a customized
|
||||
coercion, you can overload the "__coerce__" operator itself. The signature
|
||||
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
|
||||
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:
|
||||
|
||||
<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(&custom_coerce, "__coerce__");
|
||||
</pre></blockquote>
|
||||
|
||||
Note that the later use of automatic operator wrapping on a
|
||||
<code>class_builder</code> or a call to
|
||||
“<code>some_class.def_standard_coerce()</code>” will cause any
|
||||
custom coercion function to be replaced by the standard one.
|
||||
Note that the standard coercion (defined by use of automatic
|
||||
operator wrapping on a <code>class_builder</code> or a call to
|
||||
<code>class_builder::def_standard_coerce()</code>) will never be applied if
|
||||
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>
|
||||
|
||||
@@ -330,7 +346,7 @@ some_class.def(&custom_coerce, "__coerce__");
|
||||
this is done as usual:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum power(BigNum const& first, BigNum const& second, BigNum const& module);
|
||||
BigNum power(BigNum const& first, BigNum const& second, BigNum const& modulus);
|
||||
typedef BigNum (ternary_function1)(const BigNum&, const BigNum&, const BigNum&);
|
||||
...
|
||||
bignum_class.def((ternary_function1)&power, "__pow__");
|
||||
@@ -353,19 +369,19 @@ bignum_class.def((ternary_function2)&power, "__pow__");
|
||||
</pre></blockquote>
|
||||
|
||||
In the second variant, however, <code>BigNum</code> appears only as second
|
||||
argument, and in the last one it is the third argument. These functions
|
||||
must be presented to py_cpp such that that the <code>BigNum</code>
|
||||
argument, and in the last one it's the third argument. These functions
|
||||
must be presented to BPL such that that the <code>BigNum</code>
|
||||
argument appears in first position:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum rpower(BigNum const& second, int first, int modulus)
|
||||
{
|
||||
return power(first, second, third);
|
||||
return power(first, second, modulus);
|
||||
}
|
||||
|
||||
BigNum rrpower(BigNum const& third, int first, int second)
|
||||
BigNum rrpower(BigNum const& modulus, int first, int second)
|
||||
{
|
||||
return power(first, second, third);
|
||||
return power(first, second, modulus);
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -381,8 +397,8 @@ Note that "__rrpow__" is an extension not present in plain Python.
|
||||
|
||||
<h2><a name="numeric_table">Table of Automatically Wrapped Methods</a></h2>
|
||||
<p>
|
||||
Py_cpp can automatically wrap the following <a href=
|
||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
|
||||
BPL can automatically wrap the following <a href=
|
||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||
special methods</a>:
|
||||
|
||||
<p>
|
||||
@@ -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
|
||||
considerably from the ones found in C++. For example, Python's typical
|
||||
iteration idiom looks like
|
||||
|
||||
<blockquote><pre>
|
||||
for i in S:
|
||||
</blockquote></pre>
|
||||
</pre></blockquote>
|
||||
|
||||
while in C++ one writes
|
||||
while in C++ one writes
|
||||
|
||||
<blockquote><pre>
|
||||
for (iterator i = S.begin(), end = S.end(); i != end)
|
||||
</blockquote></pre>
|
||||
for (iterator i = S.begin(), end = S.end(); i != end; ++i)
|
||||
</pre></blockquote>
|
||||
|
||||
<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
|
||||
@@ -655,12 +672,12 @@ for (iterator i = S.begin(), end = S.end(); i != end)
|
||||
|
||||
<p>
|
||||
It is a better idea to support the standard <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/sequence-types.html">Python
|
||||
href="http://www.python.org/doc/current/ref/sequence-types.html">Python
|
||||
sequence and mapping protocols</a> for your wrapped containers. These
|
||||
operators have to be wrapped manually because there are no corresponding
|
||||
C++ operators that could be used for automatic wrapping. The Python
|
||||
documentation lists the relevant <a href=
|
||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/sequence-types.html">
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html">
|
||||
container operators</a>. In particular, expose __getitem__, __setitem__
|
||||
and remember to raise the appropriate Python exceptions
|
||||
(<code>PyExc_IndexError</code> for sequences,
|
||||
@@ -689,7 +706,7 @@ void throw_key_error_if_end(
|
||||
|
||||
// Define some simple wrapper functions which match the Python protocol
|
||||
// for __getitem__, __setitem__, and __delitem__. Just as in Python, a
|
||||
// free function with a “self” first parameter makes a fine class method.
|
||||
// free function with a ``self'' first parameter makes a fine class method.
|
||||
|
||||
const std::string& get_item(const StringMap& self, std::size_t key)
|
||||
{
|
||||
@@ -755,13 +772,13 @@ KeyError: 2
|
||||
<h2><a name="getter_setter">Customized Attribute Access</a></h2>
|
||||
|
||||
<p>
|
||||
Just like built-in Python classes, py_cpp extension classes support <a
|
||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/attribute-access.html">special
|
||||
Just like built-in Python classes, BPL extension classes support <a
|
||||
href="http://www.python.org/doc/current/ref/attribute-access.html">special
|
||||
the usual attribute access methods</a> <code>__getattr__</code>,
|
||||
<code>__setattr__</code>, and <code>__delattr__</code>.
|
||||
Because writing these functions can
|
||||
be tedious in the common case where the attributes being accessed are
|
||||
known statically, py_cpp checks the special names
|
||||
known statically, BPL checks the special names
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -774,10 +791,10 @@ KeyError: 2
|
||||
|
||||
to provide functional access to the attribute <em><name></em>. This
|
||||
facility can be used from C++ or entirely from Python. For example, the
|
||||
following shows how we can implement a “computed attribute” in Python:
|
||||
following shows how we can implement a ``computed attribute'' in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> class Range(AnyPy_cppExtensionClass):
|
||||
>>> class Range(AnyBPLExtensionClass):
|
||||
... def __init__(self, start, end):
|
||||
... self.start = start
|
||||
... self.end = end
|
||||
@@ -793,7 +810,7 @@ KeyError: 2
|
||||
Direct Access to Data Members
|
||||
</h4>
|
||||
<p>
|
||||
Py_cpp uses the special <code>
|
||||
BPL uses the special <code>
|
||||
__xxxattr__<em><name></em>__</code> functionality described above
|
||||
to allow direct access to data members through the following special
|
||||
functions on <code>class_builder<></code> and <code>
|
||||
@@ -873,14 +890,14 @@ if (PyInstance_Check(r)) { ...
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Previous: <a href="inheritance.html">Inheritance</a> Next: <a href=
|
||||
"under-the-hood.html">A Peek Under the Hood</a> Up: <a href=
|
||||
"index.html">Top</a>
|
||||
Next: <a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||
Previous: <a href="inheritance.html">Inheritance</a>
|
||||
Up: <a href= "index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams and Ullrich Köthe 2000.
|
||||
Permission to copy, use, modify, sell and distribute this document is
|
||||
granted provided this copyright notice appears in all copies. This
|
||||
document is provided “as is” 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.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"example1.html#add_world_class">add it to the module</a> it goes into the
|
||||
module's dictionary to be looked up under the name "world".
|
||||
<p>
|
||||
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
|
||||
<a href="example1.html#Constructor_example">provide an argument list</a>
|
||||
because they can't be named in C++). Then, it calls the appropriate
|
||||
@@ -48,8 +48,8 @@
|
||||
the top of your module's init function, then <code>def</code> the member
|
||||
functions later to avoid problems with inter-class dependencies.
|
||||
<p>
|
||||
Previous: <a href="overriding.html">Function Overloading</a>
|
||||
Next: <a href="building.html">Building a Module with Py_cpp</a>
|
||||
Next: <a href="building.html">Building a Module with BPL</a>
|
||||
Previous: <a href="special.html">Special Method and Operator Support</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
|
||||
41
example/rwgk1.cpp
Normal file
41
example/rwgk1.cpp
Normal 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
17
example/test_rwgk1.py
Normal 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()
|
||||
@@ -27,8 +27,8 @@ class class_builder
|
||||
|
||||
// define constructors
|
||||
template <class signature>
|
||||
void def(const signature& signature)
|
||||
{ m_class->def(signature); }
|
||||
void def(const signature& s)
|
||||
{ m_class->def(s); }
|
||||
|
||||
// export heterogeneous reverse-argument operators
|
||||
// (type of lhs: 'left', of rhs: 'right')
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# else
|
||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
|
||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
|
||||
# define BOOST_PYTHON_CONVERSION python
|
||||
# define BOOST_PYTHON_CONVERSION boost::python
|
||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';'
|
||||
# endif
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file automatically generated for 5-argument constructors by
|
||||
// This file automatically generated for 10-argument constructors by
|
||||
// gen_extclass.python
|
||||
|
||||
#ifndef EXTENSION_CLASS_DWA052000_H_
|
||||
@@ -363,8 +363,8 @@ class extension_class
|
||||
~extension_class();
|
||||
|
||||
// define constructors
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
inline void def(constructor<A1, A2, A3, A4, A5>)
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
inline void def(constructor<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>)
|
||||
// The following incantation builds a signature1, signature2,... object. It
|
||||
// should _all_ get optimized away.
|
||||
{ add_constructor(
|
||||
@@ -373,7 +373,12 @@ class extension_class
|
||||
prepend(type<A3>::id(),
|
||||
prepend(type<A4>::id(),
|
||||
prepend(type<A5>::id(),
|
||||
signature0()))))));
|
||||
prepend(type<A6>::id(),
|
||||
prepend(type<A7>::id(),
|
||||
prepend(type<A8>::id(),
|
||||
prepend(type<A9>::id(),
|
||||
prepend(type<A10>::id(),
|
||||
signature0())))))))))));
|
||||
}
|
||||
|
||||
|
||||
@@ -625,6 +630,16 @@ public:
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {}
|
||||
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
|
||||
@@ -676,6 +691,21 @@ public:
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
|
||||
m_held(p, a1, a2, a3, a4, a5) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
|
||||
public: // implementation of instance_holder_base required interface
|
||||
bool held_by_value() { return true; }
|
||||
@@ -721,8 +751,6 @@ class extension_instance : public instance
|
||||
// Template function implementations
|
||||
//
|
||||
|
||||
tuple extension_class_coerce(ref l, ref r);
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::extension_class()
|
||||
: extension_class_base(typeid(T).name())
|
||||
@@ -743,7 +771,7 @@ void extension_class<T, U>::def_standard_coerce()
|
||||
ref coerce_fct = dict().get_item(string("__coerce__"));
|
||||
|
||||
if(coerce_fct.get() == 0) // not yet defined
|
||||
this->def(&extension_class_coerce, "__coerce__");
|
||||
this->def(&standard_coerce, "__coerce__");
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#endif // EXTENSION_CLASS_DWA052000_H_
|
||||
|
||||
|
||||
@@ -110,11 +110,11 @@ template <class T, class A1, class A2> struct init2;
|
||||
template <class T, class A1, class A2, class A3> struct init3;
|
||||
template <class T, class A1, class A2, class A3, class A4> struct init4;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5> struct init5;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct Init6;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct Init7;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct Init8;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct Init9;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct Init10;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct init6;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct init7;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct init8;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct init9;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct init10;
|
||||
|
||||
template <class T>
|
||||
struct init_function
|
||||
@@ -165,7 +165,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
|
||||
return new Init6<T,
|
||||
return new init6<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -176,7 +176,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
|
||||
return new Init7<T,
|
||||
return new init7<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -188,7 +188,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
|
||||
return new Init8<T,
|
||||
return new init8<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -201,7 +201,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
|
||||
return new Init9<T,
|
||||
return new init9<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -215,7 +215,7 @@ struct init_function
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
|
||||
return new Init10<T,
|
||||
return new init10<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
@@ -353,7 +353,7 @@ struct init5 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct Init6 : init
|
||||
struct init6 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -379,7 +379,7 @@ struct Init6 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
struct Init7 : init
|
||||
struct init7 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -407,7 +407,7 @@ struct Init7 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
struct Init8 : init
|
||||
struct init8 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -437,7 +437,7 @@ struct Init8 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
struct Init9 : init
|
||||
struct init9 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
@@ -469,7 +469,7 @@ struct Init9 : init
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
struct Init10 : init
|
||||
struct init10 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
|
||||
@@ -1,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
|
||||
# ifndef DEBUG_PYTHON
|
||||
# ifndef BOOST_DEBUG_PYTHON
|
||||
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
|
||||
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# endif
|
||||
|
||||
@@ -18,11 +18,10 @@ namespace boost { namespace python {
|
||||
|
||||
class module_builder
|
||||
{
|
||||
typedef PyObject * (*raw_function_ptr)(boost::python::tuple const &, boost::python::dictionary const &);
|
||||
|
||||
public:
|
||||
// Create a module. REQUIRES: only one module_builder is created per module.
|
||||
module_builder(const char* name);
|
||||
~module_builder();
|
||||
|
||||
// Add elements to the module
|
||||
void add(detail::function* x, const char* name);
|
||||
@@ -41,13 +40,29 @@ class module_builder
|
||||
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:
|
||||
PyObject* m_module;
|
||||
static PyMethodDef initial_methods[1];
|
||||
};
|
||||
|
||||
//
|
||||
// inline implementations
|
||||
//
|
||||
inline PyObject* module_builder::module() const
|
||||
{
|
||||
return m_module;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
#ifndef OPERATORS_UK112000_H_
|
||||
#define OPERATORS_UK112000_H_
|
||||
|
||||
#include <boost/python/detail/functions.hpp>
|
||||
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
|
||||
# include <sstream>
|
||||
#else
|
||||
# include <strstream>
|
||||
#endif
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
|
||||
// When STLport is used with native streams, _STL::ostringstream().str() is not
|
||||
// _STL::string, but std::string. This confuses to_python(), so we'll use
|
||||
// strstream instead. Also, GCC 2.95.2 doesn't have sstream.
|
||||
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
# include <sstream>
|
||||
# else
|
||||
# include <strstream>
|
||||
# endif
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
tuple standard_coerce(ref l, ref r);
|
||||
|
||||
namespace detail {
|
||||
|
||||
// helper class for automatic operand type detection
|
||||
@@ -473,17 +480,15 @@ namespace detail
|
||||
{
|
||||
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;
|
||||
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>());
|
||||
return BOOST_PYTHON_CONVERSION::to_python(s.str());
|
||||
#else
|
||||
std::ostrstream s;
|
||||
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()) << char();
|
||||
#endif
|
||||
|
||||
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
|
||||
return BOOST_PYTHON_CONVERSION::to_python(s.str());
|
||||
#else
|
||||
return BOOST_PYTHON_CONVERSION::to_python(const_cast<char const *>(s.str()));
|
||||
#endif
|
||||
}
|
||||
|
||||
217
release_notes.txt
Normal file
217
release_notes.txt
Normal 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
|
||||
@@ -840,7 +840,27 @@ namespace {
|
||||
void add_current_module_name(dictionary& name_space)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,24 +46,19 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
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)
|
||||
{
|
||||
// Introduced sequence points for exception-safety.
|
||||
ref first(operator_dispatcher::create(l, l));
|
||||
ref second;
|
||||
|
||||
if(r->ob_type == &operator_dispatcher::type_obj)
|
||||
{
|
||||
second = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
second = ref(operator_dispatcher::create(r, ref()));
|
||||
}
|
||||
return boost::python::tuple(first, second);
|
||||
}
|
||||
return tuple(first, second);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
enum { unwrap_exception_code = -1000 };
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ from gen_singleton import *
|
||||
from gen_extclass import *
|
||||
|
||||
def gen_all(args):
|
||||
open('callback.h', 'w').write(gen_callback(args))
|
||||
open('caller.h', 'w').write(gen_caller(args))
|
||||
open('init_function.h', 'w').write(gen_init_function(args))
|
||||
open('signatures.h', 'w').write(gen_signatures(args))
|
||||
open('instance.h', 'w').write(gen_singleton(args))
|
||||
open('extclass.h', 'w').write(gen_extclass(args))
|
||||
open('callback.hpp', 'w').write(gen_callback(args))
|
||||
open('caller.hpp', 'w').write(gen_caller(args))
|
||||
open('init_function.hpp', 'w').write(gen_init_function(args))
|
||||
open('signatures.hpp', 'w').write(gen_signatures(args))
|
||||
open('instance.hpp', 'w').write(gen_singleton(args))
|
||||
open('extension_class.hpp', 'w').write(gen_extclass(args))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
@@ -707,8 +707,6 @@ class extension_instance : public instance
|
||||
// Template function implementations
|
||||
//
|
||||
|
||||
tuple extension_class_coerce(ref l, ref r);
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::extension_class()
|
||||
: extension_class_base(typeid(T).name())
|
||||
@@ -729,7 +727,7 @@ void extension_class<T, U>::def_standard_coerce()
|
||||
ref coerce_fct = dict().get_item(string("__coerce__"));
|
||||
|
||||
if(coerce_fct.get() == 0) // not yet defined
|
||||
this->def(&extension_class_coerce, "__coerce__");
|
||||
this->def(&standard_coerce, "__coerce__");
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
|
||||
@@ -14,10 +14,15 @@ namespace {
|
||||
ref name_holder;
|
||||
}
|
||||
|
||||
bool module_builder::initializing()
|
||||
{
|
||||
return name_holder.get() != 0;
|
||||
}
|
||||
|
||||
string module_builder::name()
|
||||
{
|
||||
// If this fails, you haven't created a module_builder object
|
||||
assert(name_holder.get() != 0);
|
||||
assert(initializing());
|
||||
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__")));
|
||||
}
|
||||
|
||||
module_builder::~module_builder()
|
||||
{
|
||||
name_holder.reset();
|
||||
}
|
||||
|
||||
void
|
||||
module_builder::add(detail::function* x, const char* name)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <math.h> // for pow()
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
namespace extclass_demo {
|
||||
namespace bpl_test {
|
||||
|
||||
FooCallback::FooCallback(PyObject* self, int x)
|
||||
: Foo(x), m_self(self)
|
||||
@@ -714,12 +714,14 @@ const Record* get_record()
|
||||
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
|
||||
inline PyObject* to_python(const extclass_demo::Record* p)
|
||||
inline PyObject* to_python(const bpl_test::Record* p)
|
||||
{
|
||||
return to_python(*p);
|
||||
}
|
||||
@@ -731,7 +733,7 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
/* */
|
||||
/************************************************************/
|
||||
|
||||
namespace extclass_demo {
|
||||
namespace bpl_test {
|
||||
|
||||
struct EnumOwner
|
||||
{
|
||||
@@ -753,8 +755,8 @@ struct EnumOwner
|
||||
}
|
||||
|
||||
namespace boost { namespace python {
|
||||
template class enum_as_int_converters<extclass_demo::EnumOwner::enum_type>;
|
||||
using extclass_demo::pow;
|
||||
template class enum_as_int_converters<bpl_test::EnumOwner::enum_type>;
|
||||
using bpl_test::pow;
|
||||
}} // namespace boost::python
|
||||
|
||||
// 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__");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -1055,21 +1057,21 @@ PyObject* raw(boost::python::tuple const& args, boost::python::dictionary const&
|
||||
|
||||
void init_module()
|
||||
{
|
||||
boost::python::module_builder demo("demo");
|
||||
init_module(demo);
|
||||
boost::python::module_builder test("test");
|
||||
init_module(test);
|
||||
|
||||
// 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"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void initdemo()
|
||||
void inittest()
|
||||
{
|
||||
try {
|
||||
extclass_demo::init_module();
|
||||
bpl_test::init_module();
|
||||
}
|
||||
catch(...) {
|
||||
boost::python::handle_exception();
|
||||
@@ -1083,7 +1085,7 @@ CompareIntPairPythonClass::CompareIntPairPythonClass(boost::python::module_build
|
||||
def(&CompareIntPair::operator(), "__call__");
|
||||
}
|
||||
|
||||
} // namespace extclass_demo
|
||||
} // namespace bpl_test
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
@@ -1124,7 +1126,7 @@ BOOL WINAPI DllMain(
|
||||
switch(fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_DETACH:
|
||||
assert(extclass_demo::total_Ints == 0);
|
||||
assert(bpl_test::total_Ints == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef EXTCLASS_DEMO_DWA052200_H_
|
||||
# define EXTCLASS_DEMO_DWA052200_H_
|
||||
#ifndef BPL_TEST_DWA052200_H_
|
||||
# define BPL_TEST_DWA052200_H_
|
||||
//
|
||||
// Example code demonstrating extension class usage
|
||||
//
|
||||
@@ -21,7 +21,7 @@
|
||||
# include <string>
|
||||
# include <map>
|
||||
|
||||
namespace extclass_demo {
|
||||
namespace bpl_test {
|
||||
|
||||
//
|
||||
// example: Foo, Bar, and Baz are C++ classes we want to wrap.
|
||||
@@ -226,6 +226,6 @@ struct CompareIntPairPythonClass
|
||||
CompareIntPairPythonClass(boost::python::module_builder&);
|
||||
};
|
||||
|
||||
} // namespace extclass_demo
|
||||
} // namespace bpl_test
|
||||
|
||||
#endif // EXTCLASS_DEMO_DWA052200_H_
|
||||
#endif // BPL_TEST_DWA052200_H_
|
||||
|
||||
@@ -209,7 +209,7 @@ Polymorphism also works:
|
||||
Pickling tests:
|
||||
|
||||
>>> world.__module__
|
||||
'demo'
|
||||
'test'
|
||||
>>> world.__safe_for_unpickling__
|
||||
1
|
||||
>>> world.__reduce__()
|
||||
@@ -1072,7 +1072,7 @@ test methodologies for wrapping functions that return a pointer
|
||||
1
|
||||
'''
|
||||
|
||||
from demo import *
|
||||
from test import *
|
||||
import string
|
||||
import re
|
||||
import sys
|
||||
@@ -1080,8 +1080,8 @@ import sys
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
import doctest, test_extclass
|
||||
doctest.testmod(test_extclass)
|
||||
import doctest, comprehensive
|
||||
doctest.testmod(comprehensive)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
1112
test/doctest.py
Normal file
1112
test/doctest.py
Normal file
File diff suppressed because it is too large
Load Diff
426
todo.txt
Normal file
426
todo.txt
Normal 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 ;)
|
||||
Reference in New Issue
Block a user