mirror of
https://github.com/boostorg/python.git
synced 2026-01-30 20:12:37 +00:00
Compare commits
10 Commits
boost-1.22
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dcb0b1996 | ||
|
|
de57613c7e | ||
|
|
ade195b9ac | ||
|
|
daf0865cdf | ||
|
|
2fa4bb7410 | ||
|
|
6db04861ed | ||
|
|
dac8e861c8 | ||
|
|
f0a0e9ec02 | ||
|
|
4d3079293d | ||
|
|
9261e2a3d9 |
241
build/bpl_static.dsp
Normal file
241
build/bpl_static.dsp
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
# 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 DebugPython
|
||||||
|
!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 DebugPython"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "bpl_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE "bpl_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE "bpl_static - Win32 DebugPython" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "bpl_static - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W4 /WX /GR /GX /O2 /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "bpl_static - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "bpl_static - Win32 DebugPython"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "bpl_static___Win32_DebugPython"
|
||||||
|
# PROP BASE Intermediate_Dir "bpl_static___Win32_DebugPython"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "DebugPython"
|
||||||
|
# PROP Intermediate_Dir "DebugPython"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /EHs /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# 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"
|
||||||
|
# Name "bpl_static - Win32 DebugPython"
|
||||||
|
# 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
|
||||||
108
build/build.dsw
Normal file
108
build/build.dsw
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
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: "getting_started1"=.\getting_started1\getting_started1.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
Begin Project Dependency
|
||||||
|
Project_Dep_Name bpl_static
|
||||||
|
End Project Dependency
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "getting_started2"=.\getting_started2\getting_started2.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
begin source code control
|
||||||
|
getting_started2
|
||||||
|
.\getting_started2
|
||||||
|
end source code control
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
Begin Project Dependency
|
||||||
|
Project_Dep_Name bpl_static
|
||||||
|
End Project Dependency
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "rwgk1"=.\rwgk1\rwgk1.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
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.
58
build/como.mak
Normal file
58
build/como.mak
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Revision History:
|
||||||
|
# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve) UNTESTED!
|
||||||
|
# 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams)
|
||||||
|
# 04 Mar 01 Changed library name to libboost_python.a (David Abrahams)
|
||||||
|
|
||||||
|
LIBSRC = \
|
||||||
|
classes.cpp \
|
||||||
|
conversions.cpp \
|
||||||
|
cross_module.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 $@
|
||||||
|
|
||||||
|
getting_started1: getting_started1.o libboost_python.a
|
||||||
|
como-dyn-link -o ../example/getting_started1.$(MODULE_EXTENSION) $(PYTHON_LIB) getting_started1.o -L. -lboost_python
|
||||||
|
ln -s ../test/doctest.py ../example
|
||||||
|
python ../example/test_getting_started1.py
|
||||||
|
|
||||||
|
getting_started1.o: ../example/getting_started1.cpp
|
||||||
|
como --pic $(INC) -o $*.o -c $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||||
|
|
||||||
|
libboost_python.a: $(LIBOBJ)
|
||||||
|
rm -f libboost_python.a
|
||||||
|
ar cq libboost_python.a $(LIBOBJ)
|
||||||
|
|
||||||
|
DEP = $(OBJ:.o=.d)
|
||||||
|
|
||||||
|
ifneq "$(MAKECMDGOALS)" "clean"
|
||||||
|
include $(DEP)
|
||||||
|
endif
|
||||||
136
build/example1/example1.dsp
Normal file
136
build/example1/example1.dsp
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# 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 DebugPython
|
||||||
|
!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 DebugPython"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "example1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "example1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "example1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# 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 /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "example1 - Win32 DebugPython"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "example1___Win32_DebugPython"
|
||||||
|
# PROP BASE Intermediate_Dir "example1___Win32_DebugPython"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "DebugPython"
|
||||||
|
# PROP Intermediate_Dir "DebugPython"
|
||||||
|
# PROP Ignore_Export_Lib 1
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /EHs /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/hello_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "example1 - Win32 Release"
|
||||||
|
# Name "example1 - Win32 Debug"
|
||||||
|
# Name "example1 - Win32 DebugPython"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# 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
|
||||||
132
build/filemgr.py
Normal file
132
build/filemgr.py
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# Revision history:
|
||||||
|
# 12 Apr 01 use os.path, shutil
|
||||||
|
# Initial version: R.W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
bpl_src = "/libs/python/src"
|
||||||
|
bpl_tst = "/libs/python/test"
|
||||||
|
bpl_exa = "/libs/python/example"
|
||||||
|
files = (
|
||||||
|
bpl_src + "/classes.cpp",
|
||||||
|
bpl_src + "/conversions.cpp",
|
||||||
|
bpl_src + "/extension_class.cpp",
|
||||||
|
bpl_src + "/functions.cpp",
|
||||||
|
bpl_src + "/init_function.cpp",
|
||||||
|
bpl_src + "/module_builder.cpp",
|
||||||
|
bpl_src + "/objects.cpp",
|
||||||
|
bpl_src + "/types.cpp",
|
||||||
|
bpl_src + "/cross_module.cpp",
|
||||||
|
bpl_tst + "/comprehensive.cpp",
|
||||||
|
bpl_tst + "/comprehensive.hpp",
|
||||||
|
bpl_tst + "/comprehensive.py",
|
||||||
|
bpl_tst + "/doctest.py",
|
||||||
|
bpl_exa + "/abstract.cpp",
|
||||||
|
bpl_exa + "/getting_started1.cpp",
|
||||||
|
bpl_exa + "/getting_started2.cpp",
|
||||||
|
bpl_exa + "/simple_vector.cpp",
|
||||||
|
bpl_exa + "/do_it_yourself_converters.cpp",
|
||||||
|
bpl_exa + "/pickle1.cpp",
|
||||||
|
bpl_exa + "/pickle2.cpp",
|
||||||
|
bpl_exa + "/pickle3.cpp",
|
||||||
|
bpl_exa + "/test_abstract.py",
|
||||||
|
bpl_exa + "/test_getting_started1.py",
|
||||||
|
bpl_exa + "/test_getting_started2.py",
|
||||||
|
bpl_exa + "/test_simple_vector.py",
|
||||||
|
bpl_exa + "/test_do_it_yourself_converters.py",
|
||||||
|
bpl_exa + "/test_pickle1.py",
|
||||||
|
bpl_exa + "/test_pickle2.py",
|
||||||
|
bpl_exa + "/test_pickle3.py",
|
||||||
|
bpl_exa + "/noncopyable.h",
|
||||||
|
bpl_exa + "/noncopyable_export.cpp",
|
||||||
|
bpl_exa + "/noncopyable_import.cpp",
|
||||||
|
bpl_exa + "/dvect.h",
|
||||||
|
bpl_exa + "/dvect.cpp",
|
||||||
|
bpl_exa + "/dvect_conversions.cpp",
|
||||||
|
bpl_exa + "/dvect_defs.cpp",
|
||||||
|
bpl_exa + "/ivect.h",
|
||||||
|
bpl_exa + "/ivect.cpp",
|
||||||
|
bpl_exa + "/ivect_conversions.cpp",
|
||||||
|
bpl_exa + "/ivect_defs.cpp",
|
||||||
|
bpl_exa + "/tst_noncopyable.py",
|
||||||
|
bpl_exa + "/tst_dvect1.py",
|
||||||
|
bpl_exa + "/tst_dvect2.py",
|
||||||
|
bpl_exa + "/tst_ivect1.py",
|
||||||
|
bpl_exa + "/tst_ivect2.py",
|
||||||
|
bpl_exa + "/test_cross_module.py",
|
||||||
|
)
|
||||||
|
|
||||||
|
defs = (
|
||||||
|
"boost_python_test",
|
||||||
|
"abstract",
|
||||||
|
"getting_started1",
|
||||||
|
"getting_started2",
|
||||||
|
"simple_vector",
|
||||||
|
"do_it_yourself_converters",
|
||||||
|
"pickle1",
|
||||||
|
"pickle2",
|
||||||
|
"pickle3",
|
||||||
|
"noncopyable_export",
|
||||||
|
"noncopyable_import",
|
||||||
|
"ivect",
|
||||||
|
"dvect",
|
||||||
|
)
|
||||||
|
|
||||||
|
if (__name__ == "__main__"):
|
||||||
|
|
||||||
|
import sys, os, shutil
|
||||||
|
|
||||||
|
path = sys.argv[1]
|
||||||
|
mode = sys.argv[2]
|
||||||
|
if (not mode in ("softlinks", "unlink", "cp", "rm", "copy", "del")):
|
||||||
|
raise RuntimeError, \
|
||||||
|
"usage: python filemgr.py path <softlinks|unlink|cp|rm|copy|del>"
|
||||||
|
|
||||||
|
if (mode in ("cp", "copy")):
|
||||||
|
for fn in files:
|
||||||
|
f = os.path.basename(fn)
|
||||||
|
print "Copying: " + f
|
||||||
|
shutil.copy(path + fn, ".")
|
||||||
|
|
||||||
|
elif (mode == "softlinks"):
|
||||||
|
for fn in files:
|
||||||
|
f = os.path.basename(fn)
|
||||||
|
if (os.path.exists(f)):
|
||||||
|
print "File exists: " + f
|
||||||
|
else:
|
||||||
|
print "Linking: " + f
|
||||||
|
os.symlink(path + fn, f)
|
||||||
|
|
||||||
|
elif (mode in ("rm", "del")):
|
||||||
|
for fn in files:
|
||||||
|
f = os.path.basename(fn)
|
||||||
|
if (os.path.exists(f)):
|
||||||
|
print "Removing: " + f
|
||||||
|
try: os.unlink(f)
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
elif (mode == "unlink"):
|
||||||
|
for fn in files:
|
||||||
|
f = os.path.basename(fn)
|
||||||
|
if (os.path.exists(f)):
|
||||||
|
if (os.path.islink(f)):
|
||||||
|
print "Unlinking: " + f
|
||||||
|
try: os.unlink(f)
|
||||||
|
except: pass
|
||||||
|
else:
|
||||||
|
print "Not a softlink: " + f
|
||||||
|
|
||||||
|
if (mode in ("softlinks", "cp", "copy")):
|
||||||
|
for d in defs:
|
||||||
|
fn = d + ".def"
|
||||||
|
print "Creating: " + fn
|
||||||
|
f = open(fn, "w")
|
||||||
|
f.write("EXPORTS\n")
|
||||||
|
f.write("\tinit" + d + "\n")
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
if (mode in ("unlink", "rm", "del")):
|
||||||
|
for d in defs:
|
||||||
|
fn = d + ".def"
|
||||||
|
if (os.path.exists(fn)):
|
||||||
|
print "Removing: " + fn
|
||||||
|
try: os.unlink(fn)
|
||||||
|
except: pass
|
||||||
87
build/gcc.mak
Normal file
87
build/gcc.mak
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Revision History
|
||||||
|
|
||||||
|
# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve)
|
||||||
|
# 17 Apr 01 build shared library (patch provided by Dan Nuffer)
|
||||||
|
# 04 Mar 01 Changed library name to libboost_python.a, various cleanups,
|
||||||
|
# attempted Cygwin compatibility. Still needs testing on Linux
|
||||||
|
# (David Abrahams)
|
||||||
|
|
||||||
|
|
||||||
|
LIBSRC = \
|
||||||
|
classes.cpp \
|
||||||
|
conversions.cpp \
|
||||||
|
cross_module.cpp \
|
||||||
|
extension_class.cpp \
|
||||||
|
functions.cpp \
|
||||||
|
init_function.cpp \
|
||||||
|
module_builder.cpp \
|
||||||
|
objects.cpp \
|
||||||
|
types.cpp
|
||||||
|
|
||||||
|
LIBOBJ = $(LIBSRC:.cpp=.o)
|
||||||
|
OBJ = $(LIBOBJ)
|
||||||
|
|
||||||
|
LIBNAME = libboost_python
|
||||||
|
# libpython2.0.dll
|
||||||
|
|
||||||
|
ifeq "$(OS)" "Windows_NT"
|
||||||
|
ROOT=c:/cygnus
|
||||||
|
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -I$(PYTHON_INC)
|
||||||
|
MODULE_EXTENSION=dll
|
||||||
|
PYTHON_LIB=c:/cygnus/usr/local/lib/python2.0/config/libpython2.0.dll.a
|
||||||
|
SHARED_LIB = $(LIBNAME).dll
|
||||||
|
else
|
||||||
|
PYTHON_INC=$(ROOT)/usr/local/Python-2.0/include/python2.0
|
||||||
|
BOOST_INC=../../..
|
||||||
|
INC = -I$(BOOST_INC) -I$(PYTHON_INC)
|
||||||
|
MODULE_EXTENSION=so
|
||||||
|
VERSION=1
|
||||||
|
SHARED_LIB = $(LIBNAME).so.$(VERSION)
|
||||||
|
endif
|
||||||
|
|
||||||
|
%.o: ../src/%.cpp
|
||||||
|
g++ -fPIC -Wall -W $(INC) $(CXXFLAGS) -o $*.o -c $<
|
||||||
|
|
||||||
|
%.d: ../src/%.cpp
|
||||||
|
@echo creating $@
|
||||||
|
@set -e; g++ -M $(INC) -c $< \
|
||||||
|
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||||
|
[ -s $@ ] || rm -f $@
|
||||||
|
|
||||||
|
|
||||||
|
PYTHON = python
|
||||||
|
|
||||||
|
all: test $(SHARED_LIB) getting_started1
|
||||||
|
|
||||||
|
test: comprehensive.o $(LIBNAME).a $(SHARED_LIB)
|
||||||
|
g++ $(CXXFLAGS) -shared -o ../test/boost_python_test.$(MODULE_EXTENSION) comprehensive.o -L. -lboost_python $(PYTHON_LIB)
|
||||||
|
$(PYTHON) ../test/comprehensive.py
|
||||||
|
|
||||||
|
comprehensive.o: ../test/comprehensive.cpp
|
||||||
|
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||||
|
|
||||||
|
|
||||||
|
getting_started1: getting_started1.o $(LIBNAME).a
|
||||||
|
g++ $(CXXFLAGS) -shared -o ../example/getting_started1.$(MODULE_EXTENSION) getting_started1.o -L. -lboost_python $(PYTHON_LIB)
|
||||||
|
ln -s ../test/doctest.py ../example
|
||||||
|
$(PYTHON) ../example/test_getting_started1.py
|
||||||
|
|
||||||
|
getting_started1.o: ../example/getting_started1.cpp
|
||||||
|
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||||
|
|
||||||
|
$(LIBNAME).a: $(LIBOBJ)
|
||||||
|
rm -f $@
|
||||||
|
ar cqs $@ $(LIBOBJ)
|
||||||
|
|
||||||
|
$(SHARED_LIB): $(LIBOBJ)
|
||||||
|
g++ $(CXXFLAGS) -shared -o $@ -Wl,--soname=$(LIBNAME).$(MODULE_EXTENSION)
|
||||||
|
|
||||||
|
DEP = $(OBJ:.o=.d)
|
||||||
|
|
||||||
|
ifneq "$(MAKECMDGOALS)" "clean"
|
||||||
|
include $(DEP)
|
||||||
|
endif
|
||||||
136
build/getting_started1/getting_started1.dsp
Normal file
136
build/getting_started1/getting_started1.dsp
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="getting_started1" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=getting_started1 - Win32 DebugPython
|
||||||
|
!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 "getting_started1.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 "getting_started1.mak" CFG="getting_started1 - Win32 DebugPython"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "getting_started1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "getting_started1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "getting_started1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=xicl6.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "getting_started1 - 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" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /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=xilink6.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 /subsystem:windows /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 /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "getting_started1 - 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" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /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=xilink6.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 /subsystem:windows /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 /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "getting_started1 - Win32 DebugPython"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "DebugPython"
|
||||||
|
# PROP BASE Intermediate_Dir "DebugPython"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "DebugPython"
|
||||||
|
# PROP Intermediate_Dir "DebugPython"
|
||||||
|
# PROP Ignore_Export_Lib 1
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /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=xilink6.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 /subsystem:windows /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 /incremental:no /pdb:"DebugPython/boost_python_test_d.pdb" /debug /machine:I386 /out:"DebugPython/getting_started1_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||||
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "getting_started1 - Win32 Release"
|
||||||
|
# Name "getting_started1 - Win32 Debug"
|
||||||
|
# Name "getting_started1 - Win32 DebugPython"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\example\getting_started1.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
|
||||||
135
build/getting_started2/getting_started2.dsp
Normal file
135
build/getting_started2/getting_started2.dsp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="getting_started2" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=getting_started2 - Win32 DebugPython
|
||||||
|
!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 "getting_started2.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 "getting_started2.mak" CFG="getting_started2 - Win32 DebugPython"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "getting_started2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "getting_started2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "getting_started2 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName "getting_started2"
|
||||||
|
# PROP Scc_LocalPath "."
|
||||||
|
CPP=xicl6.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "getting_started2 - 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" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /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=xilink6.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 /subsystem:windows /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 /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "getting_started2 - 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" /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" /FR /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=xilink6.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 /subsystem:windows /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 /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "getting_started2 - Win32 DebugPython"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "getting_started2___Win32_DebugPython"
|
||||||
|
# PROP BASE Intermediate_Dir "getting_started2___Win32_DebugPython"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "getting_started2___Win32_DebugPython"
|
||||||
|
# PROP Intermediate_Dir "getting_started2___Win32_DebugPython"
|
||||||
|
# PROP Ignore_Export_Lib 1
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /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" /D "BOOST_DEBUG_PYTHON" /FR /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=xilink6.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 /subsystem:windows /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 /subsystem:windows /dll /debug /machine:I386 /out:"DebugPython/getting_started2_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\pcbuild"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "getting_started2 - Win32 Release"
|
||||||
|
# Name "getting_started2 - Win32 Debug"
|
||||||
|
# Name "getting_started2 - Win32 DebugPython"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\example\getting_started2.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
|
||||||
160
build/irix_CC.mak
Normal file
160
build/irix_CC.mak
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# Create a new empty directory anywhere (preferably not in the boost tree).
|
||||||
|
# Copy this Makefile to that new directory and rename it to "Makefile"
|
||||||
|
# Adjust the pathnames below.
|
||||||
|
#
|
||||||
|
# make softlinks Create softlinks to source code and tests
|
||||||
|
# make Compile all sources
|
||||||
|
# make test Run doctest tests
|
||||||
|
# make clean Remove all object files
|
||||||
|
# make unlink Remove softlinks
|
||||||
|
#
|
||||||
|
# Revision history:
|
||||||
|
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
||||||
|
# Initial version: R.W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
ROOT=$(HOME)
|
||||||
|
BOOST=$(ROOT)/boost
|
||||||
|
|
||||||
|
PYEXE=/usr/local/Python-1.5.2/bin/python
|
||||||
|
PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
||||||
|
#PYEXE=/usr/local/Python-2.0/bin/python
|
||||||
|
#PYINC=-I/usr/local/Python-2.0/include/python2.0
|
||||||
|
STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers
|
||||||
|
|
||||||
|
STDOPTS=
|
||||||
|
WARNOPTS=-woff 1001,1234,1682
|
||||||
|
OPTOPTS=-g
|
||||||
|
|
||||||
|
CPP=CC -LANG:std -n32 -mips4
|
||||||
|
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
||||||
|
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
||||||
|
MAKEDEP=-M
|
||||||
|
|
||||||
|
LD=CC -LANG:std -n32 -mips4
|
||||||
|
LDOPTS=-shared
|
||||||
|
|
||||||
|
OBJ=classes.o conversions.o extension_class.o functions.o \
|
||||||
|
init_function.o module_builder.o \
|
||||||
|
objects.o types.o cross_module.o
|
||||||
|
DEPOBJ=$(OBJ) \
|
||||||
|
comprehensive.o \
|
||||||
|
abstract.o \
|
||||||
|
getting_started1.o getting_started2.o \
|
||||||
|
simple_vector.o \
|
||||||
|
do_it_yourself_converters.o \
|
||||||
|
pickle1.o pickle2.o pickle3.o \
|
||||||
|
noncopyable_export.o noncopyable_import.o \
|
||||||
|
ivect.o dvect.o
|
||||||
|
|
||||||
|
.SUFFIXES: .o .cpp
|
||||||
|
|
||||||
|
all: libboost_python.a \
|
||||||
|
boost_python_test.so \
|
||||||
|
abstract.so \
|
||||||
|
getting_started1.so getting_started2.so \
|
||||||
|
simple_vector.so \
|
||||||
|
do_it_yourself_converters.so \
|
||||||
|
pickle1.so pickle2.so pickle3.so \
|
||||||
|
noncopyable_export.so noncopyable_import.so \
|
||||||
|
ivect.so dvect.so
|
||||||
|
|
||||||
|
libboost_python.a: $(OBJ)
|
||||||
|
rm -f libboost_python.a
|
||||||
|
$(CPP) -ar -o libboost_python.a $(OBJ)
|
||||||
|
|
||||||
|
boost_python_test.so: $(OBJ) comprehensive.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
||||||
|
|
||||||
|
abstract.so: $(OBJ) abstract.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
||||||
|
|
||||||
|
getting_started1.so: $(OBJ) getting_started1.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
||||||
|
|
||||||
|
getting_started2.so: $(OBJ) getting_started2.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
||||||
|
|
||||||
|
simple_vector.so: $(OBJ) simple_vector.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so
|
||||||
|
|
||||||
|
do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so
|
||||||
|
|
||||||
|
pickle1.so: $(OBJ) pickle1.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so
|
||||||
|
|
||||||
|
pickle2.so: $(OBJ) pickle2.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so
|
||||||
|
|
||||||
|
pickle3.so: $(OBJ) pickle3.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so
|
||||||
|
|
||||||
|
noncopyable_export.so: $(OBJ) noncopyable_export.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
||||||
|
noncopyable_export.o -o noncopyable_export.so
|
||||||
|
|
||||||
|
noncopyable_import.so: $(OBJ) noncopyable_import.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
||||||
|
noncopyable_import.o -o noncopyable_import.so
|
||||||
|
|
||||||
|
ivect.so: $(OBJ) ivect.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
|
||||||
|
|
||||||
|
dvect.so: $(OBJ) dvect.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CPP) $(CPPOPTS) -c $*.cpp
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(PYEXE) comprehensive.py
|
||||||
|
$(PYEXE) test_abstract.py
|
||||||
|
$(PYEXE) test_getting_started1.py
|
||||||
|
$(PYEXE) test_getting_started2.py
|
||||||
|
$(PYEXE) test_simple_vector.py
|
||||||
|
$(PYEXE) test_do_it_yourself_converters.py
|
||||||
|
$(PYEXE) test_pickle1.py
|
||||||
|
$(PYEXE) test_pickle2.py
|
||||||
|
$(PYEXE) test_pickle3.py
|
||||||
|
$(PYEXE) test_cross_module.py
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||||
|
rm -f comprehensive.o boost_python_test.so
|
||||||
|
rm -f abstract.o abstract.so
|
||||||
|
rm -f getting_started1.o getting_started1.so
|
||||||
|
rm -f getting_started2.o getting_started2.so
|
||||||
|
rm -f simple_vector.o simple_vector.so
|
||||||
|
rm -f do_it_yourself_converters.o do_it_yourself_converters.so
|
||||||
|
rm -f pickle1.o pickle1.so
|
||||||
|
rm -f pickle2.o pickle2.so
|
||||||
|
rm -f pickle3.o pickle3.so
|
||||||
|
rm -f noncopyable_export.o noncopyable_export.so
|
||||||
|
rm -f noncopyable_import.o noncopyable_import.so
|
||||||
|
rm -f ivect.o ivect.so
|
||||||
|
rm -f dvect.o dvect.so
|
||||||
|
rm -f so_locations *.pyc
|
||||||
|
rm -rf ii_files
|
||||||
|
|
||||||
|
softlinks:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks
|
||||||
|
|
||||||
|
unlink:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink
|
||||||
|
|
||||||
|
cp:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp
|
||||||
|
|
||||||
|
rm:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm
|
||||||
|
|
||||||
|
depend:
|
||||||
|
@ cat Makefile.nodepend; \
|
||||||
|
for obj in $(DEPOBJ); \
|
||||||
|
do \
|
||||||
|
bn=`echo "$$obj" | cut -d. -f1`; \
|
||||||
|
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
||||||
|
done
|
||||||
|
|
||||||
160
build/linux_gcc.mak
Normal file
160
build/linux_gcc.mak
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# Create a new empty directory anywhere (preferably not in the boost tree).
|
||||||
|
# Copy this Makefile to that new directory and rename it to "Makefile"
|
||||||
|
# Adjust the pathnames below.
|
||||||
|
#
|
||||||
|
# make softlinks Create softlinks to source code and tests
|
||||||
|
# make Compile all sources
|
||||||
|
# make test Run doctest tests
|
||||||
|
# make clean Remove all object files
|
||||||
|
# make unlink Remove softlinks
|
||||||
|
#
|
||||||
|
# Revision history:
|
||||||
|
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
||||||
|
# Initial version: R.W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
ROOT=$(HOME)
|
||||||
|
BOOST=$(ROOT)/boost
|
||||||
|
|
||||||
|
PYEXE=PYTHONPATH=. /usr/bin/python
|
||||||
|
PYINC=-I/usr/include/python1.5
|
||||||
|
#PYEXE=/usr/local/Python-1.5.2/bin/python
|
||||||
|
#PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
||||||
|
#PYEXE=/usr/local/Python-2.0/bin/python
|
||||||
|
#PYINC=-I/usr/local/Python-2.0/include/python2.0
|
||||||
|
|
||||||
|
STDOPTS=-ftemplate-depth-21 -fPIC
|
||||||
|
WARNOPTS=
|
||||||
|
OPTOPTS=-g
|
||||||
|
|
||||||
|
CPP=g++
|
||||||
|
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
||||||
|
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
||||||
|
MAKEDEP=-M
|
||||||
|
|
||||||
|
LD=$(CPP)
|
||||||
|
LDOPTS=-shared
|
||||||
|
|
||||||
|
OBJ=classes.o conversions.o extension_class.o functions.o \
|
||||||
|
init_function.o module_builder.o \
|
||||||
|
objects.o types.o cross_module.o
|
||||||
|
DEPOBJ=$(OBJ) \
|
||||||
|
comprehensive.o \
|
||||||
|
abstract.o \
|
||||||
|
getting_started1.o getting_started2.o \
|
||||||
|
simple_vector.o \
|
||||||
|
do_it_yourself_converters.o \
|
||||||
|
pickle1.o pickle2.o pickle3.o \
|
||||||
|
noncopyable_export.o noncopyable_import.o \
|
||||||
|
ivect.o dvect.o
|
||||||
|
|
||||||
|
.SUFFIXES: .o .cpp
|
||||||
|
|
||||||
|
all: libboost_python.a \
|
||||||
|
boost_python_test.so \
|
||||||
|
abstract.so \
|
||||||
|
getting_started1.so getting_started2.so \
|
||||||
|
simple_vector.so \
|
||||||
|
do_it_yourself_converters.so \
|
||||||
|
pickle1.so pickle2.so pickle3.so \
|
||||||
|
noncopyable_export.so noncopyable_import.so \
|
||||||
|
ivect.so dvect.so
|
||||||
|
|
||||||
|
libboost_python.a: $(OBJ)
|
||||||
|
rm -f libboost_python.a
|
||||||
|
ar r libboost_python.a $(OBJ)
|
||||||
|
|
||||||
|
boost_python_test.so: $(OBJ) comprehensive.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
||||||
|
|
||||||
|
abstract.so: $(OBJ) abstract.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
||||||
|
|
||||||
|
getting_started1.so: $(OBJ) getting_started1.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
||||||
|
|
||||||
|
getting_started2.so: $(OBJ) getting_started2.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
||||||
|
|
||||||
|
simple_vector.so: $(OBJ) simple_vector.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so
|
||||||
|
|
||||||
|
do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so
|
||||||
|
|
||||||
|
pickle1.so: $(OBJ) pickle1.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so
|
||||||
|
|
||||||
|
pickle2.so: $(OBJ) pickle2.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so
|
||||||
|
|
||||||
|
pickle3.so: $(OBJ) pickle3.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so
|
||||||
|
|
||||||
|
noncopyable_export.so: $(OBJ) noncopyable_export.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
||||||
|
noncopyable_export.o -o noncopyable_export.so
|
||||||
|
|
||||||
|
noncopyable_import.so: $(OBJ) noncopyable_import.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
||||||
|
noncopyable_import.o -o noncopyable_import.so
|
||||||
|
|
||||||
|
ivect.so: $(OBJ) ivect.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
|
||||||
|
|
||||||
|
dvect.so: $(OBJ) dvect.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CPP) $(CPPOPTS) -c $*.cpp
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(PYEXE) comprehensive.py
|
||||||
|
$(PYEXE) test_abstract.py
|
||||||
|
$(PYEXE) test_getting_started1.py
|
||||||
|
$(PYEXE) test_getting_started2.py
|
||||||
|
$(PYEXE) test_simple_vector.py
|
||||||
|
$(PYEXE) test_do_it_yourself_converters.py
|
||||||
|
$(PYEXE) test_pickle1.py
|
||||||
|
$(PYEXE) test_pickle2.py
|
||||||
|
$(PYEXE) test_pickle3.py
|
||||||
|
$(PYEXE) test_cross_module.py
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||||
|
rm -f comprehensive.o boost_python_test.so
|
||||||
|
rm -f abstract.o abstract.so
|
||||||
|
rm -f getting_started1.o getting_started1.so
|
||||||
|
rm -f getting_started2.o getting_started2.so
|
||||||
|
rm -f simple_vector.o simple_vector.so
|
||||||
|
rm -f do_it_yourself_converters.o do_it_yourself_converters.so
|
||||||
|
rm -f pickle1.o pickle1.so
|
||||||
|
rm -f pickle2.o pickle2.so
|
||||||
|
rm -f pickle3.o pickle3.so
|
||||||
|
rm -f noncopyable_export.o noncopyable_export.so
|
||||||
|
rm -f noncopyable_import.o noncopyable_import.so
|
||||||
|
rm -f ivect.o ivect.so
|
||||||
|
rm -f dvect.o dvect.so
|
||||||
|
rm -f so_locations *.pyc
|
||||||
|
|
||||||
|
softlinks:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks
|
||||||
|
|
||||||
|
unlink:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink
|
||||||
|
|
||||||
|
cp:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp
|
||||||
|
|
||||||
|
rm:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm
|
||||||
|
|
||||||
|
depend:
|
||||||
|
@ cat Makefile.nodepend; \
|
||||||
|
for obj in $(DEPOBJ); \
|
||||||
|
do \
|
||||||
|
bn=`echo "$$obj" | cut -d. -f1`; \
|
||||||
|
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
||||||
|
done
|
||||||
|
|
||||||
189
build/mingw32.mak
Normal file
189
build/mingw32.mak
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# make copy Copy the sources and tests
|
||||||
|
# make Compile all sources
|
||||||
|
# make test Run doctest tests
|
||||||
|
# make clean Remove all object files
|
||||||
|
# make del Remove the sources and tests
|
||||||
|
#
|
||||||
|
# Revision history:
|
||||||
|
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
||||||
|
# Initial version: R.W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
# To install mingw32, follow instructions at:
|
||||||
|
# http://starship.python.net/crew/kernr/mingw32/Notes.html
|
||||||
|
# In particular, install:
|
||||||
|
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/gcc-2.95.2-msvcrt.exe
|
||||||
|
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/fixes/quote-fix-msvcrt.exe
|
||||||
|
# http://starship.python.net/crew/kernr/mingw32/Python-1.5.2-mingw32.zip
|
||||||
|
# Unpack the first two archives in the default locations and update your PATH.
|
||||||
|
# Unpack the third archive in \usr.
|
||||||
|
|
||||||
|
# Note: comprehensive.cpp generates compiler errors and later crashes.
|
||||||
|
# L:\boost\boost\python\detail\extension_class.hpp:643: warning:
|
||||||
|
# alignment of `vtable for class
|
||||||
|
# boost::python::detail::held_instance<bpl_test::Derived1>'
|
||||||
|
# is greater than maximum object file alignment. Using 16.
|
||||||
|
# Could this be fixed with compiler options?
|
||||||
|
# -fhuge-objects looks interesting, but requires recompiling the C++ library.
|
||||||
|
# (what exactly does that mean?)
|
||||||
|
# -fvtable-thunks eliminates the compiler warning, but
|
||||||
|
# "import boost_python_test" still causes a crash.
|
||||||
|
|
||||||
|
ROOT=L:
|
||||||
|
BOOST_WIN="$(ROOT)\boost"
|
||||||
|
BOOST_UNIX=$(HOME)/boost
|
||||||
|
|
||||||
|
PYEXE="C:\Program files\Python\python.exe"
|
||||||
|
PYINC=-I"C:\usr\include\python1.5"
|
||||||
|
PYLIB="C:\usr\lib\libpython15.a"
|
||||||
|
|
||||||
|
STDOPTS=-ftemplate-depth-21
|
||||||
|
WARNOPTS=
|
||||||
|
OPTOPTS=-g
|
||||||
|
|
||||||
|
CPP=g++
|
||||||
|
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \
|
||||||
|
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
||||||
|
|
||||||
|
LD=g++
|
||||||
|
LDOPTS=-shared
|
||||||
|
|
||||||
|
OBJ=classes.o conversions.o extension_class.o functions.o \
|
||||||
|
init_function.o module_builder.o \
|
||||||
|
objects.o types.o cross_module.o
|
||||||
|
|
||||||
|
.SUFFIXES: .o .cpp
|
||||||
|
|
||||||
|
all: libboost_python.a \
|
||||||
|
abstract.pyd \
|
||||||
|
getting_started1.pyd getting_started2.pyd \
|
||||||
|
simple_vector.pyd \
|
||||||
|
do_it_yourself_converters.pyd \
|
||||||
|
pickle1.pyd pickle2.pyd pickle3.pyd \
|
||||||
|
noncopyable_export.pyd noncopyable_import.pyd \
|
||||||
|
ivect.pyd dvect.pyd
|
||||||
|
|
||||||
|
libboost_python.a: $(OBJ)
|
||||||
|
del libboost_python.a
|
||||||
|
ar r libboost_python.a $(OBJ)
|
||||||
|
|
||||||
|
DLLWRAPOPTS=-s --driver-name g++ -s \
|
||||||
|
--entry _DllMainCRTStartup@12 --target=i386-mingw32
|
||||||
|
|
||||||
|
boost_python_test.pyd: $(OBJ) comprehensive.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname boost_python_test.pyd \
|
||||||
|
--def boost_python_test.def \
|
||||||
|
$(OBJ) comprehensive.o $(PYLIB)
|
||||||
|
|
||||||
|
abstract.pyd: $(OBJ) abstract.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname abstract.pyd \
|
||||||
|
--def abstract.def \
|
||||||
|
$(OBJ) abstract.o $(PYLIB)
|
||||||
|
|
||||||
|
getting_started1.pyd: $(OBJ) getting_started1.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname getting_started1.pyd \
|
||||||
|
--def getting_started1.def \
|
||||||
|
$(OBJ) getting_started1.o $(PYLIB)
|
||||||
|
|
||||||
|
getting_started2.pyd: $(OBJ) getting_started2.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname getting_started2.pyd \
|
||||||
|
--def getting_started2.def \
|
||||||
|
$(OBJ) getting_started2.o $(PYLIB)
|
||||||
|
|
||||||
|
simple_vector.pyd: $(OBJ) simple_vector.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname simple_vector.pyd \
|
||||||
|
--def simple_vector.def \
|
||||||
|
$(OBJ) simple_vector.o $(PYLIB)
|
||||||
|
|
||||||
|
do_it_yourself_converters.pyd: $(OBJ) do_it_yourself_converters.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname do_it_yourself_converters.pyd \
|
||||||
|
--def do_it_yourself_converters.def \
|
||||||
|
$(OBJ) do_it_yourself_converters.o $(PYLIB)
|
||||||
|
|
||||||
|
pickle1.pyd: $(OBJ) pickle1.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname pickle1.pyd \
|
||||||
|
--def pickle1.def \
|
||||||
|
$(OBJ) pickle1.o $(PYLIB)
|
||||||
|
|
||||||
|
pickle2.pyd: $(OBJ) pickle2.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname pickle2.pyd \
|
||||||
|
--def pickle2.def \
|
||||||
|
$(OBJ) pickle2.o $(PYLIB)
|
||||||
|
|
||||||
|
pickle3.pyd: $(OBJ) pickle3.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname pickle3.pyd \
|
||||||
|
--def pickle3.def \
|
||||||
|
$(OBJ) pickle3.o $(PYLIB)
|
||||||
|
|
||||||
|
noncopyable_export.pyd: $(OBJ) noncopyable_export.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname noncopyable_export.pyd \
|
||||||
|
--def noncopyable_export.def \
|
||||||
|
$(OBJ) noncopyable_export.o $(PYLIB)
|
||||||
|
|
||||||
|
noncopyable_import.pyd: $(OBJ) noncopyable_import.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname noncopyable_import.pyd \
|
||||||
|
--def noncopyable_import.def \
|
||||||
|
$(OBJ) noncopyable_import.o $(PYLIB)
|
||||||
|
|
||||||
|
ivect.pyd: $(OBJ) ivect.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname ivect.pyd \
|
||||||
|
--def ivect.def \
|
||||||
|
$(OBJ) ivect.o $(PYLIB)
|
||||||
|
|
||||||
|
dvect.pyd: $(OBJ) dvect.o
|
||||||
|
dllwrap $(DLLWRAPOPTS) \
|
||||||
|
--dllname dvect.pyd \
|
||||||
|
--def dvect.def \
|
||||||
|
$(OBJ) dvect.o $(PYLIB)
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CPP) $(CPPOPTS) -c $*.cpp
|
||||||
|
|
||||||
|
test:
|
||||||
|
# $(PYEXE) comprehensive.py
|
||||||
|
$(PYEXE) test_abstract.py
|
||||||
|
$(PYEXE) test_getting_started1.py
|
||||||
|
$(PYEXE) test_getting_started2.py
|
||||||
|
$(PYEXE) test_simple_vector.py
|
||||||
|
$(PYEXE) test_do_it_yourself_converters.py
|
||||||
|
$(PYEXE) test_pickle1.py
|
||||||
|
$(PYEXE) test_pickle2.py
|
||||||
|
$(PYEXE) test_pickle3.py
|
||||||
|
$(PYEXE) test_cross_module.py
|
||||||
|
|
||||||
|
clean:
|
||||||
|
del *.o
|
||||||
|
del *.a
|
||||||
|
del *.pyd
|
||||||
|
del *.pyc
|
||||||
|
|
||||||
|
softlinks:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks
|
||||||
|
|
||||||
|
unlink:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink
|
||||||
|
|
||||||
|
cp:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp
|
||||||
|
|
||||||
|
rm:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm
|
||||||
|
|
||||||
|
copy:
|
||||||
|
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy
|
||||||
|
|
||||||
|
del:
|
||||||
|
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del
|
||||||
135
build/rwgk1/rwgk1.dsp
Normal file
135
build/rwgk1/rwgk1.dsp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# 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 DebugPython
|
||||||
|
!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 DebugPython"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "rwgk1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "rwgk1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "rwgk1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# 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 Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD 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 /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "rwgk1 - Win32 DebugPython"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "rwgk1___Win32_DebugPython"
|
||||||
|
# PROP BASE Intermediate_Dir "rwgk1___Win32_DebugPython"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "DebugPython"
|
||||||
|
# PROP Intermediate_Dir "DebugPython"
|
||||||
|
# PROP Ignore_Export_Lib 1
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/rwgk1_d.dll" /pdbtype:sept /libpath:"C:\tools\python\src\PCbuild"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "rwgk1 - Win32 Release"
|
||||||
|
# Name "rwgk1 - Win32 Debug"
|
||||||
|
# Name "rwgk1 - Win32 DebugPython"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# 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
|
||||||
145
build/test/test.dsp
Normal file
145
build/test/test.dsp
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# 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 DebugPython
|
||||||
|
!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 DebugPython"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "test - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# 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
|
||||||
|
# SUBTRACT CPP /Fr
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# 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/boost_python_test.dll" /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
|
||||||
|
# SUBTRACT CPP /Fr
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# 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 /incremental:no /debug /machine:I386 /out:"Debug/boost_python_test.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "test - Win32 DebugPython"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "test___Win32_DebugPython"
|
||||||
|
# PROP BASE Intermediate_Dir "test___Win32_DebugPython"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "DebugPython"
|
||||||
|
# PROP Intermediate_Dir "DebugPython"
|
||||||
|
# PROP Ignore_Export_Lib 1
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /Zm200 /EHs /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||||
|
# SUBTRACT BASE LINK32 /pdb:none
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/boost_python_test_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||||
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "test - Win32 Release"
|
||||||
|
# Name "test - Win32 Debug"
|
||||||
|
# Name "test - Win32 DebugPython"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# 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
|
||||||
175
build/tru64_cxx.mak
Normal file
175
build/tru64_cxx.mak
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# Create a new empty directory anywhere (preferably not in the boost tree).
|
||||||
|
# Copy this Makefile to that new directory and rename it to "Makefile"
|
||||||
|
# Adjust the pathnames below.
|
||||||
|
#
|
||||||
|
# make softlinks Create softlinks to source code and tests
|
||||||
|
# make Compile all sources
|
||||||
|
# make test Run doctest tests
|
||||||
|
# make clean Remove all object files
|
||||||
|
# make unlink Remove softlinks
|
||||||
|
#
|
||||||
|
# Revision history:
|
||||||
|
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
||||||
|
# Initial version: R.W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
ROOT=$(HOME)
|
||||||
|
BOOST=$(ROOT)/boost
|
||||||
|
|
||||||
|
PYEXE=/usr/local/Python-1.5.2/bin/python
|
||||||
|
PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
||||||
|
#PYEXE=/usr/local/Python-2.0/bin/python
|
||||||
|
#PYINC=-I/usr/local/Python-2.0/include/python2.0
|
||||||
|
#STLPORTINC=-I/usr/local/STLport-4.1b3/stlport
|
||||||
|
#STLPORTINC=-I/usr/local/STLport-4.1b4/stlport
|
||||||
|
#STLPORTOPTS= \
|
||||||
|
# -D__USE_STD_IOSTREAM \
|
||||||
|
# -D__STL_NO_SGI_IOSTREAMS \
|
||||||
|
# -D__STL_USE_NATIVE_STRING \
|
||||||
|
# -D__STL_NO_NEW_C_HEADERS \
|
||||||
|
# -D_RWSTD_COMPILE_INSTANTIATE=1
|
||||||
|
STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers
|
||||||
|
|
||||||
|
STDOPTS=-std strict_ansi
|
||||||
|
# use -msg_display_number to obtain integer tags for -msg_disable
|
||||||
|
WARNOPTS=-msg_disable 186,450,1115
|
||||||
|
OPTOPTS=-g
|
||||||
|
|
||||||
|
CPP=cxx
|
||||||
|
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
||||||
|
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
||||||
|
MAKEDEP=-Em
|
||||||
|
|
||||||
|
LD=cxx
|
||||||
|
LDOPTS=-shared -expect_unresolved 'Py*' -expect_unresolved '_Py*'
|
||||||
|
|
||||||
|
#HIDDEN=-hidden
|
||||||
|
|
||||||
|
OBJ=classes.o conversions.o extension_class.o functions.o \
|
||||||
|
init_function.o module_builder.o \
|
||||||
|
objects.o types.o cross_module.o
|
||||||
|
DEPOBJ=$(OBJ) \
|
||||||
|
comprehensive.o \
|
||||||
|
abstract.o \
|
||||||
|
getting_started1.o getting_started2.o \
|
||||||
|
simple_vector.o \
|
||||||
|
do_it_yourself_converters.o \
|
||||||
|
pickle1.o pickle2.o pickle3.o \
|
||||||
|
noncopyable_export.o noncopyable_import.o \
|
||||||
|
ivect.o dvect.o
|
||||||
|
|
||||||
|
.SUFFIXES: .o .cpp
|
||||||
|
|
||||||
|
all: libboost_python.a \
|
||||||
|
boost_python_test.so \
|
||||||
|
abstract.so \
|
||||||
|
getting_started1.so getting_started2.so \
|
||||||
|
simple_vector.so \
|
||||||
|
do_it_yourself_converters.so \
|
||||||
|
pickle1.so pickle2.so pickle3.so \
|
||||||
|
noncopyable_export.so noncopyable_import.so \
|
||||||
|
ivect.so dvect.so
|
||||||
|
|
||||||
|
libboost_python.a: $(OBJ)
|
||||||
|
rm -f libboost_python.a
|
||||||
|
cd cxx_repository; \
|
||||||
|
ls -1 > ../libboost_python.a.input; \
|
||||||
|
ar r ../libboost_python.a -input ../libboost_python.a.input
|
||||||
|
rm -f libboost_python.a.input
|
||||||
|
ar r libboost_python.a $(OBJ)
|
||||||
|
|
||||||
|
boost_python_test.so: $(OBJ) comprehensive.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
||||||
|
|
||||||
|
abstract.so: $(OBJ) abstract.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
||||||
|
|
||||||
|
getting_started1.so: $(OBJ) getting_started1.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
||||||
|
|
||||||
|
getting_started2.so: $(OBJ) getting_started2.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
||||||
|
|
||||||
|
simple_vector.so: $(OBJ) simple_vector.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so
|
||||||
|
|
||||||
|
do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so
|
||||||
|
|
||||||
|
pickle1.so: $(OBJ) pickle1.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so
|
||||||
|
|
||||||
|
pickle2.so: $(OBJ) pickle2.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so
|
||||||
|
|
||||||
|
pickle3.so: $(OBJ) pickle3.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so
|
||||||
|
|
||||||
|
noncopyable_export.so: $(OBJ) noncopyable_export.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
||||||
|
noncopyable_export.o -o noncopyable_export.so
|
||||||
|
|
||||||
|
noncopyable_import.so: $(OBJ) noncopyable_import.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
||||||
|
noncopyable_import.o -o noncopyable_import.so
|
||||||
|
|
||||||
|
ivect.so: $(OBJ) ivect.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
|
||||||
|
|
||||||
|
dvect.so: $(OBJ) dvect.o
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CPP) $(CPPOPTS) -c $*.cpp
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(PYEXE) comprehensive.py
|
||||||
|
$(PYEXE) test_abstract.py
|
||||||
|
$(PYEXE) test_getting_started1.py
|
||||||
|
$(PYEXE) test_getting_started2.py
|
||||||
|
$(PYEXE) test_simple_vector.py
|
||||||
|
$(PYEXE) test_do_it_yourself_converters.py
|
||||||
|
$(PYEXE) test_pickle1.py
|
||||||
|
$(PYEXE) test_pickle2.py
|
||||||
|
$(PYEXE) test_pickle3.py
|
||||||
|
$(PYEXE) test_cross_module.py
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||||
|
rm -f comprehensive.o boost_python_test.so
|
||||||
|
rm -f abstract.o abstract.so
|
||||||
|
rm -f getting_started1.o getting_started1.so
|
||||||
|
rm -f getting_started2.o getting_started2.so
|
||||||
|
rm -f simple_vector.o simple_vector.so
|
||||||
|
rm -f do_it_yourself_converters.o do_it_yourself_converters.so
|
||||||
|
rm -f pickle1.o pickle1.so
|
||||||
|
rm -f pickle2.o pickle2.so
|
||||||
|
rm -f pickle3.o pickle3.so
|
||||||
|
rm -f noncopyable_export.o noncopyable_export.so
|
||||||
|
rm -f noncopyable_import.o noncopyable_import.so
|
||||||
|
rm -f ivect.o ivect.so
|
||||||
|
rm -f dvect.o dvect.so
|
||||||
|
rm -f so_locations *.pyc
|
||||||
|
rm -rf cxx_repository
|
||||||
|
|
||||||
|
softlinks:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks
|
||||||
|
|
||||||
|
unlink:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink
|
||||||
|
|
||||||
|
cp:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp
|
||||||
|
|
||||||
|
rm:
|
||||||
|
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm
|
||||||
|
|
||||||
|
depend:
|
||||||
|
@ cat Makefile.nodepend; \
|
||||||
|
for obj in $(DEPOBJ); \
|
||||||
|
do \
|
||||||
|
bn=`echo "$$obj" | cut -d. -f1`; \
|
||||||
|
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
||||||
|
done
|
||||||
|
|
||||||
129
build/vc60.mak
Normal file
129
build/vc60.mak
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# make copy Copy the sources and tests
|
||||||
|
# make Compile all sources
|
||||||
|
# make test Run doctest tests
|
||||||
|
# make clean Remove all object files
|
||||||
|
# make del Remove the sources and tests
|
||||||
|
#
|
||||||
|
# Revision history:
|
||||||
|
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
||||||
|
# Initial version: R.W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
ROOT=L:
|
||||||
|
BOOST_WIN="$(ROOT)\boost"
|
||||||
|
BOOST_UNIX=$(HOME)/boost
|
||||||
|
|
||||||
|
PYEXE="C:\Program files\Python\python.exe"
|
||||||
|
PYINC=/I"C:\Program files\Python\include"
|
||||||
|
PYLIB="C:\Program files\Python\libs\python15.lib"
|
||||||
|
|
||||||
|
STDOPTS=/nologo /MD /GR /GX /Zm200
|
||||||
|
WARNOPTS=
|
||||||
|
OPTOPTS=
|
||||||
|
|
||||||
|
CPP=cl.exe
|
||||||
|
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) /I$(BOOST_WIN) $(PYINC) \
|
||||||
|
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
||||||
|
|
||||||
|
LD=link.exe
|
||||||
|
LDOPTS=/nologo /dll /incremental:no
|
||||||
|
|
||||||
|
OBJ=classes.obj conversions.obj extension_class.obj functions.obj \
|
||||||
|
init_function.obj module_builder.obj \
|
||||||
|
objects.obj types.obj cross_module.obj
|
||||||
|
|
||||||
|
.SUFFIXES: .obj .cpp
|
||||||
|
|
||||||
|
all: boost_python.lib \
|
||||||
|
boost_python_test.pyd \
|
||||||
|
abstract.pyd \
|
||||||
|
getting_started1.pyd getting_started2.pyd \
|
||||||
|
simple_vector.pyd \
|
||||||
|
do_it_yourself_converters.pyd \
|
||||||
|
pickle1.pyd pickle2.pyd pickle3.pyd \
|
||||||
|
noncopyable_export.pyd noncopyable_import.pyd \
|
||||||
|
ivect.pyd dvect.pyd
|
||||||
|
|
||||||
|
boost_python.lib: $(OBJ)
|
||||||
|
$(LD) -lib /nologo /out:boost_python.lib $(OBJ)
|
||||||
|
|
||||||
|
boost_python_test.pyd: $(OBJ) comprehensive.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) /export:initboost_python_test /out:"boost_python_test.pyd"
|
||||||
|
|
||||||
|
abstract.pyd: $(OBJ) abstract.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) /export:initabstract /out:"abstract.pyd"
|
||||||
|
|
||||||
|
getting_started1.pyd: $(OBJ) getting_started1.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) /export:initgetting_started1 /out:"getting_started1.pyd"
|
||||||
|
|
||||||
|
getting_started2.pyd: $(OBJ) getting_started2.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) /export:initgetting_started2 /out:"getting_started2.pyd"
|
||||||
|
|
||||||
|
simple_vector.pyd: $(OBJ) simple_vector.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) /export:initsimple_vector /out:"simple_vector.pyd"
|
||||||
|
|
||||||
|
do_it_yourself_converters.pyd: $(OBJ) do_it_yourself_converters.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.obj $(PYLIB) /export:initdo_it_yourself_converters /out:"do_it_yourself_converters.pyd"
|
||||||
|
|
||||||
|
pickle1.pyd: $(OBJ) pickle1.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd"
|
||||||
|
|
||||||
|
pickle2.pyd: $(OBJ) pickle2.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) /export:initpickle2 /out:"pickle2.pyd"
|
||||||
|
|
||||||
|
pickle3.pyd: $(OBJ) pickle3.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) /export:initpickle3 /out:"pickle3.pyd"
|
||||||
|
|
||||||
|
noncopyable_export.pyd: $(OBJ) noncopyable_export.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) /export:initnoncopyable_export /out:"noncopyable_export.pyd"
|
||||||
|
|
||||||
|
noncopyable_import.pyd: $(OBJ) noncopyable_import.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) /export:initnoncopyable_import /out:"noncopyable_import.pyd"
|
||||||
|
|
||||||
|
ivect.pyd: $(OBJ) ivect.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) /export:initivect /out:"ivect.pyd"
|
||||||
|
|
||||||
|
dvect.pyd: $(OBJ) dvect.obj
|
||||||
|
$(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd"
|
||||||
|
|
||||||
|
.cpp.obj:
|
||||||
|
$(CPP) $(CPPOPTS) /c $*.cpp
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(PYEXE) comprehensive.py --broken-auto-ptr
|
||||||
|
$(PYEXE) test_abstract.py
|
||||||
|
$(PYEXE) test_getting_started1.py
|
||||||
|
$(PYEXE) test_getting_started2.py
|
||||||
|
$(PYEXE) test_simple_vector.py
|
||||||
|
$(PYEXE) test_do_it_yourself_converters.py
|
||||||
|
$(PYEXE) test_pickle1.py
|
||||||
|
$(PYEXE) test_pickle2.py
|
||||||
|
$(PYEXE) test_pickle3.py
|
||||||
|
$(PYEXE) test_cross_module.py --broken-auto-ptr
|
||||||
|
|
||||||
|
clean:
|
||||||
|
del *.obj
|
||||||
|
del *.lib
|
||||||
|
del *.exp
|
||||||
|
del *.idb
|
||||||
|
del *.pyd
|
||||||
|
del *.pyc
|
||||||
|
|
||||||
|
softlinks:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks
|
||||||
|
|
||||||
|
unlink:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink
|
||||||
|
|
||||||
|
cp:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp
|
||||||
|
|
||||||
|
rm:
|
||||||
|
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm
|
||||||
|
|
||||||
|
copy:
|
||||||
|
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy
|
||||||
|
|
||||||
|
del:
|
||||||
|
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del
|
||||||
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,43 +1,180 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
Building a Module with Py_cpp
|
|
||||||
</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
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Right now, the only supported configuration is one in which the py_cpp
|
|
||||||
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:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
<a href="../../../libs/python/src/extension_class.cpp">extclass.cpp</a>
|
|
||||||
<a href="../../../libs/python/src/functions.cpp">functions.cpp</a>
|
|
||||||
<a href="../../../libs/python/src/init_function.cpp">init_function.cpp</a>
|
|
||||||
<a href="../../../libs/python/src/module_builder.cpp">module.cpp</a>
|
|
||||||
<a href="../../../libs/python/src/types.cpp">newtypes.cpp</a>
|
|
||||||
<a href="../../../libs/python/src/objects.cpp">objects.cpp</a>
|
|
||||||
<a href="../../../libs/python/src/conversions.cpp">py.cpp</a>
|
|
||||||
<a href="../../../libs/python/src/classes.cpp">subclass.cpp</a>
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Previous: <a href="under-the-hood.html">A Peek Under the Hood</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided “as
|
|
||||||
is” without express or implied warranty, and with no claim as to
|
|
||||||
its suitability for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Nov 26, 2000
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||||
|
|
||||||
|
<title>Building an Extension Module</title>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h1><img width="277" height="86" align="center" src=
|
||||||
|
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Building an
|
||||||
|
Extension Module</h1>
|
||||||
|
|
||||||
|
<p>The build process for Boost is currently undergoing some evolution,
|
||||||
|
and, it is to be hoped, improvement. The following facts may help:
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
Makefiles for various platforms and a Visual Studio project
|
||||||
|
reside in the Boost subdirectory <tt>libs/python/build</tt>.
|
||||||
|
Build targets include:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The <tt>boost_python</tt> library for static linking with your
|
||||||
|
extension module. On the various Unices, this library will be
|
||||||
|
called <tt>libboost_python.a</tt>. When using Visual C++, the
|
||||||
|
library will be called <tt>boost_python.lib</tt>.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<li>A comprehensive test of Boost.Python features. This test builds
|
||||||
|
a Boost.Python extension module, then runs Python to import the
|
||||||
|
module, and runs a series of tests on it using <tt><a href=
|
||||||
|
"../test/doctest.py">doctest</a></tt>. Source code for the module
|
||||||
|
and tests is available in the Boost subdirectory
|
||||||
|
<tt>libs/python/test</tt>.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<li>Various examples from the Boost subdirectory
|
||||||
|
<tt>libs/python/example</tt>.
|
||||||
|
All these examples include a doctest modeled
|
||||||
|
on the comprehensive test above.
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
There is a group of makefiles with support for simultaneous
|
||||||
|
compilation on multiple platforms and a consistent set of
|
||||||
|
features that build the <tt>boost_python</tt> library for static
|
||||||
|
linking, the comprehensive test, and all examples in
|
||||||
|
<tt>libs/python/example</tt>:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="../build/vc60.mak">vc60.mak</a>:
|
||||||
|
Visual C++ 6.0 Service Pack 4
|
||||||
|
|
||||||
|
<li><a href="../build/mingw32.mak">mingw32.mak</a>:
|
||||||
|
mingw32 (Win32-targeted) gcc 2.95.2
|
||||||
|
|
||||||
|
<li><a href="../build/linux_gcc.mak">linux_gcc.mak</a>:
|
||||||
|
gcc 2.95.2 on Linux/Unix
|
||||||
|
|
||||||
|
<li><a href="../build/tru64_cxx.mak">tru64_cxx.mak</a>:
|
||||||
|
Compaq Alpha using the Compaq cxx compiler
|
||||||
|
|
||||||
|
<li><a href="../build/irix_CC.mak">irix_CC.mak</a>:
|
||||||
|
Silicon Graphics IRIX 6.5 CC compiler
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<a href="http://cctbx.sourceforge.net/page_installation_adv.html#installation_boost_python"
|
||||||
|
>Usage of these makefiles is described here.</a>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
There is another group of makefiles for GNU make.
|
||||||
|
These makefiles are less redundant than the makefiles
|
||||||
|
in the group above,
|
||||||
|
but the list of compilation targets is not as complete
|
||||||
|
and there is no support for simultaneous compilation
|
||||||
|
on multiple platforms.
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="../build/como.mak">como.mak</a>:
|
||||||
|
Comeau C++ on Linux
|
||||||
|
|
||||||
|
<li><a href="../build/gcc.mak">gcc.mak</a>:
|
||||||
|
GCC on Linux/Unix.
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
A project workspace for Microsoft Visual Studio is provided at <tt><a
|
||||||
|
href="../build/build.dsw">libs/python/build/build.dsw</a></tt>. The
|
||||||
|
include paths for this project may need to be changed for your
|
||||||
|
installation. They currently assume that python has been installed at
|
||||||
|
<tt>c:\tools\python</tt>. Three configurations of all targets are
|
||||||
|
supported:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Release (optimization, <tt>-DNDEBUG</tt>)
|
||||||
|
|
||||||
|
<li>Debug (no optimization <tt>-D_DEBUG</tt>)
|
||||||
|
|
||||||
|
<li>DebugPython (no optimization, <tt>-D_DEBUG
|
||||||
|
-DBOOST_DEBUG_PYTHON</tt>)
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>When extension modules are built with Visual C++ using
|
||||||
|
<tt>-D_DEBUG</tt>, Python defaults to <i>force</i> linking with a
|
||||||
|
special debugging version of the Python DLL. Since this debug DLL
|
||||||
|
isn't supplied with the default Python installation for Windows,
|
||||||
|
Boost.Python uses <tt><a href=
|
||||||
|
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a></tt>
|
||||||
|
to temporarily undefine <tt>_DEBUG</tt> when <tt>Python.h</tt> is
|
||||||
|
<tt>#include</tt>d.
|
||||||
|
|
||||||
|
<p>If you want the extra runtime checks available with the debugging
|
||||||
|
version of the library, <tt>#define BOOST_DEBUG_PYTHON</tt> to
|
||||||
|
re-enable library forcing, and link with the DebugPython version of
|
||||||
|
<tt>boost_python.lib</tt>. You'll need to get the debugging version
|
||||||
|
of the Python executable (<tt>python_d.exe</tt>) and DLL
|
||||||
|
(<tt>python20_d.dll</tt> or <tt>python15_d.dll</tt>). The Python
|
||||||
|
sources include project files for building these. If you <a href=
|
||||||
|
"http://www.python.org">download</a> them, change the name of the
|
||||||
|
top-level directory to <tt>src</tt>, and install it under
|
||||||
|
<tt>c:\tools\python</tt>, the workspace supplied by Boost.Python will
|
||||||
|
be able to use it without modification. Just open
|
||||||
|
<tt>c:\tools\python\src\pcbuild\pcbuild.dsw</tt> and invoke "build
|
||||||
|
all" to generate all the debugging targets.
|
||||||
|
|
||||||
|
<p>If you do not <tt>#define BOOST_DEBUG_PYTHON</tt>, be sure that
|
||||||
|
any source files <tt>#include <<a href=
|
||||||
|
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a>></tt>
|
||||||
|
instead of the usual <tt>Python.h</tt>, or you will have link
|
||||||
|
incompatibilities.<br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
If your platform isn't directly supported, you can build a static
|
||||||
|
library from the following source files (in the Boost subdirectory
|
||||||
|
<tt>libs/python/src</tt>), or compile them directly and link the
|
||||||
|
resulting objects into your extension module:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/classes.cpp">classes.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/conversions.cpp">conversions.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/cross_module.cpp">cross_module.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/extension_class.cpp">extension_class.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/functions.cpp">functions.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/init_function.cpp">init_function.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/module_builder.cpp">module_builder.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/objects.cpp">objects.cpp</a>
|
||||||
|
|
||||||
|
<li><a href=
|
||||||
|
"../../../libs/python/src/types.cpp">types.cpp</a>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
Next: <a href="enums.html">Wrapping Enums</a> Previous: <a href=
|
||||||
|
"under-the-hood.html">A Peek Under the Hood</a> Up: <a href=
|
||||||
|
"index.html">Top</a>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<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: Apr 17, 2001 (R.W. Grosse-Kunstleve)
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -6,20 +6,23 @@
|
|||||||
<div>
|
<div>
|
||||||
<h1>
|
<h1>
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Comparisons with
|
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
||||||
|
Comparisons with
|
||||||
Other Systems
|
Other Systems
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<h2>CXX</h2>
|
<h2>CXX</h2>
|
||||||
<p>
|
<p>
|
||||||
Like py_cpp, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
Like Boost.Python, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
||||||
provide a C++-oriented interface to Python. In most cases, like py_cpp,
|
provide a C++-oriented interface to Python. In most cases, as with the
|
||||||
it relieves the user from worrying about reference-counts. As far as I
|
boost library, it relieves the user from worrying about
|
||||||
can tell, there is no support for subclassing C++ extension types in
|
reference-counts. Both libraries automatically convert thrown C++
|
||||||
Python. An even more-significant difference is that a user's C++ code is
|
exceptions into Python exceptions. As far as I can tell, CXX has no
|
||||||
still basically “dealing with Python objects”, though they are wrapped
|
support for subclassing C++ extension types in Python. An even
|
||||||
in C++ classes. This means such jobs as argument parsing and conversion
|
more significant difference is that a user's C++ code is still basically
|
||||||
are still left to be done explicitly by the user.
|
``dealing with Python objects'', though they are wrapped in
|
||||||
|
C++ classes. This means such jobs as argument parsing and conversion are
|
||||||
|
still left to be done explicitly by the user.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
CXX claims to interoperate well with the C++ Standard Library
|
CXX claims to interoperate well with the C++ Standard Library
|
||||||
@@ -38,11 +41,15 @@
|
|||||||
<p>
|
<p>
|
||||||
As far as I can tell, CXX enables one to write what is essentially
|
As far as I can tell, CXX enables one to write what is essentially
|
||||||
idiomatic Python code in C++, manipulating Python objects through the
|
idiomatic Python code in C++, manipulating Python objects through the
|
||||||
same fully-generic interfaces we use in Python. I think it would be fair
|
same fully-generic interfaces we use in Python. While you're hardly
|
||||||
to say that while you're not programming directly to the “bare
|
programming directly to the ``bare metal'' with CXX, it basically
|
||||||
metal” with CXX, in comparison to py_cpp, it presents a low-level
|
presents a ``C++-ized'' version of the Python 'C' API. Some fraction of
|
||||||
interface to Python. That use is also supported by the py_cpp object
|
that capability is available in Boost.Python through <tt><a
|
||||||
wrappers.
|
href="../../../boost/python/objects.hpp">boost/python/objects.hpp</a></tt>,
|
||||||
|
which provides C++ objects corresponding to Python lists, tuples,
|
||||||
|
strings, and dictionaries, and through <tt><a
|
||||||
|
href="../../../boost/python/callback.hpp">boost/python/callback.hpp</a></tt>,
|
||||||
|
which allows you to call back into python with C++ arguments.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
|
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
|
||||||
@@ -51,11 +58,11 @@
|
|||||||
fill in the other half. Here is his response to the commentary above:
|
fill in the other half. Here is his response to the commentary above:
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
“My intention with CXX was not to do what you are doing. It was to enable a
|
``My intention with CXX was not to do what you are doing. It was to enable a
|
||||||
person to write an extension directly in C++ rather than C. I figured others had
|
person to write an extension directly in C++ rather than C. I figured others had
|
||||||
the wrapping business covered. I thought maybe CXX would provide an easier
|
the wrapping business covered. I thought maybe CXX would provide an easier
|
||||||
target language for those making wrappers, but I never explored
|
target language for those making wrappers, but I never explored
|
||||||
that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<h2>SWIG</h2>
|
<h2>SWIG</h2>
|
||||||
@@ -65,28 +72,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
|
languages. Swig relies on a parser to read your source code and produce
|
||||||
additional source code files which can be compiled into a Python (or
|
additional source code files which can be compiled into a Python (or
|
||||||
Perl or Tcl) extension module. It has been successfully used to create
|
Perl or Tcl) extension module. It has been successfully used to create
|
||||||
many Python extension modules. Like py_cpp, SWIG is trying to allow an
|
many Python extension modules. Like Boost.Python, SWIG is trying to allow an
|
||||||
existing interface to be wrapped with little or no change to the
|
existing interface to be wrapped with little or no change to the
|
||||||
existing code. The documentation says “SWIG parses a form of ANSI C
|
existing code. The documentation says ``SWIG parses a form of ANSI C
|
||||||
syntax that has been extended with a number of special directives. As a
|
syntax that has been extended with a number of special directives. As a
|
||||||
result, interfaces are usually built by grabbing a header file and
|
result, interfaces are usually built by grabbing a header file and
|
||||||
tweaking it a little bit.” For C++ interfaces, the tweaking has often
|
tweaking it a little bit.'' For C++ interfaces, the tweaking has often
|
||||||
proven to amount to more than just a little bit. One user
|
proven to amount to more than just a little bit. One user
|
||||||
writes:
|
writes:
|
||||||
|
|
||||||
<blockquote> “The problem with swig (when I used it) is that it
|
<blockquote> ``The problem with swig (when I used it) is that it
|
||||||
couldnt handle templates, didnt do func overloading properly etc. For
|
couldnt handle templates, didnt do func overloading properly etc. For
|
||||||
ANSI C libraries this was fine. But for usual C++ code this was a
|
ANSI C libraries this was fine. But for usual C++ code this was a
|
||||||
problem. Simple things work. But for anything very complicated (or
|
problem. Simple things work. But for anything very complicated (or
|
||||||
realistic), one had to write code by hand. I believe py_cpp doesn't have
|
realistic), one had to write code by hand. I believe Boost.Python doesn't have
|
||||||
this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
|
this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
|
||||||
wrap correctly.”<br><i>-Prabhu Ramachandran</i>
|
wrap correctly.''<br><i>-Prabhu Ramachandran</i>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
By contrast, py_cpp doesn't attempt to parse C++ - the problem is simply
|
By contrast, Boost.Python doesn't attempt to parse C++ - the problem is simply
|
||||||
too complex to do correctly. <a name="sic">Technically</a>, one does
|
too complex to do correctly. <a name="sic">Technically</a>, one does
|
||||||
write code by hand to use py_cpp. The goal, however, has been to make
|
write code by hand to use Boost.Python. The goal, however, has been to make
|
||||||
that code nearly as simple as listing the names of the classes and
|
that code nearly as simple as listing the names of the classes and
|
||||||
member functions you want to expose in Python.
|
member functions you want to expose in Python.
|
||||||
|
|
||||||
@@ -95,7 +102,7 @@ that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
|||||||
<a
|
<a
|
||||||
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
|
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
|
||||||
is a system similar to SWIG, though seemingly more
|
is a system similar to SWIG, though seemingly more
|
||||||
C++-oriented. The author says that like py_cpp, SIP supports overriding
|
C++-oriented. The author says that like Boost.Python, SIP supports overriding
|
||||||
extension class member functions in Python subclasses. It appears to
|
extension class member functions in Python subclasses. It appears to
|
||||||
have been designed specifically to directly support some features of
|
have been designed specifically to directly support some features of
|
||||||
PyQt/PyKDE, which is its primary client. Documentation is almost
|
PyQt/PyKDE, which is its primary client. Documentation is almost
|
||||||
@@ -113,7 +120,7 @@ that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
|||||||
to a wide range of computer languages, including Common Lisp, C++, C,
|
to a wide range of computer languages, including Common Lisp, C++, C,
|
||||||
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
|
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
|
||||||
header file describing the interface, of which the user is expected to
|
header file describing the interface, of which the user is expected to
|
||||||
provide an implementation. Unlike py_cpp, this means that the system
|
provide an implementation. Unlike Boost.Python, this means that the system
|
||||||
imposes implementation details on your C++ code at the deepest level. It
|
imposes implementation details on your C++ code at the deepest level. It
|
||||||
is worth noting that some of the C++ names generated by ILU are supposed
|
is worth noting that some of the C++ names generated by ILU are supposed
|
||||||
to be reserved to the C++ implementation. It is unclear from the
|
to be reserved to the C++ implementation. It is unclear from the
|
||||||
@@ -124,7 +131,7 @@ that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
|||||||
<a
|
<a
|
||||||
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</a>
|
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</a>
|
||||||
is another very ambitious project aimed at generating Python wrappers for
|
is another very ambitious project aimed at generating Python wrappers for
|
||||||
interfaces written in “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
|
implemented. Like SWIG, it aims to parse source code and automatically
|
||||||
generate wrappers, though it appears to take a more sophisticated approach
|
generate wrappers, though it appears to take a more sophisticated approach
|
||||||
to parsing in general and C++ in particular, so it should do a much better
|
to parsing in general and C++ in particular, so it should do a much better
|
||||||
@@ -148,73 +155,77 @@ an inheritance relationship?
|
|||||||
<h2>Zope ExtensionClasses</h2>
|
<h2>Zope ExtensionClasses</h2>
|
||||||
<p>
|
<p>
|
||||||
<a href="http:http://www.digicool.com/releases/ExtensionClass">
|
<a href="http:http://www.digicool.com/releases/ExtensionClass">
|
||||||
ExtensionClasses in Zope</a> use the same underlying mechanism as py_cpp
|
ExtensionClasses in Zope</a> use the same underlying mechanism as Boost.Python
|
||||||
to support subclassing of extension types in Python, including
|
to support subclassing of extension types in Python, including
|
||||||
multiple-inheritance. Both systems support pickling/unpickling of
|
multiple-inheritance. Both systems support pickling/unpickling of
|
||||||
extension class instances in very similar ways. Both systems rely on the
|
extension class instances in very similar ways. Both systems rely on the
|
||||||
same “<a
|
same ``<a
|
||||||
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
|
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
|
||||||
Beaudry Hack</a>” that also inspired Don's MESS System.
|
Beaudry Hack</a>'' that also inspired Don's MESS System.
|
||||||
<p>
|
<p>
|
||||||
The major differences are:
|
The major differences are:
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>Zope is entirely 'C' language-based. It doesn't require a C++
|
||||||
|
compiler, so it's much more portable than Boost.Python, which stresses
|
||||||
|
the limits of even some modern C++ implementations.
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
py_cpp lifts the burden on the user to parse and convert function
|
Boost.Python lifts the burden on the user to parse and convert function
|
||||||
argument types. Zope provides no such facility.
|
argument types. Zope provides no such facility.
|
||||||
<li>
|
<li>
|
||||||
py_cpp lifts the burden on the user to maintain Python
|
Boost.Python lifts the burden on the user to maintain Python
|
||||||
reference-counts.
|
reference-counts.
|
||||||
<li>
|
<li>
|
||||||
py_cpp supports function overloading; Zope does not.
|
Boost.Python supports function overloading; Zope does not.
|
||||||
<li>
|
<li>
|
||||||
py_cpp supplies a simple mechanism for exposing read-only and
|
Boost.Python supplies a simple mechanism for exposing read-only and
|
||||||
read/write access to data members of the wrapped C++ type as Python
|
read/write access to data members of the wrapped C++ type as Python
|
||||||
attributes.
|
attributes.
|
||||||
<li>
|
<li>
|
||||||
Writing a Zope ExtensionClass is significantly more complex than
|
Writing a Zope ExtensionClass is significantly more complex than
|
||||||
exposing a C++ class to python using py_cpp (mostly a summary of the
|
exposing a C++ class to python using Boost.Python (mostly a summary of the
|
||||||
previous 4 items). <a href=
|
previous 4 items). <a href=
|
||||||
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
|
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
|
||||||
Zope Example</a> illustrates the differences.
|
Zope Example</a> illustrates the differences.
|
||||||
<li>
|
<li>
|
||||||
Zope's ExtensionClasses are specifically motivated by “the need for a
|
Zope's ExtensionClasses are specifically motivated by ``the need for a
|
||||||
C-based persistence mechanism”. Py_cpp's are motivated by the desire
|
C-based persistence mechanism''. Boost.Python's are motivated by the desire
|
||||||
to simply reflect a C++ API into Python with as little modification as
|
to simply reflect a C++ API into Python with as little modification as
|
||||||
possible.
|
possible.
|
||||||
<li>
|
<li>
|
||||||
The following Zope restriction does not apply to py_cpp: “At most one
|
The following Zope restriction does not apply to Boost.Python: ``At most one
|
||||||
base extension direct or indirect super class may define C data
|
base extension direct or indirect super class may define C data
|
||||||
members. If an extension subclass inherits from multiple base
|
members. If an extension subclass inherits from multiple base
|
||||||
extension classes, then all but one must be mix-in classes that
|
extension classes, then all but one must be mix-in classes that
|
||||||
provide extension methods but no data.”
|
provide extension methods but no data.''
|
||||||
<li>
|
<li>
|
||||||
Zope requires use of the somewhat funky inheritedAttribute (search for
|
Zope requires use of the somewhat funky inheritedAttribute (search for
|
||||||
“inheritedAttribute” on <a
|
``inheritedAttribute'' on <a
|
||||||
href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
|
href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
|
||||||
method to access base class methods. In py_cpp, base class methods can
|
method to access base class methods. In Boost.Python, base class methods can
|
||||||
be accessed in the usual way by writing
|
be accessed in the usual way by writing
|
||||||
“<code>BaseClass.method</code>”.
|
``<code>BaseClass.method</code>''.
|
||||||
<li>
|
<li>
|
||||||
Zope supplies some creative but esoteric idioms such as <a href=
|
Zope supplies some creative but esoteric idioms such as <a href=
|
||||||
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
|
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
|
||||||
Acquisition</a>. No specific support for this is built into py_cpp.
|
Acquisition</a>. No specific support for this is built into Boost.Python.
|
||||||
<li>
|
<li>
|
||||||
Zope's ComputedAttribute support is designed to be used from Python.
|
Zope's ComputedAttribute support is designed to be used from Python.
|
||||||
<a href="special.html#getter_setter">The analogous feature of
|
<a href="special.html#getter_setter">The analogous feature of
|
||||||
py_cpp</a> can be used from C++ or Python. The feature is arguably
|
Boost.Python</a> can be used from C++ or Python. The feature is arguably
|
||||||
easier to use in py_cpp.
|
easier to use in Boost.Python.
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
|
Next: <a href="example1.html">A Simple Example Using Boost.Python</a>
|
||||||
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
|
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
|
||||||
Next: <a href="example1.html">A Simple Example Using py_cpp</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
Up: <a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||||
sell and distribute this document is granted provided this copyright
|
sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided “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
|
express or implied warranty, and with no claim as to its suitability
|
||||||
for any purpose.
|
for any purpose.
|
||||||
<p>
|
<p>
|
||||||
Updated: Nov 26, 2000
|
Updated: Mar 6, 2001
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
336
doc/cross_module.html
Normal file
336
doc/cross_module.html
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||||
|
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
|
||||||
|
<title>Cross-extension-module dependencies</title>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<img src="../../../c++boost.gif"
|
||||||
|
alt="c++boost.gif (8819 bytes)"
|
||||||
|
align="center"
|
||||||
|
width="277" height="86">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h1>Cross-extension-module dependencies</h1>
|
||||||
|
|
||||||
|
It is good programming practice to organize large projects as modules
|
||||||
|
that interact with each other via well defined interfaces. With
|
||||||
|
Boost.Python it is possible to reflect this organization at the C++
|
||||||
|
level at the Python level. This is, each logical C++ module can be
|
||||||
|
organized as a separate Python extension module.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
At first sight this might seem natural and straightforward. However, it
|
||||||
|
is a fairly complex problem to establish cross-extension-module
|
||||||
|
dependencies while maintaining the same ease of use Boost.Python
|
||||||
|
provides for classes that are wrapped in the same extension module. To
|
||||||
|
a large extent this complexity can be hidden from the author of a
|
||||||
|
Boost.Python extension module, but not entirely.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>The recipe</h2>
|
||||||
|
|
||||||
|
Suppose there is an extension module that exposes certain instances of
|
||||||
|
the C++ <tt>std::vector</tt> template library such that it can be used
|
||||||
|
from Python in the following manner:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import std_vector
|
||||||
|
v = std_vector.double([1, 2, 3, 4])
|
||||||
|
v.push_back(5)
|
||||||
|
v.size()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
Suppose the <tt>std_vector</tt> module is done well and reflects all
|
||||||
|
C++ functions that are useful at the Python level, for all C++ built-in
|
||||||
|
data types (<tt>std_vector.int</tt>, <tt>std_vector.long</tt>, etc.).
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Suppose further that there is statistic module with a C++ class that
|
||||||
|
has constructors or member functions that use or return a
|
||||||
|
<tt>std::vector</tt>. For example:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
class xy {
|
||||||
|
public:
|
||||||
|
xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
|
||||||
|
const std::vector<double>& x() const { return m_x; }
|
||||||
|
const std::vector<double>& y() const { return m_y; }
|
||||||
|
double correlation();
|
||||||
|
private:
|
||||||
|
std::vector<double> m_x;
|
||||||
|
std::vector<double> m_y;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
What is more natural than reusing the <tt>std_vector</tt> extension
|
||||||
|
module to expose these constructors or functions to Python?
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unfortunately, what seems natural needs a little work in both the
|
||||||
|
<tt>std_vector</tt> and the <tt>statistics</tt> module.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In the <tt>std_vector</tt> extension module,
|
||||||
|
<tt>std::vector<double></tt> is exposed to Python in the usual
|
||||||
|
way with the <tt>class_builder<></tt> template. To also enable the
|
||||||
|
automatic conversion of <tt>std::vector<double></tt> function
|
||||||
|
arguments or return values in other Boost.Python C++ modules, the
|
||||||
|
converters that convert a <tt>std::vector<double></tt> C++ object
|
||||||
|
to a Python object and vice versa (i.e. the <tt>to_python()</tt> and
|
||||||
|
<tt>from_python()</tt> template functions) have to be exported. For
|
||||||
|
example:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
#include <boost/python/cross_module.hpp>
|
||||||
|
//...
|
||||||
|
class_builder<std::vector<double> > v_double(std_vector_module, "double");
|
||||||
|
export_converters(v_double);
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
In the extension module that wraps <tt>class xy</tt> we can now import
|
||||||
|
these converters with the <tt>import_converters<></tt> template.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
#include <boost/python/cross_module.hpp>
|
||||||
|
//...
|
||||||
|
import_converters<std::vector<double> > v_double_converters("std_vector", "double");
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
That is all. All the attributes that are defined for
|
||||||
|
<tt>std_vector.double</tt> in the <tt>std_vector</tt> Boost.Python
|
||||||
|
module will be available for the returned objects of <tt>xy.x()</tt>
|
||||||
|
and <tt>xy.y()</tt>. Similarly, the constructor for <tt>xy</tt> will
|
||||||
|
accept objects that were created by the <tt>std_vector</tt>module.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Placement of <tt>import_converters<></tt> template instantiations</h2>
|
||||||
|
|
||||||
|
<tt>import_converts<></tt> can be viewed as a drop-in replacement
|
||||||
|
for <tt>class_wrapper<></tt>, and the recommendations for the
|
||||||
|
placement of <tt>class_wrapper<></tt> template instantiations
|
||||||
|
also apply to to <tt>import_converts<></tt>. In particular, it is
|
||||||
|
important that an instantiation of <tt>class_wrapper<></tt> is
|
||||||
|
visible to any code which wraps a C++ function with a <tt>T</tt>,
|
||||||
|
<tt>T*</tt>, const <tt>T&</tt>, etc. parameter or return value.
|
||||||
|
Therefore you may want to group all <tt>class_wrapper<></tt> and
|
||||||
|
<tt>import_converts<></tt> instantiations at the top of your
|
||||||
|
module's init function, then <tt>def()</tt> the member functions later
|
||||||
|
to avoid problems with inter-class dependencies.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Non-copyable types</h2>
|
||||||
|
|
||||||
|
<tt>export_converters()</tt> instantiates C++ template functions that
|
||||||
|
invoke the copy constructor of the wrapped type. For a type that is
|
||||||
|
non-copyable this will result in compile-time error messages. In such a
|
||||||
|
case, <tt>export_converters_noncopyable()</tt> can be used to export
|
||||||
|
the converters that do not involve the copy constructor of the wrapped
|
||||||
|
type. For example:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
class_builder<store> py_store(your_module, "store");
|
||||||
|
export_converters_noncopyable(py_store);
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
The corresponding <tt>import_converters<></tt> statement does not
|
||||||
|
need any special attention:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import_converters<store> py_store("noncopyable_export", "store");
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Python module search path</h2>
|
||||||
|
|
||||||
|
The <tt>std_vector</tt> and <tt>statistics</tt> modules can now be used
|
||||||
|
in the following way:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import std_vector
|
||||||
|
import statistics
|
||||||
|
x = std_vector.double([1, 2, 3, 4])
|
||||||
|
y = std_vector.double([2, 4, 6, 8])
|
||||||
|
xy = statistics.xy(x, y)
|
||||||
|
xy.correlation()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
In this example it is clear that Python has to be able to find both the
|
||||||
|
<tt>std_vector</tt> and the <tt>statistics</tt> extension module. In
|
||||||
|
other words, both extension modules need to be in the Python module
|
||||||
|
search path (<tt>sys.path</tt>).
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The situation is not always this obvious. Suppose the
|
||||||
|
<tt>statistics</tt> module has a <tt>random()</tt> function that
|
||||||
|
returns a vector of random numbers with a given length:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import statistics
|
||||||
|
x = statistics.random(5)
|
||||||
|
y = statistics.random(5)
|
||||||
|
xy = statistics.xy(x, y)
|
||||||
|
xy.correlation()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
A naive user will not easily anticipate that the <tt>std_vector</tt>
|
||||||
|
module is used to pass the <tt>x</tt> and <tt>y</tt> vectors around. If
|
||||||
|
the <tt>std_vector</tt> module is in the Python module search path,
|
||||||
|
this form of ignorance is of no harm. On the contrary, we are glad
|
||||||
|
that we do not have to bother the user with details like this.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If the <tt>std_vector</tt> module is not in the Python module search
|
||||||
|
path, a Python exception will be raised:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
Traceback (innermost last):
|
||||||
|
File "foo.py", line 2, in ?
|
||||||
|
x = statistics.random(5)
|
||||||
|
ImportError: No module named std_vector
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
As is the case with any system of a non-trivial complexity, it is
|
||||||
|
important that the setup is consistent and complete.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Two-way module dependencies</h2>
|
||||||
|
|
||||||
|
Boost.Python supports two-way module dependencies. This is best
|
||||||
|
illustrated by a simple example.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Suppose there is a module <tt>ivect</tt> that implements vectors of
|
||||||
|
integers, and a similar module <tt>dvect</tt> that implements vectors
|
||||||
|
of doubles. We want to be able do convert an integer vector to a double
|
||||||
|
vector and vice versa. For example:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import ivect
|
||||||
|
iv = ivect.ivect((1,2,3,4,5))
|
||||||
|
dv = iv.as_dvect()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
The last expression will implicitly import the <tt>dvect</tt> module in
|
||||||
|
order to enable the conversion of the C++ representation of
|
||||||
|
<tt>dvect</tt> to a Python object. The analogous is possible for a
|
||||||
|
<tt>dvect</tt>:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import dvect
|
||||||
|
dv = dvect.dvect((1,2,3,4,5))
|
||||||
|
iv = dv.as_ivect()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
Now the <tt>ivect</tt> module is imported implicitly.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note that the two-way dependencies are possible because the
|
||||||
|
dependencies are resolved only when needed. This is, the initialization
|
||||||
|
of the <tt>ivect</tt> module does not rely on the <tt>dvect</tt>
|
||||||
|
module, and vice versa. Only if <tt>as_dvect()</tt> or
|
||||||
|
<tt>as_ivect()</tt> is actually invoked will the corresponding module
|
||||||
|
be implicitly imported. This also means that, for example, the
|
||||||
|
<tt>dvect</tt> module does not have to be available at all if
|
||||||
|
<tt>as_dvect()</tt> is never used.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Clarification of compile-time and link-time dependencies</h2>
|
||||||
|
|
||||||
|
Boost.Python's support for resolving cross-module dependencies at
|
||||||
|
runtime does not imply that compile-time dependencies are eliminated.
|
||||||
|
For example, the statistics extension module in the example above will
|
||||||
|
need to <tt>#include <vector></tt>. This is immediately obvious
|
||||||
|
from the definition of <tt>class xy</tt>.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If a library is wrapped that consists of both header files and compiled
|
||||||
|
components (e.g. <tt>libdvect.a</tt>, <tt>dvect.lib</tt>, etc.), both
|
||||||
|
the Boost.Python extension module with the
|
||||||
|
<tt>export_converters()</tt> statement and the module with the
|
||||||
|
<tt>import_converters<></tt> statement need to be linked against
|
||||||
|
the object library. Ideally one would build a shared library (e.g.
|
||||||
|
<tt>libdvect.so</tt>, <tt>dvect.dll</tt>, etc.). However, this
|
||||||
|
introduces the issue of having to configure the search path for the
|
||||||
|
dynamic loading correctly. For small libraries it is therefore often
|
||||||
|
more convenient to ignore the fact that the object files are loaded
|
||||||
|
into memory more than once.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Summary of motivation for cross-module support</h2>
|
||||||
|
|
||||||
|
The main purpose of Boost.Python's cross-module support is to allow for
|
||||||
|
a modular system layout. With this support it is straightforward to
|
||||||
|
reflect C++ code organization at the Python level. Without the
|
||||||
|
cross-module support, a multi-purpose module like <tt>std_vector</tt>
|
||||||
|
would be impractical because the entire wrapper code would somehow have
|
||||||
|
to be duplicated in all extension modules that use it, making them
|
||||||
|
harder to maintain and harder to build.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Another motivation for the cross-module support is that two extension
|
||||||
|
modules that wrap the same class cannot both be imported into Python.
|
||||||
|
For example, if there are two modules <tt>A</tt> and <tt>B</tt> that
|
||||||
|
both wrap a given <tt>class X</tt>, this will work:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import A
|
||||||
|
x = A.X()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
This will also work:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import B
|
||||||
|
x = B.X()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
However, this will fail:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import A
|
||||||
|
import B
|
||||||
|
python: /net/cci/rwgk/boost/boost/python/detail/extension_class.hpp:866:
|
||||||
|
static void boost::python::detail::class_registry<X>::register_class(boost::python::detail::extension_class_base *):
|
||||||
|
Assertion `static_class_object == 0' failed.
|
||||||
|
Abort
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
A good solution is to wrap <tt>class X</tt> only once. Depending on the
|
||||||
|
situation, this could be done by module <tt>A</tt> or <tt>B</tt>, or an
|
||||||
|
additional small extension module that only wraps and exports
|
||||||
|
<tt>class X</tt>.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Finally, there can be important psychological or political reasons for
|
||||||
|
using the cross-module support. If a group of classes is lumped
|
||||||
|
together with many others in a huge module, the authors will have
|
||||||
|
difficulties in being identified with their work. The situation is
|
||||||
|
much more transparent if the work is represented by a module with a
|
||||||
|
recognizable name. This is not just a question of strong egos, but also
|
||||||
|
of getting credit and funding.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Why not use <tt>export_converters()</tt> universally?</h2>
|
||||||
|
|
||||||
|
There is some overhead associated with the Boost.Python cross-module
|
||||||
|
support. Depending on the platform, the size of the code generated by
|
||||||
|
<tt>export_converters()</tt> is roughly 10%-20% of that generated
|
||||||
|
by <tt>class_builder<></tt>. For a large extension module with
|
||||||
|
many wrapped classes, this could mean a significant difference.
|
||||||
|
Therefore the general recommendation is to use
|
||||||
|
<tt>export_converters()</tt> only for classes that are likely to
|
||||||
|
be used as function arguments or return values in other modules.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
© Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy,
|
||||||
|
use, modify, sell and distribute this document is granted provided this
|
||||||
|
copyright notice appears in all copies. This document is provided "as
|
||||||
|
is" without express or implied warranty, and with no claim as to its
|
||||||
|
suitability for any purpose.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Updated: April 2001
|
||||||
|
|
||||||
|
</div>
|
||||||
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 |
|
||||||
|
+---------------------+ +---+ +----------------------+
|
||||||
@@ -6,33 +6,54 @@
|
|||||||
<div>
|
<div>
|
||||||
<h1>
|
<h1>
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Wrapping enums
|
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
||||||
|
Wrapping enums
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p>Because there is in general no way to deduce that a value of arbitrary type T
|
<p>Because there is in general no way to deduce that a value of arbitrary type T
|
||||||
is an enumeration constant, py_cpp cannot automatically convert enum values to
|
is an enumeration constant, the Boost Python Library cannot automatically
|
||||||
and from Python. To handle this case, you need to decide how you want the enum
|
convert enum values to and from Python. To handle this case, you need to decide
|
||||||
to show up in Python (since Python doesn't have enums). Once you have done that,
|
how you want the enum to show up in Python (since Python doesn't have
|
||||||
you can write some simple <code>from_python()</code> and
|
enums). Once you have done that, you can write some simple
|
||||||
<code>to_python()</code> functions.
|
<code>from_python()</code> and <code>to_python()</code> functions.
|
||||||
|
|
||||||
<p>If you are satisfied with a Python int as a way to represent your enum
|
<p>If you are satisfied with a Python int as a way to represent your enum
|
||||||
values, py_cpp provides a shorthand for these functions. You just need to
|
values, we provide a shorthand for these functions. You just need to cause
|
||||||
instantiate <code>boost::python::enum_as_int_converters<EnumType></code> where
|
<code>boost::python::enum_as_int_converters<EnumType></code> to be
|
||||||
|
instantiated, where
|
||||||
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
|
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li><blockquote>
|
<li>Explicit instantiation:
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template class boost::python::enum_as_int_converters<my_enum>;
|
||||||
|
</blockquote></pre>
|
||||||
|
|
||||||
|
Some buggy C++ implementations require a class to be instantiated in the same
|
||||||
|
namespace in which it is defined. In that case, the simple incantation above becomes:
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
|
...
|
||||||
|
} // close my_namespace
|
||||||
|
|
||||||
// drop into namespace python and explicitly instantiate
|
// drop into namespace python and explicitly instantiate
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
namespace boost { namespace python {
|
||||||
template class enum_as_int_converters<extclass_demo::EnumOwner::enum_type>;
|
template class enum_as_int_converters<my_enum_type>;
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
}} // namespace boost::python
|
||||||
|
|
||||||
|
namespace my_namespace { // re-open my_namespace
|
||||||
|
...
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<li><blockquote><pre>
|
|
||||||
|
|
||||||
|
<li>If you have such an implementation, you may find this technique more convenient
|
||||||
|
<blockquote><pre>
|
||||||
// instantiate as base class in any namespace
|
// instantiate as base class in any namespace
|
||||||
struct EnumTypeConverters
|
struct EnumTypeConverters
|
||||||
: boost::python::py_enum_as_int_converters<EnumType>
|
: boost::python::enum_as_int_converters<EnumType>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
</blockquote></pre>
|
</blockquote></pre>
|
||||||
@@ -54,7 +75,7 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
|||||||
from_python(x, boost::python::type<long>()));
|
from_python(x, boost::python::type<long>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(MyEnumType x)
|
PyObject* to_python(boost::python::semantics, MyEnumType x)
|
||||||
{
|
{
|
||||||
return to_python(static_cast<long>(x));
|
return to_python(static_cast<long>(x));
|
||||||
}
|
}
|
||||||
@@ -66,11 +87,12 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|||||||
<code>long</code> type.
|
<code>long</code> type.
|
||||||
|
|
||||||
You may also want to add a bunch of lines like this to your module
|
You may also want to add a bunch of lines like this to your module
|
||||||
initialization:
|
initialization. These bind the corresponding enum values to the appropriate
|
||||||
|
names so they can be used from Python:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
mymodule.add(boost::python::to_python(boost::python::search_namespace, enum_value_1), "enum_value_1");
|
||||||
mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
mymodule.add(boost::python::to_python(boost::python::search_namespace, enum_value_2), "enum_value_2");
|
||||||
...
|
...
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
@@ -78,17 +100,21 @@ You can also add these to an extension class definition, if your enum happens to
|
|||||||
be local to a class and you want the analogous interface in Python:
|
be local to a class and you want the analogous interface in Python:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
my_class.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
my_class_builder.add(boost::python::to_python(boost::python::search_namespace, enum_value_1), "enum_value_1");
|
||||||
my_class.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
my_class_builder.add(boost::python::to_python(boost::python::search_namespace, enum_value_2), "enum_value_2");
|
||||||
...
|
...
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
<p>
|
||||||
|
Next: <a href="pointers.html">Pointers and Smart Pointers</a>
|
||||||
|
Previous: <a href="building.html">Building an Extension Module</a>
|
||||||
|
Up: <a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||||
sell and distribute this document is granted provided this copyright
|
sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided “as
|
notice appears in all copies. This document is provided ``as
|
||||||
is” without express or implied warranty, and with no claim as to
|
is'' without express or implied warranty, and with no claim as to
|
||||||
its suitability for any purpose.
|
its suitability for any purpose.
|
||||||
<p>
|
<p>
|
||||||
Updated: Nov 26, 2000
|
Updated: Mar 6, 2001
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
<title>
|
<title>
|
||||||
A Simple Example Using py_cpp
|
A Simple Example
|
||||||
</title>
|
</title>
|
||||||
<div>
|
<div>
|
||||||
<h1>
|
<h1>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"c++boost.gif (8819 bytes)">
|
"c++boost.gif (8819 bytes)">
|
||||||
</h1>
|
</h1>
|
||||||
<h1>
|
<h1>
|
||||||
A Simple Example Using py_cpp
|
A Simple Example
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
Suppose we have the following C++ API which we want to expose in
|
Suppose we have the following C++ API which we want to expose in
|
||||||
@@ -18,104 +18,57 @@
|
|||||||
<pre>
|
<pre>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace hello {
|
namespace { // Avoid cluttering the global namespace.
|
||||||
class world
|
|
||||||
{
|
// A couple of simple C++ functions that we want to expose to Python.
|
||||||
public:
|
std::string greet() { return "hello, world"; }
|
||||||
world(int);
|
int square(int number) { return number * number; }
|
||||||
~world();
|
|
||||||
std::string get() const { return "hi, world"; }
|
|
||||||
...
|
|
||||||
};
|
|
||||||
std::size_t length(const world& x) { return std::strlen(x.get()); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>
|
<p>
|
||||||
Here is the C++ code for a python module called <code>hello</code>
|
Here is the C++ code for a python module called <tt>getting_started1</tt>
|
||||||
which exposes the API using py_cpp:
|
which exposes the API.
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
#include <boost/python/class_builder.hpp>
|
#include <boost/python/class_builder.hpp>
|
||||||
// Python requires an exported function called init<module-name> in every
|
namespace python = boost::python;
|
||||||
// extension module. This is where we build the module contents.
|
|
||||||
extern "C"
|
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
||||||
#ifdef _WIN32
|
|
||||||
__declspec(dllexport)
|
|
||||||
#endif
|
|
||||||
void inithello()
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// create an object representing this extension module
|
// Create an object representing this extension module.
|
||||||
boost::python::module_builder hello("hello");
|
python::module_builder this_module("getting_started1");
|
||||||
// Create the Python type object for our extension class
|
|
||||||
boost::python::class_builder<hello::world> world_class(hello, "world");
|
// Add regular functions to the module.
|
||||||
// Add the __init__ function
|
this_module.def(greet, "greet");
|
||||||
world_class.def(boost::python::constructor<int>());
|
this_module.def(square, "square");
|
||||||
// Add a regular member function
|
}
|
||||||
world_class.def(&hello::world::get, "get");
|
catch(...)
|
||||||
// Add a regular function to the module
|
{
|
||||||
hello.def(hello::length, "length");
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
}
|
}
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
boost::python::handle_exception(); // Deal with the exception for Python
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Win32 DLL boilerplate
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <windows.h>
|
|
||||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>
|
<p>
|
||||||
That's it! If we build this shared library and put it on our <code>
|
That's it! If we build this shared library and put it on our <code>
|
||||||
PYTHONPATH</code> we can now access our C++ class and function from
|
PYTHONPATH</code> we can now access our C++ functions from
|
||||||
Python.
|
Python.
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
>>> import hello
|
>>> import getting_started1
|
||||||
>>> hi_world = hello.world(3)
|
>>> print getting_started1.greet()
|
||||||
>>> hi_world.get()
|
hello, world
|
||||||
'hi, world'
|
>>> number = 11
|
||||||
>>> hello.length(hi_world)
|
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||||
9
|
11 * 11 = 121
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
|
||||||
<p>
|
<p>
|
||||||
We can even make a subclass of <code>hello.world</code>:
|
Next: <a href="exporting_classes.html">Exporting Classes</a>
|
||||||
<blockquote>
|
Previous: <a href="comparisons.html">Comparisons with other systems</a> Up:
|
||||||
<pre>
|
|
||||||
>>> class my_subclass(hello.world):
|
|
||||||
... def get(self):
|
|
||||||
... return 'hello, world'
|
|
||||||
...
|
|
||||||
>>> y = my_subclass(4)
|
|
||||||
>>> y.get()
|
|
||||||
'hello, world'
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> hello.length(y)
|
|
||||||
9
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Of course, you may now have a slightly empty feeling in the pit of
|
|
||||||
your little pythonic stomach. Perhaps you feel your subclass deserves
|
|
||||||
to have a <code>length()</code> of <code>12</code>? If so, <a href=
|
|
||||||
"overriding.html">read on</a>...
|
|
||||||
<p>
|
|
||||||
Previous: <a href="comparisons.html">Comparisons with other systems</a> Next: <a href="overriding.html">Overridable virtual functions</a> Up:
|
|
||||||
<a href="index.html">Top</a>
|
<a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||||
@@ -124,6 +77,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
|||||||
express or implied warranty, and with no claim as to its suitability
|
express or implied warranty, and with no claim as to its suitability
|
||||||
for any purpose.
|
for any purpose.
|
||||||
<p>
|
<p>
|
||||||
Updated: Nov 26, 2000
|
Updated: Mar 6, 2000
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
144
doc/exporting_classes.html
Normal file
144
doc/exporting_classes.html
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||||
|
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<title>
|
||||||
|
Exporting Classes
|
||||||
|
</title>
|
||||||
|
<div>
|
||||||
|
<h1>
|
||||||
|
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
||||||
|
"c++boost.gif (8819 bytes)">
|
||||||
|
</h1>
|
||||||
|
<h1>
|
||||||
|
Exporting Classes
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
Now let's expose a C++ class to Python:
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A friendly class.
|
||||||
|
class hello
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
hello(const std::string& country) { this->country = country; }
|
||||||
|
std::string greet() const { return "Hello from " + country; }
|
||||||
|
private:
|
||||||
|
std::string country;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A function taking a hello object as an argument.
|
||||||
|
std::string invite(const hello& w) {
|
||||||
|
return w.greet() + "! Please come soon!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</blockquote></pre> <p>
|
||||||
|
To expose the class, we use a <tt>class_builder</tt> in addition to the
|
||||||
|
<tt>module_builder</tt> from the previous example. Class member functions
|
||||||
|
are exposed by using the <tt>def()</tt> member function on the
|
||||||
|
<tt>class_builder</tt>:
|
||||||
|
<blockquote><pre>
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(getting_started2)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create an object representing this extension module.
|
||||||
|
python::module_builder this_module("getting_started2");
|
||||||
|
|
||||||
|
// Create the Python type object for our extension class.
|
||||||
|
python::class_builder<hello> hello_class(this_module, "hello");
|
||||||
|
|
||||||
|
// Add the __init__ function.
|
||||||
|
hello_class.def(python::constructor<std::string>());
|
||||||
|
// Add a regular member function.
|
||||||
|
hello_class.def(&hello::greet, "greet");
|
||||||
|
|
||||||
|
// Add invite() as a regular function to the module.
|
||||||
|
this_module.def(invite, "invite");
|
||||||
|
|
||||||
|
// Even better, invite() can also be made a member of hello_class!!!
|
||||||
|
hello_class.def(invite, "invite");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</blockquote></pre>
|
||||||
|
<p>
|
||||||
|
Now we can use the class normally from Python:
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
>>> from getting_started2 import *
|
||||||
|
>>> hi = hello('California')
|
||||||
|
>>> hi.greet()
|
||||||
|
'Hello from California'
|
||||||
|
>>> invite(hi)
|
||||||
|
'Hello from California! Please come soon!'
|
||||||
|
>>> hi.invite()
|
||||||
|
'Hello from California! Please come soon!'
|
||||||
|
</blockquote></pre>
|
||||||
|
|
||||||
|
Notes:<ul>
|
||||||
|
<li> We expose the class' constructor by calling <tt>def()</tt> on the
|
||||||
|
<tt>class_builder</tt> with an argument whose type is
|
||||||
|
<tt>constructor<</tt><i>params</i><tt>></tt>, where <i>params</i>
|
||||||
|
matches the list of constructor argument types:
|
||||||
|
|
||||||
|
|
||||||
|
<li>Regular member functions are defined by calling <tt>def()</tt> with a
|
||||||
|
member function pointer and its Python name:
|
||||||
|
|
||||||
|
<li>Any function added to a class whose initial argument matches the class (or
|
||||||
|
any base) will act like a member function in Python.
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
We can even make a subclass of <code>hello.world</code>:
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
>>> class wordy(hello):
|
||||||
|
... def greet(self):
|
||||||
|
... return hello.greet(self) + ', where the weather is fine'
|
||||||
|
...
|
||||||
|
>>> hi2 = wordy('Florida')
|
||||||
|
>>> hi2.greet()
|
||||||
|
'Hello from Florida, where the weather is fine'
|
||||||
|
>>> invite(hi2)
|
||||||
|
'Hello from Florida! Please come soon!'
|
||||||
|
</blockquote></pre>
|
||||||
|
<p>
|
||||||
|
Pretty cool! You can't do that with an ordinary Python extension type!
|
||||||
|
|
||||||
|
Of course, you may now have a slightly empty feeling in the pit of
|
||||||
|
your little pythonic stomach. Perhaps you wanted to see the following
|
||||||
|
<tt>wordy</tt> invitation:
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
'Hello from Florida, where the weather is fine! Please come soon!'
|
||||||
|
</blockquote></pre>
|
||||||
|
|
||||||
|
After all, <tt>invite</tt> calls <tt>hello::greet()</tt>, and you
|
||||||
|
reimplemented that in your Python subclass, <tt>wordy</tt>. If so, <a
|
||||||
|
href= "overriding.html">read on</a>...
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Next: <a href="overriding.html">Overridable virtual functions</a>
|
||||||
|
Previous: <a href="example1.html">A Simple Example</a> Up:
|
||||||
|
<a href="index.html">Top</a>
|
||||||
|
<p>
|
||||||
|
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||||
|
sell and distribute this document is granted provided this copyright
|
||||||
|
notice appears in all copies. This document is provided "as is" without
|
||||||
|
express or implied warranty, and with no claim as to its suitability
|
||||||
|
for any purpose.
|
||||||
|
<p>
|
||||||
|
Updated: Mar 6, 2001
|
||||||
|
</div>
|
||||||
|
|
||||||
@@ -38,11 +38,11 @@
|
|||||||
</ul>
|
</ul>
|
||||||
This last item typically occupies a great deal of code in an extension
|
This last item typically occupies a great deal of code in an extension
|
||||||
module. Remember that Python is a completely dynamic language. A callable
|
module. Remember that Python is a completely dynamic language. A callable
|
||||||
object receives its arguments in a tuple; it is up to that object to
|
object receives its arguments in a tuple; it is up to that object to extract
|
||||||
extract those arguments from the tuple, check their types, and raise
|
those arguments from the tuple, check their types, and raise appropriate
|
||||||
appropriate exceptions. There are numerous other tedious details that need
|
exceptions. There are numerous other tedious details that need to be
|
||||||
to be managed; too many to mention here. Py_cpp is designed to lift most of
|
managed; too many to mention here. The Boost Python Library is designed to
|
||||||
that burden.<br>
|
lift most of that burden.<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -56,10 +56,10 @@
|
|||||||
sublcassing the extension type. Aside from being tedious, it's not really
|
sublcassing the extension type. Aside from being tedious, it's not really
|
||||||
the same as having a true class, because there's no way for the user to
|
the same as having a true class, because there's no way for the user to
|
||||||
override a method of the extension type which is called from the
|
override a method of the extension type which is called from the
|
||||||
extension module. Py_cpp solves this problem by taking advantage of <a
|
extension module. Boost.Python solves this problem by taking advantage of <a
|
||||||
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
|
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
|
||||||
feature</a> to provide objects which look, walk, and hiss almost exactly
|
feature</a> to provide objects which look, walk, and hiss almost exactly
|
||||||
like regular Python classes. Py_cpp classes are actually cleaner than
|
like regular Python classes. Boost.Python classes are actually cleaner than
|
||||||
Python classes in some subtle ways; a more detailed discussion will
|
Python classes in some subtle ways; a more detailed discussion will
|
||||||
follow (someday).</p>
|
follow (someday).</p>
|
||||||
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
|
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
|
||||||
|
|||||||
177
doc/index.html
177
doc/index.html
@@ -1,29 +1,24 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
||||||
<title>
|
<title>
|
||||||
py_cpp Python/C++ binding documentation
|
The Boost Python Library (Boost.Python)
|
||||||
</title>
|
</title>
|
||||||
<h1>
|
<h1>
|
||||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
|
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
|
||||||
align="center" height="86"> py_cpp<a href="#naming_contest">*</a>
|
align="center" height="86"><br>The Boost Python Library (Boost.Python)
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p>
|
|
||||||
The source code for py_cpp, including a MSVC demo project is available <a
|
|
||||||
href="py_cpp_20001106.zip">here</a>.
|
|
||||||
|
|
||||||
<h2>Synopsis</h2>
|
<h2>Synopsis</h2>
|
||||||
<p>
|
<p>
|
||||||
py_cpp is a system for quickly and easily interfacing C++ code with <a
|
Use the Boost Python Library to quickly and easily export a C++ library to <a
|
||||||
href="http:www.python.org">Python</a> such that the Python interface is
|
href="http://www.python.org">Python</a> such that the Python interface is
|
||||||
very similar to the C++ interface. It is designed to be minimally
|
very similar to the C++ interface. It is designed to be minimally
|
||||||
intrusive on your C++ design. In most cases, you should not have to alter
|
intrusive on your C++ design. In most cases, you should not have to alter
|
||||||
your C++ classes in any way in order to use them with py_cpp. The system
|
your C++ classes in any way in order to use them with Boost.Python. The system
|
||||||
<em>should</em> simply “reflect” your C++ classes and functions into
|
<em>should</em> simply ``reflect'' your C++ classes and functions into
|
||||||
Python. The major features of py_cpp include support for:
|
Python. The major features of Boost.Python include support for:
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="inheritance.hml">Subclassing extension types in Python</a>
|
<li><a href="inheritance.html">Subclassing extension types in Python</a>
|
||||||
<li><a href="overriding.html">Overriding virtual functions in Python</a>
|
<li><a href="overriding.html">Overriding virtual functions in Python</a>
|
||||||
<li><a href="overloading.html">[Member] function Overloading</a>
|
<li><a href="overloading.html">[Member] function Overloading</a>
|
||||||
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
|
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
|
||||||
@@ -32,9 +27,27 @@ among others.
|
|||||||
|
|
||||||
|
|
||||||
<h2>Supported Platforms</h2>
|
<h2>Supported Platforms</h2>
|
||||||
<p>py_cpp has been tested in the following configurations:
|
<p>Boost.Python is known to have been tested in the following configurations:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>Against Python 2.0 using the following compiler/library combinations:
|
||||||
|
<ul>
|
||||||
|
<li><a
|
||||||
|
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
|
||||||
|
with the native library.
|
||||||
|
|
||||||
|
<li>An upcoming release of <a
|
||||||
|
href="http://www.metrowerks.com/products/windows/">Metrowerks
|
||||||
|
CodeWarrior Pro6 for Windows</a> with the native library (the first
|
||||||
|
release has a bug that's fatal to Boost.Python)
|
||||||
|
|
||||||
|
<li><a
|
||||||
|
href="http://developer.intel.com/software/products/compilers/c50/">Intel
|
||||||
|
C++ 5.0</a>. Compilation succeeds, but tests <font
|
||||||
|
color="#FF0000"><b>FAILED at runtime</b></font> due to a bug in its
|
||||||
|
exception-handling implementation.
|
||||||
|
</ul>
|
||||||
|
|
||||||
<li>Against Python 1.5.2 using the following compiler/library:
|
<li>Against Python 1.5.2 using the following compiler/library:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@@ -56,29 +69,17 @@ among others.
|
|||||||
href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve</a>]
|
href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve</a>]
|
||||||
|
|
||||||
<li>An upcoming release of <a href="http://www.metrowerks.com/products/windows/">Metrowerks CodeWarrior
|
<li>An upcoming release of <a href="http://www.metrowerks.com/products/windows/">Metrowerks CodeWarrior
|
||||||
Pro6 for Windows</a> (the first release has a bug that's fatal to py_cpp)
|
Pro6 for Windows</a> (the first release has a bug that's fatal to Boost.Python)
|
||||||
</ul>
|
</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>
|
||||||
</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>
|
<h2>Credits</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="mailto:abrahams@mediaone.net">David Abrahams</a> originated
|
<li><a href="../../../people/dave_abrahams.htm">David Abrahams</a> originated
|
||||||
and wrote py_cpp.
|
and wrote most of the library, and continues to coordinate development.
|
||||||
|
|
||||||
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
|
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
|
||||||
had independently developed a similar system. When he discovered py_cpp,
|
had independently developed a similar system. When he discovered Boost.Python,
|
||||||
he generously contributed countless hours of coding and much insight into
|
he generously contributed countless hours of coding and much insight into
|
||||||
improving it. He is responsible for an early version of the support for <a
|
improving it. He is responsible for an early version of the support for <a
|
||||||
href="overloading.html">function overloading</a> and wrote the support for
|
href="overloading.html">function overloading</a> and wrote the support for
|
||||||
@@ -87,16 +88,22 @@ among others.
|
|||||||
Python and C++, and has designed an extremely easy-to-use way of
|
Python and C++, and has designed an extremely easy-to-use way of
|
||||||
exposing <a href="special.html#numeric">numeric operators</a>, including
|
exposing <a href="special.html#numeric">numeric operators</a>, including
|
||||||
a way to avoid explicit coercion by means of overloading.
|
a way to avoid explicit coercion by means of overloading.
|
||||||
|
|
||||||
|
<li><a href="http://cci.lbl.gov/staff/ralf_grosse-kunstleve.html">Ralf W.
|
||||||
|
Grosse-Kunstleve</a> contributed <a href="pickle.html">pickle support</a>
|
||||||
|
and numerous other small improvements. He's working on a way to allow
|
||||||
|
types exported by multiple modules to interact.
|
||||||
|
|
||||||
<li>The members of the boost mailing list and the Python community supplied
|
<li>The members of the boost mailing list and the Python community
|
||||||
invaluable early feedback. In particular, Ron Clarke, Mark Evans, Anton
|
supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans,
|
||||||
Gluck, Ralf W. Grosse-Kunstleve, Prabhu Ramachandran, and Barry Scott took
|
Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott took the
|
||||||
the brave step of trying to use py_cpp while it was still in early stages
|
brave step of trying to use Boost.Python while it was still in early
|
||||||
of development.
|
stages of development.
|
||||||
|
|
||||||
<li>The development of py_cpp wouldn't have been
|
<li>The development of Boost.Python wouldn't have been possible without
|
||||||
possible without the generous support of <a href="http://www.dragonsys.com/">Dragon Systems/Lernout and
|
the generous support of <a href="http://www.dragonsys.com/">Dragon
|
||||||
Hauspie, Inc</a> who supported its development as an open-source project.
|
Systems/Lernout and Hauspie, Inc</a> who supported its development as an
|
||||||
|
open-source project.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Table of Contents</h2>
|
<h2>Table of Contents</h2>
|
||||||
@@ -105,10 +112,12 @@ among others.
|
|||||||
<li><a href="extending.html">A Brief Introduction to writing Python
|
<li><a href="extending.html">A Brief Introduction to writing Python
|
||||||
extension modules</a>
|
extension modules</a>
|
||||||
|
|
||||||
<li><a href="comparisons.html">Comparisons between py_cpp and other
|
<li><a href="comparisons.html">Comparisons between Boost.Python and other
|
||||||
systems for extending Python</a>
|
systems for extending Python</a>
|
||||||
|
|
||||||
<li><a href="example1.html">A Simple Example Using py_cpp</a>
|
<li><a href="example1.html">A Simple Example</a>
|
||||||
|
|
||||||
|
<li><a href="exporting_classes.html">Exporting Classes</a>
|
||||||
|
|
||||||
<li><a href="overriding.html">Overridable Virtual Functions</a>
|
<li><a href="overriding.html">Overridable Virtual Functions</a>
|
||||||
|
|
||||||
@@ -120,92 +129,38 @@ among others.
|
|||||||
|
|
||||||
<li><a href="under-the-hood.html">A Peek Under the Hood</a>
|
<li><a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||||
|
|
||||||
<li><a href="building.html">Building a Module with Py_cpp</a>
|
<li><a href="building.html">Building an Extension Module</a>
|
||||||
|
|
||||||
<li>Advanced Topics
|
<li><a href="pickle.html">Pickle Support</a>
|
||||||
|
|
||||||
<ol>
|
<li><a href="cross_module.html">Cross-Extension-Module Dependencies</a>
|
||||||
<li>class_builder<>
|
|
||||||
|
|
||||||
<li><a href="enums.html">enums</a>
|
<li><a href="enums.html">Wrapping Enums</a>
|
||||||
|
|
||||||
<li>References
|
<li><a href="pointers.html">Pointers and Smart Pointers</a>
|
||||||
|
|
||||||
<li><a href="pointers.html">Pointers and Smart Pointers</a>
|
<li><a href="data_structures.txt">Internal Data Structures</a>
|
||||||
|
|
||||||
<li>Built-in Python Types
|
|
||||||
|
|
||||||
<li>Other Extension Types
|
|
||||||
|
|
||||||
<li>Templates
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
More sophisticated examples are given in
|
Documentation is a major ongoing project; assistance is greatly
|
||||||
<code>extclass_demo.cpp</code>, <code> extclass_demo.h</code>, and <code>
|
appreciated! In the meantime, useful examples of every Boost.Python feature should
|
||||||
test_extclass.py</code> in the <a href="py_cpp.tgz">source code
|
be evident in the regression test files <code>test/comprehensive.[<a
|
||||||
archive</a>. There's much more here, and much more documentation to
|
href="../test/comprehensive.py">py</a>/<a
|
||||||
come...
|
href="../test/comprehensive.hpp">hpp</a>/<a
|
||||||
|
href="../test/comprehensive.cpp">cpp</a>]</code>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Questions should be directed to <a href=
|
Questions should be directed to <a href=
|
||||||
"http://www.egroups.com/list/boost">the boost mailing list</a>.
|
"http://www.yahoogroups.com/list/boost">the boost mailing list</a>.
|
||||||
|
|
||||||
<h2>Naming Contest</h2>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Yes, I know py_cpp is a lousy name. Problem is, the best names my puny
|
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||||
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
|
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
|
express or implied warranty, and with no claim as to its suitability for
|
||||||
any purpose.
|
any purpose.
|
||||||
<p>
|
<p>
|
||||||
Updated: Nov 26, 2000
|
Updated: Mar 6, 2001
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
<h2>Inheritance in Python</h2>
|
<h2>Inheritance in Python</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Py_cpp extension classes support single and multiple-inheritance in
|
Boost.Python extension classes support single and multiple-inheritance in
|
||||||
Python, just like regular Python classes. You can mix built-in Python
|
Python, just like regular Python classes. You can arbitrarily mix
|
||||||
classes with py_cpp extension classes in a derived class' tuple of
|
built-in Python classes with extension classes in a derived class'
|
||||||
bases. Whenever a py_cpp extension class is among the bases for a new
|
tuple of bases. Whenever a Boost.Python extension class is among the bases for a
|
||||||
class in Python, the result is an extension class:
|
new class in Python, the result is an extension class:
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
>>> class MyPythonClass:
|
>>> class MyPythonClass:
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
||||||
<p>
|
<p>
|
||||||
Py_cpp also allows us to represent C++ inheritance relationships so that
|
Boost.Python also allows us to represent C++ inheritance relationships so that
|
||||||
wrapped derived classes may be passed where values, pointers, or
|
wrapped derived classes may be passed where values, pointers, or
|
||||||
references to a base class are expected as arguments. The
|
references to a base class are expected as arguments. The
|
||||||
<code>declare_base</code> member function of
|
<code>declare_base</code> member function of
|
||||||
@@ -71,22 +71,22 @@ int get_derived_x(const Derived& d) {
|
|||||||
return d.x;
|
return d.x;
|
||||||
}
|
}
|
||||||
<hr>
|
<hr>
|
||||||
#include <boost/python/class_builder.hpp>
|
#include <boost/python/class_builder.hpp>
|
||||||
extern "C"
|
|
||||||
#ifdef _WIN32
|
// namespace alias for code brevity
|
||||||
__declspec(dllexport)
|
namespace python = boost::python;
|
||||||
#endif
|
|
||||||
void initmy_module()
|
BOOST_PYTHON_MODULE_INIT(my_module)
|
||||||
{
|
{
|
||||||
try
|
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");
|
python::class_builder<Base> base_class(my_module, "Base");
|
||||||
base_class.def(boost::python::constructor<void>());
|
base_class.def(python::constructor<void>());
|
||||||
|
|
||||||
boost::python::class_builder<Derived> derived_class(my_module, "Derived");
|
python::class_builder<Derived> derived_class(my_module, "Derived");
|
||||||
derived_class.def(boost::python::constructor<void>());
|
derived_class.def(python::constructor<void>());
|
||||||
<b>// Establish the inheritance relationship between Base and Derived
|
<b>// Establish the inheritance relationship between Base and Derived
|
||||||
derived_class.declare_base(base_class);</b>
|
derived_class.declare_base(base_class);</b>
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ void initmy_module()
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
boost::python::handle_exception(); // Deal with the exception for Python
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
@@ -111,11 +111,19 @@ void initmy_module()
|
|||||||
>>> derived = Derived()
|
>>> derived = Derived()
|
||||||
>>> get_name(base)
|
>>> get_name(base)
|
||||||
'Base'
|
'Base'
|
||||||
</pre><i>objects of wrapped class Derived may be passed where Base is expected</i><pre>
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
<i>objects of wrapped class Derived may be passed where Base is expected</i>
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
>>> get_name(derived)
|
>>> get_name(derived)
|
||||||
'Derived'
|
'Derived'
|
||||||
</pre><i>objects of wrapped class Derived can be passed where Derived is
|
</pre>
|
||||||
expected but where type information has been lost.</i><pre>
|
</blockquote>
|
||||||
|
<i>objects of wrapped class Derived can be passed where Derived is
|
||||||
|
expected but where type information has been lost.</i>
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
>>> get_derived_x(derived_as_base())
|
>>> get_derived_x(derived_as_base())
|
||||||
-1
|
-1
|
||||||
</pre>
|
</pre>
|
||||||
@@ -135,12 +143,12 @@ struct Base2 {};
|
|||||||
struct Derived2 { int f(); };
|
struct Derived2 { int f(); };
|
||||||
<hr>
|
<hr>
|
||||||
...
|
...
|
||||||
boost::python::class_builder<Base> base2_class(my_module, "Base2");
|
python::class_builder<Base> base2_class(my_module, "Base2");
|
||||||
base2_class.def(boost::python::constructor<void>());
|
base2_class.def(python::constructor<void>());
|
||||||
|
|
||||||
boost::python::class_builder<Derived2> derived2_class(my_module, "Derived2");
|
python::class_builder<Derived2> derived2_class(my_module, "Derived2");
|
||||||
derived2_class.def(boost::python::constructor<void>());
|
derived2_class.def(python::constructor<void>());
|
||||||
derived_class.declare_base(base_class, <b>boost::python::without_downcast</b>);
|
derived_class.declare_base(base_class, <b>python::without_downcast</b>);
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@@ -150,8 +158,8 @@ struct Derived2 { int f(); };
|
|||||||
references, or values.
|
references, or values.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
Next: <a href="special.html">Special Method and Operator Support</a>
|
||||||
Previous: <a href="overloading.html">Function Overloading</a>
|
Previous: <a href="overloading.html">Function Overloading</a>
|
||||||
Next: <a href="special.html">Special Method Names</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
Up: <a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ private:
|
|||||||
};
|
};
|
||||||
...
|
...
|
||||||
|
|
||||||
void initoverload_demo()
|
BOOST_PYTHON_MODULE_INIT(overload_demo)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -113,18 +113,17 @@ namespace scope as Python member functions.
|
|||||||
|
|
||||||
<h2>Overload Resolution</h2>
|
<h2>Overload Resolution</h2>
|
||||||
<p>
|
<p>
|
||||||
The function overload resolution mechanism in py_cpp works as
|
The function overload resolution mechanism works as follows:
|
||||||
follows:
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li>Attribute lookup for extension classes proceeds in <a
|
<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
|
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
|
class is found which has a matching attribute, only functions overloaded
|
||||||
in the context of that class are candidates for overload resolution. In
|
in the context of that class are candidates for overload resolution. In
|
||||||
this sense, overload resolution mirrors the C++ mechanism, where a name
|
this sense, overload resolution mirrors the C++ mechanism, where a name
|
||||||
in a derived class “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.
|
class.
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
@@ -133,24 +132,24 @@ namespace scope as Python member functions.
|
|||||||
<code>def()</code>ed. The first function whose signature can be made to
|
<code>def()</code>ed. The first function whose signature can be made to
|
||||||
match each argument passed is the one which is ultimately called.
|
match each argument passed is the one which is ultimately called.
|
||||||
This means in particular that you cannot overload the same function on
|
This means in particular that you cannot overload the same function on
|
||||||
both “<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.
|
automatically converts either of the two types into the other one.
|
||||||
If the “<code>float</code>” overload is found first, it is used
|
If the ``<code>float</code>'' overload is found first, it is used
|
||||||
also used for arguments of type “<code>int</code>” as well, and the
|
also used for arguments of type ``<code>int</code>'' as well, and the
|
||||||
“<code>int</code>” version of the function is never invoked.
|
``<code>int</code>'' version of the function is never invoked.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Prev: <a href="overriding.html">Overridable Virtual Functions</a>
|
Next: <a href="inheritance.html">Inheritance</a>
|
||||||
Next: <a href="inheritance.html">Special Method Names</a>
|
Previous: <a href="overriding.html">Overridable Virtual Functions</a>
|
||||||
Up: <a href="index.html">Top</a>
|
Up: <a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||||
sell and distribute this document is granted provided this copyright
|
sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided “as
|
notice appears in all copies. This document is provided ``as
|
||||||
is” without express or implied warranty, and with no claim as to
|
is'' without express or implied warranty, and with no claim as to
|
||||||
its suitability for any purpose.
|
its suitability for any purpose.
|
||||||
<p>
|
<p>
|
||||||
Updated: Nov 26, 2000
|
Updated: Mar 6, 2001
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<h1>Overridable Virtual Functions</h1>
|
<h1>Overridable Virtual Functions</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In the <a href="example1.html">previous example</a> we exposed a simple
|
In the <a href="exporting_classes.html">previous example</a> we exposed a simple
|
||||||
C++ class in Python and showed that we could write a subclass. We even
|
C++ class in Python and showed that we could write a subclass. We even
|
||||||
redefined one of the functions in our derived class. Now we will learn
|
redefined one of the functions in our derived class. Now we will learn
|
||||||
how to make the function behave virtually <em>when called from C++</em>.
|
how to make the function behave virtually <em>when called from C++</em>.
|
||||||
@@ -17,16 +17,17 @@
|
|||||||
|
|
||||||
<h2><a name="overriding_example">Example</a></h2>
|
<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>hello::greet()</code> is a virtual
|
||||||
member function:
|
member function:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
class world
|
class hello
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
world(int);
|
hello(const std::string& country) { this->country = country; }
|
||||||
virtual ~world();
|
<b>virtual</b> std::string greet() const { return "Hello from " + country; }
|
||||||
<b>virtual</b> std::string get() const { return "hi, world"; }
|
virtual ~hello(); // Good practice
|
||||||
|
...
|
||||||
};
|
};
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
@@ -37,21 +38,28 @@ class world
|
|||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
|
|
||||||
<li><a name="derived_1">A</a> <code>PyObject*</code> data member that holds a
|
<li><a name="derived_1">A</a> <code>PyObject*</code> data member (usually
|
||||||
reference to the corresponding Python object.
|
called <tt>self</tt>) that holds a pointer to the Python object corresponding
|
||||||
|
to our C++ <tt>hello</tt> instance.
|
||||||
|
|
||||||
<li><a name="derived_2">A</a> constructor for each exposed constructor of the
|
<li><a name="derived_2">For</a> each exposed constructor of the
|
||||||
base class which stores an additional initial <code>PyObject*</code> argument
|
base class <tt>T</tt>, a constructor which takes the same parameters preceded by an initial
|
||||||
in the data member described above.
|
<code>PyObject*</code> argument. The initial argument should be stored in the <tt>self</tt> data
|
||||||
|
member described above.
|
||||||
|
|
||||||
<li><a name="derived_3">An</a> implementation of each virtual function you may
|
<li><a name="derived_3">If</a> the class being wrapped is ever returned <i>by
|
||||||
|
value</i> from a wrapped function, be sure you do the same for the
|
||||||
|
<tt>T</tt>'s copy constructor: you'll need a constructor taking arguments
|
||||||
|
<tt>(PyObject*, const T&)</tt>.
|
||||||
|
|
||||||
|
<li><a name="derived_4">An</a> implementation of each virtual function you may
|
||||||
wish to override in Python which uses
|
wish to override in Python which uses
|
||||||
<code>boost::python::callback<<i>return-type</i>>::call_method()</code> to call
|
<tt>callback<</tt><i>return-type</i><tt>>::call_method(self, "</tt><i>name</i><tt>", </tt><i>args...</i><tt>)</tt> to call
|
||||||
the Python override.
|
the Python override.
|
||||||
|
|
||||||
<li><a name="derived_4">For</a> each non-pure virtual function meant to be
|
<li><a name="derived_5">For</a> each non-pure virtual function meant to be
|
||||||
overridable from Python, a static member function (or a free function) taking
|
overridable from Python, a static member function (or a free function) taking
|
||||||
a reference or pointer to the base type as the first parameter and which
|
a reference or pointer to the <tt>T</tt> as the first parameter and which
|
||||||
forwards any additional parameters neccessary to the <i>default</i>
|
forwards any additional parameters neccessary to the <i>default</i>
|
||||||
implementation of the virtual function. See also <a href="#private">this
|
implementation of the virtual function. See also <a href="#private">this
|
||||||
note</a> if the base class virtual function is private.
|
note</a> if the base class virtual function is private.
|
||||||
@@ -59,52 +67,60 @@ class world
|
|||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
struct world_callback : world
|
struct hello_callback : hello
|
||||||
{
|
{
|
||||||
world_callback(PyObject* self, int x) // <a href="#derived_2">2</a>
|
// hello constructor storing initial self_ parameter
|
||||||
: world(x),
|
hello_callback(PyObject* self_, const std::string& x) // <a href="#derived_2">2</a>
|
||||||
m_self(self) {}
|
: hello(x), self(self_) {}
|
||||||
|
|
||||||
std::string get() const // <a href="#derived_3">3</a>
|
// In case hello is returned by-value from a wrapped function
|
||||||
{ return boost::python::callback<std::string>::call_method(m_self, "get"); }
|
hello_callback(PyObject* self_, const hello& x) // <a href="#derived_3">3</a>
|
||||||
|
: hello(x), self(self_) {}
|
||||||
|
|
||||||
static std::string <a name= "default_implementation">default_get</a>(const hello::world& self) const // <a href="#derived_4">4</a>
|
// Override greet to call back into Python
|
||||||
{ return self.world::get(); }
|
std::string greet() const // <a href="#derived_4">4</a>
|
||||||
|
{ return boost::python::callback<std::string>::call_method(self, "greet"); }
|
||||||
|
|
||||||
|
// Supplies the default implementation of greet
|
||||||
|
static std::string <a name= "default_implementation">default_greet</a>(const hello& self_) const // <a href="#derived_5">5</a>
|
||||||
|
{ return self_.hello::greet(); }
|
||||||
private:
|
private:
|
||||||
PyObject* m_self; // <a href="#derived_1">1</a>
|
PyObject* self; // <a href="#derived_1">1</a>
|
||||||
};
|
};
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Finally, we add <code>world_callback</code> to the <code>
|
Finally, we add <tt>hello_callback</tt> to the <tt>
|
||||||
class_builder<></code> declaration in our module initialization
|
class_builder<></tt> declaration in our module initialization
|
||||||
function, and when we define the function, we must tell py_cpp about the default
|
function, and when we define the function, we must tell Boost.Python about the default
|
||||||
implementation:
|
implementation:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
// Create the <a name=
|
// Create the <a name=
|
||||||
"world_class">Python type object</a> for our extension class
|
"hello_class">Python type object</a> for our extension class
|
||||||
boost::python::class_builder<hello::world<strong>,world_callback></strong> world_class(hello, "world");
|
boost::python::class_builder<hello<strong>,hello_callback></strong> hello_class(hello, "hello");
|
||||||
// Add a virtual member function
|
// Add a virtual member function
|
||||||
world_class.def(&world::get, "get", &<b>world_callback::default_get</b>);
|
hello_class.def(&hello::greet, "greet", &<b>hello_callback::default_greet</b>);
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Now our subclass of <code>hello.world</code> behaves as expected:
|
Now our Python subclass of <tt>hello</tt> behaves as expected:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
>>> class my_subclass(hello.world):
|
>>> class wordy(hello):
|
||||||
... def get(self):
|
... def greet(self):
|
||||||
... return 'hello, world'
|
... return hello.greet(self) + ', where the weather is fine'
|
||||||
...
|
...
|
||||||
>>> hello.length(my_subclass())
|
>>> hi2 = wordy('Florida')
|
||||||
12
|
>>> hi2.greet()
|
||||||
|
'Hello from Florida, where the weather is fine'
|
||||||
|
>>> invite(hi2)
|
||||||
|
'Hello from Florida, where the weather is fine! Please come soon!'
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a name="why_derived">*</a>You may ask, "Why do we need this derived
|
<a name="why_derived">*</a>You may ask, "Why do we need this derived
|
||||||
class? This could have been designed so that everything gets done right
|
class? This could have been designed so that everything gets done right
|
||||||
inside of <code>hello::world</code>." One of the goals of py_cpp is to be
|
inside of <tt>hello</tt>." One of the goals of Boost.Python is to be
|
||||||
minimally intrusive on an existing C++ design. In principle, it should be
|
minimally intrusive on an existing C++ design. In principle, it should be
|
||||||
possible to expose the interface for a 3rd party library without changing
|
possible to expose the interface for a 3rd party library without changing
|
||||||
it. To unintrusively hook into the virtual functions so that a Python
|
it. To unintrusively hook into the virtual functions so that a Python
|
||||||
@@ -117,32 +133,29 @@ world_class.def(&world::get, "get", &<b>world_callback::default_get</b>)
|
|||||||
deal with than a virtual function with a default implementation. First of
|
deal with than a virtual function with a default implementation. First of
|
||||||
all, you obviously don't need to <a href="#default_implementation"> supply
|
all, you obviously don't need to <a href="#default_implementation"> supply
|
||||||
a default implementation</a>. Secondly, you don't need to call
|
a default implementation</a>. Secondly, you don't need to call
|
||||||
<code>def()</code> on the <code>extension_class<></code> instance
|
<tt>def()</tt> on the <tt>extension_class<></tt> instance
|
||||||
for the virtual function. In fact, you wouldn't <em>want</em> to: if the
|
for the virtual function. In fact, you wouldn't <em>want</em> to: if the
|
||||||
corresponding attribute on the Python class stays undefined, you'll get an
|
corresponding attribute on the Python class stays undefined, you'll get an
|
||||||
<code>AttributeError</code> in Python when you try to call the function,
|
<tt>AttributeError</tt> in Python when you try to call the function,
|
||||||
indicating that it should have been implemented. For example:
|
indicating that it should have been implemented. For example:
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
struct baz {
|
struct baz {
|
||||||
<strong>virtual</strong> int pure(int) = 0;
|
<strong>virtual</strong> int pure(int) = 0;
|
||||||
|
int calls_pure(int x) { return pure(x) + 1000; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct baz_callback {
|
struct baz_callback {
|
||||||
int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
|
int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C"
|
BOOST_PYTHON_MODULE_INIT(foobar)
|
||||||
#ifdef _WIN32
|
|
||||||
__declspec(dllexport)
|
|
||||||
#endif
|
|
||||||
initfoobar()
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
boost::python::module_builder foobar("foobar");
|
boost::python::module_builder foobar("foobar");
|
||||||
boost::python::class_builder<baz,baz_callback> baz_class("baz");
|
boost::python::class_builder<baz,baz_callback> baz_class("baz");
|
||||||
baz_class.def(&baz::pure, "pure");
|
baz_class.def(&baz::calls_pure, "calls_pure");
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@@ -161,12 +174,18 @@ initfoobar()
|
|||||||
Traceback (innermost last):
|
Traceback (innermost last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
AttributeError: pure
|
AttributeError: pure
|
||||||
|
>>> x.calls_pure(1)
|
||||||
|
Traceback (innermost last):
|
||||||
|
File "<stdin>", line 1, in ?
|
||||||
|
AttributeError: pure
|
||||||
>>> class mumble(baz):
|
>>> class mumble(baz):
|
||||||
... def pure(self, x): return x + 1
|
... def pure(self, x): return x + 1
|
||||||
...
|
...
|
||||||
>>> y = mumble()
|
>>> y = mumble()
|
||||||
>>> y.pure(99)
|
>>> y.pure(99)
|
||||||
100
|
100
|
||||||
|
>>> y.calls_pure(99)
|
||||||
|
1100
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
<a name="private"><h2>Private Non-Pure Virtual Functions</h2></a>
|
<a name="private"><h2>Private Non-Pure Virtual Functions</h2></a>
|
||||||
@@ -180,16 +199,17 @@ this limited way without breaking binary compatibility (though it will certainly
|
|||||||
break the <a
|
break the <a
|
||||||
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
|
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
|
||||||
|
|
||||||
|
<hr>
|
||||||
<p>
|
<p>
|
||||||
Prev: <a href="example1.html">A Simple Example Using py_cpp</a> Next: <a
|
Next: <a href="overloading.html">Function Overloading</a>
|
||||||
href="overloading.html">Function Overloading</a> Up: <a href=
|
Previous: <a href="exporting_classes.html">Exporting Classes</a>
|
||||||
"index.html">Top</a>
|
Up: <a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||||
sell and distribute this document is granted provided this copyright
|
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
|
express or implied warranty, and with no claim as to its suitability for
|
||||||
any purpose.
|
any purpose.
|
||||||
<p>
|
<p>
|
||||||
Updated: Nov 26, 2000
|
Updated: Mar 21, 2001
|
||||||
|
|
||||||
|
|||||||
272
doc/pickle.html
Normal file
272
doc/pickle.html
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||||
|
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
|
||||||
|
<title>Boost.Python Pickle Support</title>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<img src="../../../c++boost.gif"
|
||||||
|
alt="c++boost.gif (8819 bytes)"
|
||||||
|
align="center"
|
||||||
|
width="277" height="86">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h1>Boost.Python Pickle Support</h1>
|
||||||
|
|
||||||
|
Pickle is a Python module for object serialization, also known
|
||||||
|
as persistence, marshalling, or flattening.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
It is often necessary to save and restore the contents of an object to
|
||||||
|
a file. One approach to this problem is to write a pair of functions
|
||||||
|
that read and write data from a file in a special format. A powerful
|
||||||
|
alternative approach is to use Python's pickle module. Exploiting
|
||||||
|
Python's ability for introspection, the pickle module recursively
|
||||||
|
converts nearly arbitrary Python objects into a stream of bytes that
|
||||||
|
can be written to a file.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The Boost Python Library supports the pickle module by emulating the
|
||||||
|
interface implemented by Jim Fulton's ExtensionClass module that is
|
||||||
|
included in the
|
||||||
|
<a href="http://www.zope.org/"
|
||||||
|
>ZOPE</a>
|
||||||
|
distribution.
|
||||||
|
This interface is similar to that for regular Python classes as
|
||||||
|
described in detail in the
|
||||||
|
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
|
||||||
|
>Python Library Reference for pickle.</a>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>The Boost.Python Pickle Interface</h2>
|
||||||
|
|
||||||
|
At the user level, the Boost.Python pickle interface involves three special
|
||||||
|
methods:
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
<strong><tt>__getinitargs__</tt></strong>
|
||||||
|
<dd>
|
||||||
|
When an instance of a Boost.Python extension class is pickled, the
|
||||||
|
pickler tests if the instance has a <tt>__getinitargs__</tt> method.
|
||||||
|
This method must return a Python tuple (it is most convenient to use
|
||||||
|
a boost::python::tuple). When the instance is restored by the
|
||||||
|
unpickler, the contents of this tuple are used as the arguments for
|
||||||
|
the class constructor.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If <tt>__getinitargs__</tt> is not defined, the class constructor
|
||||||
|
will be called without arguments.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<dt>
|
||||||
|
<strong><tt>__getstate__</tt></strong>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
When an instance of a Boost.Python extension class is pickled, the
|
||||||
|
pickler tests if the instance has a <tt>__getstate__</tt> method.
|
||||||
|
This method should return a Python object representing the state of
|
||||||
|
the instance.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If <tt>__getstate__</tt> is not defined, the instance's
|
||||||
|
<tt>__dict__</tt> is pickled (if it is not empty).
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<dt>
|
||||||
|
<strong><tt>__setstate__</tt></strong>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
When an instance of a Boost.Python extension class is restored by the
|
||||||
|
unpickler, it is first constructed using the result of
|
||||||
|
<tt>__getinitargs__</tt> as arguments (see above). Subsequently the
|
||||||
|
unpickler tests if the new instance has a <tt>__setstate__</tt>
|
||||||
|
method. If so, this method is called with the result of
|
||||||
|
<tt>__getstate__</tt> (a Python object) as the argument.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If <tt>__setstate__</tt> is not defined, the result of
|
||||||
|
<tt>__getstate__</tt> must be a Python dictionary. The items of this
|
||||||
|
dictionary are added to the instance's <tt>__dict__</tt>.
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
If both <tt>__getstate__</tt> and <tt>__setstate__</tt> are defined,
|
||||||
|
the Python object returned by <tt>__getstate__</tt> need not be a
|
||||||
|
dictionary. The <tt>__getstate__</tt> and <tt>__setstate__</tt> methods
|
||||||
|
can do what they want.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Pitfalls and Safety Guards</h2>
|
||||||
|
|
||||||
|
In Boost.Python extension modules with many extension classes,
|
||||||
|
providing complete pickle support for all classes would be a
|
||||||
|
significant overhead. In general complete pickle support should only be
|
||||||
|
implemented for extension classes that will eventually be pickled.
|
||||||
|
However, the author of a Boost.Python extension module might not
|
||||||
|
anticipate correctly which classes need support for pickle.
|
||||||
|
Unfortunately, the pickle protocol described above has two important
|
||||||
|
pitfalls that the end user of a Boost.Python extension module might not
|
||||||
|
be aware of:
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
<strong>Pitfall 1:</strong>
|
||||||
|
Both <tt>__getinitargs__</tt> and <tt>__getstate__</tt> are not defined.
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
In this situation the unpickler calls the class constructor without
|
||||||
|
arguments and then adds the <tt>__dict__</tt> that was pickled by
|
||||||
|
default to that of the new instance.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
However, most C++ classes wrapped with Boost.Python will have member
|
||||||
|
data that are not restored correctly by this procedure. To alert the
|
||||||
|
user to this problem, a safety guard is provided. If both
|
||||||
|
<tt>__getinitargs__</tt> and <tt>__getstate__</tt> are not defined,
|
||||||
|
Boost.Python tests if the class has an attribute
|
||||||
|
<tt>__dict_defines_state__</tt>. An exception is raised if this
|
||||||
|
attribute is not defined:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
In the rare cases where this is not the desired behavior, the safety
|
||||||
|
guard can deliberately be disabled. The corresponding C++ code for
|
||||||
|
this is, e.g.:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
class_builder<your_class> py_your_class(your_module, "your_class");
|
||||||
|
py_your_class.dict_defines_state();
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
It is also possible to override the safety guard at the Python level.
|
||||||
|
E.g.:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import your_bpl_module
|
||||||
|
class your_class(your_bpl_module.your_class):
|
||||||
|
__dict_defines_state__ = 1
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<dt>
|
||||||
|
<strong>Pitfall 2:</strong>
|
||||||
|
<tt>__getstate__</tt> is defined and the instance's <tt>__dict__</tt> is not empty.
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
The author of a Boost.Python extension class might provide a
|
||||||
|
<tt>__getstate__</tt> method without considering the possibilities
|
||||||
|
that:
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
his class is used in Python as a base class. Most likely the
|
||||||
|
<tt>__dict__</tt> of instances of the derived class needs to be
|
||||||
|
pickled in order to restore the instances correctly.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<li>
|
||||||
|
the user adds items to the instance's <tt>__dict__</tt> directly.
|
||||||
|
Again, the <tt>__dict__</tt> of the instance then needs to be
|
||||||
|
pickled.
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
To alert the user to this highly unobvious problem, a safety guard is
|
||||||
|
provided. If <tt>__getstate__</tt> is defined and the instance's
|
||||||
|
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has
|
||||||
|
an attribute <tt>__getstate_manages_dict__</tt>. An exception is
|
||||||
|
raised if this attribute is not defined:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
To resolve this problem, it should first be established that the
|
||||||
|
<tt>__getstate__</tt> and <tt>__setstate__</tt> methods manage the
|
||||||
|
instances's <tt>__dict__</tt> correctly. Note that this can be done
|
||||||
|
both at the C++ and the Python level. Finally, the safety guard
|
||||||
|
should intentionally be overridden. E.g. in C++:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
class_builder<your_class> py_your_class(your_module, "your_class");
|
||||||
|
py_your_class.getstate_manages_dict();
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
In Python:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
import your_bpl_module
|
||||||
|
class your_class(your_bpl_module.your_class):
|
||||||
|
__getstate_manages_dict__ = 1
|
||||||
|
def __getstate__(self):
|
||||||
|
# your code here
|
||||||
|
def __setstate__(self, state):
|
||||||
|
# your code here
|
||||||
|
</pre>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Practical Advice</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Avoid using <tt>__getstate__</tt> if the instance can also be
|
||||||
|
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
|
||||||
|
avoids Pitfall 2.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<li>
|
||||||
|
If <tt>__getstate__</tt> is required, include the instance's
|
||||||
|
<tt>__dict__</tt> in the Python object that is returned.
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Examples</h2>
|
||||||
|
|
||||||
|
There are three files in <tt>boost/libs/python/example</tt> that
|
||||||
|
show how so provide pickle support.
|
||||||
|
|
||||||
|
<h3><a href="../example/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>
|
||||||
|
|
||||||
|
The C++ class in this example can be fully restored by passing the
|
||||||
|
appropriate argument to the constructor. Therefore it is sufficient
|
||||||
|
to define the pickle interface method <tt>__getinitargs__</tt>.
|
||||||
|
|
||||||
|
<h3><a href="../example/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>
|
||||||
|
|
||||||
|
The C++ class in this example contains member data that cannot be
|
||||||
|
restored by any of the constructors. Therefore it is necessary to
|
||||||
|
provide the <tt>__getstate__</tt>/<tt>__setstate__</tt> pair of
|
||||||
|
pickle interface methods.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For simplicity, the <tt>__dict__</tt> is not included in the result
|
||||||
|
of <tt>__getstate__</tt>. This is not generally recommended, but a
|
||||||
|
valid approach if it is anticipated that the object's
|
||||||
|
<tt>__dict__</tt> will always be empty. Note that the safety guards
|
||||||
|
will catch the cases where this assumption is violated.
|
||||||
|
|
||||||
|
<h3><a href="../example/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>
|
||||||
|
|
||||||
|
This example is similar to <a
|
||||||
|
href="../example/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the
|
||||||
|
object's <tt>__dict__</tt> is included in the result of
|
||||||
|
<tt>__getstate__</tt>. This requires more code but is unavoidable
|
||||||
|
if the object's <tt>__dict__</tt> is not always empty.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
© Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy,
|
||||||
|
use, modify, sell and distribute this document is granted provided this
|
||||||
|
copyright notice appears in all copies. This document is provided "as
|
||||||
|
is" without express or implied warranty, and with no claim as to its
|
||||||
|
suitability for any purpose.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Updated: March 21, 2001
|
||||||
|
</div>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
In general, raw pointers passed to or returned from functions are problematic
|
In general, raw pointers passed to or returned from functions are problematic
|
||||||
for py_cpp because pointers have too many potential meanings. Is it an iterator?
|
for Boost.Python because pointers have too many potential meanings. Is it an iterator?
|
||||||
A pointer to a single element? An array? When used as a return value, is the
|
A pointer to a single element? An array? When used as a return value, is the
|
||||||
caller expected to manage (delete) the pointed-to object or is the pointer
|
caller expected to manage (delete) the pointed-to object or is the pointer
|
||||||
really just a reference? If the latter, what happens to Python references to the
|
really just a reference? If the latter, what happens to Python references to the
|
||||||
@@ -34,12 +34,10 @@ converted from/to Python strings.
|
|||||||
<h3>Can you avoid the problem?</h3>
|
<h3>Can you avoid the problem?</h3>
|
||||||
|
|
||||||
<p>My first piece of advice to anyone with a case not covered above is
|
<p>My first piece of advice to anyone with a case not covered above is
|
||||||
“find a way to avoid the problem.” For example, if you have just one
|
``find a way to avoid the problem.'' For example, if you have just one
|
||||||
or two functions returning a pointer to a single (not an array of) <code>const
|
or two functions that return a pointer to an individual <code>const
|
||||||
T*</code> for some wrapped <code>T</code>, you may be able to write a “thin
|
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 (Since py_cpp
|
converting wrapper'' over those two functions as follows:
|
||||||
converts <code>const T&</code> values <code>to_python</code> by copying the T
|
|
||||||
into a new extension instance, Foo must have a public copy constructor):
|
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
const Foo* f(); // original function
|
const Foo* f(); // original function
|
||||||
@@ -47,6 +45,10 @@ const Foo& f_wrapper() { return *f(); }
|
|||||||
...
|
...
|
||||||
my_module.def(f_wrapper, "f");
|
my_module.def(f_wrapper, "f");
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
<p>
|
||||||
|
Foo must have a public copy constructor for this technique to work, since Boost.Python
|
||||||
|
converts <code>const T&</code> values <code>to_python</code> by copying the <code>T</code>
|
||||||
|
value into a new extension instance.
|
||||||
|
|
||||||
<h2>Dealing with the problem</h2>
|
<h2>Dealing with the problem</h2>
|
||||||
|
|
||||||
@@ -63,9 +65,9 @@ wrapped <code>T</code>, you may want to provide an automatic
|
|||||||
thin wrappers. You can do this simply as follows:
|
thin wrappers. You can do this simply as follows:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is an MSVC / gcc 2.95.2 bug workaround
|
||||||
PyObject* to_python(const Foo* p) {
|
PyObject* to_python(boost::python::semantics, const Foo* p) {
|
||||||
return to_python(*p); // convert const Foo* in terms of const Foo&
|
return to_python(boost::python::search_namespace, *p); // convert const Foo* in terms of const Foo&
|
||||||
}
|
}
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
@@ -81,14 +83,14 @@ code before the last Python reference to it disappears:
|
|||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||||
PyObject* to_python(Foo* p)
|
PyObject* to_python(boost::python::semantics, Foo* p)
|
||||||
{
|
{
|
||||||
return boost::python::PyExtensionClassConverters<Foo>::ptr_to_python(p);
|
return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const Foo* p)
|
PyObject* to_python(boost::python::semantics, const Foo* p)
|
||||||
{
|
{
|
||||||
return to_python(const_cast<Foo*>(p));
|
return to_python(const_cast<Foo*>(p));
|
||||||
}
|
}
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
@@ -118,7 +120,7 @@ return value. You can handle this case by returning a Python tuple:
|
|||||||
typedef unsigned ErrorCode;
|
typedef unsigned ErrorCode;
|
||||||
const char* f(int* in_out_x); // original function
|
const char* f(int* in_out_x); // original function
|
||||||
...
|
...
|
||||||
#include <boost/python/objects.hpp>
|
#include <boost/python/objects.hpp>
|
||||||
const boost::python::tuple f_wrapper(int in_x) {
|
const boost::python::tuple f_wrapper(int in_x) {
|
||||||
const char* s = f(in_x);
|
const char* s = f(in_x);
|
||||||
return boost::python::tuple(s, in_x);
|
return boost::python::tuple(s, in_x);
|
||||||
@@ -131,8 +133,9 @@ my_module.def(f_wrapper, "f");
|
|||||||
>>> str,out_x = f(3)
|
>>> str,out_x = f(3)
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Previous: <a href="enums.html">Enums</a>
|
||||||
|
Up: <a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||||
sell and distribute this document is granted provided this copyright
|
sell and distribute this document is granted provided this copyright
|
||||||
|
|||||||
151
doc/special.html
151
doc/special.html
@@ -1,11 +1,10 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
<title>
|
||||||
Special Method and Operator Support
|
Special Method and Operator Support
|
||||||
</title>
|
</title>
|
||||||
<div>
|
<div>
|
||||||
<h1>
|
<h1>
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center" src=
|
<img width="277" height="86" id="_x0000_i1025" align="middle" src=
|
||||||
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Special Method and
|
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Special Method and
|
||||||
Operator Support
|
Operator Support
|
||||||
</h1>
|
</h1>
|
||||||
@@ -13,8 +12,8 @@
|
|||||||
Overview
|
Overview
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
Py_cpp supports all of the standard <a href=
|
Boost.Python supports all of the standard <a href=
|
||||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
|
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||||
special method names</a> supported by real Python class instances <em>
|
special method names</a> supported by real Python class instances <em>
|
||||||
except</em> <code>__complex__</code> (more on the reasons <a href=
|
except</em> <code>__complex__</code> (more on the reasons <a href=
|
||||||
"#reasons">below</a>). In addition, it can quickly and easily expose
|
"#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
|
Python provides a number of special operators for basic customization of a
|
||||||
class. Only a brief description is provided below; more complete
|
class. Only a brief description is provided below; more complete
|
||||||
documentation can be found <a
|
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>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
<b><tt class='method'>__init__</tt></b>(<i>self</i>)
|
<b><tt class='method'>__init__</tt></b>(<i>self</i>)
|
||||||
<dd>
|
<dd>
|
||||||
Initialize the class instance. For extension classes not subclassed in
|
Initialize the class instance. For extension classes not subclassed in
|
||||||
Python, this is provided by the
|
Python, <code> __init__</code> is defined by
|
||||||
<code>boost::python::constructor<...>()</code> construct and should <i>not</i> be explicitly <code>def</code>ed.
|
|
||||||
|
<pre> my_class.def(boost::python::constructor<...>())</pre>
|
||||||
|
|
||||||
|
(see section <a href="example1.html">"A Simple Example Using Boost.Python"</a>).<p>
|
||||||
<dt>
|
<dt>
|
||||||
<b><tt class='method'>__del__</tt></b>(<i>self</i>)
|
<b><tt class='method'>__del__</tt></b>(<i>self</i>)
|
||||||
<dd>
|
<dd>
|
||||||
Called when the extension instance is about to be destroyed.
|
Called when the extension instance is about to be destroyed. For extension classes
|
||||||
|
not subclassed in Python, <code> __del__</code> is always defined automatically by
|
||||||
|
means of the class' destructor.
|
||||||
<dt>
|
<dt>
|
||||||
<b><tt class='method'>__repr__</tt></b>(<i>self</i>)
|
<b><tt class='method'>__repr__</tt></b>(<i>self</i>)
|
||||||
<dd>
|
<dd>
|
||||||
@@ -78,7 +82,7 @@
|
|||||||
<dt>
|
<dt>
|
||||||
<b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>)
|
<b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>)
|
||||||
<dd>
|
<dd>
|
||||||
Called when the instance is “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
|
is defined, <code><var>x</var>(arg1, arg2, ...)</code> is a shorthand for
|
||||||
<code><var>x</var>.__call__(arg1, arg2, ...)</code>.
|
<code><var>x</var>.__call__(arg1, arg2, ...)</code>.
|
||||||
</dl>
|
</dl>
|
||||||
@@ -100,7 +104,7 @@ std::string to_string(Foo const& f)
|
|||||||
boost::python::class_builder<Foo> foo_class(my_module, "Foo");
|
boost::python::class_builder<Foo> foo_class(my_module, "Foo");
|
||||||
foo_class.def(&to_string, "__str__");
|
foo_class.def(&to_string, "__str__");
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
Note that py_cpp also supports <em>automatic wrapping</em> of
|
Note that Boost.Python also supports <em>automatic wrapping</em> of
|
||||||
<code>__str__</code> and <code>__cmp__</code>. This is explained in the <a
|
<code>__str__</code> and <code>__cmp__</code>. This is explained in the <a
|
||||||
href="#numeric">next section</a> and the <a href="#numeric_table">Table of
|
href="#numeric">next section</a> and the <a href="#numeric_table">Table of
|
||||||
Automatically Wrapped Methods</a>.
|
Automatically Wrapped Methods</a>.
|
||||||
@@ -110,10 +114,10 @@ foo_class.def(&to_string, "__str__");
|
|||||||
<p>
|
<p>
|
||||||
Numeric operators can be exposed manually, by <code>def</code>ing C++
|
Numeric operators can be exposed manually, by <code>def</code>ing C++
|
||||||
[member] functions that support the standard Python <a
|
[member] functions that support the standard Python <a
|
||||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/numeric-types.html">numeric
|
href="http://www.python.org/doc/current/ref/numeric-types.html">numeric
|
||||||
protocols</a>. This is the basic same technique used to expose
|
protocols</a>. This is the same basic technique used to expose
|
||||||
<code>to_string()</code> as <code>__str__()</code> above, and is <a
|
<code>to_string()</code> as <code>__str__()</code> above, and is <a
|
||||||
href="#numeric_manual">covered in detail below</a>. Py_cpp also supports
|
href="#numeric_manual">covered in detail below</a>. Boost.Python also supports
|
||||||
<i>automatic wrapping</i> of numeric operators whenever they have already
|
<i>automatic wrapping</i> of numeric operators whenever they have already
|
||||||
been defined in C++.
|
been defined in C++.
|
||||||
|
|
||||||
@@ -121,7 +125,7 @@ foo_class.def(&to_string, "__str__");
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Supose we wanted to expose a C++ class
|
Supose we wanted to expose a C++ class
|
||||||
<code>BigNum</code> which supports addition, so that we can write (in C++):
|
<code>BigNum</code> which supports addition. That is, in C++ we can write:
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
BigNum a, b, c;
|
BigNum a, b, c;
|
||||||
...
|
...
|
||||||
@@ -143,7 +147,7 @@ bignum_class.def(boost::python::operators<boost::python::op_add>());
|
|||||||
|
|
||||||
Since BigNum also supports subtraction, multiplication, and division, we
|
Since BigNum also supports subtraction, multiplication, and division, we
|
||||||
want to export those also. This can be done in a single command by
|
want to export those also. This can be done in a single command by
|
||||||
“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=
|
identifiers and the corresponding operators can be found in the <a href=
|
||||||
"#numeric_table">Table of Automatically Wrapped Methods</a>):
|
"#numeric_table">Table of Automatically Wrapped Methods</a>):
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
@@ -170,7 +174,7 @@ a = i + b;
|
|||||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>());
|
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>());
|
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>());
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
Py_cpp uses overloading to register several variants of the same
|
Boost.Python uses overloading to register several variants of the same
|
||||||
operation (more on this in the context of <a href="#coercion">
|
operation (more on this in the context of <a href="#coercion">
|
||||||
coercion</a>). Again, several operators can be exported at once:
|
coercion</a>). Again, several operators can be exported at once:
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
@@ -181,7 +185,7 @@ bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::pyt
|
|||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
The type of the operand not mentioned is taken from the class being wrapped. In
|
The type of the operand not mentioned is taken from the class being wrapped. In
|
||||||
our example, the class object is <code>bignum_class</code>, and thus the
|
our example, the class object is <code>bignum_class</code>, and thus the
|
||||||
other operand's type is “<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>
|
this default by explicitly specifying a type in the <code>
|
||||||
operators</code> template:
|
operators</code> template:
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
@@ -189,15 +193,18 @@ bignum_class.def(boost::python::operators<boost::python::op_add, BigNum>()
|
|||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
<p>
|
<p>
|
||||||
Note that automatic wrapping uses the <em>expression</em>
|
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
|
regardless of whether the C++ operators are supplied as free functions
|
||||||
<blockquote><pre>
|
|
||||||
|
<blockquote><pre>
|
||||||
BigNum operator+(BigNum, BigNum)
|
BigNum operator+(BigNum, BigNum)
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
or as member
|
|
||||||
functions <blockquote><pre>
|
or as member functions
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
BigNum::operator+(BigNum).
|
BigNum::operator+(BigNum).
|
||||||
</blockquote></pre>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
For the Python built-in functions <code>pow()</code> and
|
For the Python built-in functions <code>pow()</code> and
|
||||||
@@ -218,8 +225,7 @@ namespace boost { namespace python {
|
|||||||
<p>
|
<p>
|
||||||
In some cases, automatic wrapping of operators may be impossible or
|
In some cases, automatic wrapping of operators may be impossible or
|
||||||
undesirable. Suppose, for example, that the modulo operation for BigNums
|
undesirable. Suppose, for example, that the modulo operation for BigNums
|
||||||
is defined by a set of functions <code>mod()</code> (for automatic
|
is defined by a set of functions called <code>mod()</code>:
|
||||||
wrapping, we would need <code>operator%()</code>):
|
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
BigNum mod(BigNum const& left, BigNum const& right);
|
BigNum mod(BigNum const& left, BigNum const& right);
|
||||||
@@ -228,8 +234,9 @@ BigNum mod(int left, BigNum const& right);
|
|||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In order to create the Python operator "__mod__" from these functions, we
|
For automatic wrapping of the modulo function, <code>operator%()</code> would be needed.
|
||||||
have to wrap them manually:
|
Therefore, the <code>mod()</code>-functions must be wrapped manually. That is, we have
|
||||||
|
to export them explicitly with the Python special name "__mod__":
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
bignum_class.def((BigNum (*)(BigNum const&, BigNum const&))&mod, "__mod__");
|
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>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The third form (with <code>int</code> as left operand) cannot be wrapped
|
The third form of <code>mod()</code> (with <code>int</code> as left operand) cannot
|
||||||
this way. We must first create a function <code>rmod()</code> with the
|
be wrapped directly. We must first create a function <code>rmod()</code> with the
|
||||||
operands reversed:
|
operands reversed:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
@@ -248,7 +255,7 @@ BigNum rmod(BigNum const& right, int left)
|
|||||||
}
|
}
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
This function must be wrapped under the name "__rmod__":
|
This function must be wrapped under the name "__rmod__" (standing for "reverse mod"):
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
bignum_class.def(&rmod, "__rmod__");
|
bignum_class.def(&rmod, "__rmod__");
|
||||||
@@ -261,9 +268,9 @@ bignum_class.def(&rmod, "__rmod__");
|
|||||||
<p>
|
<p>
|
||||||
Automatic and manual wrapping can be mixed arbitrarily. Note that you
|
Automatic and manual wrapping can be mixed arbitrarily. Note that you
|
||||||
cannot overload the same operator for a given extension class on both
|
cannot overload the same operator for a given extension class on both
|
||||||
“<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
|
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.
|
used for either of the two types.
|
||||||
|
|
||||||
<h3><a name="coercion">Coercion</a></h3>
|
<h3><a name="coercion">Coercion</a></h3>
|
||||||
@@ -271,18 +278,18 @@ bignum_class.def(&rmod, "__rmod__");
|
|||||||
|
|
||||||
Plain Python can only execute operators with identical types on the left
|
Plain Python can only execute operators with identical types on the left
|
||||||
and right hand side. If it encounters an expression where the types of
|
and right hand side. If it encounters an expression where the types of
|
||||||
the left and right operand differ, it tries to coerce these type to a
|
the left and right operand differ, it tries to coerce these types to a
|
||||||
common type before invoking the actual operator. Implementing good
|
common type before invoking the actual operator. Implementing good
|
||||||
coercion functions can be difficult if many type combinations must be
|
coercion functions can be difficult if many type combinations must be
|
||||||
supported.
|
supported.
|
||||||
<p>
|
<p>
|
||||||
Py_cpp solves this problem the same way that C++ does: with <em><a
|
Boost.Python solves this problem the same way that C++ does: with <em><a
|
||||||
href="overloading.html">overloading</a></em>. This technique drastically
|
href="overloading.html">overloading</a></em>. This technique drastically
|
||||||
simplifies the code neccessary to support operators: you just register
|
simplifies the code neccessary to support operators: you just register
|
||||||
operators for all desired type combinations, and py_cpp automatically
|
operators for all desired type combinations, and Boost.Python automatically
|
||||||
ensures that the correct function is called in each case; there is no
|
ensures that the correct function is called in each case; there is no
|
||||||
need for user-defined coercion functions. To enable operator
|
need for user-defined coercion functions. To enable operator
|
||||||
overloading, py_cpp provides a standard coercion which is <em>implicitly
|
overloading, Boost.Python provides a standard coercion which is <em>implicitly
|
||||||
registered</em> whenever automatic operator wrapping is used.
|
registered</em> whenever automatic operator wrapping is used.
|
||||||
<p>
|
<p>
|
||||||
If you wrap all operator functions manually, but still want to use
|
If you wrap all operator functions manually, but still want to use
|
||||||
@@ -295,7 +302,7 @@ bignum_class.def_standard_coerce();
|
|||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
If you encounter a situation where you absolutely need a customized
|
If you encounter a situation where you absolutely need a customized
|
||||||
coercion, you can overload the "__coerce__" operator itself. The signature
|
coercion, you can still define the "__coerce__" operator manually. The signature
|
||||||
of a coercion function should look like one of the following (the first is
|
of a coercion function should look like one of the following (the first is
|
||||||
the safest):
|
the safest):
|
||||||
|
|
||||||
@@ -310,13 +317,22 @@ PyObject* custom_coerce(PyObject* left, PyObject* right);
|
|||||||
converted to the same type. Such a function is wrapped as usual:
|
converted to the same type. Such a function is wrapped as usual:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
|
// this must be called before any use of automatic operator
|
||||||
|
// wrapping or a call to some_class.def_standard_coerce()
|
||||||
some_class.def(&custom_coerce, "__coerce__");
|
some_class.def(&custom_coerce, "__coerce__");
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
Note that the later use of automatic operator wrapping on a
|
Note that the standard coercion (defined by use of automatic
|
||||||
<code>class_builder</code> or a call to
|
operator wrapping on a <code>class_builder</code> or a call to
|
||||||
“<code>some_class.def_standard_coerce()</code>” will cause any
|
<code>class_builder::def_standard_coerce()</code>) will never be applied if
|
||||||
custom coercion function to be replaced by the standard one.
|
a custom coercion function has been registered. Therefore, in
|
||||||
|
your coercion function you should call
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
boost::python::standard_coerce(left, right);
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
for all cases that you don't want to handle yourself.
|
||||||
|
|
||||||
<h3><a name="ternary_pow">The Ternary <code>pow()</code> Operator</a></h3>
|
<h3><a name="ternary_pow">The Ternary <code>pow()</code> Operator</a></h3>
|
||||||
|
|
||||||
@@ -330,7 +346,7 @@ some_class.def(&custom_coerce, "__coerce__");
|
|||||||
this is done as usual:
|
this is done as usual:
|
||||||
|
|
||||||
<blockquote><pre>
|
<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&);
|
typedef BigNum (ternary_function1)(const BigNum&, const BigNum&, const BigNum&);
|
||||||
...
|
...
|
||||||
bignum_class.def((ternary_function1)&power, "__pow__");
|
bignum_class.def((ternary_function1)&power, "__pow__");
|
||||||
@@ -353,19 +369,19 @@ bignum_class.def((ternary_function2)&power, "__pow__");
|
|||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
In the second variant, however, <code>BigNum</code> appears only as second
|
In the second variant, however, <code>BigNum</code> appears only as second
|
||||||
argument, and in the last one it is the third argument. These functions
|
argument, and in the last one it's the third argument. These functions
|
||||||
must be presented to py_cpp such that that the <code>BigNum</code>
|
must be presented to Boost.Python such that that the <code>BigNum</code>
|
||||||
argument appears in first position:
|
argument appears in first position:
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
BigNum rpower(BigNum const& second, int first, int modulus)
|
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>
|
</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>
|
<h2><a name="numeric_table">Table of Automatically Wrapped Methods</a></h2>
|
||||||
<p>
|
<p>
|
||||||
Py_cpp can automatically wrap the following <a href=
|
Boost.Python can automatically wrap the following <a href=
|
||||||
"http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/specialnames.html">
|
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||||
special methods</a>:
|
special methods</a>:
|
||||||
|
|
||||||
<p>
|
<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
|
to Python's iteration and access protocols. These protocols differ
|
||||||
considerably from the ones found in C++. For example, Python's typical
|
considerably from the ones found in C++. For example, Python's typical
|
||||||
iteration idiom looks like
|
iteration idiom looks like
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
for i in S:
|
for i in S:
|
||||||
</blockquote></pre>
|
</pre></blockquote>
|
||||||
|
|
||||||
while in C++ one writes
|
while in C++ one writes
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
for (iterator i = S.begin(), end = S.end(); i != end)
|
for (iterator i = S.begin(), end = S.end(); i != end; ++i)
|
||||||
</blockquote></pre>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>One could try to wrap C++ iterators in order to carry the C++ idiom into
|
<p>One could try to wrap C++ iterators in order to carry the C++ idiom into
|
||||||
Python. However, this does not work very well because
|
Python. However, this does not work very well because
|
||||||
@@ -655,12 +672,12 @@ for (iterator i = S.begin(), end = S.end(); i != end)
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
It is a better idea to support the standard <a
|
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
|
sequence and mapping protocols</a> for your wrapped containers. These
|
||||||
operators have to be wrapped manually because there are no corresponding
|
operators have to be wrapped manually because there are no corresponding
|
||||||
C++ operators that could be used for automatic wrapping. The Python
|
C++ operators that could be used for automatic wrapping. The Python
|
||||||
documentation lists the relevant <a href=
|
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__
|
container operators</a>. In particular, expose __getitem__, __setitem__
|
||||||
and remember to raise the appropriate Python exceptions
|
and remember to raise the appropriate Python exceptions
|
||||||
(<code>PyExc_IndexError</code> for sequences,
|
(<code>PyExc_IndexError</code> for sequences,
|
||||||
@@ -682,14 +699,14 @@ void throw_key_error_if_end(
|
|||||||
{
|
{
|
||||||
if (p == m.end())
|
if (p == m.end())
|
||||||
{
|
{
|
||||||
PyErr_SetObject(PyExc_KeyError, boost::python::converters::to_python(key));
|
PyErr_SetObject(PyExc_KeyError, to_python(boost::python::search_namespace, key));
|
||||||
throw boost::python::error_already_set();
|
throw boost::python::error_already_set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define some simple wrapper functions which match the Python protocol
|
// Define some simple wrapper functions which match the Python protocol
|
||||||
// for __getitem__, __setitem__, and __delitem__. Just as in Python, a
|
// for __getitem__, __setitem__, and __delitem__. Just as in Python, a
|
||||||
// free function with a “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)
|
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>
|
<h2><a name="getter_setter">Customized Attribute Access</a></h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Just like built-in Python classes, py_cpp extension classes support <a
|
Just like built-in Python classes, Boost.Python extension classes support <a
|
||||||
href="http://www.pythonlabs.com/pub/www.python.org/doc/current/ref/attribute-access.html">special
|
href="http://www.python.org/doc/current/ref/attribute-access.html">special
|
||||||
the usual attribute access methods</a> <code>__getattr__</code>,
|
the usual attribute access methods</a> <code>__getattr__</code>,
|
||||||
<code>__setattr__</code>, and <code>__delattr__</code>.
|
<code>__setattr__</code>, and <code>__delattr__</code>.
|
||||||
Because writing these functions can
|
Because writing these functions can
|
||||||
be tedious in the common case where the attributes being accessed are
|
be tedious in the common case where the attributes being accessed are
|
||||||
known statically, py_cpp checks the special names
|
known statically, Boost.Python checks the special names
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -774,10 +791,10 @@ KeyError: 2
|
|||||||
|
|
||||||
to provide functional access to the attribute <em><name></em>. This
|
to provide functional access to the attribute <em><name></em>. This
|
||||||
facility can be used from C++ or entirely from Python. For example, the
|
facility can be used from C++ or entirely from Python. For example, the
|
||||||
following shows how we can implement a “computed attribute” in Python:
|
following shows how we can implement a ``computed attribute'' in Python:
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
>>> class Range(AnyPy_cppExtensionClass):
|
>>> class Range(AnyBoost.PythonExtensionClass):
|
||||||
... def __init__(self, start, end):
|
... def __init__(self, start, end):
|
||||||
... self.start = start
|
... self.start = start
|
||||||
... self.end = end
|
... self.end = end
|
||||||
@@ -793,7 +810,7 @@ KeyError: 2
|
|||||||
Direct Access to Data Members
|
Direct Access to Data Members
|
||||||
</h4>
|
</h4>
|
||||||
<p>
|
<p>
|
||||||
Py_cpp uses the special <code>
|
Boost.Python uses the special <code>
|
||||||
__xxxattr__<em><name></em>__</code> functionality described above
|
__xxxattr__<em><name></em>__</code> functionality described above
|
||||||
to allow direct access to data members through the following special
|
to allow direct access to data members through the following special
|
||||||
functions on <code>class_builder<></code> and <code>
|
functions on <code>class_builder<></code> and <code>
|
||||||
@@ -873,14 +890,14 @@ if (PyInstance_Check(r)) { ...
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>
|
<p>
|
||||||
Previous: <a href="inheritance.html">Inheritance</a> Next: <a href=
|
Next: <a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||||
"under-the-hood.html">A Peek Under the Hood</a> Up: <a href=
|
Previous: <a href="inheritance.html">Inheritance</a>
|
||||||
"index.html">Top</a>
|
Up: <a href= "index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams and Ullrich Köthe 2000.
|
© Copyright David Abrahams and Ullrich Köthe 2000.
|
||||||
Permission to copy, use, modify, sell and distribute this document is
|
Permission to copy, use, modify, sell and distribute this document is
|
||||||
granted provided this copyright notice appears in all copies. This
|
granted provided this copyright notice appears in all copies. This
|
||||||
document is provided “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.
|
warranty, and with no claim as to its suitability for any purpose.
|
||||||
<p>
|
<p>
|
||||||
Updated: Nov 26, 2000
|
Updated: Nov 26, 2000
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
The Title Of This Page
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">The Title Of This
|
|
||||||
Page
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
<p>
|
|
||||||
Prev: <a href="prev.html">Previous</a>
|
|
||||||
Next: <a href="next.html">Next</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability
|
|
||||||
for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Nov 26, 2000
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -22,12 +22,12 @@
|
|||||||
"example1.html#add_world_class">add it to the module</a> it goes into the
|
"example1.html#add_world_class">add it to the module</a> it goes into the
|
||||||
module's dictionary to be looked up under the name "world".
|
module's dictionary to be looked up under the name "world".
|
||||||
<p>
|
<p>
|
||||||
Py_cpp uses C++'s template argument deduction mechanism to determine the
|
Boost.Python uses C++'s template argument deduction mechanism to determine the
|
||||||
types of arguments to functions (except constructors, for which we must
|
types of arguments to functions (except constructors, for which we must
|
||||||
<a href="example1.html#Constructor_example">provide an argument list</a>
|
<a href="example1.html#Constructor_example">provide an argument list</a>
|
||||||
because they can't be named in C++). Then, it calls the appropriate
|
because they can't be named in C++). Then, it calls the appropriate
|
||||||
overloaded functions <code>PyObject*
|
overloaded functions <code>PyObject*
|
||||||
to_python(</code><em>S</em><code>)</code> and <em>
|
to_python(boost::python::semantics, </code><em>S</em><code>)</code> and <em>
|
||||||
S'</em><code>from_python(PyObject*,
|
S'</em><code>from_python(PyObject*,
|
||||||
type<</code><em>S</em><code>>)</code> which convert between any C++
|
type<</code><em>S</em><code>>)</code> which convert between any C++
|
||||||
type <em>S</em> and a <code>PyObject*</code>, the type which represents a
|
type <em>S</em> and a <code>PyObject*</code>, the type which represents a
|
||||||
@@ -48,8 +48,8 @@
|
|||||||
the top of your module's init function, then <code>def</code> the member
|
the top of your module's init function, then <code>def</code> the member
|
||||||
functions later to avoid problems with inter-class dependencies.
|
functions later to avoid problems with inter-class dependencies.
|
||||||
<p>
|
<p>
|
||||||
Previous: <a href="overriding.html">Function Overloading</a>
|
Next: <a href="building.html">Building a Module with Boost.Python</a>
|
||||||
Next: <a href="building.html">Building a Module with Py_cpp</a>
|
Previous: <a href="special.html">Special Method and Operator Support</a>
|
||||||
Up: <a href="index.html">Top</a>
|
Up: <a href="index.html">Top</a>
|
||||||
<p>
|
<p>
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||||
|
|||||||
24
example/README
Normal file
24
example/README
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
To get started with the Boost Python Library, use the examples
|
||||||
|
getting_started1.cpp and getting_started2.cpp.
|
||||||
|
|
||||||
|
Examples for providing pickle support can be found in:
|
||||||
|
pickle1.cpp
|
||||||
|
pickle2.cpp
|
||||||
|
pickle3.cpp
|
||||||
|
See also: libs/python/doc/pickle.html
|
||||||
|
|
||||||
|
Other advanced concepts are introduced by:
|
||||||
|
abstract.cpp
|
||||||
|
simple_vector.cpp
|
||||||
|
do_it_yourself_converters.cpp
|
||||||
|
|
||||||
|
Examples for the cross-module support are provided by:
|
||||||
|
noncopyable_export.cpp
|
||||||
|
noncopyable_import.cpp
|
||||||
|
dvect.cpp
|
||||||
|
ivect.cpp
|
||||||
|
See also: libs/python/doc/cross_module.html
|
||||||
|
|
||||||
|
The files example1.cpp and rwgk1.cpp are obsolete. They are only
|
||||||
|
included because the Visual Studio project in the build directory still
|
||||||
|
refers to them.
|
||||||
32
example/abstract.cpp
Normal file
32
example/abstract.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Example by Ullrich Koethe
|
||||||
|
#include "boost/python/class_builder.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct Abstract
|
||||||
|
{
|
||||||
|
virtual std::string test() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Abstract_callback: Abstract
|
||||||
|
{
|
||||||
|
Abstract_callback(PyObject * self)
|
||||||
|
: m_self(self)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string test()
|
||||||
|
{
|
||||||
|
return boost::python::callback<std::string>::call_method(m_self, "test");
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject * m_self;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(abstract)
|
||||||
|
{
|
||||||
|
boost::python::module_builder a("abstract");
|
||||||
|
|
||||||
|
boost::python::class_builder<Abstract, Abstract_callback>
|
||||||
|
a_class(a, "Abstract");
|
||||||
|
a_class.def(boost::python::constructor<>()); // wrap a constructor
|
||||||
|
a_class.def(&Abstract::test, "test");
|
||||||
|
}
|
||||||
128
example/do_it_yourself_converters.cpp
Normal file
128
example/do_it_yourself_converters.cpp
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
/*
|
||||||
|
|
||||||
|
This example shows how to convert a class from and to native
|
||||||
|
Python objects, such as tuples.
|
||||||
|
|
||||||
|
We do not want to expose the helper class MillerIndex as an
|
||||||
|
Extension Class. However, in order to simplify the wrapper code,
|
||||||
|
we want to define from_python() and to_python() functions for
|
||||||
|
class MillerIndex.
|
||||||
|
|
||||||
|
Consider the alternatives:
|
||||||
|
|
||||||
|
- Expose MillerIndex as an Extension Class.
|
||||||
|
We need a constructor MillerIndex(python::tuple).
|
||||||
|
Python function calls become more complex:
|
||||||
|
foo(MillerIndex((1,2,3)) instead of foo((1,2,3))
|
||||||
|
We need a method such as MillerIndex().as_tuple().
|
||||||
|
|
||||||
|
- Define a wrapper function for each function that we
|
||||||
|
want to expose, e.g.:
|
||||||
|
void add(const IndexingSet& ixset, const python::tuple PyMIx)
|
||||||
|
|
||||||
|
The first alternative introduces a new type that the user has to
|
||||||
|
deal with. Other modules using Miller indices might organize them in
|
||||||
|
different ways, for example to increase runtime efficiency for
|
||||||
|
important procedures. This means, the user has to know how to
|
||||||
|
convert between the different kinds of Miller index representations.
|
||||||
|
This can quickly become a nuisance. Relying on native Python data
|
||||||
|
structures minimizes the number of special types the user has to
|
||||||
|
learn and convert. Of course, this argument is only valid for
|
||||||
|
small and relatively simply classes.
|
||||||
|
|
||||||
|
If there are many member functions with MillerIndex arguments, the
|
||||||
|
second alternative is impractical, and concentrating the conversion
|
||||||
|
mechanism in one central place is essential for code
|
||||||
|
maintainability. An added benefit is that more convenient (smarter)
|
||||||
|
conversion functions can be provided without cluttering the rest of
|
||||||
|
the wrapper code.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// The helper class.
|
||||||
|
//
|
||||||
|
class MillerIndex {
|
||||||
|
public:
|
||||||
|
int v[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
// The main class. Imagine that there are MANY member functions
|
||||||
|
// like add() and get().
|
||||||
|
//
|
||||||
|
class IndexingSet {
|
||||||
|
private:
|
||||||
|
std::vector<MillerIndex> VMIx;
|
||||||
|
public:
|
||||||
|
void add(const MillerIndex& MIx) { VMIx.push_back(MIx); }
|
||||||
|
MillerIndex get(std::size_t i) const { return VMIx[i]; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
|
// Convert a Python tuple to a MillerIndex object.
|
||||||
|
//
|
||||||
|
MillerIndex from_python(PyObject* p, python::type<const MillerIndex&>)
|
||||||
|
{
|
||||||
|
python::tuple tup
|
||||||
|
= python::tuple(python::ref(p, python::ref::increment_count));
|
||||||
|
if (tup.size() != 3) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"expecting exactly 3 values in tuple.");
|
||||||
|
throw python::error_already_set();
|
||||||
|
}
|
||||||
|
MillerIndex result;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
result.v[i] = from_python(tup[i].get(), python::type<int>());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similar conversion for MillerIndex objects passed by value.
|
||||||
|
// Not actually used, but included to show the principle.
|
||||||
|
//
|
||||||
|
MillerIndex from_python(PyObject* p, python::type<MillerIndex>)
|
||||||
|
{
|
||||||
|
return from_python(p, python::type<const MillerIndex&>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a MillerIndex object to a Python tuple.
|
||||||
|
//
|
||||||
|
PyObject* to_python(const MillerIndex& hkl, python::lookup_tag)
|
||||||
|
{
|
||||||
|
python::tuple result(3);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
result.set_item(i, hkl.v[i]);
|
||||||
|
return result.reference().release();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(do_it_yourself_converters)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create an object representing this extension module.
|
||||||
|
python::module_builder this_module("do_it_yourself_converters");
|
||||||
|
|
||||||
|
// Create the Python type object for our extension class.
|
||||||
|
python::class_builder<IndexingSet> ixset_class(this_module, "IndexingSet");
|
||||||
|
|
||||||
|
// Add the __init__ function.
|
||||||
|
ixset_class.def(python::constructor<>());
|
||||||
|
// Add the member functions.
|
||||||
|
ixset_class.def(&IndexingSet::add, "add");
|
||||||
|
ixset_class.def(&IndexingSet::get, "get");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
45
example/dvect.cpp
Normal file
45
example/dvect.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
// See root/libs/python/doc/cross_module.html for an introduction.
|
||||||
|
|
||||||
|
#include "dvect.h"
|
||||||
|
#include "ivect.h"
|
||||||
|
#include <boost/python/cross_module.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
# include "dvect_conversions.cpp"
|
||||||
|
# include "ivect_conversions.cpp"
|
||||||
|
|
||||||
|
vects::ivect dvect_as_ivect(const vects::dvect& dv)
|
||||||
|
{
|
||||||
|
vects::ivect iv(dv.size());
|
||||||
|
vects::ivect::iterator iviter = iv.begin();
|
||||||
|
for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast<int>(dv[i]);
|
||||||
|
return iv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(dvect)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
python::module_builder this_module("dvect");
|
||||||
|
|
||||||
|
python::class_builder<vects::dvect> dvect_class(this_module, "dvect");
|
||||||
|
python::export_converters(dvect_class);
|
||||||
|
|
||||||
|
python::import_converters<vects::ivect> ivect_converters("ivect", "ivect");
|
||||||
|
|
||||||
|
dvect_class.def(python::constructor<python::tuple>());
|
||||||
|
dvect_class.def(&vects::dvect::as_tuple, "as_tuple");
|
||||||
|
dvect_class.def(dvect_as_ivect, "as_ivect");
|
||||||
|
|
||||||
|
# include "dvect_defs.cpp"
|
||||||
|
# include "ivect_defs.cpp"
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
30
example/dvect.h
Normal file
30
example/dvect.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef DVECT_H
|
||||||
|
#define DVECT_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
|
||||||
|
namespace vects {
|
||||||
|
|
||||||
|
struct dvect : public std::vector<double>
|
||||||
|
{
|
||||||
|
dvect() : std::vector<double>() {}
|
||||||
|
dvect(size_t n) : std::vector<double>(n) {}
|
||||||
|
dvect(boost::python::tuple tuple) : std::vector<double>(tuple.size())
|
||||||
|
{
|
||||||
|
std::vector<double>::iterator v_it = begin();
|
||||||
|
for (int i = 0; i < tuple.size(); i++)
|
||||||
|
v_it[i] = from_python(tuple[i].get(), boost::python::type<double>());
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::python::tuple as_tuple() const
|
||||||
|
{
|
||||||
|
boost::python::tuple t(size());
|
||||||
|
for (int i = 0; i < size(); i++)
|
||||||
|
t.set_item(i, (*this)[i]);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DVECT_H
|
||||||
51
example/dvect_conversions.cpp
Normal file
51
example/dvect_conversions.cpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// basics first: const reference converters
|
||||||
|
boost::python::tuple const_dvect_reference_as_tuple(const vects::dvect& dv)
|
||||||
|
{
|
||||||
|
return dv.as_tuple();
|
||||||
|
}
|
||||||
|
|
||||||
|
// to_python smart pointer conversions
|
||||||
|
std::auto_ptr<vects::dvect> dvect_as_auto_ptr(const vects::dvect& dv)
|
||||||
|
{
|
||||||
|
return std::auto_ptr<vects::dvect>(new vects::dvect(dv));
|
||||||
|
}
|
||||||
|
boost::shared_ptr<vects::dvect> dvect_as_shared_ptr(const vects::dvect& dv)
|
||||||
|
{
|
||||||
|
return boost::shared_ptr<vects::dvect>(new vects::dvect(dv));
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart pointers passed by value
|
||||||
|
boost::python::ref auto_ptr_value_dvect_as_tuple(std::auto_ptr<vects::dvect> dv)
|
||||||
|
{
|
||||||
|
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return dv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
boost::python::ref shared_ptr_value_dvect_as_tuple(boost::shared_ptr<vects::dvect> dv)
|
||||||
|
{
|
||||||
|
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return dv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart pointers passed by reference
|
||||||
|
boost::python::ref auto_ptr_reference_dvect_as_tuple(std::auto_ptr<vects::dvect>& dv)
|
||||||
|
{
|
||||||
|
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return dv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
boost::python::ref shared_ptr_reference_dvect_as_tuple(boost::shared_ptr<vects::dvect>& dv)
|
||||||
|
{
|
||||||
|
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return dv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart pointers passed by const reference
|
||||||
|
boost::python::ref auto_ptr_const_reference_dvect_as_tuple(const std::auto_ptr<vects::dvect>& dv)
|
||||||
|
{
|
||||||
|
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return dv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
boost::python::ref shared_ptr_const_reference_dvect_as_tuple(const boost::shared_ptr<vects::dvect>& dv)
|
||||||
|
{
|
||||||
|
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return dv->as_tuple().reference();
|
||||||
|
}
|
||||||
13
example/dvect_defs.cpp
Normal file
13
example/dvect_defs.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
this_module.def(dvect_as_auto_ptr, "dvect_as_auto_ptr");
|
||||||
|
this_module.def(dvect_as_shared_ptr, "dvect_as_shared_ptr");
|
||||||
|
|
||||||
|
this_module.def(const_dvect_reference_as_tuple, "const_dvect_reference_as_tuple");
|
||||||
|
|
||||||
|
this_module.def(auto_ptr_value_dvect_as_tuple, "auto_ptr_value_dvect_as_tuple");
|
||||||
|
this_module.def(shared_ptr_value_dvect_as_tuple, "shared_ptr_value_dvect_as_tuple");
|
||||||
|
|
||||||
|
this_module.def(auto_ptr_reference_dvect_as_tuple, "auto_ptr_reference_dvect_as_tuple");
|
||||||
|
this_module.def(shared_ptr_reference_dvect_as_tuple, "shared_ptr_reference_dvect_as_tuple");
|
||||||
|
|
||||||
|
this_module.def(auto_ptr_const_reference_dvect_as_tuple, "auto_ptr_const_reference_dvect_as_tuple");
|
||||||
|
this_module.def(shared_ptr_const_reference_dvect_as_tuple, "shared_ptr_const_reference_dvect_as_tuple");
|
||||||
32
example/getting_started1.cpp
Normal file
32
example/getting_started1.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A couple of simple C++ functions that we want to expose to Python.
|
||||||
|
std::string greet() { return "hello, world"; }
|
||||||
|
int square(int number) { return number * number; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
// Python requires an exported function called init<module-name> in every
|
||||||
|
// extension module. This is where we build the module contents.
|
||||||
|
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create an object representing this extension module.
|
||||||
|
python::module_builder this_module("getting_started1");
|
||||||
|
|
||||||
|
// Add regular functions to the module.
|
||||||
|
this_module.def(greet, "greet");
|
||||||
|
this_module.def(square, "square");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
52
example/getting_started2.cpp
Normal file
52
example/getting_started2.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A friendly class.
|
||||||
|
class hello
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
hello(const std::string& country) { this->country = country; }
|
||||||
|
std::string greet() const { return "Hello from " + country; }
|
||||||
|
private:
|
||||||
|
std::string country;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A function taking a hello object as an argument.
|
||||||
|
std::string invite(const hello& w) {
|
||||||
|
return w.greet() + "! Please come soon!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(getting_started2)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create an object representing this extension module.
|
||||||
|
python::module_builder this_module("getting_started2");
|
||||||
|
|
||||||
|
// Create the Python type object for our extension class.
|
||||||
|
python::class_builder<hello> hello_class(this_module, "hello");
|
||||||
|
|
||||||
|
// Add the __init__ function.
|
||||||
|
hello_class.def(python::constructor<std::string>());
|
||||||
|
// Add a regular member function.
|
||||||
|
hello_class.def(&hello::greet, "greet");
|
||||||
|
|
||||||
|
// Add invite() as a regular function to the module.
|
||||||
|
this_module.def(invite, "invite");
|
||||||
|
|
||||||
|
// Even better, invite() can also be made a member of hello_class!!!
|
||||||
|
hello_class.def(invite, "invite");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
45
example/ivect.cpp
Normal file
45
example/ivect.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
// See root/libs/python/doc/cross_module.html for an introduction.
|
||||||
|
|
||||||
|
#include "dvect.h"
|
||||||
|
#include "ivect.h"
|
||||||
|
#include <boost/python/cross_module.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
# include "dvect_conversions.cpp"
|
||||||
|
# include "ivect_conversions.cpp"
|
||||||
|
|
||||||
|
vects::dvect ivect_as_dvect(const vects::ivect& iv)
|
||||||
|
{
|
||||||
|
vects::dvect dv(iv.size());
|
||||||
|
vects::dvect::iterator dviter = dv.begin();
|
||||||
|
for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast<double>(iv[i]);
|
||||||
|
return dv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(ivect)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
python::module_builder this_module("ivect");
|
||||||
|
|
||||||
|
python::class_builder<vects::ivect> ivect_class(this_module, "ivect");
|
||||||
|
python::export_converters(ivect_class);
|
||||||
|
|
||||||
|
python::import_converters<vects::dvect> dvect_converters("dvect", "dvect");
|
||||||
|
|
||||||
|
ivect_class.def(python::constructor<python::tuple>());
|
||||||
|
ivect_class.def(&vects::ivect::as_tuple, "as_tuple");
|
||||||
|
ivect_class.def(ivect_as_dvect, "as_dvect");
|
||||||
|
|
||||||
|
# include "dvect_defs.cpp"
|
||||||
|
# include "ivect_defs.cpp"
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
30
example/ivect.h
Normal file
30
example/ivect.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef IVECT_H
|
||||||
|
#define IVECT_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
|
||||||
|
namespace vects {
|
||||||
|
|
||||||
|
struct ivect : public std::vector<int>
|
||||||
|
{
|
||||||
|
ivect() : std::vector<int>() {}
|
||||||
|
ivect(size_t n) : std::vector<int>(n) {}
|
||||||
|
ivect(boost::python::tuple tuple) : std::vector<int>(tuple.size())
|
||||||
|
{
|
||||||
|
std::vector<int>::iterator v_it = begin();
|
||||||
|
for (int i = 0; i < tuple.size(); i++)
|
||||||
|
v_it[i] = from_python(tuple[i].get(), boost::python::type<int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::python::tuple as_tuple() const
|
||||||
|
{
|
||||||
|
boost::python::tuple t(size());
|
||||||
|
for (int i = 0; i < size(); i++)
|
||||||
|
t.set_item(i, (*this)[i]);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IVECT_H
|
||||||
51
example/ivect_conversions.cpp
Normal file
51
example/ivect_conversions.cpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// basics first: const reference converters
|
||||||
|
boost::python::tuple const_ivect_reference_as_tuple(const vects::ivect& iv)
|
||||||
|
{
|
||||||
|
return iv.as_tuple();
|
||||||
|
}
|
||||||
|
|
||||||
|
// to_python smart pointer conversions
|
||||||
|
std::auto_ptr<vects::ivect> ivect_as_auto_ptr(const vects::ivect& iv)
|
||||||
|
{
|
||||||
|
return std::auto_ptr<vects::ivect>(new vects::ivect(iv));
|
||||||
|
}
|
||||||
|
boost::shared_ptr<vects::ivect> ivect_as_shared_ptr(const vects::ivect& iv)
|
||||||
|
{
|
||||||
|
return boost::shared_ptr<vects::ivect>(new vects::ivect(iv));
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart pointers passed by value
|
||||||
|
boost::python::ref auto_ptr_value_ivect_as_tuple(std::auto_ptr<vects::ivect> iv)
|
||||||
|
{
|
||||||
|
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return iv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
boost::python::ref shared_ptr_value_ivect_as_tuple(boost::shared_ptr<vects::ivect> iv)
|
||||||
|
{
|
||||||
|
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return iv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart pointers passed by reference
|
||||||
|
boost::python::ref auto_ptr_reference_ivect_as_tuple(std::auto_ptr<vects::ivect>& iv)
|
||||||
|
{
|
||||||
|
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return iv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
boost::python::ref shared_ptr_reference_ivect_as_tuple(boost::shared_ptr<vects::ivect>& iv)
|
||||||
|
{
|
||||||
|
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return iv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart pointers passed by const reference
|
||||||
|
boost::python::ref auto_ptr_const_reference_ivect_as_tuple(const std::auto_ptr<vects::ivect>& iv)
|
||||||
|
{
|
||||||
|
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return iv->as_tuple().reference();
|
||||||
|
}
|
||||||
|
boost::python::ref shared_ptr_const_reference_ivect_as_tuple(const boost::shared_ptr<vects::ivect>& iv)
|
||||||
|
{
|
||||||
|
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
||||||
|
return iv->as_tuple().reference();
|
||||||
|
}
|
||||||
13
example/ivect_defs.cpp
Normal file
13
example/ivect_defs.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
this_module.def(ivect_as_auto_ptr, "ivect_as_auto_ptr");
|
||||||
|
this_module.def(ivect_as_shared_ptr, "ivect_as_shared_ptr");
|
||||||
|
|
||||||
|
this_module.def(const_ivect_reference_as_tuple, "const_ivect_reference_as_tuple");
|
||||||
|
|
||||||
|
this_module.def(auto_ptr_value_ivect_as_tuple, "auto_ptr_value_ivect_as_tuple");
|
||||||
|
this_module.def(shared_ptr_value_ivect_as_tuple, "shared_ptr_value_ivect_as_tuple");
|
||||||
|
|
||||||
|
this_module.def(auto_ptr_reference_ivect_as_tuple, "auto_ptr_reference_ivect_as_tuple");
|
||||||
|
this_module.def(shared_ptr_reference_ivect_as_tuple, "shared_ptr_reference_ivect_as_tuple");
|
||||||
|
|
||||||
|
this_module.def(auto_ptr_const_reference_ivect_as_tuple, "auto_ptr_const_reference_ivect_as_tuple");
|
||||||
|
this_module.def(shared_ptr_const_reference_ivect_as_tuple, "shared_ptr_const_reference_ivect_as_tuple");
|
||||||
14
example/noncopyable.h
Normal file
14
example/noncopyable.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef NONCOPYABLE_H
|
||||||
|
#define NONCOPYABLE_H
|
||||||
|
|
||||||
|
class store
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
store(const store&) { } // Disable the copy constructor.
|
||||||
|
int number;
|
||||||
|
public:
|
||||||
|
store(const int i) : number(i) { }
|
||||||
|
int recall() const { return number; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NONCOPYABLE_H
|
||||||
25
example/noncopyable_export.cpp
Normal file
25
example/noncopyable_export.cpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
// See root/libs/python/doc/cross_module.html for an introduction.
|
||||||
|
|
||||||
|
#include <boost/python/cross_module.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
#include "noncopyable.h"
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(noncopyable_export)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
python::module_builder this_module("noncopyable_export");
|
||||||
|
|
||||||
|
python::class_builder<store> store_class(this_module, "store");
|
||||||
|
python::export_converters_noncopyable(store_class);
|
||||||
|
|
||||||
|
store_class.def(python::constructor<int>());
|
||||||
|
store_class.def(&store::recall, "recall");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
42
example/noncopyable_import.cpp
Normal file
42
example/noncopyable_import.cpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
// See root/libs/python/doc/cross_module.html for an introduction.
|
||||||
|
|
||||||
|
#include <boost/python/cross_module.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
#include "noncopyable.h"
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A function with store objects as both input and output parameters.
|
||||||
|
// Because the copy constructor is disabled, we cannot pass a store
|
||||||
|
// object by value. Instead, we pass a smart pointer.
|
||||||
|
std::auto_ptr<store> add_stores(const store& s1, const store& s2)
|
||||||
|
{
|
||||||
|
int sum = s1.recall() + s2.recall();
|
||||||
|
std::auto_ptr<store> ss = std::auto_ptr<store>(new store(sum));
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(noncopyable_import)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
python::module_builder this_module("noncopyable_import");
|
||||||
|
|
||||||
|
python::import_converters<store>
|
||||||
|
dvect_converters("noncopyable_export", "store");
|
||||||
|
|
||||||
|
// Imagine all the additional classes with member functions
|
||||||
|
// that have store objects as input and output parameters.
|
||||||
|
// Lots and lots of them.
|
||||||
|
// However, to keep this example simple, we only define a
|
||||||
|
// module-level function.
|
||||||
|
this_module.def(add_stores, "add_stores");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
64
example/pickle1.cpp
Normal file
64
example/pickle1.cpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
/*
|
||||||
|
This example shows how to make an Extension Class "pickleable".
|
||||||
|
|
||||||
|
The world class below can be fully restored by passing the
|
||||||
|
appropriate argument to the constructor. Therefore it is sufficient
|
||||||
|
to define the pickle interface method __getinitargs__.
|
||||||
|
|
||||||
|
For more information refer to boost/libs/python/doc/pickle.html.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A friendly class.
|
||||||
|
class world
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string country;
|
||||||
|
int secret_number;
|
||||||
|
public:
|
||||||
|
world(const std::string& country) : secret_number(0) {
|
||||||
|
this->country = country;
|
||||||
|
}
|
||||||
|
std::string greet() const { return "Hello from " + country + "!"; }
|
||||||
|
std::string get_country() const { return country; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Support for pickle.
|
||||||
|
python::ref world_getinitargs(const world& w) {
|
||||||
|
python::tuple result(1);
|
||||||
|
result.set_item(0, w.get_country());
|
||||||
|
return result.reference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(pickle1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create an object representing this extension module.
|
||||||
|
python::module_builder this_module("pickle1");
|
||||||
|
|
||||||
|
// Create the Python type object for our extension class.
|
||||||
|
python::class_builder<world> world_class(this_module, "world");
|
||||||
|
|
||||||
|
// Add the __init__ function.
|
||||||
|
world_class.def(python::constructor<std::string>());
|
||||||
|
// Add a regular member function.
|
||||||
|
world_class.def(&world::greet, "greet");
|
||||||
|
|
||||||
|
// Support for pickle.
|
||||||
|
world_class.def(world_getinitargs, "__getinitargs__");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
98
example/pickle2.cpp
Normal file
98
example/pickle2.cpp
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
/*
|
||||||
|
This example shows how to make an Extension Class "pickleable".
|
||||||
|
|
||||||
|
The world class below contains member data (secret_number) that
|
||||||
|
cannot be restored by any of the constructors. Therefore it is
|
||||||
|
necessary to provide the __getstate__/__setstate__ pair of pickle
|
||||||
|
interface methods.
|
||||||
|
|
||||||
|
For simplicity, the __dict__ is not included in the result of
|
||||||
|
__getstate__. This is not generally recommended, but a valid
|
||||||
|
approach if it is anticipated that the object's __dict__ will
|
||||||
|
always be empty. Note that safety guard are provided to catch the
|
||||||
|
cases where this assumption is not true.
|
||||||
|
|
||||||
|
pickle3.cpp shows how to include the object's __dict__ in the
|
||||||
|
result of __getstate__.
|
||||||
|
|
||||||
|
For more information refer to boost/libs/python/doc/pickle.html.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A friendly class.
|
||||||
|
class world
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
world(const std::string& country) : secret_number(0) {
|
||||||
|
this->country = country;
|
||||||
|
}
|
||||||
|
std::string greet() const { return "Hello from " + country + "!"; }
|
||||||
|
std::string get_country() const { return country; }
|
||||||
|
void set_secret_number(int number) { secret_number = number; }
|
||||||
|
int get_secret_number() const { return secret_number; }
|
||||||
|
private:
|
||||||
|
std::string country;
|
||||||
|
int secret_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Support for pickle.
|
||||||
|
|
||||||
|
python::ref world_getinitargs(const world& w) {
|
||||||
|
python::tuple result(1);
|
||||||
|
result.set_item(0, w.get_country());
|
||||||
|
return result.reference(); // returning the reference avoids the copying.
|
||||||
|
}
|
||||||
|
|
||||||
|
python::ref world_getstate(const world& w) {
|
||||||
|
python::tuple result(1);
|
||||||
|
result.set_item(0, w.get_secret_number());
|
||||||
|
return result.reference(); // returning the reference avoids the copying.
|
||||||
|
}
|
||||||
|
|
||||||
|
void world_setstate(world& w, python::tuple state) {
|
||||||
|
if (state.size() != 1) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"Unexpected argument in call to __setstate__.");
|
||||||
|
throw python::error_already_set();
|
||||||
|
}
|
||||||
|
int number = from_python(state[0].get(), python::type<int>());
|
||||||
|
if (number != 42)
|
||||||
|
w.set_secret_number(number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(pickle2)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create an object representing this extension module.
|
||||||
|
python::module_builder this_module("pickle2");
|
||||||
|
|
||||||
|
// Create the Python type object for our extension class.
|
||||||
|
python::class_builder<world> world_class(this_module, "world");
|
||||||
|
|
||||||
|
// Add the __init__ function.
|
||||||
|
world_class.def(python::constructor<std::string>());
|
||||||
|
// Add a regular member function.
|
||||||
|
world_class.def(&world::greet, "greet");
|
||||||
|
world_class.def(&world::get_secret_number, "get_secret_number");
|
||||||
|
world_class.def(&world::set_secret_number, "set_secret_number");
|
||||||
|
|
||||||
|
// Support for pickle.
|
||||||
|
world_class.def(world_getinitargs, "__getinitargs__");
|
||||||
|
world_class.def(world_getstate, "__getstate__");
|
||||||
|
world_class.def(world_setstate, "__setstate__");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
149
example/pickle3.cpp
Normal file
149
example/pickle3.cpp
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
/*
|
||||||
|
This example shows how to make an Extension Class "pickleable".
|
||||||
|
|
||||||
|
The world class below contains member data (secret_number) that
|
||||||
|
cannot be restored by any of the constructors. Therefore it is
|
||||||
|
necessary to provide the __getstate__/__setstate__ pair of pickle
|
||||||
|
interface methods.
|
||||||
|
|
||||||
|
The object's __dict__ is included in the result of __getstate__.
|
||||||
|
This requires more code (compare with pickle2.cpp), but is
|
||||||
|
unavoidable if the object's __dict__ is not always empty.
|
||||||
|
|
||||||
|
For more information refer to boost/libs/python/doc/pickle.html.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
namespace boost { namespace python {
|
||||||
|
|
||||||
|
ref getattr(PyObject* o, const std::string& attr_name) {
|
||||||
|
return ref(PyObject_GetAttrString(o, const_cast<char*>(attr_name.c_str())));
|
||||||
|
}
|
||||||
|
ref getattr(const ref& r, const std::string& attr_name) {
|
||||||
|
return getattr(r.get(), attr_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A friendly class.
|
||||||
|
class world
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
world(const std::string& country) : secret_number(0) {
|
||||||
|
this->country = country;
|
||||||
|
}
|
||||||
|
std::string greet() const { return "Hello from " + country + "!"; }
|
||||||
|
std::string get_country() const { return country; }
|
||||||
|
void set_secret_number(int number) { secret_number = number; }
|
||||||
|
int get_secret_number() const { return secret_number; }
|
||||||
|
private:
|
||||||
|
std::string country;
|
||||||
|
int secret_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Support for pickle.
|
||||||
|
python::ref world_getinitargs(const world& w) {
|
||||||
|
python::tuple result(1);
|
||||||
|
result.set_item(0, w.get_country());
|
||||||
|
return result.reference(); // returning the reference avoids the copying.
|
||||||
|
}
|
||||||
|
|
||||||
|
python::ref world_getstate(python::tuple const & args,
|
||||||
|
python::dictionary const & keywords);
|
||||||
|
|
||||||
|
PyObject* world_setstate(python::tuple const & args,
|
||||||
|
python::dictionary const & keywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(pickle3)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create an object representing this extension module.
|
||||||
|
python::module_builder this_module("pickle3");
|
||||||
|
|
||||||
|
// Create the Python type object for our extension class.
|
||||||
|
python::class_builder<world> world_class(this_module, "world");
|
||||||
|
|
||||||
|
// Add the __init__ function.
|
||||||
|
world_class.def(python::constructor<std::string>());
|
||||||
|
// Add a regular member function.
|
||||||
|
world_class.def(&world::greet, "greet");
|
||||||
|
world_class.def(&world::get_secret_number, "get_secret_number");
|
||||||
|
world_class.def(&world::set_secret_number, "set_secret_number");
|
||||||
|
|
||||||
|
// Support for pickle.
|
||||||
|
world_class.def(world_getinitargs, "__getinitargs__");
|
||||||
|
world_class.def_raw(world_getstate, "__getstate__");
|
||||||
|
world_class.def_raw(world_setstate, "__setstate__");
|
||||||
|
world_class.getstate_manages_dict();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using boost::python::type;
|
||||||
|
using boost::python::ref;
|
||||||
|
using boost::python::tuple;
|
||||||
|
using boost::python::list;
|
||||||
|
using boost::python::dictionary;
|
||||||
|
using boost::python::getattr;
|
||||||
|
|
||||||
|
ref world_getstate(tuple const & args, dictionary const & keywords)
|
||||||
|
{
|
||||||
|
if(args.size() != 1 || keywords.size() != 0) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
|
||||||
|
throw boost::python::argument_error();
|
||||||
|
}
|
||||||
|
const world& w = from_python(args[0].get(), type<const world&>());
|
||||||
|
ref mydict = getattr(args[0], "__dict__");
|
||||||
|
tuple result(2);
|
||||||
|
// store the object's __dict__
|
||||||
|
result.set_item(0, mydict);
|
||||||
|
// store the internal state of the C++ object
|
||||||
|
result.set_item(1, w.get_secret_number());
|
||||||
|
return result.reference(); // returning the reference avoids the copying.
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* world_setstate(tuple const & args, dictionary const & keywords)
|
||||||
|
{
|
||||||
|
if(args.size() != 2 || keywords.size() != 0) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
|
||||||
|
throw boost::python::argument_error();
|
||||||
|
}
|
||||||
|
world& w = from_python(args[0].get(), type<world&>());
|
||||||
|
ref mydict = getattr(args[0], "__dict__");
|
||||||
|
tuple state = from_python(args[1].get(), type<tuple>());
|
||||||
|
if (state.size() != 2) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"Unexpected argument in call to __setstate__.");
|
||||||
|
throw python::error_already_set();
|
||||||
|
}
|
||||||
|
// restore the object's __dict__
|
||||||
|
dictionary odict = from_python(mydict.get(), type<dictionary>());
|
||||||
|
const dictionary& pdict = from_python(state[0].get(), type<const dictionary&>());
|
||||||
|
list pkeys(pdict.keys());
|
||||||
|
for (int i = 0; i < pkeys.size(); i++) {
|
||||||
|
ref k(pkeys[i]);
|
||||||
|
//odict[k] = pdict[k]; // XXX memory leak!
|
||||||
|
odict[k] = pdict.get_item(k); // this does not leak.
|
||||||
|
}
|
||||||
|
// restore the internal state of the C++ object
|
||||||
|
int number = from_python(state[1].get(), type<int>());
|
||||||
|
if (number != 42)
|
||||||
|
w.set_secret_number(number);
|
||||||
|
return python::detail::none();
|
||||||
|
}
|
||||||
|
}
|
||||||
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
|
||||||
110
example/simple_vector.cpp
Normal file
110
example/simple_vector.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Example by Ralf W. Grosse-Kunstleve
|
||||||
|
|
||||||
|
#include <boost/python/class_builder.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
|
||||||
|
namespace { // Avoid cluttering the global namespace.
|
||||||
|
|
||||||
|
// A wrapper is used to define additional constructors.
|
||||||
|
//
|
||||||
|
struct vector_double_wrapper: std::vector<double>
|
||||||
|
{
|
||||||
|
// Tell the compiler how to convert a base class object to
|
||||||
|
// this wrapper object.
|
||||||
|
vector_double_wrapper(PyObject*, const std::vector<double>& vd)
|
||||||
|
: std::vector<double>(vd) {}
|
||||||
|
|
||||||
|
vector_double_wrapper(PyObject* self)
|
||||||
|
: std::vector<double>() {}
|
||||||
|
|
||||||
|
vector_double_wrapper(PyObject* self, int n)
|
||||||
|
: std::vector<double>(n) {}
|
||||||
|
|
||||||
|
vector_double_wrapper(PyObject* self, python::tuple tuple)
|
||||||
|
: std::vector<double>(tuple.size())
|
||||||
|
{
|
||||||
|
std::vector<double>::iterator vd = begin();
|
||||||
|
for (int i = 0; i < tuple.size(); i++)
|
||||||
|
vd[i] = from_python(tuple[i].get(), python::type<double>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void raise_vector_IndexError() {
|
||||||
|
PyErr_SetString(PyExc_IndexError, "vector index out of range");
|
||||||
|
throw python::error_already_set();
|
||||||
|
}
|
||||||
|
|
||||||
|
double getitem(const std::vector<double>& vd, std::size_t key) {
|
||||||
|
if (key >= vd.size()) raise_vector_IndexError();
|
||||||
|
return vd[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setitem(std::vector<double>& vd, std::size_t key, double d) {
|
||||||
|
if (key >= vd.size()) raise_vector_IndexError();
|
||||||
|
std::vector<double>::iterator vditer = vd.begin();
|
||||||
|
vditer[key] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delitem(std::vector<double>& vd, std::size_t key) {
|
||||||
|
if (key >= vd.size()) raise_vector_IndexError();
|
||||||
|
std::vector<double>::iterator vditer = vd.begin();
|
||||||
|
vd.erase(vditer + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert vector_double to a regular Python tuple.
|
||||||
|
//
|
||||||
|
python::tuple as_tuple(const std::vector<double>& vd)
|
||||||
|
{
|
||||||
|
python::tuple t(vd.size());
|
||||||
|
for (int i = 0; i < vd.size(); i++)
|
||||||
|
t.set_item(i, vd[i]);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function returning a vector_double object to Python.
|
||||||
|
//
|
||||||
|
std::vector<double> foo(int n)
|
||||||
|
{
|
||||||
|
std::vector<double> vd(n);
|
||||||
|
std::vector<double>::iterator vditer = vd.begin();
|
||||||
|
for (int i = 0; i < n; i++) vditer[i] = double(i);
|
||||||
|
return vd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as foo(), but avoid copying on return.
|
||||||
|
//
|
||||||
|
std::auto_ptr<std::vector<double> > bar(int n)
|
||||||
|
{
|
||||||
|
std::auto_ptr<std::vector<double> > vdptr(new std::vector<double>(n));
|
||||||
|
std::vector<double>::iterator vditer = vdptr->begin();
|
||||||
|
for (int i = 0; i < n; i++) vditer[i] = double(10 * i);
|
||||||
|
return vdptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE_INIT(simple_vector)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
python::module_builder this_module("simple_vector");
|
||||||
|
|
||||||
|
python::class_builder<std::vector<double>, vector_double_wrapper>
|
||||||
|
vector_double(this_module, "vector_double");
|
||||||
|
|
||||||
|
vector_double.def(python::constructor<>());
|
||||||
|
vector_double.def(python::constructor<const int>());
|
||||||
|
vector_double.def(python::constructor<python::tuple>());
|
||||||
|
vector_double.def(&std::vector<double>::size, "__len__");
|
||||||
|
vector_double.def(getitem, "__getitem__");
|
||||||
|
vector_double.def(setitem, "__setitem__");
|
||||||
|
vector_double.def(delitem, "__delitem__");
|
||||||
|
vector_double.def(as_tuple, "as_tuple");
|
||||||
|
|
||||||
|
this_module.def(foo, "foo");
|
||||||
|
this_module.def(bar, "bar");
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
python::handle_exception(); // Deal with the exception for Python
|
||||||
|
}
|
||||||
|
}
|
||||||
23
example/test_abstract.py
Normal file
23
example/test_abstract.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Example by Ullrich Koethe
|
||||||
|
r'''>>> from abstract import *
|
||||||
|
>>> class A(Abstract):
|
||||||
|
... def __init__(self, text):
|
||||||
|
... Abstract.__init__(self) # call the base class constructor
|
||||||
|
... self.text = text
|
||||||
|
... def test(self): # implement abstract function
|
||||||
|
... return self.text
|
||||||
|
...
|
||||||
|
>>> a = A("Hello")
|
||||||
|
>>> a.test()
|
||||||
|
'Hello'
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_abstract
|
||||||
|
doctest.testmod(test_abstract)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
139
example/test_cross_module.py
Normal file
139
example/test_cross_module.py
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
r'''>>> import tst_noncopyable
|
||||||
|
>>> tst_noncopyable.f()
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
>>> import tst_dvect1
|
||||||
|
>>> tst_dvect1.f()
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
>>> import tst_ivect1
|
||||||
|
>>> tst_ivect1.f()
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
>>> import sys
|
||||||
|
>>> if ("--broken-auto-ptr" in sys.argv):
|
||||||
|
... broken_auto_ptr = 1
|
||||||
|
... else:
|
||||||
|
... broken_auto_ptr = 0
|
||||||
|
>>> import tst_dvect2
|
||||||
|
>>> tst_dvect2.f(broken_auto_ptr)
|
||||||
|
1. auto_ptr_value_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. auto_ptr_value_ivect_as_tuple
|
||||||
|
None
|
||||||
|
1. auto_ptr_value_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. auto_ptr_value_dvect_as_tuple
|
||||||
|
None
|
||||||
|
1. shared_ptr_value_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. shared_ptr_value_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. shared_ptr_value_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. shared_ptr_value_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. auto_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. auto_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. auto_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. auto_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. shared_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. shared_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. shared_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. shared_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. auto_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. auto_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. auto_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. auto_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. shared_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. shared_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. shared_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. shared_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
>>> import tst_ivect2
|
||||||
|
>>> tst_ivect2.f(broken_auto_ptr)
|
||||||
|
1. auto_ptr_value_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. auto_ptr_value_dvect_as_tuple
|
||||||
|
None
|
||||||
|
1. auto_ptr_value_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. auto_ptr_value_ivect_as_tuple
|
||||||
|
None
|
||||||
|
1. shared_ptr_value_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. shared_ptr_value_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. shared_ptr_value_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. shared_ptr_value_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. auto_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. auto_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. auto_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. auto_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. shared_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. shared_ptr_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. shared_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. shared_ptr_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. auto_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. auto_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. auto_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. auto_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
1. shared_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
2. shared_ptr_const_reference_dvect_as_tuple
|
||||||
|
(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
1. shared_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
2. shared_ptr_const_reference_ivect_as_tuple
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_cross_module
|
||||||
|
doctest.testmod(test_cross_module)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
22
example/test_do_it_yourself_converters.py
Normal file
22
example/test_do_it_yourself_converters.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
r'''>>> import do_it_yourself_converters
|
||||||
|
>>> ixset = do_it_yourself_converters.IndexingSet()
|
||||||
|
>>> ixset.add((1,2,3))
|
||||||
|
>>> ixset.add((4,5,6))
|
||||||
|
>>> ixset.add((7,8,9))
|
||||||
|
>>> print ixset.get(0)
|
||||||
|
(1, 2, 3)
|
||||||
|
>>> print ixset.get(1)
|
||||||
|
(4, 5, 6)
|
||||||
|
>>> print ixset.get(2)
|
||||||
|
(7, 8, 9)
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_do_it_yourself_converters
|
||||||
|
doctest.testmod(test_do_it_yourself_converters)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
17
example/test_getting_started1.py
Normal file
17
example/test_getting_started1.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
r'''>>> import getting_started1
|
||||||
|
>>> print getting_started1.greet()
|
||||||
|
hello, world
|
||||||
|
>>> number = 11
|
||||||
|
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||||
|
11 * 11 = 121
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_getting_started1
|
||||||
|
doctest.testmod(test_getting_started1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
29
example/test_getting_started2.py
Normal file
29
example/test_getting_started2.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
r'''>>> from getting_started2 import *
|
||||||
|
>>> hi = hello('California')
|
||||||
|
>>> hi.greet()
|
||||||
|
'Hello from California'
|
||||||
|
>>> invite(hi)
|
||||||
|
'Hello from California! Please come soon!'
|
||||||
|
>>> hi.invite()
|
||||||
|
'Hello from California! Please come soon!'
|
||||||
|
|
||||||
|
>>> class wordy(hello):
|
||||||
|
... def greet(self):
|
||||||
|
... return hello.greet(self) + ', where the weather is fine'
|
||||||
|
...
|
||||||
|
>>> hi2 = wordy('Florida')
|
||||||
|
>>> hi2.greet()
|
||||||
|
'Hello from Florida, where the weather is fine'
|
||||||
|
>>> invite(hi2)
|
||||||
|
'Hello from Florida! Please come soon!'
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_getting_started2
|
||||||
|
doctest.testmod(test_getting_started2)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
31
example/test_pickle1.py
Normal file
31
example/test_pickle1.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
r'''>>> import pickle1
|
||||||
|
>>> import re
|
||||||
|
>>> import pickle
|
||||||
|
>>> pickle1.world.__module__
|
||||||
|
'pickle1'
|
||||||
|
>>> pickle1.world.__safe_for_unpickling__
|
||||||
|
1
|
||||||
|
>>> pickle1.world.__reduce__()
|
||||||
|
'world'
|
||||||
|
>>> assert re.match(
|
||||||
|
... "\(<extension class pickle1.world at [0-9a-fA-FxX]+>, \('Hello',\)\)",
|
||||||
|
... repr(pickle1.world('Hello').__reduce__()))
|
||||||
|
>>>
|
||||||
|
>>> wd = pickle1.world('California')
|
||||||
|
>>> pstr = pickle.dumps(wd)
|
||||||
|
>>> wl = pickle.loads(pstr)
|
||||||
|
>>> print wd.greet()
|
||||||
|
Hello from California!
|
||||||
|
>>> print wl.greet()
|
||||||
|
Hello from California!
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_pickle1
|
||||||
|
doctest.testmod(test_pickle1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
45
example/test_pickle2.py
Normal file
45
example/test_pickle2.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
r'''>>> import pickle2
|
||||||
|
>>> import re
|
||||||
|
>>> import pickle
|
||||||
|
>>> pickle2.world.__module__
|
||||||
|
'pickle2'
|
||||||
|
>>> pickle2.world.__safe_for_unpickling__
|
||||||
|
1
|
||||||
|
>>> pickle2.world.__reduce__()
|
||||||
|
'world'
|
||||||
|
>>> assert re.match(
|
||||||
|
... "\(<extension class pickle2.world at [0-9a-fA-FxX]+>, \('Hello',\), \(0,\)\)",
|
||||||
|
... repr(pickle2.world('Hello').__reduce__()))
|
||||||
|
>>>
|
||||||
|
>>> for number in (24, 42):
|
||||||
|
... wd = pickle2.world('California')
|
||||||
|
... wd.set_secret_number(number)
|
||||||
|
... pstr = pickle.dumps(wd)
|
||||||
|
... wl = pickle.loads(pstr)
|
||||||
|
... print wd.greet(), wd.get_secret_number()
|
||||||
|
... print wl.greet(), wl.get_secret_number()
|
||||||
|
Hello from California! 24
|
||||||
|
Hello from California! 24
|
||||||
|
Hello from California! 42
|
||||||
|
Hello from California! 0
|
||||||
|
|
||||||
|
# Now show that the __dict__ is not taken care of.
|
||||||
|
>>> wd = pickle2.world('California')
|
||||||
|
>>> wd.x = 1
|
||||||
|
>>> wd.__dict__
|
||||||
|
{'x': 1}
|
||||||
|
>>> try: pstr = pickle.dumps(wd)
|
||||||
|
... except RuntimeError, err: print err[0]
|
||||||
|
...
|
||||||
|
Incomplete pickle support (__getstate_manages_dict__ not set)
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_pickle2
|
||||||
|
doctest.testmod(test_pickle2)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
38
example/test_pickle3.py
Normal file
38
example/test_pickle3.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
r'''>>> import pickle3
|
||||||
|
>>> import re
|
||||||
|
>>> import pickle
|
||||||
|
>>> pickle3.world.__module__
|
||||||
|
'pickle3'
|
||||||
|
>>> pickle3.world.__safe_for_unpickling__
|
||||||
|
1
|
||||||
|
>>> pickle3.world.__reduce__()
|
||||||
|
'world'
|
||||||
|
>>> assert re.match(
|
||||||
|
... "\(<extension class pickle3.world at [0-9a-fA-FxX]+>, \('Hello',\), \(\{\}, 0\)\)",
|
||||||
|
... repr(pickle3.world('Hello').__reduce__()))
|
||||||
|
>>>
|
||||||
|
>>> for number in (24, 42):
|
||||||
|
... wd = pickle3.world('California')
|
||||||
|
... wd.set_secret_number(number)
|
||||||
|
... wd.x = 2 * number
|
||||||
|
... wd.y = 'y' * number
|
||||||
|
... wd.z = 3. * number
|
||||||
|
... pstr = pickle.dumps(wd)
|
||||||
|
... wl = pickle.loads(pstr)
|
||||||
|
... print wd.greet(), wd.get_secret_number(), wd.__dict__
|
||||||
|
... print wl.greet(), wl.get_secret_number(), wl.__dict__
|
||||||
|
Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||||
|
Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||||
|
Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||||
|
Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'}
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_pickle3
|
||||||
|
doctest.testmod(test_pickle3)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
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()
|
||||||
40
example/test_simple_vector.py
Normal file
40
example/test_simple_vector.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
r'''>>> import simple_vector
|
||||||
|
>>> v=simple_vector.vector_double()
|
||||||
|
>>> print v.as_tuple()
|
||||||
|
()
|
||||||
|
>>> v=simple_vector.vector_double(5)
|
||||||
|
>>> print v.as_tuple()
|
||||||
|
(0.0, 0.0, 0.0, 0.0, 0.0)
|
||||||
|
>>> print len(v)
|
||||||
|
5
|
||||||
|
>>> v=simple_vector.vector_double((3,4,5))
|
||||||
|
>>> print v.as_tuple()
|
||||||
|
(3.0, 4.0, 5.0)
|
||||||
|
>>> print v[1]
|
||||||
|
4.0
|
||||||
|
>>> v[1] = 40
|
||||||
|
>>> print v.as_tuple()
|
||||||
|
(3.0, 40.0, 5.0)
|
||||||
|
>>> for e in v:
|
||||||
|
... print e
|
||||||
|
3.0
|
||||||
|
40.0
|
||||||
|
5.0
|
||||||
|
>>> del v[1]
|
||||||
|
>>> print v.as_tuple()
|
||||||
|
(3.0, 5.0)
|
||||||
|
>>> print simple_vector.foo(11).as_tuple()
|
||||||
|
(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
|
||||||
|
>>> print simple_vector.bar(12).as_tuple()
|
||||||
|
(0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0)
|
||||||
|
'''
|
||||||
|
|
||||||
|
def run(args = None):
|
||||||
|
if args is not None:
|
||||||
|
import sys
|
||||||
|
sys.argv = args
|
||||||
|
import doctest, test_simple_vector
|
||||||
|
doctest.testmod(test_simple_vector)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
20
example/tst_dvect1.py
Normal file
20
example/tst_dvect1.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
def f():
|
||||||
|
import dvect
|
||||||
|
dv = dvect.dvect((1,2,3,4,5))
|
||||||
|
print dv.as_tuple()
|
||||||
|
iv = dv.as_ivect()
|
||||||
|
print iv.as_tuple()
|
||||||
|
print dvect.const_ivect_reference_as_tuple(iv)
|
||||||
|
aiv = dvect.ivect_as_auto_ptr(iv)
|
||||||
|
print dvect.const_ivect_reference_as_tuple(aiv)
|
||||||
|
siv = dvect.ivect_as_shared_ptr(iv)
|
||||||
|
print dvect.const_ivect_reference_as_tuple(siv)
|
||||||
|
print aiv.as_tuple()
|
||||||
|
print siv.as_tuple()
|
||||||
|
|
||||||
|
if (__name__ == "__main__"):
|
||||||
|
import sys, string
|
||||||
|
n = 1
|
||||||
|
if (len(sys.argv) > 1): n = string.atoi(sys.argv[1])
|
||||||
|
for i in xrange(n):
|
||||||
|
f()
|
||||||
98
example/tst_dvect2.py
Normal file
98
example/tst_dvect2.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
def f(broken_auto_ptr):
|
||||||
|
import dvect
|
||||||
|
import ivect
|
||||||
|
#
|
||||||
|
dv = dvect.dvect((1,2,3,4,5))
|
||||||
|
iv = dv.as_ivect()
|
||||||
|
#
|
||||||
|
aiv = dvect.ivect_as_auto_ptr(iv)
|
||||||
|
print '1. auto_ptr_value_ivect_as_tuple'
|
||||||
|
print ivect.auto_ptr_value_ivect_as_tuple(aiv)
|
||||||
|
print '2. auto_ptr_value_ivect_as_tuple'
|
||||||
|
if (not broken_auto_ptr):
|
||||||
|
print ivect.auto_ptr_value_ivect_as_tuple(aiv)
|
||||||
|
else:
|
||||||
|
print None
|
||||||
|
#
|
||||||
|
adv = dvect.dvect_as_auto_ptr(dv)
|
||||||
|
print '1. auto_ptr_value_dvect_as_tuple'
|
||||||
|
print ivect.auto_ptr_value_dvect_as_tuple(adv)
|
||||||
|
print '2. auto_ptr_value_dvect_as_tuple'
|
||||||
|
if (not broken_auto_ptr):
|
||||||
|
print ivect.auto_ptr_value_dvect_as_tuple(adv)
|
||||||
|
else:
|
||||||
|
print None
|
||||||
|
#
|
||||||
|
siv = dvect.ivect_as_shared_ptr(iv)
|
||||||
|
print '1. shared_ptr_value_ivect_as_tuple'
|
||||||
|
print ivect.shared_ptr_value_ivect_as_tuple(siv)
|
||||||
|
print '2. shared_ptr_value_ivect_as_tuple'
|
||||||
|
print ivect.shared_ptr_value_ivect_as_tuple(siv)
|
||||||
|
#
|
||||||
|
sdv = dvect.dvect_as_shared_ptr(dv)
|
||||||
|
print '1. shared_ptr_value_dvect_as_tuple'
|
||||||
|
print ivect.shared_ptr_value_dvect_as_tuple(sdv)
|
||||||
|
print '2. shared_ptr_value_dvect_as_tuple'
|
||||||
|
print ivect.shared_ptr_value_dvect_as_tuple(sdv)
|
||||||
|
#
|
||||||
|
aiv = dvect.ivect_as_auto_ptr(iv)
|
||||||
|
print '1. auto_ptr_reference_ivect_as_tuple'
|
||||||
|
print ivect.auto_ptr_reference_ivect_as_tuple(aiv)
|
||||||
|
print '2. auto_ptr_reference_ivect_as_tuple'
|
||||||
|
print ivect.auto_ptr_reference_ivect_as_tuple(aiv)
|
||||||
|
#
|
||||||
|
adv = dvect.dvect_as_auto_ptr(dv)
|
||||||
|
print '1. auto_ptr_reference_dvect_as_tuple'
|
||||||
|
print ivect.auto_ptr_reference_dvect_as_tuple(adv)
|
||||||
|
print '2. auto_ptr_reference_dvect_as_tuple'
|
||||||
|
print ivect.auto_ptr_reference_dvect_as_tuple(adv)
|
||||||
|
#
|
||||||
|
siv = dvect.ivect_as_shared_ptr(iv)
|
||||||
|
print '1. shared_ptr_reference_ivect_as_tuple'
|
||||||
|
print ivect.shared_ptr_reference_ivect_as_tuple(siv)
|
||||||
|
print '2. shared_ptr_reference_ivect_as_tuple'
|
||||||
|
print ivect.shared_ptr_reference_ivect_as_tuple(siv)
|
||||||
|
#
|
||||||
|
sdv = dvect.dvect_as_shared_ptr(dv)
|
||||||
|
print '1. shared_ptr_reference_dvect_as_tuple'
|
||||||
|
print ivect.shared_ptr_reference_dvect_as_tuple(sdv)
|
||||||
|
print '2. shared_ptr_reference_dvect_as_tuple'
|
||||||
|
print ivect.shared_ptr_reference_dvect_as_tuple(sdv)
|
||||||
|
#
|
||||||
|
aiv = dvect.ivect_as_auto_ptr(iv)
|
||||||
|
print '1. auto_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv)
|
||||||
|
print '2. auto_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv)
|
||||||
|
#
|
||||||
|
adv = dvect.dvect_as_auto_ptr(dv)
|
||||||
|
print '1. auto_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print ivect.auto_ptr_const_reference_dvect_as_tuple(adv)
|
||||||
|
print '2. auto_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print ivect.auto_ptr_const_reference_dvect_as_tuple(adv)
|
||||||
|
#
|
||||||
|
siv = dvect.ivect_as_shared_ptr(iv)
|
||||||
|
print '1. shared_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print ivect.shared_ptr_const_reference_ivect_as_tuple(siv)
|
||||||
|
print '2. shared_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print ivect.shared_ptr_const_reference_ivect_as_tuple(siv)
|
||||||
|
#
|
||||||
|
sdv = dvect.dvect_as_shared_ptr(dv)
|
||||||
|
print '1. shared_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv)
|
||||||
|
print '2. shared_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv)
|
||||||
|
|
||||||
|
if (__name__ == "__main__"):
|
||||||
|
import sys, string
|
||||||
|
broken_auto_ptr = 0
|
||||||
|
n = 1
|
||||||
|
if (len(sys.argv) > 1):
|
||||||
|
if (sys.argv[1] == "--broken-auto-ptr"):
|
||||||
|
broken_auto_ptr = 1
|
||||||
|
if (len(sys.argv) > 2):
|
||||||
|
n = string.atoi(sys.argv[2])
|
||||||
|
else:
|
||||||
|
n = string.atoi(sys.argv[1])
|
||||||
|
for i in xrange(n):
|
||||||
|
f(broken_auto_ptr)
|
||||||
20
example/tst_ivect1.py
Normal file
20
example/tst_ivect1.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
def f():
|
||||||
|
import ivect
|
||||||
|
iv = ivect.ivect((1,2,3,4,5))
|
||||||
|
print iv.as_tuple()
|
||||||
|
dv = iv.as_dvect()
|
||||||
|
print dv.as_tuple()
|
||||||
|
print ivect.const_dvect_reference_as_tuple(dv)
|
||||||
|
adv = ivect.dvect_as_auto_ptr(dv)
|
||||||
|
print ivect.const_dvect_reference_as_tuple(adv)
|
||||||
|
sdv = ivect.dvect_as_shared_ptr(dv)
|
||||||
|
print ivect.const_dvect_reference_as_tuple(sdv)
|
||||||
|
print adv.as_tuple()
|
||||||
|
print sdv.as_tuple()
|
||||||
|
|
||||||
|
if (__name__ == "__main__"):
|
||||||
|
import sys, string
|
||||||
|
n = 1
|
||||||
|
if (len(sys.argv) > 1): n = string.atoi(sys.argv[1])
|
||||||
|
for i in xrange(n):
|
||||||
|
f()
|
||||||
98
example/tst_ivect2.py
Normal file
98
example/tst_ivect2.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
def f(broken_auto_ptr):
|
||||||
|
import ivect
|
||||||
|
import dvect
|
||||||
|
#
|
||||||
|
iv = ivect.ivect((1,2,3,4,5))
|
||||||
|
dv = iv.as_dvect()
|
||||||
|
#
|
||||||
|
adv = ivect.dvect_as_auto_ptr(dv)
|
||||||
|
print '1. auto_ptr_value_dvect_as_tuple'
|
||||||
|
print dvect.auto_ptr_value_dvect_as_tuple(adv)
|
||||||
|
print '2. auto_ptr_value_dvect_as_tuple'
|
||||||
|
if (not broken_auto_ptr):
|
||||||
|
print dvect.auto_ptr_value_dvect_as_tuple(adv)
|
||||||
|
else:
|
||||||
|
print None
|
||||||
|
#
|
||||||
|
aiv = ivect.ivect_as_auto_ptr(iv)
|
||||||
|
print '1. auto_ptr_value_ivect_as_tuple'
|
||||||
|
print dvect.auto_ptr_value_ivect_as_tuple(aiv)
|
||||||
|
print '2. auto_ptr_value_ivect_as_tuple'
|
||||||
|
if (not broken_auto_ptr):
|
||||||
|
print dvect.auto_ptr_value_ivect_as_tuple(aiv)
|
||||||
|
else:
|
||||||
|
print None
|
||||||
|
#
|
||||||
|
sdv = ivect.dvect_as_shared_ptr(dv)
|
||||||
|
print '1. shared_ptr_value_dvect_as_tuple'
|
||||||
|
print dvect.shared_ptr_value_dvect_as_tuple(sdv)
|
||||||
|
print '2. shared_ptr_value_dvect_as_tuple'
|
||||||
|
print dvect.shared_ptr_value_dvect_as_tuple(sdv)
|
||||||
|
#
|
||||||
|
siv = ivect.ivect_as_shared_ptr(iv)
|
||||||
|
print '1. shared_ptr_value_ivect_as_tuple'
|
||||||
|
print dvect.shared_ptr_value_ivect_as_tuple(siv)
|
||||||
|
print '2. shared_ptr_value_ivect_as_tuple'
|
||||||
|
print dvect.shared_ptr_value_ivect_as_tuple(siv)
|
||||||
|
#
|
||||||
|
adv = ivect.dvect_as_auto_ptr(dv)
|
||||||
|
print '1. auto_ptr_reference_dvect_as_tuple'
|
||||||
|
print dvect.auto_ptr_reference_dvect_as_tuple(adv)
|
||||||
|
print '2. auto_ptr_reference_dvect_as_tuple'
|
||||||
|
print dvect.auto_ptr_reference_dvect_as_tuple(adv)
|
||||||
|
#
|
||||||
|
aiv = ivect.ivect_as_auto_ptr(iv)
|
||||||
|
print '1. auto_ptr_reference_ivect_as_tuple'
|
||||||
|
print dvect.auto_ptr_reference_ivect_as_tuple(aiv)
|
||||||
|
print '2. auto_ptr_reference_ivect_as_tuple'
|
||||||
|
print dvect.auto_ptr_reference_ivect_as_tuple(aiv)
|
||||||
|
#
|
||||||
|
sdv = ivect.dvect_as_shared_ptr(dv)
|
||||||
|
print '1. shared_ptr_reference_dvect_as_tuple'
|
||||||
|
print dvect.shared_ptr_reference_dvect_as_tuple(sdv)
|
||||||
|
print '2. shared_ptr_reference_dvect_as_tuple'
|
||||||
|
print dvect.shared_ptr_reference_dvect_as_tuple(sdv)
|
||||||
|
#
|
||||||
|
siv = ivect.ivect_as_shared_ptr(iv)
|
||||||
|
print '1. shared_ptr_reference_ivect_as_tuple'
|
||||||
|
print dvect.shared_ptr_reference_ivect_as_tuple(siv)
|
||||||
|
print '2. shared_ptr_reference_ivect_as_tuple'
|
||||||
|
print dvect.shared_ptr_reference_ivect_as_tuple(siv)
|
||||||
|
#
|
||||||
|
adv = ivect.dvect_as_auto_ptr(dv)
|
||||||
|
print '1. auto_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print dvect.auto_ptr_const_reference_dvect_as_tuple(adv)
|
||||||
|
print '2. auto_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print dvect.auto_ptr_const_reference_dvect_as_tuple(adv)
|
||||||
|
#
|
||||||
|
aiv = ivect.ivect_as_auto_ptr(iv)
|
||||||
|
print '1. auto_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv)
|
||||||
|
print '2. auto_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv)
|
||||||
|
#
|
||||||
|
sdv = ivect.dvect_as_shared_ptr(dv)
|
||||||
|
print '1. shared_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv)
|
||||||
|
print '2. shared_ptr_const_reference_dvect_as_tuple'
|
||||||
|
print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv)
|
||||||
|
#
|
||||||
|
siv = ivect.ivect_as_shared_ptr(iv)
|
||||||
|
print '1. shared_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print dvect.shared_ptr_const_reference_ivect_as_tuple(siv)
|
||||||
|
print '2. shared_ptr_const_reference_ivect_as_tuple'
|
||||||
|
print dvect.shared_ptr_const_reference_ivect_as_tuple(siv)
|
||||||
|
|
||||||
|
if (__name__ == "__main__"):
|
||||||
|
import sys, string
|
||||||
|
broken_auto_ptr = 0
|
||||||
|
n = 1
|
||||||
|
if (len(sys.argv) > 1):
|
||||||
|
if (sys.argv[1] == "--broken-auto-ptr"):
|
||||||
|
broken_auto_ptr = 1
|
||||||
|
if (len(sys.argv) > 2):
|
||||||
|
n = string.atoi(sys.argv[2])
|
||||||
|
else:
|
||||||
|
n = string.atoi(sys.argv[1])
|
||||||
|
for i in xrange(n):
|
||||||
|
f(broken_auto_ptr)
|
||||||
16
example/tst_noncopyable.py
Normal file
16
example/tst_noncopyable.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
def f():
|
||||||
|
import noncopyable_export
|
||||||
|
import noncopyable_import
|
||||||
|
s1 = noncopyable_export.store(1)
|
||||||
|
print s1.recall()
|
||||||
|
s2 = noncopyable_export.store(2)
|
||||||
|
print s2.recall()
|
||||||
|
s3 = noncopyable_import.add_stores(s1, s2)
|
||||||
|
print s3.recall()
|
||||||
|
|
||||||
|
if (__name__ == "__main__"):
|
||||||
|
import sys, string
|
||||||
|
n = 1
|
||||||
|
if (len(sys.argv) > 1): n = string.atoi(sys.argv[1])
|
||||||
|
for i in xrange(n):
|
||||||
|
f()
|
||||||
@@ -46,7 +46,7 @@ struct callback
|
|||||||
template <class A1>
|
template <class A1>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1)
|
static R call_method(PyObject* self, const char* name, const A1& a1)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(O)"),
|
const_cast<char*>("(O)"),
|
||||||
p1.get()));
|
p1.get()));
|
||||||
@@ -57,7 +57,7 @@ struct callback
|
|||||||
template <class A1>
|
template <class A1>
|
||||||
static R call(PyObject* self, const A1& a1)
|
static R call(PyObject* self, const A1& a1)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(O)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(O)"),
|
||||||
p1.get()));
|
p1.get()));
|
||||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||||
@@ -67,8 +67,8 @@ struct callback
|
|||||||
template <class A1, class A2>
|
template <class A1, class A2>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OO)"),
|
const_cast<char*>("(OO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -80,8 +80,8 @@ struct callback
|
|||||||
template <class A1, class A2>
|
template <class A1, class A2>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2)
|
static R call(PyObject* self, const A1& a1, const A2& a2)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get()));
|
p2.get()));
|
||||||
@@ -92,9 +92,9 @@ struct callback
|
|||||||
template <class A1, class A2, class A3>
|
template <class A1, class A2, class A3>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOO)"),
|
const_cast<char*>("(OOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -107,9 +107,9 @@ struct callback
|
|||||||
template <class A1, class A2, class A3>
|
template <class A1, class A2, class A3>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -121,10 +121,10 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4>
|
template <class A1, class A2, class A3, class A4>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOO)"),
|
const_cast<char*>("(OOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -138,10 +138,10 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4>
|
template <class A1, class A2, class A3, class A4>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -154,11 +154,11 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOO)"),
|
const_cast<char*>("(OOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -173,11 +173,11 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -191,12 +191,12 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOO)"),
|
const_cast<char*>("(OOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -212,12 +212,12 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -232,13 +232,13 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOO)"),
|
const_cast<char*>("(OOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -255,13 +255,13 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -277,14 +277,14 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOOO)"),
|
const_cast<char*>("(OOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -302,14 +302,14 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -326,15 +326,15 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOOOO)"),
|
const_cast<char*>("(OOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -353,15 +353,15 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -379,16 +379,16 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref p10(to_python(a10));
|
ref p10(to_python(a10, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOOOOO)"),
|
const_cast<char*>("(OOOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -408,16 +408,16 @@ struct callback
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref p10(to_python(a10));
|
ref p10(to_python(a10, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -455,7 +455,7 @@ struct callback<void>
|
|||||||
template <class A1>
|
template <class A1>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1)
|
static void call_method(PyObject* self, const char* name, const A1& a1)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(O)"),
|
const_cast<char*>("(O)"),
|
||||||
p1.get()));
|
p1.get()));
|
||||||
@@ -464,7 +464,7 @@ struct callback<void>
|
|||||||
template <class A1>
|
template <class A1>
|
||||||
static void call(PyObject* self, const A1& a1)
|
static void call(PyObject* self, const A1& a1)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(O)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(O)"),
|
||||||
p1.get()));
|
p1.get()));
|
||||||
}
|
}
|
||||||
@@ -472,8 +472,8 @@ struct callback<void>
|
|||||||
template <class A1, class A2>
|
template <class A1, class A2>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OO)"),
|
const_cast<char*>("(OO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -483,8 +483,8 @@ struct callback<void>
|
|||||||
template <class A1, class A2>
|
template <class A1, class A2>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2)
|
static void call(PyObject* self, const A1& a1, const A2& a2)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get()));
|
p2.get()));
|
||||||
@@ -493,9 +493,9 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3>
|
template <class A1, class A2, class A3>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOO)"),
|
const_cast<char*>("(OOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -506,9 +506,9 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3>
|
template <class A1, class A2, class A3>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -518,10 +518,10 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4>
|
template <class A1, class A2, class A3, class A4>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOO)"),
|
const_cast<char*>("(OOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -533,10 +533,10 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4>
|
template <class A1, class A2, class A3, class A4>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -547,11 +547,11 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOO)"),
|
const_cast<char*>("(OOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -564,11 +564,11 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -580,12 +580,12 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOO)"),
|
const_cast<char*>("(OOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -599,12 +599,12 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -617,13 +617,13 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOO)"),
|
const_cast<char*>("(OOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -638,13 +638,13 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -658,14 +658,14 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOOO)"),
|
const_cast<char*>("(OOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -681,14 +681,14 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -703,15 +703,15 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOOOO)"),
|
const_cast<char*>("(OOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -728,15 +728,15 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
@@ -752,16 +752,16 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref p10(to_python(a10));
|
ref p10(to_python(a10, lookup_tag()));
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(OOOOOOOOOO)"),
|
const_cast<char*>("(OOOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
@@ -779,16 +779,16 @@ struct callback<void>
|
|||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10)
|
||||||
{
|
{
|
||||||
ref p1(to_python(a1));
|
ref p1(to_python(a1, lookup_tag()));
|
||||||
ref p2(to_python(a2));
|
ref p2(to_python(a2, lookup_tag()));
|
||||||
ref p3(to_python(a3));
|
ref p3(to_python(a3, lookup_tag()));
|
||||||
ref p4(to_python(a4));
|
ref p4(to_python(a4, lookup_tag()));
|
||||||
ref p5(to_python(a5));
|
ref p5(to_python(a5, lookup_tag()));
|
||||||
ref p6(to_python(a6));
|
ref p6(to_python(a6, lookup_tag()));
|
||||||
ref p7(to_python(a7));
|
ref p7(to_python(a7, lookup_tag()));
|
||||||
ref p8(to_python(a8));
|
ref p8(to_python(a8, lookup_tag()));
|
||||||
ref p9(to_python(a9));
|
ref p9(to_python(a9, lookup_tag()));
|
||||||
ref p10(to_python(a10));
|
ref p10(to_python(a10, lookup_tag()));
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOOO)"),
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(OOOOOOOOOO)"),
|
||||||
p1.get(),
|
p1.get(),
|
||||||
p2.get(),
|
p2.get(),
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ struct caller
|
|||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
||||||
return 0;
|
return 0;
|
||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)());
|
return to_python((target.*pmf)(), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1>
|
template <class T, class A1>
|
||||||
@@ -40,7 +40,7 @@ struct caller
|
|||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &a1))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &a1))
|
||||||
return 0;
|
return 0;
|
||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)(from_python(a1, type<A1>())));
|
return to_python((target.*pmf)(from_python(a1, type<A1>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2>
|
template <class T, class A1, class A2>
|
||||||
@@ -52,7 +52,7 @@ struct caller
|
|||||||
return 0;
|
return 0;
|
||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>())));
|
from_python(a2, type<A2>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3>
|
template <class T, class A1, class A2, class A3>
|
||||||
@@ -66,7 +66,7 @@ struct caller
|
|||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>())));
|
from_python(a3, type<A3>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4>
|
template <class T, class A1, class A2, class A3, class A4>
|
||||||
@@ -82,7 +82,7 @@ struct caller
|
|||||||
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>())));
|
from_python(a4, type<A4>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5>
|
template <class T, class A1, class A2, class A3, class A4, class A5>
|
||||||
@@ -100,7 +100,7 @@ struct caller
|
|||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>())));
|
from_python(a5, type<A5>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
@@ -120,7 +120,7 @@ struct caller
|
|||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>())));
|
from_python(a6, type<A6>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
@@ -142,7 +142,7 @@ struct caller
|
|||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>())));
|
from_python(a7, type<A7>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
@@ -166,7 +166,7 @@ struct caller
|
|||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>())));
|
from_python(a8, type<A8>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
@@ -192,7 +192,7 @@ struct caller
|
|||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>()),
|
from_python(a8, type<A8>()),
|
||||||
from_python(a9, type<A9>())));
|
from_python(a9, type<A9>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
@@ -220,7 +220,7 @@ struct caller
|
|||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>()),
|
from_python(a8, type<A8>()),
|
||||||
from_python(a9, type<A9>()),
|
from_python(a9, type<A9>()),
|
||||||
from_python(a10, type<A10>())));
|
from_python(a10, type<A10>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ struct caller
|
|||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
||||||
return 0;
|
return 0;
|
||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)());
|
return to_python((target.*pmf)(), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1>
|
template <class T, class A1>
|
||||||
@@ -240,7 +240,7 @@ struct caller
|
|||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &a1))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &a1))
|
||||||
return 0;
|
return 0;
|
||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)(from_python(a1, type<A1>())));
|
return to_python((target.*pmf)(from_python(a1, type<A1>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2>
|
template <class T, class A1, class A2>
|
||||||
@@ -252,7 +252,7 @@ struct caller
|
|||||||
return 0;
|
return 0;
|
||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>())));
|
from_python(a2, type<A2>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3>
|
template <class T, class A1, class A2, class A3>
|
||||||
@@ -266,7 +266,7 @@ struct caller
|
|||||||
T& target = from_python(self, type<T&>());
|
T& target = from_python(self, type<T&>());
|
||||||
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>())));
|
from_python(a3, type<A3>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4>
|
template <class T, class A1, class A2, class A3, class A4>
|
||||||
@@ -282,7 +282,7 @@ struct caller
|
|||||||
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
return to_python((target.*pmf)(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>())));
|
from_python(a4, type<A4>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5>
|
template <class T, class A1, class A2, class A3, class A4, class A5>
|
||||||
@@ -300,7 +300,7 @@ struct caller
|
|||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>())));
|
from_python(a5, type<A5>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
@@ -320,7 +320,7 @@ struct caller
|
|||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>())));
|
from_python(a6, type<A6>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
@@ -342,7 +342,7 @@ struct caller
|
|||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>())));
|
from_python(a7, type<A7>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
@@ -366,7 +366,7 @@ struct caller
|
|||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>())));
|
from_python(a8, type<A8>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
@@ -392,7 +392,7 @@ struct caller
|
|||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>()),
|
from_python(a8, type<A8>()),
|
||||||
from_python(a9, type<A9>())));
|
from_python(a9, type<A9>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
@@ -420,14 +420,14 @@ struct caller
|
|||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>()),
|
from_python(a8, type<A8>()),
|
||||||
from_python(a9, type<A9>()),
|
from_python(a9, type<A9>()),
|
||||||
from_python(a10, type<A10>())));
|
from_python(a10, type<A10>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free functions
|
// Free functions
|
||||||
static PyObject* call(R (*f)(), PyObject* args, PyObject* /* keywords */ ) {
|
static PyObject* call(R (*f)(), PyObject* args, PyObject* /* keywords */ ) {
|
||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("")))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("")))
|
||||||
return 0;
|
return 0;
|
||||||
return to_python(f());
|
return to_python(f(), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1>
|
template <class A1>
|
||||||
@@ -435,7 +435,7 @@ struct caller
|
|||||||
PyObject* a1;
|
PyObject* a1;
|
||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &a1))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &a1))
|
||||||
return 0;
|
return 0;
|
||||||
return to_python(f(from_python(a1, type<A1>())));
|
return to_python(f(from_python(a1, type<A1>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2>
|
template <class A1, class A2>
|
||||||
@@ -445,7 +445,7 @@ struct caller
|
|||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
|
||||||
return 0;
|
return 0;
|
||||||
return to_python(f(from_python(a1, type<A1>()),
|
return to_python(f(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>())));
|
from_python(a2, type<A2>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3>
|
template <class A1, class A2, class A3>
|
||||||
@@ -457,7 +457,7 @@ struct caller
|
|||||||
return 0;
|
return 0;
|
||||||
return to_python(f(from_python(a1, type<A1>()),
|
return to_python(f(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>())));
|
from_python(a3, type<A3>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4>
|
template <class A1, class A2, class A3, class A4>
|
||||||
@@ -471,7 +471,7 @@ struct caller
|
|||||||
return to_python(f(from_python(a1, type<A1>()),
|
return to_python(f(from_python(a1, type<A1>()),
|
||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>())));
|
from_python(a4, type<A4>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5>
|
||||||
@@ -487,7 +487,7 @@ struct caller
|
|||||||
from_python(a2, type<A2>()),
|
from_python(a2, type<A2>()),
|
||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>())));
|
from_python(a5, type<A5>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
@@ -505,7 +505,7 @@ struct caller
|
|||||||
from_python(a3, type<A3>()),
|
from_python(a3, type<A3>()),
|
||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>())));
|
from_python(a6, type<A6>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
@@ -525,7 +525,7 @@ struct caller
|
|||||||
from_python(a4, type<A4>()),
|
from_python(a4, type<A4>()),
|
||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>())));
|
from_python(a7, type<A7>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
@@ -547,7 +547,7 @@ struct caller
|
|||||||
from_python(a5, type<A5>()),
|
from_python(a5, type<A5>()),
|
||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>())));
|
from_python(a8, type<A8>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
@@ -571,7 +571,7 @@ struct caller
|
|||||||
from_python(a6, type<A6>()),
|
from_python(a6, type<A6>()),
|
||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>()),
|
from_python(a8, type<A8>()),
|
||||||
from_python(a9, type<A9>())));
|
from_python(a9, type<A9>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
@@ -597,7 +597,7 @@ struct caller
|
|||||||
from_python(a7, type<A7>()),
|
from_python(a7, type<A7>()),
|
||||||
from_python(a8, type<A8>()),
|
from_python(a8, type<A8>()),
|
||||||
from_python(a9, type<A9>()),
|
from_python(a9, type<A9>()),
|
||||||
from_python(a10, type<A10>())));
|
from_python(a10, type<A10>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
|
||||||
@@ -625,7 +625,7 @@ struct caller
|
|||||||
from_python(a8, type<A8>()),
|
from_python(a8, type<A8>()),
|
||||||
from_python(a9, type<A9>()),
|
from_python(a9, type<A9>()),
|
||||||
from_python(a10, type<A10>()),
|
from_python(a10, type<A10>()),
|
||||||
from_python(a11, type<A11>())));
|
from_python(a11, type<A11>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// Revision History:
|
||||||
|
// Mar 03 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve)
|
||||||
|
|
||||||
#ifndef CLASS_WRAPPER_DWA101000_H_
|
#ifndef CLASS_WRAPPER_DWA101000_H_
|
||||||
# define CLASS_WRAPPER_DWA101000_H_
|
# define CLASS_WRAPPER_DWA101000_H_
|
||||||
|
|
||||||
@@ -16,110 +19,118 @@ class class_builder
|
|||||||
: python_extension_class_converters<T, U> // Works around MSVC6.x/GCC2.95.2 bug described below
|
: python_extension_class_converters<T, U> // Works around MSVC6.x/GCC2.95.2 bug described below
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// Construct a class named name in the given module
|
||||||
class_builder(module_builder& module, const char* name)
|
class_builder(module_builder& module, const char* name)
|
||||||
: m_class(new detail::extension_class<T, U>(name))
|
: m_class(new detail::extension_class<T, U>(name))
|
||||||
{
|
{
|
||||||
module.add(ref(as_object(m_class.get()), ref::increment_count), name);
|
module.add(ref(as_object(m_class.get()), ref::increment_count), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
~class_builder()
|
|
||||||
{}
|
|
||||||
|
|
||||||
// define constructors
|
|
||||||
template <class signature>
|
|
||||||
void def(const signature& signature)
|
|
||||||
{ m_class->def(signature); }
|
|
||||||
|
|
||||||
// export heterogeneous reverse-argument operators
|
/// Tell Boost.Python that for the purposes of pickling, the state is
|
||||||
// (type of lhs: 'left', of rhs: 'right')
|
/// completely captured in the object's __dict__.
|
||||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
inline void dict_defines_state() {
|
||||||
// boost::python::left_operand<int const &>());
|
add(ref(to_python(1, lookup_tag())), "__dict_defines_state__");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void getstate_manages_dict() {
|
||||||
|
add(ref(to_python(1, lookup_tag())), "__getstate_manages_dict__");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// define constructors
|
||||||
|
template <class signature>
|
||||||
|
void def(const signature& s)
|
||||||
|
{ m_class->def(s); }
|
||||||
|
|
||||||
|
/// export heterogeneous reverse-argument operators
|
||||||
|
/// (type of lhs: 'left', of rhs: 'right')
|
||||||
|
/// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||||
|
/// boost::python::left_operand<int const &>());
|
||||||
template <long which, class left, class right>
|
template <long which, class left, class right>
|
||||||
void def(operators<which, right> o1, left_operand<left> o2)
|
void def(operators<which, right> o1, left_operand<left> o2)
|
||||||
{ m_class->def(o1, o2); }
|
{ m_class->def(o1, o2); }
|
||||||
|
|
||||||
// export heterogeneous operators (type of lhs: 'left', of rhs: 'right')
|
/// export heterogeneous operators (type of lhs: 'left', of rhs: 'right')
|
||||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
/// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||||
// boost::python::right_operand<int const &>());
|
/// boost::python::right_operand<int const &>());
|
||||||
template <long which, class left, class right>
|
template <long which, class left, class right>
|
||||||
void def(operators<which, left> o1, right_operand<right> o2)
|
void def(operators<which, left> o1, right_operand<right> o2)
|
||||||
{ m_class->def(o1, o2); }
|
{ m_class->def(o1, o2); }
|
||||||
|
|
||||||
// define a function that passes Python arguments and keywords
|
/// define a function that passes Python arguments and keywords
|
||||||
// to C++ verbatim (as a 'tuple const &' and 'dictionary const &'
|
/// to C++ verbatim (as a 'tuple const &' and 'dictionary const &'
|
||||||
// respectively). This is useful for manual argument passing.
|
/// respectively). This is useful for manual argument passing.
|
||||||
// It's also the only possibility to pass keyword arguments to C++.
|
/// It's also the only way to pass keyword arguments to C++.
|
||||||
// Fn must have a signatur that is compatible to
|
/// Fn must have a signature that is compatible with
|
||||||
// PyObject * (*)(PyObject * aTuple, PyObject * aDictionary)
|
/// PyObject * (*)(PyObject * aTuple, PyObject * aDictionary)
|
||||||
template <class Fn>
|
template <class Fn>
|
||||||
void def_raw(Fn fn, const char* name)
|
void def_raw(Fn fn, const char* name)
|
||||||
{ m_class->def_raw(fn, name); }
|
{ m_class->def_raw(fn, name); }
|
||||||
|
|
||||||
// define member functions. In fact this works for free functions, too -
|
/// define member functions. In fact this works for free functions, too -
|
||||||
// they act like static member functions, or if they start with the
|
/// they act like static member functions, or if they start with the
|
||||||
// appropriate self argument (as a pointer or reference), they can be used
|
/// appropriate self argument (as a pointer or reference), they can be used
|
||||||
// just like ordinary member functions -- just like Python!
|
/// just like ordinary member functions -- just like Python!
|
||||||
template <class Fn>
|
template <class Fn>
|
||||||
void def(Fn fn, const char* name)
|
void def(Fn fn, const char* name)
|
||||||
{ m_class->def(fn, name); }
|
{ m_class->def(fn, name); }
|
||||||
|
|
||||||
// Define a virtual member function with a default implementation.
|
/// Define a virtual member function with a default implementation.
|
||||||
// default_fn should be a function which provides the default implementation.
|
/// default_fn should be a function which provides the default implementation.
|
||||||
// Be careful that default_fn does not in fact call fn virtually!
|
/// Be careful that default_fn does not in fact call fn virtually!
|
||||||
template <class Fn, class DefaultFn>
|
template <class Fn, class DefaultFn>
|
||||||
void def(Fn fn, const char* name, DefaultFn default_fn)
|
void def(Fn fn, const char* name, DefaultFn default_fn)
|
||||||
{ m_class->def(fn, name, default_fn); }
|
{ m_class->def(fn, name, default_fn); }
|
||||||
|
|
||||||
// Provide a function which implements x.<name>, reading from the given
|
/// Provide a function which implements x.<name>, reading from the given
|
||||||
// member (pm) of the T obj
|
/// member (pm) of the T obj
|
||||||
template <class MemberType>
|
template <class MemberType>
|
||||||
void def_getter(MemberType T::*pm, const char* name)
|
void def_getter(MemberType T::*pm, const char* name)
|
||||||
{ m_class->def_getter(pm, name); }
|
{ m_class->def_getter(pm, name); }
|
||||||
|
|
||||||
// Provide a function which implements assignment to x.<name>, writing to
|
/// Provide a function which implements assignment to x.<name>, writing to
|
||||||
// the given member (pm) of the T obj
|
/// the given member (pm) of the T obj
|
||||||
template <class MemberType>
|
template <class MemberType>
|
||||||
void def_setter(MemberType T::*pm, const char* name)
|
void def_setter(MemberType T::*pm, const char* name)
|
||||||
{ m_class->def_getter(pm, name); }
|
{ m_class->def_getter(pm, name); }
|
||||||
|
|
||||||
// Expose the given member (pm) of the T obj as a read-only attribute
|
/// Expose the given member (pm) of the T obj as a read-only attribute
|
||||||
template <class MemberType>
|
template <class MemberType>
|
||||||
void def_readonly(MemberType T::*pm, const char* name)
|
void def_readonly(MemberType T::*pm, const char* name)
|
||||||
{ m_class->def_readonly(pm, name); }
|
{ m_class->def_readonly(pm, name); }
|
||||||
|
|
||||||
// Expose the given member (pm) of the T obj as a read/write attribute
|
/// Expose the given member (pm) of the T obj as a read/write attribute
|
||||||
template <class MemberType>
|
template <class MemberType>
|
||||||
void def_read_write(MemberType T::*pm, const char* name)
|
void def_read_write(MemberType T::*pm, const char* name)
|
||||||
{ m_class->def_read_write(pm, name); }
|
{ m_class->def_read_write(pm, name); }
|
||||||
|
|
||||||
// define the standard coercion needed for operator overloading
|
/// define the standard coercion needed for operator overloading
|
||||||
void def_standard_coerce()
|
void def_standard_coerce()
|
||||||
{ m_class->def_standard_coerce(); }
|
{ m_class->def_standard_coerce(); }
|
||||||
|
|
||||||
// declare the given class a base class of this one and register
|
/// declare the given class a base class of this one and register
|
||||||
// conversion functions
|
/// conversion functions
|
||||||
template <class S, class V>
|
template <class S, class V>
|
||||||
void declare_base(class_builder<S, V> const & base)
|
void declare_base(class_builder<S, V> const & base)
|
||||||
{
|
{
|
||||||
m_class->declare_base(base.get_extension_class());
|
m_class->declare_base(base.get_extension_class());
|
||||||
}
|
}
|
||||||
|
|
||||||
// declare the given class a base class of this one and register
|
/// declare the given class a base class of this one and register
|
||||||
// upcast conversion function
|
/// upcast conversion function
|
||||||
template <class S, class V>
|
template <class S, class V>
|
||||||
void declare_base(class_builder<S, V> const & base, without_downcast_t)
|
void declare_base(class_builder<S, V> const & base, without_downcast_t)
|
||||||
{
|
{
|
||||||
m_class->declare_base(base.get_extension_class(), without_downcast);
|
m_class->declare_base(base.get_extension_class(), without_downcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the embedded ExtensioClass object
|
/// get the embedded ExtensioClass object
|
||||||
detail::extension_class<T, U> * get_extension_class() const
|
detail::extension_class<T, U> * get_extension_class() const
|
||||||
{
|
{
|
||||||
return m_class.get();
|
return m_class.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// set an arbitrary attribute. Useful for non-function class data members,
|
/// set an arbitrary attribute. Useful for non-function class data members,
|
||||||
// e.g. enums
|
/// e.g. enums
|
||||||
void add(PyObject* x, const char* name)
|
void add(PyObject* x, const char* name)
|
||||||
{ m_class->set_attribute(name, x); }
|
{ m_class->set_attribute(name, x); }
|
||||||
void add(ref x, const char* name)
|
void add(ref x, const char* name)
|
||||||
@@ -133,8 +144,8 @@ class class_builder
|
|||||||
m_class->declare_base(base);
|
m_class->declare_base(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
// declare the given class a base class of this one and register
|
/// declare the given class a base class of this one and register
|
||||||
// upcast conversion function
|
/// upcast conversion function
|
||||||
template <class S, class V>
|
template <class S, class V>
|
||||||
void declare_base(detail::extension_class<S, V> * base, without_downcast_t)
|
void declare_base(detail::extension_class<S, V> * base, without_downcast_t)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -284,14 +284,14 @@ PyObject* class_t<T>::instance_mapping_subscript(PyObject* obj, PyObject* key) c
|
|||||||
template <class T>
|
template <class T>
|
||||||
PyObject* class_t<T>::instance_sequence_item(PyObject* obj, int n) const
|
PyObject* class_t<T>::instance_sequence_item(PyObject* obj, int n) const
|
||||||
{
|
{
|
||||||
ref key(to_python(n));
|
ref key(to_python(n, lookup_tag()));
|
||||||
return downcast<T>(obj)->get_subscript(key.get());
|
return downcast<T>(obj)->get_subscript(key.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
int class_t<T>::instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const
|
int class_t<T>::instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const
|
||||||
{
|
{
|
||||||
ref key(to_python(n));
|
ref key(to_python(n, lookup_tag()));
|
||||||
downcast<T>(obj)->set_subscript(key.get(), value);
|
downcast<T>(obj)->set_subscript(key.get(), value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,11 @@
|
|||||||
//
|
//
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// 04 Mar 01 Fixed std::complex<> stuff to work with MSVC (David Abrahams)
|
||||||
|
// 03 Mar 01 added: converters for [plain] char and std::complex
|
||||||
|
// (Ralf W. Grosse-Kunstleve)
|
||||||
|
|
||||||
#ifndef METHOD_DWA122899_H_
|
#ifndef METHOD_DWA122899_H_
|
||||||
# define METHOD_DWA122899_H_
|
# define METHOD_DWA122899_H_
|
||||||
@@ -17,6 +22,21 @@
|
|||||||
# include <boost/python/errors.hpp>
|
# include <boost/python/errors.hpp>
|
||||||
# include <string>
|
# include <string>
|
||||||
|
|
||||||
|
# ifdef BOOST_MSVC6_OR_EARLIER
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4275) // disable a bogus warning caused by <complex>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# include <complex>
|
||||||
|
|
||||||
|
# ifdef BOOST_MSVC6_OR_EARLIER
|
||||||
|
# pragma warning(pop)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
namespace boost { namespace python {
|
||||||
|
struct lookup_tag {}; // Used to find to_python functions via Koenig lookup.
|
||||||
|
}}
|
||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||||
|
|
||||||
// This can be instantiated on an enum to provide the to_python/from_python
|
// This can be instantiated on an enum to provide the to_python/from_python
|
||||||
@@ -36,16 +56,16 @@ class py_enum_as_int_converters
|
|||||||
from_python(x, boost::python::type<long>()));
|
from_python(x, boost::python::type<long>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend PyObject* to_python(EnumType x)
|
friend PyObject* to_python(EnumType x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return to_python(static_cast<long>(x));
|
return to_python(static_cast<long>(x), boost::python::lookup_tag());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
template <class EnumType> class enum_as_int_converters
|
template <class EnumType> class enum_as_int_converters
|
||||||
: public BOOST_PYTHON_CONVERSION::py_enum_as_int_converters<EnumType> {};
|
: public py_enum_as_int_converters<EnumType> {};
|
||||||
|
|
||||||
template <class P, class T> class wrapped_pointer;
|
template <class P, class T> class wrapped_pointer;
|
||||||
|
|
||||||
@@ -70,68 +90,126 @@ inline void xdecref(T* p)
|
|||||||
xdecref_impl(reinterpret_cast<PyObject*>(p_base));
|
xdecref_impl(reinterpret_cast<PyObject*>(p_base));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
void expect_complex(PyObject*);
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::complex<T> complex_from_python(PyObject* p, boost::python::type<T>)
|
||||||
|
{
|
||||||
|
expect_complex(p);
|
||||||
|
|
||||||
|
return std::complex<T>(
|
||||||
|
static_cast<T>(PyComplex_RealAsDouble(p)),
|
||||||
|
static_cast<T>(PyComplex_ImagAsDouble(p)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
PyObject* complex_to_python(const std::complex<T>& sc) {
|
||||||
|
Py_complex pcc;
|
||||||
|
pcc.real = sc.real();
|
||||||
|
pcc.imag = sc.imag();
|
||||||
|
return PyComplex_FromCComplex(pcc);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace boost::python
|
}} // namespace boost::python
|
||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
//
|
//
|
||||||
// Converters
|
// Converters
|
||||||
//
|
//
|
||||||
PyObject* to_python(long);
|
PyObject* to_python(long, boost::python::lookup_tag);
|
||||||
long from_python(PyObject* p, boost::python::type<long>);
|
long from_python(PyObject* p, boost::python::type<long>);
|
||||||
long from_python(PyObject* p, boost::python::type<const long&>);
|
long from_python(PyObject* p, boost::python::type<const long&>);
|
||||||
|
|
||||||
PyObject* to_python(unsigned long);
|
PyObject* to_python(unsigned long, boost::python::lookup_tag);
|
||||||
unsigned long from_python(PyObject* p, boost::python::type<unsigned long>);
|
unsigned long from_python(PyObject* p, boost::python::type<unsigned long>);
|
||||||
unsigned long from_python(PyObject* p, boost::python::type<const unsigned long&>);
|
unsigned long from_python(PyObject* p, boost::python::type<const unsigned long&>);
|
||||||
|
|
||||||
PyObject* to_python(int);
|
PyObject* to_python(int, boost::python::lookup_tag);
|
||||||
int from_python(PyObject*, boost::python::type<int>);
|
int from_python(PyObject*, boost::python::type<int>);
|
||||||
int from_python(PyObject*, boost::python::type<const int&>);
|
int from_python(PyObject*, boost::python::type<const int&>);
|
||||||
|
|
||||||
PyObject* to_python(unsigned int);
|
PyObject* to_python(unsigned int, boost::python::lookup_tag);
|
||||||
unsigned int from_python(PyObject*, boost::python::type<unsigned int>);
|
unsigned int from_python(PyObject*, boost::python::type<unsigned int>);
|
||||||
unsigned int from_python(PyObject*, boost::python::type<const unsigned int&>);
|
unsigned int from_python(PyObject*, boost::python::type<const unsigned int&>);
|
||||||
|
|
||||||
PyObject* to_python(short);
|
PyObject* to_python(short, boost::python::lookup_tag);
|
||||||
short from_python(PyObject*, boost::python::type<short>);
|
short from_python(PyObject*, boost::python::type<short>);
|
||||||
short from_python(PyObject*, boost::python::type<const short&>);
|
short from_python(PyObject*, boost::python::type<const short&>);
|
||||||
|
|
||||||
PyObject* to_python(unsigned short);
|
PyObject* to_python(unsigned short, boost::python::lookup_tag);
|
||||||
unsigned short from_python(PyObject*, boost::python::type<unsigned short>);
|
unsigned short from_python(PyObject*, boost::python::type<unsigned short>);
|
||||||
unsigned short from_python(PyObject*, boost::python::type<const unsigned short&>);
|
unsigned short from_python(PyObject*, boost::python::type<const unsigned short&>);
|
||||||
|
|
||||||
PyObject* to_python(signed char);
|
PyObject* to_python(char, boost::python::lookup_tag);
|
||||||
|
char from_python(PyObject*, boost::python::type<char>);
|
||||||
|
char from_python(PyObject*, boost::python::type<const char&>);
|
||||||
|
|
||||||
|
PyObject* to_python(signed char, boost::python::lookup_tag);
|
||||||
signed char from_python(PyObject*, boost::python::type<signed char>);
|
signed char from_python(PyObject*, boost::python::type<signed char>);
|
||||||
signed char from_python(PyObject*, boost::python::type<const signed char&>);
|
signed char from_python(PyObject*, boost::python::type<const signed char&>);
|
||||||
|
|
||||||
PyObject* to_python(unsigned char);
|
PyObject* to_python(unsigned char, boost::python::lookup_tag);
|
||||||
unsigned char from_python(PyObject*, boost::python::type<unsigned char>);
|
unsigned char from_python(PyObject*, boost::python::type<unsigned char>);
|
||||||
unsigned char from_python(PyObject*, boost::python::type<const unsigned char&>);
|
unsigned char from_python(PyObject*, boost::python::type<const unsigned char&>);
|
||||||
|
|
||||||
PyObject* to_python(float);
|
PyObject* to_python(float, boost::python::lookup_tag);
|
||||||
float from_python(PyObject*, boost::python::type<float>);
|
float from_python(PyObject*, boost::python::type<float>);
|
||||||
float from_python(PyObject*, boost::python::type<const float&>);
|
float from_python(PyObject*, boost::python::type<const float&>);
|
||||||
|
|
||||||
PyObject* to_python(double);
|
PyObject* to_python(double, boost::python::lookup_tag);
|
||||||
double from_python(PyObject*, boost::python::type<double>);
|
double from_python(PyObject*, boost::python::type<double>);
|
||||||
double from_python(PyObject*, boost::python::type<const double&>);
|
double from_python(PyObject*, boost::python::type<const double&>);
|
||||||
|
|
||||||
PyObject* to_python(bool);
|
PyObject* to_python(bool, boost::python::lookup_tag);
|
||||||
bool from_python(PyObject*, boost::python::type<bool>);
|
bool from_python(PyObject*, boost::python::type<bool>);
|
||||||
bool from_python(PyObject*, boost::python::type<const bool&>);
|
bool from_python(PyObject*, boost::python::type<const bool&>);
|
||||||
|
|
||||||
PyObject* to_python(void);
|
PyObject* to_python(boost::python::lookup_tag);
|
||||||
void from_python(PyObject*, boost::python::type<void>);
|
void from_python(PyObject*, boost::python::type<void>);
|
||||||
|
|
||||||
PyObject* to_python(const char* s);
|
PyObject* to_python(const char* s, boost::python::lookup_tag);
|
||||||
const char* from_python(PyObject*, boost::python::type<const char*>);
|
const char* from_python(PyObject*, boost::python::type<const char*>);
|
||||||
|
|
||||||
PyObject* to_python(const std::string& s);
|
PyObject* to_python(const std::string& s, boost::python::lookup_tag);
|
||||||
std::string from_python(PyObject*, boost::python::type<std::string>);
|
std::string from_python(PyObject*, boost::python::type<std::string>);
|
||||||
std::string from_python(PyObject*, boost::python::type<const std::string&>);
|
std::string from_python(PyObject*, boost::python::type<const std::string&>);
|
||||||
|
|
||||||
|
inline PyObject* to_python(const std::complex<float>& x, boost::python::lookup_tag)
|
||||||
|
{
|
||||||
|
return boost::python::detail::complex_to_python<float>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PyObject* to_python(const std::complex<double>& x, boost::python::lookup_tag)
|
||||||
|
{
|
||||||
|
return boost::python::detail::complex_to_python<double>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::complex<double> from_python(PyObject* p,
|
||||||
|
boost::python::type<std::complex<double> >) {
|
||||||
|
return boost::python::detail::complex_from_python(p, boost::python::type<double>());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::complex<double> from_python(PyObject* p,
|
||||||
|
boost::python::type<const std::complex<double>&>) {
|
||||||
|
return boost::python::detail::complex_from_python(p, boost::python::type<double>());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::complex<float> from_python(PyObject* p,
|
||||||
|
boost::python::type<std::complex<float> >) {
|
||||||
|
return boost::python::detail::complex_from_python(p, boost::python::type<float>());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::complex<float> from_python(PyObject* p,
|
||||||
|
boost::python::type<const std::complex<float>&>) {
|
||||||
|
return boost::python::detail::complex_from_python(p, boost::python::type<float>());
|
||||||
|
}
|
||||||
|
|
||||||
// For when your C++ function really wants to pass/return a PyObject*
|
// For when your C++ function really wants to pass/return a PyObject*
|
||||||
PyObject* to_python(PyObject*);
|
PyObject* to_python(PyObject*, boost::python::lookup_tag);
|
||||||
PyObject* from_python(PyObject*, boost::python::type<PyObject*>);
|
PyObject* from_python(PyObject*, boost::python::type<PyObject*>);
|
||||||
|
|
||||||
// Some standard conversions to/from smart pointer types. You can add your own
|
// Some standard conversions to/from smart pointer types. You can add your own
|
||||||
@@ -185,13 +263,13 @@ boost::shared_ptr<T> from_python(PyObject*p, boost::python::type<boost::shared_p
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
template <class T>
|
template <class T>
|
||||||
PyObject* to_python(std::auto_ptr<T> p)
|
PyObject* to_python(std::auto_ptr<T> p, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return new boost::python::wrapped_pointer<std::auto_ptr<T>, T>(p);
|
return new boost::python::wrapped_pointer<std::auto_ptr<T>, T>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
PyObject* to_python(boost::shared_ptr<T> p)
|
PyObject* to_python(boost::shared_ptr<T> p, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return new boost::python::wrapped_pointer<boost::shared_ptr<T>, T>(p);
|
return new boost::python::wrapped_pointer<boost::shared_ptr<T>, T>(p);
|
||||||
}
|
}
|
||||||
@@ -202,43 +280,43 @@ PyObject* to_python(boost::shared_ptr<T> p)
|
|||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BOOST_MSVC6_OR_EARLIER
|
#ifndef BOOST_MSVC6_OR_EARLIER
|
||||||
inline PyObject* to_python(double d)
|
inline PyObject* to_python(double d, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyFloat_FromDouble(d);
|
return PyFloat_FromDouble(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* to_python(float f)
|
inline PyObject* to_python(float f, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyFloat_FromDouble(f);
|
return PyFloat_FromDouble(f);
|
||||||
}
|
}
|
||||||
#endif // BOOST_MSVC6_OR_EARLIER
|
#endif // BOOST_MSVC6_OR_EARLIER
|
||||||
|
|
||||||
inline PyObject* to_python(long l)
|
inline PyObject* to_python(long l, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyInt_FromLong(l);
|
return PyInt_FromLong(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* to_python(int x)
|
inline PyObject* to_python(int x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyInt_FromLong(x);
|
return PyInt_FromLong(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* to_python(short x)
|
inline PyObject* to_python(short x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyInt_FromLong(x);
|
return PyInt_FromLong(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* to_python(bool b)
|
inline PyObject* to_python(bool b, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyInt_FromLong(b);
|
return PyInt_FromLong(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* to_python(void)
|
inline PyObject* to_python(boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return boost::python::detail::none();
|
return boost::python::detail::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* to_python(const char* s)
|
inline PyObject* to_python(const char* s, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyString_FromString(s);
|
return PyString_FromString(s);
|
||||||
}
|
}
|
||||||
@@ -248,7 +326,7 @@ inline std::string from_python(PyObject* p, boost::python::type<const std::strin
|
|||||||
return from_python(p, boost::python::type<std::string>());
|
return from_python(p, boost::python::type<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* to_python(PyObject* p)
|
inline PyObject* to_python(PyObject* p, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
Py_INCREF(p);
|
Py_INCREF(p);
|
||||||
return p;
|
return p;
|
||||||
@@ -304,6 +382,11 @@ inline unsigned short from_python(PyObject* p, boost::python::type<const unsigne
|
|||||||
return from_python(p, boost::python::type<unsigned short>());
|
return from_python(p, boost::python::type<unsigned short>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline char from_python(PyObject* p, boost::python::type<const char&>)
|
||||||
|
{
|
||||||
|
return from_python(p, boost::python::type<char>());
|
||||||
|
}
|
||||||
|
|
||||||
inline signed char from_python(PyObject* p, boost::python::type<const signed char&>)
|
inline signed char from_python(PyObject* p, boost::python::type<const signed char&>)
|
||||||
{
|
{
|
||||||
return from_python(p, boost::python::type<signed char>());
|
return from_python(p, boost::python::type<signed char>());
|
||||||
|
|||||||
320
include/boost/python/cross_module.hpp
Normal file
320
include/boost/python/cross_module.hpp
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
/* (C) Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy, use,
|
||||||
|
modify, sell and distribute this software is granted provided this
|
||||||
|
copyright notice appears in all copies. This software is provided
|
||||||
|
"as is" without express or implied warranty, and with no claim as to
|
||||||
|
its suitability for any purpose.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Implementation of Boost.Python cross-module support.
|
||||||
|
See root/libs/python/doc/cross_module.html for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CROSS_MODULE_HPP
|
||||||
|
# define CROSS_MODULE_HPP
|
||||||
|
|
||||||
|
# include <boost/python/class_builder.hpp>
|
||||||
|
|
||||||
|
namespace boost { namespace python {
|
||||||
|
struct import_error : error_already_set {};
|
||||||
|
struct export_error : error_already_set {};
|
||||||
|
}}
|
||||||
|
|
||||||
|
namespace boost { namespace python { namespace detail {
|
||||||
|
|
||||||
|
// Concept: throw exception if api_major is changed
|
||||||
|
// show warning on stderr if api_minor is changed
|
||||||
|
const int export_converters_api_major = 4;
|
||||||
|
const int export_converters_api_minor = 1;
|
||||||
|
extern const char* converters_attribute_name;
|
||||||
|
void* import_converter_object(const std::string& module_name,
|
||||||
|
const std::string& py_class_name,
|
||||||
|
const std::string& attribute_name);
|
||||||
|
void check_export_converters_api(const int importing_major,
|
||||||
|
const int importing_minor,
|
||||||
|
const int imported_major,
|
||||||
|
const int imported_minor);
|
||||||
|
|
||||||
|
}}}
|
||||||
|
|
||||||
|
// forward declaration
|
||||||
|
namespace boost { namespace python { namespace detail {
|
||||||
|
template <class T> class import_extension_class;
|
||||||
|
}}}
|
||||||
|
|
||||||
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
|
/* This class template is instantiated by import_converters<T>.
|
||||||
|
This class is a look-alike of class python_extension_class_converters.
|
||||||
|
The converters in this class are wrappers that call converters
|
||||||
|
imported from another module.
|
||||||
|
To ensure that the dynamic loader resolves all symbols in the
|
||||||
|
intended way, the signature of all friend functions is changed with
|
||||||
|
respect to the original functions in class
|
||||||
|
python_extension_class_converters by adding an arbitrary additional
|
||||||
|
parameter with a default value, in this case "bool sig = false".
|
||||||
|
See also: comments for class export_converter_object_base below.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
class python_import_extension_class_converters
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
friend python_import_extension_class_converters py_extension_class_converters(boost::python::type<T>, bool sig = false) {
|
||||||
|
return python_import_extension_class_converters();
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* m_to_python(const T& x) const {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->dispatcher_to_python(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend T* from_python(PyObject* p, boost::python::type<T*> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_Ts(p, t);
|
||||||
|
}
|
||||||
|
friend const T* from_python(PyObject* p, boost::python::type<const T*> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_cTs(p, t);
|
||||||
|
}
|
||||||
|
friend const T* from_python(PyObject* p, boost::python::type<const T*const&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_cTscr(p, t);
|
||||||
|
}
|
||||||
|
friend T* from_python(PyObject* p, boost::python::type<T* const&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_Tscr(p, t);
|
||||||
|
}
|
||||||
|
friend T& from_python(PyObject* p, boost::python::type<T&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_Tr(p, t);
|
||||||
|
}
|
||||||
|
friend const T& from_python(PyObject* p, boost::python::type<const T&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_cTr(p, t);
|
||||||
|
}
|
||||||
|
friend const T& from_python(PyObject* p, boost::python::type<T> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_T(p, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_aTr(p, t);
|
||||||
|
}
|
||||||
|
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> > t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_aT(p, t);
|
||||||
|
}
|
||||||
|
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_caTr(p, t);
|
||||||
|
}
|
||||||
|
friend PyObject* to_python(std::auto_ptr<T> x, boost::python::lookup_tag, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->dispatcher_to_python(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_sTr(p, t);
|
||||||
|
}
|
||||||
|
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> > t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_sT(p, t);
|
||||||
|
}
|
||||||
|
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&> t, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_csTr(p, t);
|
||||||
|
}
|
||||||
|
friend PyObject* to_python(boost::shared_ptr<T> x, boost::python::lookup_tag, bool sig = false) {
|
||||||
|
return boost::python::detail::import_extension_class<T>::get_converters()->dispatcher_to_python(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
|
namespace boost { namespace python {
|
||||||
|
|
||||||
|
/* This class template is instantiated by export_converters().
|
||||||
|
A pointer to this class is exported/imported via the Python API.
|
||||||
|
Using the Python API ensures maximum portability.
|
||||||
|
All member functions are virtual. This is, what we export/import
|
||||||
|
is essentially just a pointer to a vtbl.
|
||||||
|
To work around a deficiency of Visual C++ 6.0, the name of each
|
||||||
|
from_python() member functions is made unique by appending a few
|
||||||
|
characters (derived in a ad-hoc manner from the corresponding type).
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
struct export_converter_object_base
|
||||||
|
{
|
||||||
|
virtual int get_api_major() const { return detail::export_converters_api_major; }
|
||||||
|
virtual int get_api_minor() const { return detail::export_converters_api_minor; }
|
||||||
|
|
||||||
|
virtual PyObject* dispatcher_to_python(const T& x) = 0;
|
||||||
|
|
||||||
|
virtual T* from_python_Ts(PyObject* p, type<T*> t) = 0;
|
||||||
|
virtual const T* from_python_cTs(PyObject* p, type<const T*> t) = 0;
|
||||||
|
virtual const T* from_python_cTscr(PyObject* p, type<const T*const&> t) = 0;
|
||||||
|
virtual T* from_python_Tscr(PyObject* p, type<T* const&> t) = 0;
|
||||||
|
virtual T& from_python_Tr(PyObject* p, type<T&> t) = 0;
|
||||||
|
virtual const T& from_python_cTr(PyObject* p, type<const T&> t) = 0;
|
||||||
|
virtual const T& from_python_T(PyObject* p, type<T> t) = 0;
|
||||||
|
|
||||||
|
virtual std::auto_ptr<T>& from_python_aTr(PyObject* p, type<std::auto_ptr<T>&> t) = 0;
|
||||||
|
virtual std::auto_ptr<T> from_python_aT(PyObject* p, type<std::auto_ptr<T> > t) = 0;
|
||||||
|
virtual const std::auto_ptr<T>& from_python_caTr(PyObject* p, type<const std::auto_ptr<T>&> t) = 0;
|
||||||
|
virtual PyObject* dispatcher_to_python(std::auto_ptr<T> x) = 0;
|
||||||
|
|
||||||
|
virtual boost::shared_ptr<T>& from_python_sTr(PyObject* p, type<boost::shared_ptr<T>&> t) = 0;
|
||||||
|
virtual const boost::shared_ptr<T>& from_python_sT(PyObject* p, type<boost::shared_ptr<T> > t) = 0;
|
||||||
|
virtual const boost::shared_ptr<T>& from_python_csTr(PyObject* p, type<const boost::shared_ptr<T>&> t) = 0;
|
||||||
|
virtual PyObject* dispatcher_to_python(boost::shared_ptr<T> x) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Converters to be used if T is not copyable.
|
||||||
|
template <class T>
|
||||||
|
struct export_converter_object_noncopyable : export_converter_object_base<T>
|
||||||
|
{
|
||||||
|
virtual PyObject* dispatcher_to_python(const T& x) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"to_python(const T&, boost::python::lookup_tag) converter not exported");
|
||||||
|
throw import_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual T* from_python_Ts(PyObject* p, type<T*> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual const T* from_python_cTs(PyObject* p, type<const T*> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual const T* from_python_cTscr(PyObject* p, type<const T*const&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual T* from_python_Tscr(PyObject* p, type<T* const&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual T& from_python_Tr(PyObject* p, type<T&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual const T& from_python_cTr(PyObject* p, type<const T&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual const T& from_python_T(PyObject* p, type<T> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::auto_ptr<T>& from_python_aTr(PyObject* p, type<std::auto_ptr<T>&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual std::auto_ptr<T> from_python_aT(PyObject* p, type<std::auto_ptr<T> > t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual const std::auto_ptr<T>& from_python_caTr(PyObject* p, type<const std::auto_ptr<T>&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual PyObject* dispatcher_to_python(std::auto_ptr<T> x) {
|
||||||
|
return to_python(x, lookup_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual boost::shared_ptr<T>& from_python_sTr(PyObject* p, type<boost::shared_ptr<T>&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual const boost::shared_ptr<T>& from_python_sT(PyObject* p, type<boost::shared_ptr<T> > t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual const boost::shared_ptr<T>& from_python_csTr(PyObject* p, type<const boost::shared_ptr<T>&> t) {
|
||||||
|
return from_python(p, t);
|
||||||
|
}
|
||||||
|
virtual PyObject* dispatcher_to_python(boost::shared_ptr<T> x) {
|
||||||
|
return to_python(x, lookup_tag());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The addditional to_python() converter that can be used if T is copyable.
|
||||||
|
template <class T>
|
||||||
|
struct export_converter_object : export_converter_object_noncopyable<T>
|
||||||
|
{
|
||||||
|
virtual PyObject* dispatcher_to_python(const T& x) {
|
||||||
|
return py_extension_class_converters(type<T>()).m_to_python(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/* This class template is instantiated by import_converters<T>.
|
||||||
|
Its purpose is to import the converter_object via the Python API.
|
||||||
|
The actual import is only done once. The pointer to the
|
||||||
|
imported converter object is kept in the static data member
|
||||||
|
imported_converters.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
class import_extension_class
|
||||||
|
: public python_import_extension_class_converters<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline import_extension_class(const char* module, const char* py_class) {
|
||||||
|
m_module = module;
|
||||||
|
m_py_class = py_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
static export_converter_object_base<T>* get_converters();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::string m_module;
|
||||||
|
static std::string m_py_class;
|
||||||
|
static export_converter_object_base<T>* imported_converters;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> std::string import_extension_class<T>::m_module;
|
||||||
|
template <class T> std::string import_extension_class<T>::m_py_class;
|
||||||
|
template <class T>
|
||||||
|
export_converter_object_base<T>*
|
||||||
|
import_extension_class<T>::imported_converters = 0;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
export_converter_object_base<T>*
|
||||||
|
import_extension_class<T>::get_converters() {
|
||||||
|
if (imported_converters == 0) {
|
||||||
|
void* cobject
|
||||||
|
= import_converter_object(m_module, m_py_class,
|
||||||
|
converters_attribute_name);
|
||||||
|
imported_converters
|
||||||
|
= static_cast<export_converter_object_base<T>*>(cobject);
|
||||||
|
check_export_converters_api(
|
||||||
|
export_converters_api_major,
|
||||||
|
export_converters_api_minor,
|
||||||
|
imported_converters->get_api_major(),
|
||||||
|
imported_converters->get_api_minor());
|
||||||
|
}
|
||||||
|
return imported_converters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}} // namespace boost::python::detail
|
||||||
|
|
||||||
|
namespace boost { namespace python {
|
||||||
|
|
||||||
|
// Implementation of export_converters().
|
||||||
|
template <class T, class U>
|
||||||
|
void export_converters(class_builder<T, U>& cb)
|
||||||
|
{
|
||||||
|
static export_converter_object<T> export_cvts;
|
||||||
|
cb.add(
|
||||||
|
ref(PyCObject_FromVoidPtr(reinterpret_cast<void*>(&export_cvts), NULL)),
|
||||||
|
detail::converters_attribute_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of export_converters_noncopyable().
|
||||||
|
template <class T, class U>
|
||||||
|
void export_converters_noncopyable(class_builder<T, U>& cb)
|
||||||
|
{
|
||||||
|
static export_converter_object_noncopyable<T> export_cvts;
|
||||||
|
cb.add(
|
||||||
|
ref(PyCObject_FromVoidPtr(reinterpret_cast<void*>(&export_cvts), NULL)),
|
||||||
|
detail::converters_attribute_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of import_converters<T>.
|
||||||
|
template <class T>
|
||||||
|
class import_converters
|
||||||
|
: python_import_extension_class_converters<T> // Works around MSVC6.x/GCC2.95.2 bug described
|
||||||
|
// at the bottom of class_builder.hpp.
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
import_converters(const char* module, const char* py_class)
|
||||||
|
: m_class(new detail::import_extension_class<T>(module, py_class))
|
||||||
|
{ }
|
||||||
|
private:
|
||||||
|
boost::shared_ptr<detail::import_extension_class<T> > m_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace boost::python
|
||||||
|
|
||||||
|
#endif // CROSS_MODULE_HPP
|
||||||
@@ -5,6 +5,9 @@
|
|||||||
//
|
//
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||||
|
|
||||||
#ifndef BASE_OBJECT_DWA051600_H_
|
#ifndef BASE_OBJECT_DWA051600_H_
|
||||||
# define BASE_OBJECT_DWA051600_H_
|
# define BASE_OBJECT_DWA051600_H_
|
||||||
@@ -46,9 +49,8 @@ base_object<python_type>::base_object(PyTypeObject* type_obj)
|
|||||||
std::
|
std::
|
||||||
#endif
|
#endif
|
||||||
memset(bp, 0, sizeof(base_python_type));
|
memset(bp, 0, sizeof(base_python_type));
|
||||||
ob_refcnt = 1;
|
|
||||||
ob_type = type_obj;
|
|
||||||
Py_INCREF(type_obj);
|
Py_INCREF(type_obj);
|
||||||
|
PyObject_INIT(bp, type_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class python_type>
|
template <class python_type>
|
||||||
|
|||||||
@@ -6,25 +6,16 @@
|
|||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
|
||||||
|
// Revision History:
|
||||||
|
// 24 May 01 friend lookup fixes (Ralf W. Grosse-Kunstleve)
|
||||||
|
// 04 Mar 01 Some fixes so it will compile with Intel C++ (Dave Abrahams)
|
||||||
|
|
||||||
#ifndef CONFIG_DWA052200_H_
|
#ifndef CONFIG_DWA052200_H_
|
||||||
# define CONFIG_DWA052200_H_
|
# define CONFIG_DWA052200_H_
|
||||||
|
|
||||||
# include <boost/config.hpp>
|
# include <boost/config.hpp>
|
||||||
# include <cstddef>
|
# include <cstddef>
|
||||||
|
|
||||||
# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
|
||||||
// A gcc bug forces some symbols into the global namespace
|
|
||||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
|
||||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|
||||||
# define BOOST_PYTHON_CONVERSION
|
|
||||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) using ::x
|
|
||||||
# else
|
|
||||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
|
|
||||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
|
|
||||||
# define BOOST_PYTHON_CONVERSION python
|
|
||||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';'
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if defined(BOOST_MSVC)
|
# if defined(BOOST_MSVC)
|
||||||
# if _MSC_VER <= 1200
|
# if _MSC_VER <= 1200
|
||||||
# define BOOST_MSVC6_OR_EARLIER 1
|
# define BOOST_MSVC6_OR_EARLIER 1
|
||||||
@@ -34,6 +25,29 @@
|
|||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# if defined(__GNUC__) && __GNUC__ < 3
|
||||||
|
# define BOOST_NO_FRIEND_KOENIG_LOOKUP
|
||||||
|
# endif
|
||||||
|
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
|
||||||
|
# define BOOST_NO_FRIEND_KOENIG_LOOKUP
|
||||||
|
# endif
|
||||||
|
# if defined(__DECCXX_VER) && __DECCXX_VER <= 60290024
|
||||||
|
# define BOOST_NO_FRIEND_KOENIG_LOOKUP
|
||||||
|
# endif
|
||||||
|
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730
|
||||||
|
# define BOOST_NO_FRIEND_KOENIG_LOOKUP
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(BOOST_NO_FRIEND_KOENIG_LOOKUP)
|
||||||
|
// for compilers that do not support Koenig lookup for friend functions
|
||||||
|
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
|
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
# else
|
||||||
|
// for compilers that support Koenig lookup
|
||||||
|
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
|
||||||
|
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
|
||||||
|
# endif
|
||||||
|
|
||||||
// Work around the broken library implementation/strict ansi checking on some
|
// Work around the broken library implementation/strict ansi checking on some
|
||||||
// EDG-based compilers (e.g. alpha), which incorrectly warn that the result of
|
// EDG-based compilers (e.g. alpha), which incorrectly warn that the result of
|
||||||
// offsetof() is not an integer constant expression.
|
// offsetof() is not an integer constant expression.
|
||||||
@@ -46,11 +60,18 @@
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
// The STLport puts all of the standard 'C' library names in std (as far as the
|
// The STLport puts all of the standard 'C' library names in std (as far as the
|
||||||
// user is concerned), but without it you need a fix if you're using MSVC.
|
// user is concerned), but without it you need a fix if you're using MSVC or
|
||||||
# if defined(BOOST_MSVC6_OR_EARLIER) && !defined(__STLPORT)
|
// Intel C++
|
||||||
|
# if defined(BOOST_MSVC_STD_ITERATOR)
|
||||||
# define BOOST_CSTD_
|
# define BOOST_CSTD_
|
||||||
# else
|
# else
|
||||||
# define BOOST_CSTD_ std
|
# define BOOST_CSTD_ std
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name()
|
||||||
|
#else
|
||||||
|
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name()
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // CONFIG_DWA052200_H_
|
#endif // CONFIG_DWA052200_H_
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
// (C) Copyright David Abrahams 2000-2001. Permission to copy, use, modify, sell and
|
||||||
// distribute this software is granted provided this copyright notice appears
|
// distribute this software is granted provided this copyright notice appears
|
||||||
// in all copies. This software is provided "as is" without express or implied
|
// 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.
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
@@ -6,9 +6,14 @@
|
|||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
//
|
//
|
||||||
// This file automatically generated for 5-argument constructors by
|
// This file automatically generated for 10-argument constructors by
|
||||||
// gen_extclass.python
|
// gen_extclass.python
|
||||||
|
|
||||||
|
// Revision History:
|
||||||
|
// 17 Apr 01 Comment added with reference to cross_module.hpp (R.W. Grosse-Kunstleve)
|
||||||
|
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
|
||||||
|
// to_python (Dave Abrahams)
|
||||||
|
|
||||||
#ifndef EXTENSION_CLASS_DWA052000_H_
|
#ifndef EXTENSION_CLASS_DWA052000_H_
|
||||||
# define EXTENSION_CLASS_DWA052000_H_
|
# define EXTENSION_CLASS_DWA052000_H_
|
||||||
|
|
||||||
@@ -22,6 +27,7 @@
|
|||||||
# include <boost/python/detail/init_function.hpp>
|
# include <boost/python/detail/init_function.hpp>
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
# include <boost/smart_ptr.hpp>
|
# include <boost/smart_ptr.hpp>
|
||||||
|
# include <boost/type_traits.hpp>
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
|
|
||||||
@@ -61,7 +67,7 @@ T* check_non_null(T* p)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> class held_instance;
|
template <class Held> class held_instance;
|
||||||
|
|
||||||
typedef void* (*conversion_function_ptr)(void*);
|
typedef void* (*conversion_function_ptr)(void*);
|
||||||
|
|
||||||
@@ -133,6 +139,26 @@ class class_registry
|
|||||||
static std::vector<derived_class_info> static_derived_class_info;
|
static std::vector<derived_class_info> static_derived_class_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <bool is_pointer>
|
||||||
|
struct is_null_helper
|
||||||
|
{
|
||||||
|
template <class Ptr>
|
||||||
|
static bool test(Ptr x) { return x == 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_null_helper<false>
|
||||||
|
{
|
||||||
|
template <class Ptr>
|
||||||
|
static bool test(const Ptr& x) { return x.get() == 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Ptr>
|
||||||
|
bool is_null(const Ptr& x)
|
||||||
|
{
|
||||||
|
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
|
||||||
|
}
|
||||||
|
|
||||||
}}} // namespace boost::python::detail
|
}}} // namespace boost::python::detail
|
||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
@@ -141,36 +167,45 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
|||||||
// and U. T is the class the user really intends to wrap. U is a class derived
|
// and U. T is the class the user really intends to wrap. U is a class derived
|
||||||
// from T with some virtual function overriding boilerplate, or if there are no
|
// from T with some virtual function overriding boilerplate, or if there are no
|
||||||
// virtual functions, U = held_instance<T>.
|
// virtual functions, U = held_instance<T>.
|
||||||
|
//
|
||||||
|
// A look-alike of this class in root/boost/python/cross_module.hpp
|
||||||
|
// is used for the implementation of the cross-module support
|
||||||
|
// (export_converters and import_converters). If from_python
|
||||||
|
// and to_python converters are added or removed from the class
|
||||||
|
// below, the class python_import_extension_class_converters has
|
||||||
|
// to be modified accordingly.
|
||||||
|
//
|
||||||
template <class T, class U = boost::python::detail::held_instance<T> >
|
template <class T, class U = boost::python::detail::held_instance<T> >
|
||||||
class python_extension_class_converters
|
class python_extension_class_converters
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Get an object which can be used to convert T to/from python. This is used
|
/// Get an object which can be used to convert T to/from python. This is used
|
||||||
// as a kind of concept check by the global template
|
/// as a kind of concept check by the free template function
|
||||||
//
|
///
|
||||||
// PyObject* to_python(const T& x)
|
/// PyObject* to_python(const T& x, boost::python::lookup_tag)
|
||||||
//
|
///
|
||||||
// below this class, to prevent the confusing messages that would otherwise
|
/// below this class, to prevent the confusing messages that would otherwise
|
||||||
// pop up. Now, if T hasn't been wrapped as an extension class, the user
|
/// pop up. Now, if T hasn't been wrapped as an extension class, the user
|
||||||
// will see an error message about the lack of an eligible
|
/// will see an error message about the lack of an eligible
|
||||||
// py_extension_class_converters() function.
|
/// py_extension_class_converters() function.
|
||||||
friend python_extension_class_converters py_extension_class_converters(boost::python::type<T>)
|
friend python_extension_class_converters py_extension_class_converters(
|
||||||
|
boost::python::type<T>)
|
||||||
{
|
{
|
||||||
return python_extension_class_converters();
|
return python_extension_class_converters();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a member function because in a conforming implementation, friend
|
/// This is a member function because in a conforming implementation, friend
|
||||||
// funcitons defined inline in the class body are all instantiated as soon
|
/// functions defined inline in the class body are all instantiated as soon
|
||||||
// as the enclosing class is instantiated. If T is not copyable, that causes
|
/// as the enclosing class is instantiated. If T is not copyable, that causes
|
||||||
// a compiler error. Instead, we access this function through the global
|
/// a compiler error. Instead, we access this function through the global
|
||||||
// template
|
/// template
|
||||||
//
|
///
|
||||||
// PyObject* to_python(const T& x)
|
/// PyObject* to_python(const T& x, boost::python::lookup_tag)
|
||||||
//
|
///
|
||||||
// defined below this class. Since template functions are instantiated only
|
/// defined below this class. Since template functions are instantiated only
|
||||||
// on demand, errors will be avoided unless T is noncopyable and the user
|
/// on demand, errors will be avoided unless T is noncopyable and the user
|
||||||
// writes code which causes us to try to copy a T.
|
/// writes code which causes us to try to copy a T.
|
||||||
PyObject* to_python(const T& x) const
|
PyObject* m_to_python(const T& x) const
|
||||||
{
|
{
|
||||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||||
result->add_implementation(
|
result->add_implementation(
|
||||||
@@ -178,9 +213,10 @@ class python_extension_class_converters
|
|||||||
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
|
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
|
||||||
return result.release();
|
return result.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to T*
|
/// Extract a pointer to T from the given PyObject. Will throw argument_error if obj == None.
|
||||||
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
friend
|
||||||
|
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
|
||||||
{
|
{
|
||||||
// downcast to an extension_instance, then find the actual T
|
// downcast to an extension_instance, then find the actual T
|
||||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||||
@@ -201,9 +237,16 @@ class python_extension_class_converters
|
|||||||
throw boost::python::argument_error();
|
throw boost::python::argument_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to PtrType, where PtrType can be dereferenced to obtain a T.
|
/// Convert obj to T*. If obj == None, returns 0.
|
||||||
|
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
||||||
|
{
|
||||||
|
if (obj == Py_None) return 0;
|
||||||
|
return non_null_from_python(obj, boost::python::type<T*>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract from obj a mutable reference to the PtrType object which is holding a T.
|
||||||
template <class PtrType>
|
template <class PtrType>
|
||||||
static PtrType& ptr_from_python(PyObject* obj, boost::python::type<PtrType>)
|
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
|
||||||
{
|
{
|
||||||
// downcast to an extension_instance, then find the actual T
|
// downcast to an extension_instance, then find the actual T
|
||||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||||
@@ -220,9 +263,31 @@ class python_extension_class_converters
|
|||||||
throw boost::python::argument_error();
|
throw boost::python::argument_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract from obj a reference to the PtrType object which is holding a
|
||||||
|
/// T. If it weren't for auto_ptr, it would be a constant reference. Do not
|
||||||
|
/// modify the referent except by copying an auto_ptr! If obj is None, the
|
||||||
|
/// reference denotes a default-constructed PtrType
|
||||||
template <class PtrType>
|
template <class PtrType>
|
||||||
static PyObject* ptr_to_python(PtrType x)
|
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
|
||||||
{
|
{
|
||||||
|
if (obj == Py_None)
|
||||||
|
{
|
||||||
|
static PtrType null_ptr;
|
||||||
|
return null_ptr;
|
||||||
|
}
|
||||||
|
return smart_ptr_reference(obj, boost::python::type<PtrType>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrap x in a Python object which implements the functionality of a
|
||||||
|
/// regular wrapped T by dereferencing a copy of x.
|
||||||
|
template <class PtrType>
|
||||||
|
static PyObject* smart_ptr_to_python(PtrType x)
|
||||||
|
{
|
||||||
|
if (boost::python::detail::is_null(x))
|
||||||
|
{
|
||||||
|
return boost::python::detail::none();
|
||||||
|
}
|
||||||
|
|
||||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||||
result->add_implementation(
|
result->add_implementation(
|
||||||
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
||||||
@@ -230,6 +295,9 @@ class python_extension_class_converters
|
|||||||
return result.release();
|
return result.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a Python object which is an instance of the Python type wrapper
|
||||||
|
/// for T. The result does not actually contain the neccessary instance of
|
||||||
|
/// T. This function is an implementation detail.
|
||||||
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
|
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
|
||||||
{
|
{
|
||||||
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
|
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
|
||||||
@@ -240,53 +308,53 @@ class python_extension_class_converters
|
|||||||
new boost::python::detail::extension_instance(class_object));
|
new boost::python::detail::extension_instance(class_object));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to const T*
|
/// Convert p to const T*
|
||||||
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
|
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
|
||||||
{ return from_python(p, boost::python::type<T*>()); }
|
{ return from_python(p, boost::python::type<T*>()); }
|
||||||
|
|
||||||
// Convert to const T* const&
|
/// Convert p to const T* const&
|
||||||
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
|
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
|
||||||
{ return from_python(p, boost::python::type<const T*>()); }
|
{ return from_python(p, boost::python::type<const T*>()); }
|
||||||
|
|
||||||
// Convert to T* const&
|
/// Convert p to T* const&
|
||||||
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
|
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
|
||||||
{ return from_python(p, boost::python::type<T*>()); }
|
{ return from_python(p, boost::python::type<T*>()); }
|
||||||
|
|
||||||
// Convert to T&
|
// Convert to T&
|
||||||
friend T& from_python(PyObject* p, boost::python::type<T&>)
|
friend T& from_python(PyObject* p, boost::python::type<T&>)
|
||||||
{ return *boost::python::detail::check_non_null(from_python(p, boost::python::type<T*>())); }
|
{ return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type<T*>())); }
|
||||||
|
|
||||||
// Convert to const T&
|
// Convert p to const T&
|
||||||
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
|
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
|
||||||
{ return from_python(p, boost::python::type<T&>()); }
|
{ return from_python(p, boost::python::type<T&>()); }
|
||||||
|
|
||||||
// Convert to T
|
/// Convert p to T
|
||||||
friend const T& from_python(PyObject* p, boost::python::type<T>)
|
friend const T& from_python(PyObject* p, boost::python::type<T>)
|
||||||
{ return from_python(p, boost::python::type<T&>()); }
|
{ return from_python(p, boost::python::type<T&>()); }
|
||||||
|
|
||||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
|
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
{ return smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||||
|
|
||||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
||||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||||
|
|
||||||
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
|
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||||
|
|
||||||
friend PyObject* to_python(std::auto_ptr<T> x)
|
friend PyObject* to_python(std::auto_ptr<T> x, boost::python::lookup_tag)
|
||||||
{ return ptr_to_python(x); }
|
{ return smart_ptr_to_python(x); }
|
||||||
|
|
||||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
{ return smart_ptr_reference(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||||
|
|
||||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
||||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||||
|
|
||||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
|
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||||
|
|
||||||
friend PyObject* to_python(boost::shared_ptr<T> x)
|
friend PyObject* to_python(boost::shared_ptr<T> x, boost::python::lookup_tag)
|
||||||
{ return ptr_to_python(x); }
|
{ return smart_ptr_to_python(x); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert T to_python, instantiated on demand and only if there isn't a
|
// Convert T to_python, instantiated on demand and only if there isn't a
|
||||||
@@ -294,17 +362,15 @@ class python_extension_class_converters
|
|||||||
// T is a wrapped class. See the first 2 functions declared in
|
// T is a wrapped class. See the first 2 functions declared in
|
||||||
// python_extension_class_converters above for more info.
|
// python_extension_class_converters above for more info.
|
||||||
template <class T>
|
template <class T>
|
||||||
PyObject* to_python(const T& x)
|
PyObject* to_python(const T& x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return py_extension_class_converters(boost::python::type<T>()).to_python(x);
|
return py_extension_class_converters(boost::python::type<T>()).m_to_python(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
|
|
||||||
BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters);
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <class T> class instance_holder;
|
template <class T> class instance_holder;
|
||||||
@@ -363,8 +429,8 @@ class extension_class
|
|||||||
~extension_class();
|
~extension_class();
|
||||||
|
|
||||||
// define constructors
|
// define constructors
|
||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
inline void def(constructor<A1, A2, A3, A4, A5>)
|
inline void def(constructor<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>)
|
||||||
// The following incantation builds a signature1, signature2,... object. It
|
// The following incantation builds a signature1, signature2,... object. It
|
||||||
// should _all_ get optimized away.
|
// should _all_ get optimized away.
|
||||||
{ add_constructor(
|
{ add_constructor(
|
||||||
@@ -373,7 +439,12 @@ class extension_class
|
|||||||
prepend(type<A3>::id(),
|
prepend(type<A3>::id(),
|
||||||
prepend(type<A4>::id(),
|
prepend(type<A4>::id(),
|
||||||
prepend(type<A5>::id(),
|
prepend(type<A5>::id(),
|
||||||
signature0()))))));
|
prepend(type<A6>::id(),
|
||||||
|
prepend(type<A7>::id(),
|
||||||
|
prepend(type<A8>::id(),
|
||||||
|
prepend(type<A9>::id(),
|
||||||
|
prepend(type<A10>::id(),
|
||||||
|
signature0())))))))))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -608,23 +679,33 @@ class extension_class
|
|||||||
|
|
||||||
// A simple wrapper over a T which allows us to use extension_class<T> with a
|
// A simple wrapper over a T which allows us to use extension_class<T> with a
|
||||||
// single template parameter only. See extension_class<T>, above.
|
// single template parameter only. See extension_class<T>, above.
|
||||||
template <class T>
|
template <class Held>
|
||||||
class held_instance : public T
|
class held_instance : public Held
|
||||||
{
|
{
|
||||||
// There are no member functions: we want to avoid inadvertently overriding
|
// There are no member functions: we want to avoid inadvertently overriding
|
||||||
// any virtual functions in T.
|
// any virtual functions in Held.
|
||||||
public:
|
public:
|
||||||
held_instance(PyObject*) : T() {}
|
held_instance(PyObject*) : Held() {}
|
||||||
template <class A1>
|
template <class A1>
|
||||||
held_instance(PyObject*, A1 a1) : T(a1) {}
|
held_instance(PyObject*, A1 a1) : Held(a1) {}
|
||||||
template <class A1, class A2>
|
template <class A1, class A2>
|
||||||
held_instance(PyObject*, A1 a1, A2 a2) : T(a1, a2) {}
|
held_instance(PyObject*, A1 a1, A2 a2) : Held(a1, a2) {}
|
||||||
template <class A1, class A2, class A3>
|
template <class A1, class A2, class A3>
|
||||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3) {}
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held(a1, a2, a3) {}
|
||||||
template <class A1, class A2, class A3, class A4>
|
template <class A1, class A2, class A3, class A4>
|
||||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {}
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held(a1, a2, a3, a4) {}
|
||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5>
|
||||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {}
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : Held(a1, a2, a3, a4, a5) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : Held(a1, a2, a3, a4, a5, a6) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : Held(a1, a2, a3, a4, a5, a6, a7) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : Held(a1, a2, a3, a4, a5, a6, a7, a8) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : Held(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
|
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : Held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract base class for all obj holders. Base for template class
|
// Abstract base class for all obj holders. Base for template class
|
||||||
@@ -676,6 +757,21 @@ public:
|
|||||||
template <class A1, class A2, class A3, class A4, class A5>
|
template <class A1, class A2, class A3, class A4, class A5>
|
||||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
|
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
|
||||||
m_held(p, a1, a2, a3, a4, a5) {}
|
m_held(p, a1, a2, a3, a4, a5) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
|
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
|
||||||
|
m_held(p, a1, a2, a3, a4, a5, a6) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
|
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
|
||||||
|
m_held(p, a1, a2, a3, a4, a5, a6, a7) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
|
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
|
||||||
|
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
|
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
|
||||||
|
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
|
||||||
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
|
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
|
||||||
|
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||||
|
|
||||||
public: // implementation of instance_holder_base required interface
|
public: // implementation of instance_holder_base required interface
|
||||||
bool held_by_value() { return true; }
|
bool held_by_value() { return true; }
|
||||||
@@ -721,8 +817,6 @@ class extension_instance : public instance
|
|||||||
// Template function implementations
|
// Template function implementations
|
||||||
//
|
//
|
||||||
|
|
||||||
tuple extension_class_coerce(ref l, ref r);
|
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
extension_class<T, U>::extension_class()
|
extension_class<T, U>::extension_class()
|
||||||
: extension_class_base(typeid(T).name())
|
: extension_class_base(typeid(T).name())
|
||||||
@@ -743,7 +837,7 @@ void extension_class<T, U>::def_standard_coerce()
|
|||||||
ref coerce_fct = dict().get_item(string("__coerce__"));
|
ref coerce_fct = dict().get_item(string("__coerce__"));
|
||||||
|
|
||||||
if(coerce_fct.get() == 0) // not yet defined
|
if(coerce_fct.get() == 0) // not yet defined
|
||||||
this->def(&extension_class_coerce, "__coerce__");
|
this->def(&standard_coerce, "__coerce__");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
@@ -831,4 +925,3 @@ std::vector<derived_class_info> class_registry<T>::static_derived_class_info;
|
|||||||
}}} // namespace boost::python::detail
|
}}} // namespace boost::python::detail
|
||||||
|
|
||||||
#endif // EXTENSION_CLASS_DWA052000_H_
|
#endif // EXTENSION_CLASS_DWA052000_H_
|
||||||
|
|
||||||
|
|||||||
@@ -95,8 +95,9 @@ struct raw_arguments_function : function
|
|||||||
ref(PyDict_New()));
|
ref(PyDict_New()));
|
||||||
|
|
||||||
return to_python(
|
return to_python(
|
||||||
(*m_pf)(from_python(args, boost::python::type<Args>()),
|
(*m_pf)(from_python(args, type<Args>()),
|
||||||
from_python(dict.get(), boost::python::type<Keywords>())));
|
from_python(dict.get(), type<Keywords>())),
|
||||||
|
lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* description() const
|
const char* description() const
|
||||||
@@ -263,8 +264,8 @@ PyObject* getter_function<ClassType, MemberType>::do_call(
|
|||||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return to_python(
|
return to_python(from_python(self, type<const ClassType*>())->*m_pm,
|
||||||
from_python(self, type<const ClassType*>())->*m_pm);
|
lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ClassType, class MemberType>
|
template <class ClassType, class MemberType>
|
||||||
|
|||||||
@@ -110,11 +110,11 @@ template <class T, class A1, class A2> struct init2;
|
|||||||
template <class T, class A1, class A2, class A3> struct init3;
|
template <class T, class A1, class A2, class A3> struct init3;
|
||||||
template <class T, class A1, class A2, class A3, class A4> struct init4;
|
template <class T, class A1, class A2, class A3, class A4> struct init4;
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5> struct init5;
|
template <class T, class A1, class A2, class A3, class A4, class A5> struct init5;
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct Init6;
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct init6;
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct Init7;
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct init7;
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct Init8;
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct init8;
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct Init9;
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct init9;
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct Init10;
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct init10;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct init_function
|
struct init_function
|
||||||
@@ -165,7 +165,7 @@ struct init_function
|
|||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
|
static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
|
||||||
return new Init6<T,
|
return new init6<T,
|
||||||
detail::parameter_traits<A1>::const_reference,
|
detail::parameter_traits<A1>::const_reference,
|
||||||
detail::parameter_traits<A2>::const_reference,
|
detail::parameter_traits<A2>::const_reference,
|
||||||
detail::parameter_traits<A3>::const_reference,
|
detail::parameter_traits<A3>::const_reference,
|
||||||
@@ -176,7 +176,7 @@ struct init_function
|
|||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
|
static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
|
||||||
return new Init7<T,
|
return new init7<T,
|
||||||
detail::parameter_traits<A1>::const_reference,
|
detail::parameter_traits<A1>::const_reference,
|
||||||
detail::parameter_traits<A2>::const_reference,
|
detail::parameter_traits<A2>::const_reference,
|
||||||
detail::parameter_traits<A3>::const_reference,
|
detail::parameter_traits<A3>::const_reference,
|
||||||
@@ -188,7 +188,7 @@ struct init_function
|
|||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
|
static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
|
||||||
return new Init8<T,
|
return new init8<T,
|
||||||
detail::parameter_traits<A1>::const_reference,
|
detail::parameter_traits<A1>::const_reference,
|
||||||
detail::parameter_traits<A2>::const_reference,
|
detail::parameter_traits<A2>::const_reference,
|
||||||
detail::parameter_traits<A3>::const_reference,
|
detail::parameter_traits<A3>::const_reference,
|
||||||
@@ -201,7 +201,7 @@ struct init_function
|
|||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
|
static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
|
||||||
return new Init9<T,
|
return new init9<T,
|
||||||
detail::parameter_traits<A1>::const_reference,
|
detail::parameter_traits<A1>::const_reference,
|
||||||
detail::parameter_traits<A2>::const_reference,
|
detail::parameter_traits<A2>::const_reference,
|
||||||
detail::parameter_traits<A3>::const_reference,
|
detail::parameter_traits<A3>::const_reference,
|
||||||
@@ -215,7 +215,7 @@ struct init_function
|
|||||||
|
|
||||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
|
static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
|
||||||
return new Init10<T,
|
return new init10<T,
|
||||||
detail::parameter_traits<A1>::const_reference,
|
detail::parameter_traits<A1>::const_reference,
|
||||||
detail::parameter_traits<A2>::const_reference,
|
detail::parameter_traits<A2>::const_reference,
|
||||||
detail::parameter_traits<A3>::const_reference,
|
detail::parameter_traits<A3>::const_reference,
|
||||||
@@ -353,7 +353,7 @@ struct init5 : init
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||||
struct Init6 : init
|
struct init6 : init
|
||||||
{
|
{
|
||||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||||
{
|
{
|
||||||
@@ -379,7 +379,7 @@ struct Init6 : init
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||||
struct Init7 : init
|
struct init7 : init
|
||||||
{
|
{
|
||||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||||
{
|
{
|
||||||
@@ -407,7 +407,7 @@ struct Init7 : init
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||||
struct Init8 : init
|
struct init8 : init
|
||||||
{
|
{
|
||||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||||
{
|
{
|
||||||
@@ -437,7 +437,7 @@ struct Init8 : init
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||||
struct Init9 : init
|
struct init9 : init
|
||||||
{
|
{
|
||||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||||
{
|
{
|
||||||
@@ -469,7 +469,7 @@ struct Init9 : init
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||||
struct Init10 : init
|
struct init10 : init
|
||||||
{
|
{
|
||||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,30 @@
|
|||||||
|
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||||
|
// distribute this software is granted provided this copyright notice appears
|
||||||
|
// in all copies. This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
|
// producing this work.
|
||||||
|
|
||||||
|
// This file serves as a wrapper around <Python.h> which allows it to be
|
||||||
|
// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC
|
||||||
|
// behavior so that a program may be compiled in debug mode without requiring a
|
||||||
|
// special debugging build of the Python library.
|
||||||
|
|
||||||
|
|
||||||
|
// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the
|
||||||
|
// compiler command-line.
|
||||||
|
|
||||||
|
// Revision History:
|
||||||
|
// 05 Mar 01 Suppress warnings under Cygwin with Python 2.0 (Dave Abrahams)
|
||||||
|
// 04 Mar 01 Rolled in some changes from the Dragon fork (Dave Abrahams)
|
||||||
|
// 01 Mar 01 define PyObject_INIT() for Python 1.x (Dave Abrahams)
|
||||||
|
|
||||||
|
|
||||||
|
#include <patchlevel.h>
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
# ifndef DEBUG_PYTHON
|
# ifndef BOOST_DEBUG_PYTHON
|
||||||
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
|
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
|
||||||
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||||
# endif
|
# endif
|
||||||
@@ -16,9 +41,11 @@ typedef int pid_t;
|
|||||||
# define WORD_BIT 32
|
# define WORD_BIT 32
|
||||||
# define hypot _hypot
|
# define hypot _hypot
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# define HAVE_CLOCK
|
# if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||||
# define HAVE_STRFTIME
|
# define HAVE_CLOCK
|
||||||
# define HAVE_STRERROR
|
# define HAVE_STRFTIME
|
||||||
|
# define HAVE_STRERROR
|
||||||
|
# endif
|
||||||
# define NT_THREADS
|
# define NT_THREADS
|
||||||
# define WITH_THREAD
|
# define WITH_THREAD
|
||||||
# ifndef NETSCAPE_PI
|
# ifndef NETSCAPE_PI
|
||||||
@@ -44,6 +71,8 @@ typedef int pid_t;
|
|||||||
# define _MSC_VER 900
|
# define _MSC_VER 900
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# include <limits> // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
@@ -59,3 +88,7 @@ typedef int pid_t;
|
|||||||
# define _DEBUG
|
# define _DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||||
|
# define PyObject_INIT(op, typeobj) \
|
||||||
|
( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -18,11 +18,10 @@ namespace boost { namespace python {
|
|||||||
|
|
||||||
class module_builder
|
class module_builder
|
||||||
{
|
{
|
||||||
typedef PyObject * (*raw_function_ptr)(boost::python::tuple const &, boost::python::dictionary const &);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create a module. REQUIRES: only one module_builder is created per module.
|
// Create a module. REQUIRES: only one module_builder is created per module.
|
||||||
module_builder(const char* name);
|
module_builder(const char* name);
|
||||||
|
~module_builder();
|
||||||
|
|
||||||
// Add elements to the module
|
// Add elements to the module
|
||||||
void add(detail::function* x, const char* name);
|
void add(detail::function* x, const char* name);
|
||||||
@@ -41,13 +40,29 @@ class module_builder
|
|||||||
add(detail::new_wrapped_function(fn), name);
|
add(detail::new_wrapped_function(fn), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static string name();
|
// Return true iff a module is currently being built.
|
||||||
|
static bool initializing();
|
||||||
|
|
||||||
|
// Return the name of the module currently being built.
|
||||||
|
// REQUIRES: initializing() == true
|
||||||
|
static string name();
|
||||||
|
|
||||||
|
// Return a pointer to the Python module object being built
|
||||||
|
PyObject* module() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PyObject* m_module;
|
PyObject* m_module;
|
||||||
static PyMethodDef initial_methods[1];
|
static PyMethodDef initial_methods[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// inline implementations
|
||||||
|
//
|
||||||
|
inline PyObject* module_builder::module() const
|
||||||
|
{
|
||||||
|
return m_module;
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace boost::python
|
}} // namespace boost::python
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ struct list::slice_proxy
|
|||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::tuple&);
|
PyObject* to_python(const boost::python::tuple&, boost::python::lookup_tag);
|
||||||
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple>);
|
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple>);
|
||||||
|
|
||||||
inline boost::python::tuple from_python(PyObject* p, boost::python::type<const boost::python::tuple&>)
|
inline boost::python::tuple from_python(PyObject* p, boost::python::type<const boost::python::tuple&>)
|
||||||
@@ -305,7 +305,7 @@ inline boost::python::tuple from_python(PyObject* p, boost::python::type<const b
|
|||||||
return from_python(p, boost::python::type<boost::python::tuple>());
|
return from_python(p, boost::python::type<boost::python::tuple>());
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::list&);
|
PyObject* to_python(const boost::python::list&, boost::python::lookup_tag);
|
||||||
boost::python::list from_python(PyObject* p, boost::python::type<boost::python::list>);
|
boost::python::list from_python(PyObject* p, boost::python::type<boost::python::list>);
|
||||||
|
|
||||||
inline boost::python::list from_python(PyObject* p, boost::python::type<const boost::python::list&>)
|
inline boost::python::list from_python(PyObject* p, boost::python::type<const boost::python::list&>)
|
||||||
@@ -313,7 +313,7 @@ inline boost::python::list from_python(PyObject* p, boost::python::type<const bo
|
|||||||
return from_python(p, boost::python::type<boost::python::list>());
|
return from_python(p, boost::python::type<boost::python::list>());
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::string&);
|
PyObject* to_python(const boost::python::string&, boost::python::lookup_tag);
|
||||||
boost::python::string from_python(PyObject* p, boost::python::type<boost::python::string>);
|
boost::python::string from_python(PyObject* p, boost::python::type<boost::python::string>);
|
||||||
|
|
||||||
inline boost::python::string from_python(PyObject* p, boost::python::type<const boost::python::string&>)
|
inline boost::python::string from_python(PyObject* p, boost::python::type<const boost::python::string&>)
|
||||||
@@ -321,7 +321,7 @@ inline boost::python::string from_python(PyObject* p, boost::python::type<const
|
|||||||
return from_python(p, boost::python::type<boost::python::string>());
|
return from_python(p, boost::python::type<boost::python::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::dictionary&);
|
PyObject* to_python(const boost::python::dictionary&, boost::python::lookup_tag);
|
||||||
boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::python::dictionary>);
|
boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::python::dictionary>);
|
||||||
|
|
||||||
inline boost::python::dictionary from_python(PyObject* p, boost::python::type<const boost::python::dictionary&>)
|
inline boost::python::dictionary from_python(PyObject* p, boost::python::type<const boost::python::dictionary&>)
|
||||||
|
|||||||
@@ -1,15 +1,38 @@
|
|||||||
|
// (C) Copyright Ullrich Koethe and David Abrahams 2000-2001. Permission to
|
||||||
|
// copy, use, modify, sell and distribute this software is granted provided
|
||||||
|
// this copyright notice appears in all copies. This software is provided "as
|
||||||
|
// is" without express or implied warranty, and with no claim as to its
|
||||||
|
// suitability for any purpose.
|
||||||
|
//
|
||||||
|
// The authors gratefully acknowlege the support of Dragon Systems, Inc., in
|
||||||
|
// producing this work.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// 23 Jan 2001 - Another stupid typo fix by Ralf W. Grosse-Kunstleve (David Abrahams)
|
||||||
|
// 20 Jan 2001 - Added a fix from Ralf W. Grosse-Kunstleve (David Abrahams)
|
||||||
#ifndef OPERATORS_UK112000_H_
|
#ifndef OPERATORS_UK112000_H_
|
||||||
#define OPERATORS_UK112000_H_
|
#define OPERATORS_UK112000_H_
|
||||||
|
|
||||||
#include <boost/python/detail/functions.hpp>
|
# include <boost/python/reference.hpp>
|
||||||
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
|
# include <boost/python/detail/functions.hpp>
|
||||||
# include <sstream>
|
|
||||||
#else
|
// When STLport is used with native streams, _STL::ostringstream().str() is not
|
||||||
# include <strstream>
|
// _STL::string, but std::string. This confuses to_python(), so we'll use
|
||||||
#endif
|
// strstream instead. Also, GCC 2.95.2 doesn't have sstream.
|
||||||
|
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||||
|
# define BOOST_PYTHON_USE_SSTREAM
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#if defined(BOOST_PYTHON_USE_SSTREAM)
|
||||||
|
# include <sstream>
|
||||||
|
# else
|
||||||
|
# include <strstream>
|
||||||
|
# endif
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
|
|
||||||
|
tuple standard_coerce(ref l, ref r);
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// helper class for automatic operand type detection
|
// helper class for automatic operand type detection
|
||||||
@@ -214,11 +237,11 @@ namespace detail
|
|||||||
{ \
|
{ \
|
||||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
||||||
{ \
|
{ \
|
||||||
tuple args(ref(arguments, ref::increment_count)); \
|
tuple args(ref(arguments, ref::increment_count)); \
|
||||||
\
|
\
|
||||||
return BOOST_PYTHON_CONVERSION::to_python( \
|
return to_python( \
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) oper \
|
from_python(args[0].get(), type<Left>()) oper \
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())); \
|
from_python(args[1].get(), type<Right>()), lookup_tag()); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
const char* description() const \
|
const char* description() const \
|
||||||
@@ -230,11 +253,11 @@ namespace detail
|
|||||||
{ \
|
{ \
|
||||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
||||||
{ \
|
{ \
|
||||||
tuple args(ref(arguments, ref::increment_count)); \
|
tuple args(ref(arguments, ref::increment_count)); \
|
||||||
\
|
\
|
||||||
return BOOST_PYTHON_CONVERSION::to_python( \
|
return to_python( \
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) oper \
|
from_python(args[1].get(), type<Left>()) oper \
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())); \
|
from_python(args[0].get(), type<Right>()), lookup_tag()); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
const char* description() const \
|
const char* description() const \
|
||||||
@@ -255,10 +278,10 @@ namespace detail
|
|||||||
{ \
|
{ \
|
||||||
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \
|
||||||
{ \
|
{ \
|
||||||
tuple args(ref(arguments, ref::increment_count)); \
|
tuple args(ref(arguments, ref::increment_count)); \
|
||||||
\
|
\
|
||||||
return BOOST_PYTHON_CONVERSION::to_python( \
|
return to_python( \
|
||||||
oper(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()))); \
|
oper(from_python(args[0].get(), type<operand>())), lookup_tag()); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
const char* description() const \
|
const char* description() const \
|
||||||
@@ -312,9 +335,9 @@ namespace detail
|
|||||||
throw argument_error();
|
throw argument_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
return BOOST_PYTHON_CONVERSION::to_python(
|
return to_python(
|
||||||
pow(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()),
|
pow(from_python(args[0].get(), type<Left>()),
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())));
|
from_python(args[1].get(), type<Right>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* description() const
|
const char* description() const
|
||||||
@@ -335,9 +358,9 @@ namespace detail
|
|||||||
throw argument_error();
|
throw argument_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
return BOOST_PYTHON_CONVERSION::to_python(
|
return to_python(
|
||||||
pow(BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()),
|
pow(from_python(args[1].get(), type<Left>()),
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())));
|
from_python(args[0].get(), type<Right>())), lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* description() const
|
const char* description() const
|
||||||
@@ -363,13 +386,11 @@ namespace detail
|
|||||||
PyObject * res = PyTuple_New(2);
|
PyObject * res = PyTuple_New(2);
|
||||||
|
|
||||||
PyTuple_SET_ITEM(res, 0,
|
PyTuple_SET_ITEM(res, 0,
|
||||||
BOOST_PYTHON_CONVERSION::to_python(
|
to_python(from_python(args[0].get(), type<Left>()) /
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) /
|
from_python(args[1].get(), type<Right>()), lookup_tag()));
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())));
|
|
||||||
PyTuple_SET_ITEM(res, 1,
|
PyTuple_SET_ITEM(res, 1,
|
||||||
BOOST_PYTHON_CONVERSION::to_python(
|
to_python(from_python(args[0].get(), type<Left>()) %
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) %
|
from_python(args[1].get(), type<Right>()), lookup_tag()));
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())));
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -388,13 +409,11 @@ namespace detail
|
|||||||
PyObject * res = PyTuple_New(2);
|
PyObject * res = PyTuple_New(2);
|
||||||
|
|
||||||
PyTuple_SET_ITEM(res, 0,
|
PyTuple_SET_ITEM(res, 0,
|
||||||
BOOST_PYTHON_CONVERSION::to_python(
|
to_python(from_python(args[1].get(), type<Left>()) /
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) /
|
from_python(args[0].get(), type<Right>()), lookup_tag()));
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())));
|
|
||||||
PyTuple_SET_ITEM(res, 1,
|
PyTuple_SET_ITEM(res, 1,
|
||||||
BOOST_PYTHON_CONVERSION::to_python(
|
to_python(from_python(args[1].get(), type<Left>()) %
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) %
|
from_python(args[0].get(), type<Right>()), lookup_tag()));
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())));
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -420,14 +439,14 @@ namespace detail
|
|||||||
{
|
{
|
||||||
tuple args(ref(arguments, ref::increment_count));
|
tuple args(ref(arguments, ref::increment_count));
|
||||||
|
|
||||||
return BOOST_PYTHON_CONVERSION::to_python(
|
return to_python(
|
||||||
(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>()) <
|
(from_python(args[0].get(), type<Left>()) <
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>())) ?
|
from_python(args[1].get(), type<Right>())) ?
|
||||||
- 1 :
|
- 1 :
|
||||||
(BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Right>()) <
|
(from_python(args[1].get(), type<Right>()) <
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Left>())) ?
|
from_python(args[0].get(), type<Left>())) ?
|
||||||
1 :
|
1 :
|
||||||
0) ;
|
0, lookup_tag()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* description() const
|
const char* description() const
|
||||||
@@ -442,14 +461,14 @@ namespace detail
|
|||||||
{
|
{
|
||||||
tuple args(ref(arguments, ref::increment_count));
|
tuple args(ref(arguments, ref::increment_count));
|
||||||
|
|
||||||
return BOOST_PYTHON_CONVERSION::to_python(
|
return to_python(
|
||||||
(BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>()) <
|
(from_python(args[1].get(), type<Left>()) <
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>())) ?
|
from_python(args[0].get(), type<Right>())) ?
|
||||||
- 1 :
|
- 1 :
|
||||||
(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<Right>()) <
|
(from_python(args[0].get(), type<Right>()) <
|
||||||
BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<Left>())) ?
|
from_python(args[1].get(), type<Left>())) ?
|
||||||
1 :
|
1 :
|
||||||
0) ;
|
0, lookup_tag()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* description() const
|
const char* description() const
|
||||||
@@ -461,6 +480,16 @@ namespace detail
|
|||||||
static const char * rname() { return "__rcmp__"; }
|
static const char * rname() { return "__rcmp__"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# ifndef BOOST_PYTHON_USE_SSTREAM
|
||||||
|
class unfreezer {
|
||||||
|
public:
|
||||||
|
unfreezer(std::ostrstream& s) : m_stream(s) {}
|
||||||
|
~unfreezer() { m_stream.freeze(false); }
|
||||||
|
private:
|
||||||
|
std::ostrstream& m_stream;
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
// str(): Manual specialization needed because the string conversion does not follow
|
// str(): Manual specialization needed because the string conversion does not follow
|
||||||
// the standard pattern relized by the macros.
|
// the standard pattern relized by the macros.
|
||||||
template <>
|
template <>
|
||||||
@@ -473,19 +502,18 @@ namespace detail
|
|||||||
{
|
{
|
||||||
tuple args(ref(arguments, ref::increment_count));
|
tuple args(ref(arguments, ref::increment_count));
|
||||||
|
|
||||||
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
|
// When STLport is used with native streams, _STL::ostringstream().str() is not
|
||||||
|
// _STL::string, but std::string.
|
||||||
|
# ifdef BOOST_PYTHON_USE_SSTREAM
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>());
|
s << from_python(args[0].get(), type<operand>());
|
||||||
#else
|
return to_python(s.str(), lookup_tag());
|
||||||
|
# else
|
||||||
std::ostrstream s;
|
std::ostrstream s;
|
||||||
s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<operand>()) << char();
|
s << from_python(args[0].get(), type<operand>()) << char();
|
||||||
#endif
|
auto unfreezer unfreeze(s);
|
||||||
|
return to_python(const_cast<char const *>(s.str()), lookup_tag());
|
||||||
#if !defined(__GNUC__) || defined(__SGI_STL_PORT)
|
# endif
|
||||||
return BOOST_PYTHON_CONVERSION::to_python(s.str());
|
|
||||||
#else
|
|
||||||
return BOOST_PYTHON_CONVERSION::to_python(const_cast<char const *>(s.str()));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* description() const
|
const char* description() const
|
||||||
@@ -501,4 +529,5 @@ namespace detail
|
|||||||
|
|
||||||
}} // namespace boost::python
|
}} // namespace boost::python
|
||||||
|
|
||||||
|
# undef BOOST_PYTHON_USE_SSTREAM
|
||||||
#endif /* OPERATORS_UK112000_H_ */
|
#endif /* OPERATORS_UK112000_H_ */
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ struct py_ptr_conversions : Base
|
|||||||
inline friend T from_python(PyObject* x, boost::python::type<T>)
|
inline friend T from_python(PyObject* x, boost::python::type<T>)
|
||||||
{ return T(boost::python::downcast<Value>(x).get(), T::increment_count); }
|
{ return T(boost::python::downcast<Value>(x).get(), T::increment_count); }
|
||||||
|
|
||||||
inline friend PyObject* to_python(T x)
|
inline friend PyObject* to_python(T x, boost::python::lookup_tag)
|
||||||
{ return boost::python::as_object(x.release()); }
|
{ return boost::python::as_object(x.release()); }
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -38,8 +38,6 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
|
|
||||||
BOOST_PYTHON_IMPORT_CONVERSION(py_ptr_conversions);
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class reference
|
class reference
|
||||||
: public py_ptr_conversions<reference<T>, T,
|
: public py_ptr_conversions<reference<T>, T,
|
||||||
@@ -165,7 +163,7 @@ typedef reference<PyObject> ref;
|
|||||||
template <class T>
|
template <class T>
|
||||||
ref make_ref(const T& x)
|
ref make_ref(const T& x)
|
||||||
{
|
{
|
||||||
return ref(to_python(x));
|
return ref(to_python(x, lookup_tag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace boost::python
|
}} // namespace boost::python
|
||||||
|
|||||||
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
|
||||||
@@ -5,6 +5,11 @@
|
|||||||
//
|
//
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// 04 Mar 01 Rolled in const_cast from Dragon fork (Dave Abrahams)
|
||||||
|
// 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve)
|
||||||
|
// 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function)
|
||||||
|
|
||||||
#include <boost/python/classes.hpp>
|
#include <boost/python/classes.hpp>
|
||||||
#include <boost/python/detail/functions.hpp>
|
#include <boost/python/detail/functions.hpp>
|
||||||
@@ -67,8 +72,7 @@ namespace {
|
|||||||
|
|
||||||
ref global_class_reduce()
|
ref global_class_reduce()
|
||||||
{
|
{
|
||||||
static ref result(detail::new_wrapped_function(class_reduce));
|
return ref(detail::new_wrapped_function(class_reduce));
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -93,17 +97,41 @@ namespace {
|
|||||||
ref getstate(PyObject_GetAttrString(obj, const_cast<char*>("__getstate__")),
|
ref getstate(PyObject_GetAttrString(obj, const_cast<char*>("__getstate__")),
|
||||||
ref::null_ok);
|
ref::null_ok);
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
|
||||||
|
ref dict(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
if (getstate.get() != 0)
|
if (getstate.get() != 0)
|
||||||
{
|
{
|
||||||
|
if (dict.get() != 0 && dictionary(dict).size() > 0)
|
||||||
|
{
|
||||||
|
ref getstate_manages_dict(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__getstate_manages_dict__")), ref::null_ok);
|
||||||
|
PyErr_Clear();
|
||||||
|
if (getstate_manages_dict.get() == 0)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__getstate_manages_dict__ not set)");
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ref state = ref(PyEval_CallObject(getstate.get(), NULL));
|
ref state = ref(PyEval_CallObject(getstate.get(), NULL));
|
||||||
return tuple(instance_class, initargs, state);
|
return tuple(instance_class, initargs, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref state(PyObject_GetAttrString(obj, const_cast<char*>("__dict__")), ref::null_ok);
|
if (getinitargs.get() == 0)
|
||||||
PyErr_Clear();
|
|
||||||
if (state.get() != 0 && dictionary(state).size() > 0)
|
|
||||||
{
|
{
|
||||||
return tuple(instance_class, initargs, state);
|
ref dict_defines_state(PyObject_GetAttrString(instance_class.get(), const_cast<char*>("__dict_defines_state__")), ref::null_ok);
|
||||||
|
PyErr_Clear();
|
||||||
|
if (dict_defines_state.get() == 0)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__dict_defines_state__ not set)");
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict.get() != 0 && dictionary(dict).size() > 0)
|
||||||
|
{
|
||||||
|
return tuple(instance_class, initargs, dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tuple(instance_class, initargs);
|
return tuple(instance_class, initargs);
|
||||||
@@ -111,8 +139,7 @@ namespace {
|
|||||||
|
|
||||||
ref global_instance_reduce()
|
ref global_instance_reduce()
|
||||||
{
|
{
|
||||||
static ref result(detail::new_wrapped_function(instance_reduce));
|
return ref(detail::new_wrapped_function(instance_reduce));
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +204,7 @@ namespace detail {
|
|||||||
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
|
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
|
||||||
{
|
{
|
||||||
ref target(as_object(this), ref::increment_count);
|
ref target(as_object(this), ref::increment_count);
|
||||||
return new bound_function(target, global_class_reduce());
|
return bound_function::create(target, global_class_reduce());
|
||||||
}
|
}
|
||||||
|
|
||||||
ref local_attribute = m_name_space.get_item(string(name).reference());
|
ref local_attribute = m_name_space.get_item(string(name).reference());
|
||||||
@@ -348,7 +375,7 @@ PyObject* instance::getattr(const char* name, bool use_special_function)
|
|||||||
|
|
||||||
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
|
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
|
||||||
{
|
{
|
||||||
return new detail::bound_function(ref(this, ref::increment_count), global_instance_reduce());
|
return detail::bound_function::create(ref(this, ref::increment_count), global_instance_reduce());
|
||||||
}
|
}
|
||||||
|
|
||||||
ref local_attribute = m_name_space.get_item(string(name).reference());
|
ref local_attribute = m_name_space.get_item(string(name).reference());
|
||||||
@@ -840,7 +867,27 @@ namespace {
|
|||||||
void add_current_module_name(dictionary& name_space)
|
void add_current_module_name(dictionary& name_space)
|
||||||
{
|
{
|
||||||
static string module_key("__module__", string::interned);
|
static string module_key("__module__", string::interned);
|
||||||
name_space.set_item(module_key, module_builder::name());
|
|
||||||
|
// If the user didn't specify a __module__ attribute already
|
||||||
|
if (name_space.get_item(module_key).get() == 0)
|
||||||
|
{
|
||||||
|
if (module_builder::initializing())
|
||||||
|
{
|
||||||
|
// The global __name__ is not properly set in this case
|
||||||
|
name_space.set_item(module_key, module_builder::name());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the module name from the global __name__
|
||||||
|
PyObject *globals = PyEval_GetGlobals();
|
||||||
|
if (globals != NULL)
|
||||||
|
{
|
||||||
|
PyObject *module_name = PyDict_GetItemString(globals, const_cast<char*>("__name__"));
|
||||||
|
if (module_name != NULL)
|
||||||
|
name_space.set_item(module_key, module_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,13 @@
|
|||||||
//
|
//
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// 05 Apr 01 added: from_python std::string type checking (rwgk)
|
||||||
|
// 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve)
|
||||||
|
// 11 Mar 01 std::string *MAY* include nulls (Alex Martelli)
|
||||||
|
// 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams)
|
||||||
|
// 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve)
|
||||||
|
|
||||||
#include <boost/python/conversions.hpp>
|
#include <boost/python/conversions.hpp>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
@@ -44,6 +51,19 @@ void handle_exception()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
void expect_complex(PyObject* p)
|
||||||
|
{
|
||||||
|
if (!PyComplex_Check(p))
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected a complex number");
|
||||||
|
throw boost::python::argument_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost::python::detail
|
||||||
|
|
||||||
}} // namespace boost::python
|
}} // namespace boost::python
|
||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
@@ -122,7 +142,7 @@ PyObject* integer_to_python(T value)
|
|||||||
throw boost::python::error_already_set();
|
throw boost::python::error_already_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
return to_python(value_as_long);
|
return to_python(value_as_long, boost::python::lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
int from_python(PyObject* p, boost::python::type<int> type)
|
int from_python(PyObject* p, boost::python::type<int> type)
|
||||||
@@ -130,9 +150,9 @@ int from_python(PyObject* p, boost::python::type<int> type)
|
|||||||
return integer_from_python(p, type);
|
return integer_from_python(p, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(unsigned int i)
|
PyObject* to_python(unsigned int i, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return integer_to_python(i);
|
return integer_to_python(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int from_python(PyObject* p, boost::python::type<unsigned int> type)
|
unsigned int from_python(PyObject* p, boost::python::type<unsigned int> type)
|
||||||
@@ -150,9 +170,9 @@ float from_python(PyObject* p, boost::python::type<float>)
|
|||||||
return static_cast<float>(from_python(p, boost::python::type<double>()));
|
return static_cast<float>(from_python(p, boost::python::type<double>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(unsigned short i)
|
PyObject* to_python(unsigned short i, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return integer_to_python(i);
|
return integer_to_python(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type)
|
unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type)
|
||||||
@@ -160,9 +180,27 @@ unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type
|
|||||||
return integer_from_python(p, type);
|
return integer_from_python(p, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(unsigned char i)
|
PyObject* to_python(char c, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return integer_to_python(i);
|
if (c == '\0') return PyString_FromString("");
|
||||||
|
return PyString_FromStringAndSize(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char from_python(PyObject* p, boost::python::type<char>)
|
||||||
|
{
|
||||||
|
int l = -1;
|
||||||
|
if (PyString_Check(p)) l = PyString_Size(p);
|
||||||
|
if (l < 0 || l > 1) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected string of length 0 or 1");
|
||||||
|
throw boost::python::argument_error();
|
||||||
|
}
|
||||||
|
if (l == 0) return '\0';
|
||||||
|
return PyString_AsString(p)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* to_python(unsigned char i, boost::python::lookup_tag)
|
||||||
|
{
|
||||||
|
return integer_to_python(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
|
unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
|
||||||
@@ -170,9 +208,9 @@ unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
|
|||||||
return integer_from_python(p, type);
|
return integer_from_python(p, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(signed char i)
|
PyObject* to_python(signed char i, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return integer_to_python(i);
|
return integer_to_python(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
signed char from_python(PyObject* p, boost::python::type<signed char> type)
|
signed char from_python(PyObject* p, boost::python::type<signed char> type)
|
||||||
@@ -180,7 +218,7 @@ signed char from_python(PyObject* p, boost::python::type<signed char> type)
|
|||||||
return integer_from_python(p, type);
|
return integer_from_python(p, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(unsigned long x)
|
PyObject* to_python(unsigned long x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return integer_to_python(x);
|
return integer_to_python(x);
|
||||||
}
|
}
|
||||||
@@ -206,14 +244,18 @@ const char* from_python(PyObject* p, boost::python::type<const char*>)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const std::string& s)
|
PyObject* to_python(const std::string& s, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyString_FromString(s.c_str());
|
return PyString_FromStringAndSize(s.data(), s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string from_python(PyObject* p, boost::python::type<std::string>)
|
std::string from_python(PyObject* p, boost::python::type<std::string>)
|
||||||
{
|
{
|
||||||
return std::string(from_python(p, boost::python::type<const char*>()));
|
if (! PyString_Check(p)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected a string");
|
||||||
|
throw boost::python::argument_error();
|
||||||
|
}
|
||||||
|
return std::string(PyString_AsString(p), PyString_Size(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool from_python(PyObject* p, boost::python::type<bool>)
|
bool from_python(PyObject* p, boost::python::type<bool>)
|
||||||
@@ -226,12 +268,12 @@ bool from_python(PyObject* p, boost::python::type<bool>)
|
|||||||
|
|
||||||
#ifdef BOOST_MSVC6_OR_EARLIER
|
#ifdef BOOST_MSVC6_OR_EARLIER
|
||||||
// An optimizer bug prevents these from being inlined.
|
// An optimizer bug prevents these from being inlined.
|
||||||
PyObject* to_python(double d)
|
PyObject* to_python(double d, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyFloat_FromDouble(d);
|
return PyFloat_FromDouble(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(float f)
|
PyObject* to_python(float f, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return PyFloat_FromDouble(f);
|
return PyFloat_FromDouble(f);
|
||||||
}
|
}
|
||||||
|
|||||||
87
src/cross_module.cpp
Normal file
87
src/cross_module.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/* (C) Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy, use,
|
||||||
|
modify, sell and distribute this software is granted provided this
|
||||||
|
copyright notice appears in all copies. This software is provided
|
||||||
|
"as is" without express or implied warranty, and with no claim as to
|
||||||
|
its suitability for any purpose.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve)
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include <boost/python/cross_module.hpp>
|
||||||
|
namespace python = boost::python;
|
||||||
|
# include <stdio.h> // MSVC6.0SP4 does not know std::fprintf
|
||||||
|
# include <string.h> // MSVC6.0SP4 does not know std::strcmp
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
PyObject* get_module_dict(const char* module_name)
|
||||||
|
{
|
||||||
|
python::ref module_obj(PyImport_ImportModule((char*) module_name));
|
||||||
|
PyObject* module_dict = PyModule_GetDict(module_obj.get());
|
||||||
|
if (module_dict == 0) throw python::import_error();
|
||||||
|
return module_dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace boost { namespace python { namespace detail {
|
||||||
|
|
||||||
|
const char* converters_attribute_name = "__converters__";
|
||||||
|
|
||||||
|
void* import_converter_object(const std::string& module_name,
|
||||||
|
const std::string& py_class_name,
|
||||||
|
const std::string& attribute_name)
|
||||||
|
{
|
||||||
|
static std::string err;
|
||||||
|
PyObject* module_dict = get_module_dict(const_cast<char*>(module_name.c_str()));
|
||||||
|
PyObject* py_class = PyDict_GetItemString(module_dict, const_cast<char*>(py_class_name.c_str()));
|
||||||
|
if (py_class == 0) {
|
||||||
|
err = std::string("module ") + module_name + " has no attribute " + py_class_name;
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
|
||||||
|
throw python::import_error();
|
||||||
|
}
|
||||||
|
python::ref c_obj(PyObject_GetAttrString(py_class, const_cast<char*>(attribute_name.c_str())), ref::null_ok);
|
||||||
|
if (c_obj.get() == 0) {
|
||||||
|
err = std::string("object ") + module_name + "." + py_class_name
|
||||||
|
+ " has no attribute " + attribute_name;
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
|
||||||
|
throw python::import_error();
|
||||||
|
}
|
||||||
|
if (! PyCObject_Check(c_obj.get())) {
|
||||||
|
err = std::string("object ") + module_name + "." + py_class_name + "."
|
||||||
|
+ attribute_name + " is not a PyCObject";
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
|
||||||
|
throw python::import_error();
|
||||||
|
}
|
||||||
|
return PyCObject_AsVoidPtr(c_obj.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_export_converters_api(const int importing_major,
|
||||||
|
const int importing_minor,
|
||||||
|
const int imported_major,
|
||||||
|
const int imported_minor)
|
||||||
|
{
|
||||||
|
if (importing_major != imported_major) {
|
||||||
|
// Python uses fprintf(stderr, ...) for API warnings.
|
||||||
|
fprintf(stderr,
|
||||||
|
"Fatal: export_converters_api mismatch:"
|
||||||
|
" Importing module = %d.%d"
|
||||||
|
" Imported module = %d.%d\n",
|
||||||
|
importing_major, importing_minor,
|
||||||
|
imported_major, imported_minor);
|
||||||
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"Fatal: export_converters_api mismatch");
|
||||||
|
throw import_error();
|
||||||
|
}
|
||||||
|
if (importing_minor != imported_minor) {
|
||||||
|
// Python uses fprintf(stderr, ...) for API warnings.
|
||||||
|
fprintf(stderr,
|
||||||
|
"Warning: export_converters_api mismatch:"
|
||||||
|
" Importing module = %d.%d"
|
||||||
|
" Imported module = %d.%d\n",
|
||||||
|
importing_major, importing_minor,
|
||||||
|
imported_major, imported_minor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}}} // namespace boost::python::detail
|
||||||
@@ -5,6 +5,9 @@
|
|||||||
//
|
//
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||||
|
|
||||||
#include <boost/python/detail/extension_class.hpp>
|
#include <boost/python/detail/extension_class.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -39,31 +42,26 @@ namespace detail {
|
|||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
inline PyObject* to_python(boost::python::detail::operator_dispatcher* n) { return n; }
|
inline PyObject* to_python(boost::python::detail::operator_dispatcher* n, boost::python::lookup_tag) { return n; }
|
||||||
|
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
|
|
||||||
namespace detail {
|
tuple standard_coerce(ref l, ref r)
|
||||||
|
{
|
||||||
|
// Introduced sequence points for exception-safety.
|
||||||
|
ref first(detail::operator_dispatcher::create(l, l));
|
||||||
|
|
||||||
|
ref second(r->ob_type == &detail::operator_dispatcher::type_obj
|
||||||
|
? r
|
||||||
|
: ref(detail::operator_dispatcher::create(r, ref())));
|
||||||
|
|
||||||
tuple extension_class_coerce(ref l, ref r)
|
return tuple(first, second);
|
||||||
{
|
}
|
||||||
// Introduced sequence points for exception-safety.
|
|
||||||
ref first(operator_dispatcher::create(l, l));
|
namespace detail {
|
||||||
ref second;
|
|
||||||
|
|
||||||
if(r->ob_type == &operator_dispatcher::type_obj)
|
|
||||||
{
|
|
||||||
second = r;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
second = ref(operator_dispatcher::create(r, ref()));
|
|
||||||
}
|
|
||||||
return boost::python::tuple(first, second);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum { unwrap_exception_code = -1000 };
|
enum { unwrap_exception_code = -1000 };
|
||||||
|
|
||||||
@@ -451,8 +449,8 @@ operator_dispatcher::operator_dispatcher(const ref& o, const ref& s)
|
|||||||
: m_object(o), m_self(s), m_free_list_link(0)
|
: m_object(o), m_self(s), m_free_list_link(0)
|
||||||
|
|
||||||
{
|
{
|
||||||
ob_refcnt = 1;
|
PyObject* self = this;
|
||||||
ob_type = &type_obj;
|
PyObject_INIT(self, &type_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator_dispatcher*
|
operator_dispatcher*
|
||||||
@@ -465,7 +463,9 @@ operator_dispatcher::create(const ref& object, const ref& self)
|
|||||||
free_list = result->m_free_list_link;
|
free_list = result->m_free_list_link;
|
||||||
result->m_object = object;
|
result->m_object = object;
|
||||||
result->m_self = self;
|
result->m_self = self;
|
||||||
Py_INCREF(result);
|
|
||||||
|
PyObject* result_as_pyobject = result;
|
||||||
|
PyObject_INIT(result_as_pyobject, &type_obj);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,7 +608,7 @@ int operator_dispatcher_call_cmp(PyObject* left, PyObject* right)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return BOOST_PYTHON_CONVERSION::from_python(result, type<int>());
|
return from_python(result, type<int>());
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
//
|
//
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||||
|
|
||||||
#include <boost/python/detail/functions.hpp>
|
#include <boost/python/detail/functions.hpp>
|
||||||
#include <boost/python/detail/types.hpp>
|
#include <boost/python/detail/types.hpp>
|
||||||
@@ -97,19 +100,6 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bound_function* bound_function::create(const ref& target, const ref& fn)
|
|
||||||
{
|
|
||||||
bound_function* const result = free_list;
|
|
||||||
if (result == 0)
|
|
||||||
return new bound_function(target, fn);
|
|
||||||
|
|
||||||
free_list = result->m_free_list_link;
|
|
||||||
result->m_target = target;
|
|
||||||
result->m_unbound_function = fn;
|
|
||||||
Py_INCREF(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The instance class whose obj represents the type of bound_function
|
// The instance class whose obj represents the type of bound_function
|
||||||
// objects in Python. bound_functions must be GetAttrable so the __doc__
|
// objects in Python. bound_functions must be GetAttrable so the __doc__
|
||||||
// attribute of built-in Python functions can be accessed when bound.
|
// attribute of built-in Python functions can be accessed when bound.
|
||||||
@@ -123,6 +113,21 @@ private: // type_object<bound_function> hook override
|
|||||||
void dealloc(bound_function*) const;
|
void dealloc(bound_function*) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bound_function* bound_function::create(const ref& target, const ref& fn)
|
||||||
|
{
|
||||||
|
bound_function* const result = free_list;
|
||||||
|
if (result == 0)
|
||||||
|
return new bound_function(target, fn);
|
||||||
|
|
||||||
|
free_list = result->m_free_list_link;
|
||||||
|
result->m_target = target;
|
||||||
|
result->m_unbound_function = fn;
|
||||||
|
|
||||||
|
PyObject* self = result;
|
||||||
|
PyObject_INIT(self, type_object::instance());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bound_function::bound_function(const ref& target, const ref& fn)
|
bound_function::bound_function(const ref& target, const ref& fn)
|
||||||
: python_object(type_object::instance()),
|
: python_object(type_object::instance()),
|
||||||
m_target(target),
|
m_target(target),
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ from gen_singleton import *
|
|||||||
from gen_extclass import *
|
from gen_extclass import *
|
||||||
|
|
||||||
def gen_all(args):
|
def gen_all(args):
|
||||||
open('callback.h', 'w').write(gen_callback(args))
|
open('callback.hpp', 'w').write(gen_callback(args))
|
||||||
open('caller.h', 'w').write(gen_caller(args))
|
open('caller.hpp', 'w').write(gen_caller(args))
|
||||||
open('init_function.h', 'w').write(gen_init_function(args))
|
open('init_function.hpp', 'w').write(gen_init_function(args))
|
||||||
open('signatures.h', 'w').write(gen_signatures(args))
|
open('signatures.hpp', 'w').write(gen_signatures(args))
|
||||||
open('instance.h', 'w').write(gen_singleton(args))
|
open('singleton.hpp', 'w').write(gen_singleton(args))
|
||||||
open('extclass.h', 'w').write(gen_extclass(args))
|
open('extension_class.hpp', 'w').write(gen_extclass(args))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ struct callback
|
|||||||
%{ template <%(class A%n%:, %)>
|
%{ template <%(class A%n%:, %)>
|
||||||
%} static R call_method(PyObject* self, const char* name%(, const A%n& a%n%))
|
%} static R call_method(PyObject* self, const char* name%(, const A%n& a%n%))
|
||||||
{%(
|
{%(
|
||||||
ref p%n(to_python(a%n));%)
|
ref p%n(to_python(a%n, lookup_tag()));%)
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(%(O%))")%(,
|
const_cast<char*>("(%(O%))")%(,
|
||||||
p%n.get()%)));
|
p%n.get()%)));
|
||||||
@@ -49,7 +49,7 @@ struct callback
|
|||||||
%{ template <%(class A%n%:, %)>
|
%{ template <%(class A%n%:, %)>
|
||||||
%} static R call(PyObject* self%(, const A%n& a%n%))
|
%} static R call(PyObject* self%(, const A%n& a%n%))
|
||||||
{%(
|
{%(
|
||||||
ref p%n(to_python(a%n));%)
|
ref p%n(to_python(a%n, lookup_tag()));%)
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
|
||||||
p%n.get()%)));
|
p%n.get()%)));
|
||||||
detail::callback_adjust_refcount(result.get(), type<R>());
|
detail::callback_adjust_refcount(result.get(), type<R>());
|
||||||
@@ -70,7 +70,7 @@ struct callback<void>
|
|||||||
%{ template <%(class A%n%:, %)>
|
%{ template <%(class A%n%:, %)>
|
||||||
%} static void call_method(PyObject* self, const char* name%(, const A%n& a%n%))
|
%} static void call_method(PyObject* self, const char* name%(, const A%n& a%n%))
|
||||||
{%(
|
{%(
|
||||||
ref p%n(to_python(a%n));%)
|
ref p%n(to_python(a%n, lookup_tag()));%)
|
||||||
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
ref result(PyEval_CallMethod(self, const_cast<char*>(name),
|
||||||
const_cast<char*>("(%(O%))")%(,
|
const_cast<char*>("(%(O%))")%(,
|
||||||
p%n.get()%)));
|
p%n.get()%)));
|
||||||
@@ -79,7 +79,7 @@ struct callback<void>
|
|||||||
%{ template <%(class A%n%:, %)>
|
%{ template <%(class A%n%:, %)>
|
||||||
%} static void call(PyObject* self%(, const A%n& a%n%))
|
%} static void call(PyObject* self%(, const A%n& a%n%))
|
||||||
{%(
|
{%(
|
||||||
ref p%n(to_python(a%n));%)
|
ref p%n(to_python(a%n, lookup_tag()));%)
|
||||||
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
|
ref result(PyEval_CallFunction(self, const_cast<char*>("(%(O%))")%(,
|
||||||
p%n.get()%)));
|
p%n.get()%)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,14 +97,14 @@ def gen_caller(member_function_args, free_function_args = None):
|
|||||||
return (header % (member_function_args, free_function_args)
|
return (header % (member_function_args, free_function_args)
|
||||||
+ body_sections[0]
|
+ body_sections[0]
|
||||||
+ gen_functions(member_function, member_function_args,
|
+ gen_functions(member_function, member_function_args,
|
||||||
'R', '', 'return to_python(', ');')
|
'R', '', 'return to_python(', ', lookup_tag());')
|
||||||
+ body_sections[1]
|
+ body_sections[1]
|
||||||
+ gen_functions(member_function, member_function_args,
|
+ gen_functions(member_function, member_function_args,
|
||||||
'R', ' const', 'return to_python(', ');')
|
'R', ' const', 'return to_python(', ', lookup_tag());')
|
||||||
+ body_sections[2]
|
+ body_sections[2]
|
||||||
|
|
||||||
+ gen_functions(free_function, free_function_args,
|
+ gen_functions(free_function, free_function_args,
|
||||||
'R', 'return to_python(', ');')
|
'R', 'return to_python(', ', lookup_tag());')
|
||||||
+ body_sections[3]
|
+ body_sections[3]
|
||||||
|
|
||||||
# specialized part for void return values begins here
|
# specialized part for void return values begins here
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import string
|
|||||||
|
|
||||||
def gen_extclass(args):
|
def gen_extclass(args):
|
||||||
return (
|
return (
|
||||||
"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
"""// (C) Copyright David Abrahams 2000-2001. Permission to copy, use, modify, sell and
|
||||||
// distribute this software is granted provided this copyright notice appears
|
// distribute this software is granted provided this copyright notice appears
|
||||||
// in all copies. This software is provided "as is" without express or implied
|
// 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.
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
@@ -14,6 +14,11 @@ def gen_extclass(args):
|
|||||||
// This file automatically generated for %d-argument constructors by
|
// This file automatically generated for %d-argument constructors by
|
||||||
// gen_extclass.python
|
// gen_extclass.python
|
||||||
|
|
||||||
|
// Revision History:
|
||||||
|
// 17 Apr 01 Comment added with reference to cross_module.hpp (R.W. Grosse-Kunstleve)
|
||||||
|
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
|
||||||
|
// to_python (Dave Abrahams)
|
||||||
|
|
||||||
#ifndef EXTENSION_CLASS_DWA052000_H_
|
#ifndef EXTENSION_CLASS_DWA052000_H_
|
||||||
# define EXTENSION_CLASS_DWA052000_H_
|
# define EXTENSION_CLASS_DWA052000_H_
|
||||||
|
|
||||||
@@ -27,6 +32,7 @@ def gen_extclass(args):
|
|||||||
# include <boost/python/detail/init_function.hpp>
|
# include <boost/python/detail/init_function.hpp>
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
# include <boost/smart_ptr.hpp>
|
# include <boost/smart_ptr.hpp>
|
||||||
|
# include <boost/type_traits.hpp>
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
|
|
||||||
@@ -66,7 +72,7 @@ T* check_non_null(T* p)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> class held_instance;
|
template <class Held> class held_instance;
|
||||||
|
|
||||||
typedef void* (*conversion_function_ptr)(void*);
|
typedef void* (*conversion_function_ptr)(void*);
|
||||||
|
|
||||||
@@ -138,6 +144,26 @@ class class_registry
|
|||||||
static std::vector<derived_class_info> static_derived_class_info;
|
static std::vector<derived_class_info> static_derived_class_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <bool is_pointer>
|
||||||
|
struct is_null_helper
|
||||||
|
{
|
||||||
|
template <class Ptr>
|
||||||
|
static bool test(Ptr x) { return x == 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_null_helper<false>
|
||||||
|
{
|
||||||
|
template <class Ptr>
|
||||||
|
static bool test(const Ptr& x) { return x.get() == 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Ptr>
|
||||||
|
bool is_null(const Ptr& x)
|
||||||
|
{
|
||||||
|
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
|
||||||
|
}
|
||||||
|
|
||||||
}}} // namespace boost::python::detail
|
}}} // namespace boost::python::detail
|
||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
@@ -146,36 +172,45 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
|||||||
// and U. T is the class the user really intends to wrap. U is a class derived
|
// and U. T is the class the user really intends to wrap. U is a class derived
|
||||||
// from T with some virtual function overriding boilerplate, or if there are no
|
// from T with some virtual function overriding boilerplate, or if there are no
|
||||||
// virtual functions, U = held_instance<T>.
|
// virtual functions, U = held_instance<T>.
|
||||||
|
//
|
||||||
|
// A look-alike of this class in root/boost/python/cross_module.hpp
|
||||||
|
// is used for the implementation of the cross-module support
|
||||||
|
// (export_converters and import_converters). If from_python
|
||||||
|
// and to_python converters are added or removed from the class
|
||||||
|
// below, the class python_import_extension_class_converters has
|
||||||
|
// to be modified accordingly.
|
||||||
|
//
|
||||||
template <class T, class U = boost::python::detail::held_instance<T> >
|
template <class T, class U = boost::python::detail::held_instance<T> >
|
||||||
class python_extension_class_converters
|
class python_extension_class_converters
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Get an object which can be used to convert T to/from python. This is used
|
/// Get an object which can be used to convert T to/from python. This is used
|
||||||
// as a kind of concept check by the global template
|
/// as a kind of concept check by the free template function
|
||||||
//
|
///
|
||||||
// PyObject* to_python(const T& x)
|
/// PyObject* to_python(const T& x, boost::python::lookup_tag)
|
||||||
//
|
///
|
||||||
// below this class, to prevent the confusing messages that would otherwise
|
/// below this class, to prevent the confusing messages that would otherwise
|
||||||
// pop up. Now, if T hasn't been wrapped as an extension class, the user
|
/// pop up. Now, if T hasn't been wrapped as an extension class, the user
|
||||||
// will see an error message about the lack of an eligible
|
/// will see an error message about the lack of an eligible
|
||||||
// py_extension_class_converters() function.
|
/// py_extension_class_converters() function.
|
||||||
friend python_extension_class_converters py_extension_class_converters(boost::python::type<T>)
|
friend python_extension_class_converters py_extension_class_converters(
|
||||||
|
boost::python::type<T>)
|
||||||
{
|
{
|
||||||
return python_extension_class_converters();
|
return python_extension_class_converters();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a member function because in a conforming implementation, friend
|
/// This is a member function because in a conforming implementation, friend
|
||||||
// funcitons defined inline in the class body are all instantiated as soon
|
/// functions defined inline in the class body are all instantiated as soon
|
||||||
// as the enclosing class is instantiated. If T is not copyable, that causes
|
/// as the enclosing class is instantiated. If T is not copyable, that causes
|
||||||
// a compiler error. Instead, we access this function through the global
|
/// a compiler error. Instead, we access this function through the global
|
||||||
// template
|
/// template
|
||||||
//
|
///
|
||||||
// PyObject* to_python(const T& x)
|
/// PyObject* to_python(const T& x, boost::python::lookup_tag)
|
||||||
//
|
///
|
||||||
// defined below this class. Since template functions are instantiated only
|
/// defined below this class. Since template functions are instantiated only
|
||||||
// on demand, errors will be avoided unless T is noncopyable and the user
|
/// on demand, errors will be avoided unless T is noncopyable and the user
|
||||||
// writes code which causes us to try to copy a T.
|
/// writes code which causes us to try to copy a T.
|
||||||
PyObject* to_python(const T& x) const
|
PyObject* m_to_python(const T& x) const
|
||||||
{
|
{
|
||||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||||
result->add_implementation(
|
result->add_implementation(
|
||||||
@@ -183,9 +218,10 @@ class python_extension_class_converters
|
|||||||
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
|
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
|
||||||
return result.release();
|
return result.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to T*
|
/// Extract a pointer to T from the given PyObject. Will throw argument_error if obj == None.
|
||||||
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
friend
|
||||||
|
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
|
||||||
{
|
{
|
||||||
// downcast to an extension_instance, then find the actual T
|
// downcast to an extension_instance, then find the actual T
|
||||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||||
@@ -206,9 +242,16 @@ class python_extension_class_converters
|
|||||||
throw boost::python::argument_error();
|
throw boost::python::argument_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to PtrType, where PtrType can be dereferenced to obtain a T.
|
/// Convert obj to T*. If obj == None, returns 0.
|
||||||
|
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
||||||
|
{
|
||||||
|
if (obj == Py_None) return 0;
|
||||||
|
return non_null_from_python(obj, boost::python::type<T*>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract from obj a mutable reference to the PtrType object which is holding a T.
|
||||||
template <class PtrType>
|
template <class PtrType>
|
||||||
static PtrType& ptr_from_python(PyObject* obj, boost::python::type<PtrType>)
|
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
|
||||||
{
|
{
|
||||||
// downcast to an extension_instance, then find the actual T
|
// downcast to an extension_instance, then find the actual T
|
||||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||||
@@ -225,9 +268,31 @@ class python_extension_class_converters
|
|||||||
throw boost::python::argument_error();
|
throw boost::python::argument_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract from obj a reference to the PtrType object which is holding a
|
||||||
|
/// T. If it weren't for auto_ptr, it would be a constant reference. Do not
|
||||||
|
/// modify the referent except by copying an auto_ptr! If obj is None, the
|
||||||
|
/// reference denotes a default-constructed PtrType
|
||||||
template <class PtrType>
|
template <class PtrType>
|
||||||
static PyObject* ptr_to_python(PtrType x)
|
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
|
||||||
{
|
{
|
||||||
|
if (obj == Py_None)
|
||||||
|
{
|
||||||
|
static PtrType null_ptr;
|
||||||
|
return null_ptr;
|
||||||
|
}
|
||||||
|
return smart_ptr_reference(obj, boost::python::type<PtrType>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrap x in a Python object which implements the functionality of a
|
||||||
|
/// regular wrapped T by dereferencing a copy of x.
|
||||||
|
template <class PtrType>
|
||||||
|
static PyObject* smart_ptr_to_python(PtrType x)
|
||||||
|
{
|
||||||
|
if (boost::python::detail::is_null(x))
|
||||||
|
{
|
||||||
|
return boost::python::detail::none();
|
||||||
|
}
|
||||||
|
|
||||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||||
result->add_implementation(
|
result->add_implementation(
|
||||||
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
||||||
@@ -235,6 +300,9 @@ class python_extension_class_converters
|
|||||||
return result.release();
|
return result.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a Python object which is an instance of the Python type wrapper
|
||||||
|
/// for T. The result does not actually contain the neccessary instance of
|
||||||
|
/// T. This function is an implementation detail.
|
||||||
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
|
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
|
||||||
{
|
{
|
||||||
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
|
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
|
||||||
@@ -245,53 +313,53 @@ class python_extension_class_converters
|
|||||||
new boost::python::detail::extension_instance(class_object));
|
new boost::python::detail::extension_instance(class_object));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to const T*
|
/// Convert p to const T*
|
||||||
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
|
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
|
||||||
{ return from_python(p, boost::python::type<T*>()); }
|
{ return from_python(p, boost::python::type<T*>()); }
|
||||||
|
|
||||||
// Convert to const T* const&
|
/// Convert p to const T* const&
|
||||||
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
|
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
|
||||||
{ return from_python(p, boost::python::type<const T*>()); }
|
{ return from_python(p, boost::python::type<const T*>()); }
|
||||||
|
|
||||||
// Convert to T* const&
|
/// Convert p to T* const&
|
||||||
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
|
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
|
||||||
{ return from_python(p, boost::python::type<T*>()); }
|
{ return from_python(p, boost::python::type<T*>()); }
|
||||||
|
|
||||||
// Convert to T&
|
// Convert to T&
|
||||||
friend T& from_python(PyObject* p, boost::python::type<T&>)
|
friend T& from_python(PyObject* p, boost::python::type<T&>)
|
||||||
{ return *boost::python::detail::check_non_null(from_python(p, boost::python::type<T*>())); }
|
{ return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type<T*>())); }
|
||||||
|
|
||||||
// Convert to const T&
|
// Convert p to const T&
|
||||||
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
|
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
|
||||||
{ return from_python(p, boost::python::type<T&>()); }
|
{ return from_python(p, boost::python::type<T&>()); }
|
||||||
|
|
||||||
// Convert to T
|
/// Convert p to T
|
||||||
friend const T& from_python(PyObject* p, boost::python::type<T>)
|
friend const T& from_python(PyObject* p, boost::python::type<T>)
|
||||||
{ return from_python(p, boost::python::type<T&>()); }
|
{ return from_python(p, boost::python::type<T&>()); }
|
||||||
|
|
||||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
|
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
{ return smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||||
|
|
||||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
||||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||||
|
|
||||||
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
|
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||||
|
|
||||||
friend PyObject* to_python(std::auto_ptr<T> x)
|
friend PyObject* to_python(std::auto_ptr<T> x, boost::python::lookup_tag)
|
||||||
{ return ptr_to_python(x); }
|
{ return smart_ptr_to_python(x); }
|
||||||
|
|
||||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
{ return smart_ptr_reference(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||||
|
|
||||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
||||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||||
|
|
||||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
|
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
|
||||||
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
|
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||||
|
|
||||||
friend PyObject* to_python(boost::shared_ptr<T> x)
|
friend PyObject* to_python(boost::shared_ptr<T> x, boost::python::lookup_tag)
|
||||||
{ return ptr_to_python(x); }
|
{ return smart_ptr_to_python(x); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert T to_python, instantiated on demand and only if there isn't a
|
// Convert T to_python, instantiated on demand and only if there isn't a
|
||||||
@@ -299,17 +367,15 @@ class python_extension_class_converters
|
|||||||
// T is a wrapped class. See the first 2 functions declared in
|
// T is a wrapped class. See the first 2 functions declared in
|
||||||
// python_extension_class_converters above for more info.
|
// python_extension_class_converters above for more info.
|
||||||
template <class T>
|
template <class T>
|
||||||
PyObject* to_python(const T& x)
|
PyObject* to_python(const T& x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return py_extension_class_converters(boost::python::type<T>()).to_python(x);
|
return py_extension_class_converters(boost::python::type<T>()).m_to_python(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
|
|
||||||
BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters);
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <class T> class instance_holder;
|
template <class T> class instance_holder;
|
||||||
@@ -613,15 +679,15 @@ class extension_class
|
|||||||
|
|
||||||
// A simple wrapper over a T which allows us to use extension_class<T> with a
|
// A simple wrapper over a T which allows us to use extension_class<T> with a
|
||||||
// single template parameter only. See extension_class<T>, above.
|
// single template parameter only. See extension_class<T>, above.
|
||||||
template <class T>
|
template <class Held>
|
||||||
class held_instance : public T
|
class held_instance : public Held
|
||||||
{
|
{
|
||||||
// There are no member functions: we want to avoid inadvertently overriding
|
// There are no member functions: we want to avoid inadvertently overriding
|
||||||
// any virtual functions in T.
|
// any virtual functions in Held.
|
||||||
public:"""
|
public:"""
|
||||||
+ gen_functions("""%{
|
+ gen_functions("""%{
|
||||||
template <%(class A%n%:, %)>%}
|
template <%(class A%n%:, %)>%}
|
||||||
held_instance(PyObject*%(, A%n% a%n%)) : T(%(a%n%:, %)) {}""", args)
|
held_instance(PyObject*%(, A%n% a%n%)) : Held(%(a%n%:, %)) {}""", args)
|
||||||
+ """
|
+ """
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -707,8 +773,6 @@ class extension_instance : public instance
|
|||||||
// Template function implementations
|
// Template function implementations
|
||||||
//
|
//
|
||||||
|
|
||||||
tuple extension_class_coerce(ref l, ref r);
|
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
extension_class<T, U>::extension_class()
|
extension_class<T, U>::extension_class()
|
||||||
: extension_class_base(typeid(T).name())
|
: extension_class_base(typeid(T).name())
|
||||||
@@ -729,7 +793,7 @@ void extension_class<T, U>::def_standard_coerce()
|
|||||||
ref coerce_fct = dict().get_item(string("__coerce__"));
|
ref coerce_fct = dict().get_item(string("__coerce__"));
|
||||||
|
|
||||||
if(coerce_fct.get() == 0) // not yet defined
|
if(coerce_fct.get() == 0) // not yet defined
|
||||||
this->def(&extension_class_coerce, "__coerce__");
|
this->def(&standard_coerce, "__coerce__");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
|
|||||||
@@ -14,10 +14,15 @@ namespace {
|
|||||||
ref name_holder;
|
ref name_holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool module_builder::initializing()
|
||||||
|
{
|
||||||
|
return name_holder.get() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
string module_builder::name()
|
string module_builder::name()
|
||||||
{
|
{
|
||||||
// If this fails, you haven't created a module_builder object
|
// If this fails, you haven't created a module_builder object
|
||||||
assert(name_holder.get() != 0);
|
assert(initializing());
|
||||||
return string(name_holder);
|
return string(name_holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +34,11 @@ module_builder::module_builder(const char* name)
|
|||||||
name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__")));
|
name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_builder::~module_builder()
|
||||||
|
{
|
||||||
|
name_holder.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
module_builder::add(detail::function* x, const char* name)
|
module_builder::add(detail::function* x, const char* name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ PyObject* object::get() const
|
|||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::tuple& x)
|
PyObject* to_python(const boost::python::tuple& x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return object_to_python(x);
|
return boost::python::object_to_python(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple> type)
|
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple> type)
|
||||||
@@ -59,9 +59,9 @@ boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python:
|
|||||||
return boost::python::object_from_python(p, type);
|
return boost::python::object_from_python(p, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::list& x)
|
PyObject* to_python(const boost::python::list& x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return object_to_python(x);
|
return boost::python::object_to_python(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::python::list from_python(PyObject* p, boost::python::type<boost::python::list> type)
|
boost::python::list from_python(PyObject* p, boost::python::type<boost::python::list> type)
|
||||||
@@ -69,9 +69,9 @@ boost::python::list from_python(PyObject* p, boost::python::type<boost::python::
|
|||||||
return boost::python::object_from_python(p, type);
|
return boost::python::object_from_python(p, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::dictionary& x)
|
PyObject* to_python(const boost::python::dictionary& x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return object_to_python(x);
|
return boost::python::object_to_python(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::python::dictionary> type)
|
boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::python::dictionary> type)
|
||||||
@@ -79,9 +79,9 @@ boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::py
|
|||||||
return boost::python::object_from_python(p, type);
|
return boost::python::object_from_python(p, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* to_python(const boost::python::string& x)
|
PyObject* to_python(const boost::python::string& x, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return object_to_python(x);
|
return boost::python::object_to_python(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::python::string from_python(PyObject* p, boost::python::type<boost::python::string> type)
|
boost::python::string from_python(PyObject* p, boost::python::type<boost::python::string> type)
|
||||||
|
|||||||
@@ -5,13 +5,21 @@
|
|||||||
//
|
//
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||||
// producing this work.
|
// producing this work.
|
||||||
|
|
||||||
|
// Revision History:
|
||||||
|
// 04 Mar 01 Changed name of extension module so it would work with DebugPython,
|
||||||
|
// eliminated useless test that aggravated MSVC (David Abrahams)
|
||||||
#include "comprehensive.hpp"
|
#include "comprehensive.hpp"
|
||||||
#include <boost/python/class_builder.hpp>
|
#include <boost/python/class_builder.hpp>
|
||||||
#include <stdio.h> // used for portability on broken compilers
|
#include <stdio.h> // used for portability on broken compilers
|
||||||
#include <math.h> // for pow()
|
#include <math.h> // for pow()
|
||||||
#include <boost/rational.hpp>
|
#include <boost/rational.hpp>
|
||||||
|
|
||||||
namespace extclass_demo {
|
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730
|
||||||
|
inline double pow(int x, int y) { return pow(static_cast<double>(x), y); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace bpl_test {
|
||||||
|
|
||||||
FooCallback::FooCallback(PyObject* self, int x)
|
FooCallback::FooCallback(PyObject* self, int x)
|
||||||
: Foo(x), m_self(self)
|
: Foo(x), m_self(self)
|
||||||
@@ -157,7 +165,7 @@ void throw_key_error_if_end(const StringMap& m, StringMap::const_iterator p, std
|
|||||||
{
|
{
|
||||||
if (p == m.end())
|
if (p == m.end())
|
||||||
{
|
{
|
||||||
PyErr_SetObject(PyExc_KeyError, BOOST_PYTHON_CONVERSION::to_python(key));
|
PyErr_SetObject(PyExc_KeyError, to_python(key, boost::python::lookup_tag()));
|
||||||
throw boost::python::error_already_set();
|
throw boost::python::error_already_set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,6 +246,23 @@ boost::shared_ptr<Foo> Baz::create_foo()
|
|||||||
return boost::shared_ptr<Foo>(new DerivedFromFoo(0));
|
return boost::shared_ptr<Foo>(new DerivedFromFoo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to check conversion to None
|
||||||
|
boost::shared_ptr<Foo> foo_factory(bool create)
|
||||||
|
{
|
||||||
|
return boost::shared_ptr<Foo>(create ? new DerivedFromFoo(0) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to check conversion from None
|
||||||
|
bool foo_ptr_is_null(Foo* p)
|
||||||
|
{
|
||||||
|
return p == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool foo_shared_ptr_is_null(boost::shared_ptr<Foo> p)
|
||||||
|
{
|
||||||
|
return p.get() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// We can accept smart pointer parameters
|
// We can accept smart pointer parameters
|
||||||
int Baz::get_foo_value(boost::shared_ptr<Foo> foo)
|
int Baz::get_foo_value(boost::shared_ptr<Foo> foo)
|
||||||
{
|
{
|
||||||
@@ -404,7 +429,7 @@ static int testUpcast(Base* b)
|
|||||||
|
|
||||||
static std::auto_ptr<Base> derived1Factory(int i)
|
static std::auto_ptr<Base> derived1Factory(int i)
|
||||||
{
|
{
|
||||||
return std::auto_ptr<Base>(new Derived1(i));
|
return std::auto_ptr<Base>(i < 0 ? 0 : new Derived1(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::auto_ptr<Base> derived2Factory(int i)
|
static std::auto_ptr<Base> derived2Factory(int i)
|
||||||
@@ -714,14 +739,16 @@ const Record* get_record()
|
|||||||
return &v;
|
return &v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template class boost::python::class_builder<Record>; // explicitly instantiate
|
} // namespace bpl_test
|
||||||
|
|
||||||
} // namespace extclass_demo
|
namespace boost { namespace python {
|
||||||
|
template class class_builder<bpl_test::Record>; // explicitly instantiate
|
||||||
|
}} // namespace boost::python
|
||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||||
inline PyObject* to_python(const extclass_demo::Record* p)
|
inline PyObject* to_python(const bpl_test::Record* p, boost::python::lookup_tag)
|
||||||
{
|
{
|
||||||
return to_python(*p);
|
return to_python(*p, boost::python::lookup_tag());
|
||||||
}
|
}
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||||
|
|
||||||
@@ -731,7 +758,7 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|||||||
/* */
|
/* */
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
namespace extclass_demo {
|
namespace bpl_test {
|
||||||
|
|
||||||
struct EnumOwner
|
struct EnumOwner
|
||||||
{
|
{
|
||||||
@@ -753,8 +780,8 @@ struct EnumOwner
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace boost { namespace python {
|
namespace boost { namespace python {
|
||||||
template class enum_as_int_converters<extclass_demo::EnumOwner::enum_type>;
|
template class enum_as_int_converters<bpl_test::EnumOwner::enum_type>;
|
||||||
using extclass_demo::pow;
|
using bpl_test::pow;
|
||||||
}} // namespace boost::python
|
}} // namespace boost::python
|
||||||
|
|
||||||
// This is just a way of getting the converters instantiated
|
// This is just a way of getting the converters instantiated
|
||||||
@@ -763,7 +790,7 @@ namespace boost { namespace python {
|
|||||||
//{
|
//{
|
||||||
//};
|
//};
|
||||||
|
|
||||||
namespace extclass_demo {
|
namespace bpl_test {
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
/* */
|
/* */
|
||||||
@@ -808,11 +835,37 @@ namespace extclass_demo {
|
|||||||
throw boost::python::error_already_set();
|
throw boost::python::error_already_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
const int number = BOOST_PYTHON_CONVERSION::from_python(state[0].get(), boost::python::type<int>());
|
const int number = from_python(state[0].get(), boost::python::type<int>());
|
||||||
if (number != 42)
|
if (number != 42)
|
||||||
w.set_secret_number(number);
|
w.set_secret_number(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test plain char converters.
|
||||||
|
char get_plain_char() { return 'x'; }
|
||||||
|
std::string use_plain_char(char c) { return std::string(3, c); }
|
||||||
|
|
||||||
|
// This doesn't test anything but the compiler, since it has the same signature as the above.
|
||||||
|
// Since MSVC is broken and gets the signature wrong, we'll skip it.
|
||||||
|
std::string use_const_plain_char(
|
||||||
|
#ifndef BOOST_MSVC6_OR_EARLIER
|
||||||
|
const
|
||||||
|
#endif
|
||||||
|
char c) { return std::string(5, c); }
|
||||||
|
|
||||||
|
// Test std::complex<double> converters.
|
||||||
|
std::complex<double> dpolar(double rho, double theta) {
|
||||||
|
return std::polar(rho, theta);
|
||||||
|
}
|
||||||
|
double dreal(const std::complex<double>& c) { return c.real(); }
|
||||||
|
double dimag(std::complex<double> c) { return c.imag(); }
|
||||||
|
|
||||||
|
// Test std::complex<float> converters.
|
||||||
|
std::complex<float> fpolar(float rho, float theta) {
|
||||||
|
return std::polar(rho, theta);
|
||||||
|
}
|
||||||
|
double freal(const std::complex<float>& c) { return c.real(); }
|
||||||
|
double fimag(std::complex<float> c) { return c.imag(); }
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* init the module */
|
/* init the module */
|
||||||
@@ -1034,9 +1087,29 @@ void init_module(boost::python::module_builder& m)
|
|||||||
world_class.def(world_getinitargs, "__getinitargs__");
|
world_class.def(world_getinitargs, "__getinitargs__");
|
||||||
world_class.def(world_getstate, "__getstate__");
|
world_class.def(world_getstate, "__getstate__");
|
||||||
world_class.def(world_setstate, "__setstate__");
|
world_class.def(world_setstate, "__setstate__");
|
||||||
|
|
||||||
|
// Test plain char converters.
|
||||||
|
m.def(get_plain_char, "get_plain_char");
|
||||||
|
m.def(use_plain_char, "use_plain_char");
|
||||||
|
m.def(use_const_plain_char, "use_const_plain_char");
|
||||||
|
|
||||||
|
// Test std::complex<double> converters.
|
||||||
|
m.def(dpolar, "dpolar");
|
||||||
|
m.def(dreal, "dreal");
|
||||||
|
m.def(dimag, "dimag");
|
||||||
|
|
||||||
|
// Test std::complex<float> converters.
|
||||||
|
m.def(fpolar, "fpolar");
|
||||||
|
m.def(freal, "freal");
|
||||||
|
m.def(fimag, "fimag");
|
||||||
|
|
||||||
|
// Test new null-pointer<->None conversions
|
||||||
|
m.def(foo_factory, "foo_factory");
|
||||||
|
m.def(foo_ptr_is_null, "foo_ptr_is_null");
|
||||||
|
m.def(foo_shared_ptr_is_null, "foo_shared_ptr_is_null");
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* raw(boost::python::tuple const& args, boost::python::dictionary const& keywords)
|
PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary& keywords)
|
||||||
{
|
{
|
||||||
if(args.size() != 2 || keywords.size() != 2)
|
if(args.size() != 2 || keywords.size() != 2)
|
||||||
{
|
{
|
||||||
@@ -1044,32 +1117,28 @@ PyObject* raw(boost::python::tuple const& args, boost::python::dictionary const&
|
|||||||
throw boost::python::argument_error();
|
throw boost::python::argument_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
RawTest* first = BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type<RawTest*>());
|
RawTest* first = from_python(args[0].get(), boost::python::type<RawTest*>());
|
||||||
int second = BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type<int>());
|
int second = from_python(args[1].get(), boost::python::type<int>());
|
||||||
|
|
||||||
int third = BOOST_PYTHON_CONVERSION::from_python(keywords[boost::python::string("third")].get(), boost::python::type<int>());
|
int third = from_python(keywords[boost::python::string("third")].get(), boost::python::type<int>());
|
||||||
int fourth = BOOST_PYTHON_CONVERSION::from_python(keywords[boost::python::string("fourth")].get(), boost::python::type<int>());
|
int fourth = from_python(keywords[boost::python::string("fourth")].get(), boost::python::type<int>());
|
||||||
|
|
||||||
return BOOST_PYTHON_CONVERSION::to_python(first->i_ + second + third + fourth);
|
return to_python(first->i_ + second + third + fourth, boost::python::lookup_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_module()
|
void init_module()
|
||||||
{
|
{
|
||||||
boost::python::module_builder demo("demo");
|
boost::python::module_builder boost_python_test("boost_python_test");
|
||||||
init_module(demo);
|
init_module(boost_python_test);
|
||||||
|
|
||||||
// Just for giggles, add a raw metaclass.
|
// Just for giggles, add a raw metaclass.
|
||||||
demo.add(new boost::python::meta_class<boost::python::instance>);
|
boost_python_test.add(new boost::python::meta_class<boost::python::instance>);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
BOOST_PYTHON_MODULE_INIT(boost_python_test)
|
||||||
#ifdef _WIN32
|
|
||||||
__declspec(dllexport)
|
|
||||||
#endif
|
|
||||||
void initdemo()
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
extclass_demo::init_module();
|
bpl_test::init_module();
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
boost::python::handle_exception();
|
boost::python::handle_exception();
|
||||||
@@ -1083,7 +1152,7 @@ CompareIntPairPythonClass::CompareIntPairPythonClass(boost::python::module_build
|
|||||||
def(&CompareIntPair::operator(), "__call__");
|
def(&CompareIntPair::operator(), "__call__");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extclass_demo
|
} // namespace bpl_test
|
||||||
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@@ -1124,7 +1193,7 @@ BOOL WINAPI DllMain(
|
|||||||
switch(fdwReason)
|
switch(fdwReason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
assert(extclass_demo::total_Ints == 0);
|
assert(bpl_test::total_Ints == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user