2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-20 04:42:28 +00:00

Compare commits

..

2 Commits

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

[SVN r10239]
2001-05-28 15:01:00 +00:00
Dave Abrahams
9b602d16b4 initial import
[SVN r8327]
2000-11-26 15:49:26 +00:00
784 changed files with 24287 additions and 78386 deletions

View File

@@ -1,66 +0,0 @@
if (PYTHON_LIBRARIES)
include_directories(${PYTHON_INCLUDE_PATH})
# Determine extra libraries we need to link against to build Python
# extension modules.
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "dl")
if(CMAKE_COMPILER_IS_GNUCXX)
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
endif(CMAKE_COMPILER_IS_GNUCXX)
elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSD")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread")
elseif(CMAKE_SYSTEM_NAME STREQUAL "DragonFly")
# DragonFly is a variant of FreeBSD
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread")
elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread" "dl")
if(CMAKE_COMPILER_IS_GNUCXX)
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
endif(CMAKE_COMPILER_IS_GNUCXX)
elseif(CMAKE_SYSTEM_NAME STREQUAL "QNX")
# No options necessary for QNX
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# No options necessary for Mac OS X
elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
elseif(UNIX)
# Assume -pthread and -ldl on all other variants
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread" "dl")
if(CMAKE_COMPILER_IS_GNUCXX)
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "util")
endif(CMAKE_COMPILER_IS_GNUCXX)
endif(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
################################################################################
#-- Macro for building Boost.Python extension modules
macro(boost_python_extension MODULE_NAME)
parse_arguments(BPL_EXT
""
""
${ARGN})
boost_add_single_library(
${MODULE_NAME}
${BPL_EXT_DEFAULT_ARGS}
MODULE
LINK_LIBS ${PYTHON_LIBRARIES}
DEPENDS boost_python
SHARED
)
endmacro(boost_python_extension)
#--
################################################################################
boost_library_project(
Python
SRCDIRS src
TESTDIRS test
HEADERS python.hpp python
MODULARIZED
DESCRIPTION "A framework for interfacing Python and C++. It allows you to quickly and seamlessly expose C++ classes functions and objects to Python, and vice-versa, using no special tools -- just your C++ compiler."
AUTHORS "David Abrahams <dave -at- boostpro.com>"
)
endif (PYTHON_LIBRARIES)

View File

@@ -1,94 +0,0 @@
# Copyright David Abrahams 2001-2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import os ;
import modules ;
import python ;
if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] )
{
# Attempt default configuration of python
import toolset : using ;
using python ;
if ! [ python.configured ]
{
ECHO "WARNING: No python installation configured and autoconfiguration" ;
ECHO " failed. See http://www.boost.org/libs/python/doc/building.html" ;
ECHO " for configuration instructions or pass --without-python to" ;
ECHO " suppress this message and silently skip all Boost.Python targets" ;
}
}
project boost/python
: source-location ../src
;
rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } }
lib boost_python
: # sources
numeric.cpp
list.cpp
long.cpp
dict.cpp
tuple.cpp
str.cpp
slice.cpp
converter/from_python.cpp
converter/registry.cpp
converter/type_id.cpp
object/enum.cpp
object/class.cpp
object/function.cpp
object/inheritance.cpp
object/life_support.cpp
object/pickle_support.cpp
errors.cpp
module.cpp
converter/builtin_converters.cpp
converter/arg_to_python_base.cpp
object/iterator.cpp
object/stl_iterator.cpp
object_protocol.cpp
object_operators.cpp
wrapper.cpp
import.cpp
exec.cpp
object/function_doc_signature.cpp
: # requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_SOURCE
# On Windows, all code using Python has to link to the Python
# import library.
#
# On *nix we never link libboost_python to libpython. When
# extending Python, all Python symbols are provided by the
# Python interpreter executable. When embedding Python, the
# client executable is expected to explicitly link to
# /python//python (the target representing libpython) itself.
#
# python_for_extensions is a target defined by Boost.Build to
# provide the Python include paths, and on Windows, the Python
# import library, as usage requirements.
[ cond [ python.configured ] : <library>/python//python_for_extensions ]
# we prevent building when there is no python available
# as it's not possible anyway, and to cause dependents to
# fail to build
[ unless [ python.configured ] : <build>no ]
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
: # default build
<link>shared
: # usage requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
;
boost-install boost_python ;

241
build/bpl_static.dsp Normal file
View 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
View 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

Binary file not shown.

58
build/como.mak Normal file
View 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
View 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
View 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
View 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

View 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

View 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
View 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
View 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/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
WARNOPTS=
OPTOPTS=-g
CPP=g++
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
MAKEDEP=-M
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
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
View 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

Binary file not shown.

135
build/rwgk1/rwgk1.dsp Normal file
View 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
View 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
View 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
View 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

View File

@@ -1,23 +0,0 @@
# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import docutils ;
import path ;
sources = building.rst ;
bases = $(sources:S=) ;
# This is a path relative to the html/ subdirectory where the
# generated output will eventually be moved.
stylesheet = "--stylesheet=../../../rst.css" ;
for local b in $(bases)
{
html $(b) : $(b).rst :
<docutils-html>"-gdt --source-url="./$(b).rst" --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript "$(stylesheet)
;
}
alias htmls : $(bases) ;
stage . : $(bases) ;

View File

@@ -1,22 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="refresh" content="0; URL=http://www.boost-consulting.com/writing/bpl.html">
<title>Loading: &ldquo;Building Hybrid Systems With Boost.Python&rdquo;</title>
</head>
<body>
Loading...; if nothing happens, please go to <a href= "http://www.boost-consulting.com/writing/bpl.html">http://www.boost-consulting.com/writing/bpl.html</a>.
</body>
</html>

Binary file not shown.

View File

@@ -1,5 +0,0 @@
.. Copyright David Abrahams 2006. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
This file has been moved to http://www.boost-consulting.com/writing/bpl.txt.

View File

@@ -1,912 +0,0 @@
Copyright David Abrahams 2006. Distributed under the Boost
Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
.. This is a comment. Note how any initial comments are moved by
transforms to after the document title, subtitle, and docinfo.
.. Need intro and conclusion
.. Exposing classes
.. Constructors
.. Overloading
.. Properties and data members
.. Inheritance
.. Operators and Special Functions
.. Virtual Functions
.. Call Policies
++++++++++++++++++++++++++++++++++++++++++++++
Introducing Boost.Python (Extended Abstract)
++++++++++++++++++++++++++++++++++++++++++++++
.. bibliographic fields (which also require a transform):
:Author: David Abrahams
:Address: 45 Walnut Street
Somerville, MA 02143
:Contact: dave@boost-consulting.com
:organization: `Boost Consulting`_
:date: $Date$
:status: This is a "work in progress"
:version: 1
:copyright: Copyright David Abrahams 2002. All rights reserved
:Dedication:
For my girlfriend, wife, and partner Luann
:abstract:
This paper describes the Boost.Python library, a system for
C++/Python interoperability.
.. meta::
:keywords: Boost,python,Boost.Python,C++
:description lang=en: C++/Python interoperability with Boost.Python
.. contents:: Table of Contents
.. section-numbering::
.. _`Boost Consulting`: http://www.boost-consulting.com
==============
Introduction
==============
Python and C++ are in many ways as different as two languages could
be: while C++ is usually compiled to machine-code, Python is
interpreted. Python's dynamic type system is often cited as the
foundation of its flexibility, while in C++ static typing is the
cornerstone of its efficiency. C++ has an intricate and difficult
meta-language to support compile-time polymorphism, while Python is
a uniform language with convenient runtime polymorphism.
Yet for many programmers, these very differences mean that Python and
C++ complement one another perfectly. Performance bottlenecks in
Python programs can be rewritten in C++ for maximal speed, and
authors of powerful C++ libraries choose Python as a middleware
language for its flexible system integration capabilities.
Furthermore, the surface differences mask some strong similarities:
* 'C'-family control structures (if, while, for...)
* Support for object-orientation, functional programming, and generic
programming (these are both *multi-paradigm* programming languages.)
* Comprehensive operator overloading facilities, recognizing the
importance of syntactic variability for readability and
expressivity.
* High-level concepts such as collections and iterators.
* High-level encapsulation facilities (C++: namespaces, Python: modules)
to support the design of re-usable libraries.
* Exception-handling for effective management of error conditions.
* C++ idioms in common use, such as handle/body classes and
reference-counted smart pointers mirror Python reference semantics.
Python provides a rich 'C' API for writers of 'C' extension modules.
Unfortunately, using this API directly for exposing C++ type and
function interfaces to Python is much more tedious than it should be.
This is mainly due to the limitations of the 'C' language. Compared to
C++ and Python, 'C' has only very rudimentary abstraction facilities.
Support for exception-handling is completely missing. One important
undesirable consequence is that 'C' extension module writers are
required to manually manage Python reference counts. Another unpleasant
consequence is a very high degree of repetition of similar code in 'C'
extension modules. Of course highly redundant code does not only cause
frustration for the module writer, but is also very difficult to
maintain.
The limitations of the 'C' API have lead to the development of a
variety of wrapping systems. SWIG_ is probably the most popular package
for the integration of C/C++ and Python. A more recent development is
the SIP_ package, which is specifically designed for interfacing Python
with the Qt_ graphical user interface library. Both SWIG and SIP
introduce a new specialized language for defining the inter-language
bindings. Of course being able to use a specialized language has
advantages, but having to deal with three different languages (Python,
C/C++ and the interface language) also introduces practical and mental
difficulties. The CXX_ package demonstrates an interesting alternative.
It shows that at least some parts of Python's 'C' API can be wrapped
and presented through a much more user-friendly C++ interface. However,
unlike SWIG and SIP, CXX does not include support for wrapping C++
classes as new Python types. CXX is also no longer actively developed.
In some respects Boost.Python combines ideas from SWIG and SIP with
ideas from CXX. Like SWIG and SIP, Boost.Python is a system for
wrapping C++ classes as new Python "built-in" types, and C/C++
functions as Python functions. Like CXX, Boost.Python presents Python's
'C' API through a C++ interface. Boost.Python goes beyond the scope of
other systems with the unique support for C++ virtual functions that
are overrideable in Python, support for organizing extensions as Python
packages with a central registry for inter-language type conversions,
and a convenient mechanism for tying into Python's serialization engine
(pickle). Importantly, all this is achieved without introducing a new
syntax. Boost.Python leverages the power of C++ meta-programming
techniques to introspect about the C++ type system, and presents a
simple, IDL-like C++ interface for exposing C/C++ code in extension
modules. Boost.Python is a pure C++ library, the inter-language
bindings are defined in pure C++, and other than a C++ compiler only
Python itself is required to get started with Boost.Python. Last but
not least, Boost.Python is an unrestricted open source library. There
are no strings attached even for commercial applications.
.. _SWIG: http://www.swig.org/
.. _SIP: http://www.riverbankcomputing.co.uk/sip/index.php
.. _Qt: http://www.trolltech.com/
.. _CXX: http://cxx.sourceforge.net/
===========================
Boost.Python Design Goals
===========================
The primary goal of Boost.Python is to allow users to expose C++
classes and functions to Python using nothing more than a C++
compiler. In broad strokes, the user experience should be one of
directly manipulating C++ objects from Python.
However, it's also important not to translate all interfaces *too*
literally: the idioms of each language must be respected. For
example, though C++ and Python both have an iterator concept, they are
expressed very differently. Boost.Python has to be able to bridge the
interface gap.
It must be possible to insulate Python users from crashes resulting
from trivial misuses of C++ interfaces, such as accessing
already-deleted objects. By the same token the library should
insulate C++ users from low-level Python 'C' API, replacing
error-prone 'C' interfaces like manual reference-count management and
raw ``PyObject`` pointers with more-robust alternatives.
Support for component-based development is crucial, so that C++ types
exposed in one extension module can be passed to functions exposed in
another without loss of crucial information like C++ inheritance
relationships.
Finally, all wrapping must be *non-intrusive*, without modifying or
even seeing the original C++ source code. Existing C++ libraries have
to be wrappable by third parties who only have access to header files
and binaries.
==========================
Hello Boost.Python World
==========================
And now for a preview of Boost.Python, and how it improves on the raw
facilities offered by Python. Here's a function we might want to
expose::
char const* greet(unsigned x)
{
static char const* const msgs[] = { "hello", "Boost.Python", "world!" };
if (x > 2)
throw std::range_error("greet: index out of range");
return msgs[x];
}
To wrap this function in standard C++ using the Python 'C' API, we'd
need something like this::
extern "C" // all Python interactions use 'C' linkage and calling convention
{
// Wrapper to handle argument/result conversion and checking
PyObject* greet_wrap(PyObject* args, PyObject * keywords)
{
int x;
if (PyArg_ParseTuple(args, "i", &x)) // extract/check arguments
{
char const* result = greet(x); // invoke wrapped function
return PyString_FromString(result); // convert result to Python
}
return 0; // error occurred
}
// Table of wrapped functions to be exposed by the module
static PyMethodDef methods[] = {
{ "greet", greet_wrap, METH_VARARGS, "return one of 3 parts of a greeting" }
, { NULL, NULL, 0, NULL } // sentinel
};
// module initialization function
DL_EXPORT init_hello()
{
(void) Py_InitModule("hello", methods); // add the methods to the module
}
}
Now here's the wrapping code we'd use to expose it with Boost.Python::
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(hello)
{
def("greet", greet, "return one of 3 parts of a greeting");
}
and here it is in action::
>>> import hello
>>> for x in range(3):
... print hello.greet(x)
...
hello
Boost.Python
world!
Aside from the fact that the 'C' API version is much more verbose than
the BPL one, it's worth noting that it doesn't handle a few things
correctly:
* The original function accepts an unsigned integer, and the Python
'C' API only gives us a way of extracting signed integers. The
Boost.Python version will raise a Python exception if we try to pass
a negative number to ``hello.greet``, but the other one will proceed
to do whatever the C++ implementation does when converting an
negative integer to unsigned (usually wrapping to some very large
number), and pass the incorrect translation on to the wrapped
function.
* That brings us to the second problem: if the C++ ``greet()``
function is called with a number greater than 2, it will throw an
exception. Typically, if a C++ exception propagates across the
boundary with code generated by a 'C' compiler, it will cause a
crash. As you can see in the first version, there's no C++
scaffolding there to prevent this from happening. Functions wrapped
by Boost.Python automatically include an exception-handling layer
which protects Python users by translating unhandled C++ exceptions
into a corresponding Python exception.
* A slightly more-subtle limitation is that the argument conversion
used in the Python 'C' API case can only get that integer ``x`` in
*one way*. PyArg_ParseTuple can't convert Python ``long`` objects
(arbitrary-precision integers) which happen to fit in an ``unsigned
int`` but not in a ``signed long``, nor will it ever handle a
wrapped C++ class with a user-defined implicit ``operator unsigned
int()`` conversion. The BPL's dynamic type conversion registry
allows users to add arbitrary conversion methods.
==================
Library Overview
==================
This section outlines some of the library's major features. Except as
necessary to avoid confusion, details of library implementation are
omitted.
-------------------------------------------
The fundamental type-conversion mechanism
-------------------------------------------
XXX This needs to be rewritten.
Every argument of every wrapped function requires some kind of
extraction code to convert it from Python to C++. Likewise, the
function return value has to be converted from C++ to Python.
Appropriate Python exceptions must be raised if the conversion fails.
Argument and return types are part of the function's type, and much of
this tedium can be relieved if the wrapping system can extract that
information through introspection.
Passing a wrapped C++ derived class instance to a C++ function
accepting a pointer or reference to a base class requires knowledge of
the inheritance relationship and how to translate the address of a base
class into that of a derived class.
------------------
Exposing Classes
------------------
C++ classes and structs are exposed with a similarly-terse interface.
Given::
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
The following code will expose it in our extension module::
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(hello)
{
class_<World>("World")
.def("greet", &World::greet)
.def("set", &World::set)
;
}
Although this code has a certain pythonic familiarity, people
sometimes find the syntax bit confusing because it doesn't look like
most of the C++ code they're used to. All the same, this is just
standard C++. Because of their flexible syntax and operator
overloading, C++ and Python are great for defining domain-specific
(sub)languages
(DSLs), and that's what we've done in BPL. To break it down::
class_<World>("World")
constructs an unnamed object of type ``class_<World>`` and passes
``"World"`` to its constructor. This creates a new-style Python class
called ``World`` in the extension module, and associates it with the
C++ type ``World`` in the BPL type conversion registry. We might have
also written::
class_<World> w("World");
but that would've been more verbose, since we'd have to name ``w``
again to invoke its ``def()`` member function::
w.def("greet", &World::greet)
There's nothing special about the location of the dot for member
access in the original example: C++ allows any amount of whitespace on
either side of a token, and placing the dot at the beginning of each
line allows us to chain as many successive calls to member functions
as we like with a uniform syntax. The other key fact that allows
chaining is that ``class_<>`` member functions all return a reference
to ``*this``.
So the example is equivalent to::
class_<World> w("World");
w.def("greet", &World::greet);
w.def("set", &World::set);
It's occasionally useful to be able to break down the components of a
Boost.Python class wrapper in this way, but the rest of this paper
will tend to stick to the terse syntax.
For completeness, here's the wrapped class in use:
>>> import hello
>>> planet = hello.World()
>>> planet.set('howdy')
>>> planet.greet()
'howdy'
Constructors
============
Since our ``World`` class is just a plain ``struct``, it has an
implicit no-argument (nullary) constructor. Boost.Python exposes the
nullary constructor by default, which is why we were able to write:
>>> planet = hello.World()
However, well-designed classes in any language may require constructor
arguments in order to establish their invariants. Unlike Python,
where ``__init__`` is just a specially-named method, In C++
constructors cannot be handled like ordinary member functions. In
particular, we can't take their address: ``&World::World`` is an
error. The library provides a different interface for specifying
constructors. Given::
struct World
{
World(std::string msg); // added constructor
...
we can modify our wrapping code as follows::
class_<World>("World", init<std::string>())
...
of course, a C++ class may have additional constructors, and we can
expose those as well by passing more instances of ``init<...>`` to
``def()``::
class_<World>("World", init<std::string>())
.def(init<double, double>())
...
Boost.Python allows wrapped functions, member functions, and
constructors to be overloaded to mirror C++ overloading.
Data Members and Properties
===========================
Any publicly-accessible data members in a C++ class can be easily
exposed as either ``readonly`` or ``readwrite`` attributes::
class_<World>("World", init<std::string>())
.def_readonly("msg", &World::msg)
...
and can be used directly in Python:
>>> planet = hello.World('howdy')
>>> planet.msg
'howdy'
This does *not* result in adding attributes to the ``World`` instance
``__dict__``, which can result in substantial memory savings when
wrapping large data structures. In fact, no instance ``__dict__``
will be created at all unless attributes are explicitly added from
Python. BPL owes this capability to the new Python 2.2 type system,
in particular the descriptor interface and ``property`` type.
In C++, publicly-accessible data members are considered a sign of poor
design because they break encapsulation, and style guides usually
dictate the use of "getter" and "setter" functions instead. In
Python, however, ``__getattr__``, ``__setattr__``, and since 2.2,
``property`` mean that attribute access is just one more
well-encapsulated syntactic tool at the programmer's disposal. BPL
bridges this idiomatic gap by making Python ``property`` creation
directly available to users. So if ``msg`` were private, we could
still expose it as attribute in Python as follows::
class_<World>("World", init<std::string>())
.add_property("msg", &World::greet, &World::set)
...
The example above mirrors the familiar usage of properties in Python
2.2+:
>>> class World(object):
... __init__(self, msg):
... self.__msg = msg
... def greet(self):
... return self.__msg
... def set(self, msg):
... self.__msg = msg
... msg = property(greet, set)
Operators and Special Functions
===============================
The ability to write arithmetic operators for user-defined types that
C++ and Python both allow the definition of has been a major factor in
the popularity of both languages for scientific computing. The
success of packages like NumPy attests to the power of exposing
operators in extension modules. In this example we'll wrap a class
representing a position in a large file::
class FilePos { /*...*/ };
// Linear offset
FilePos operator+(FilePos, int);
FilePos operator+(int, FilePos);
FilePos operator-(FilePos, int);
// Distance between two FilePos objects
int operator-(FilePos, FilePos);
// Offset with assignment
FilePos& operator+=(FilePos&, int);
FilePos& operator-=(FilePos&, int);
// Comparison
bool operator<(FilePos, FilePos);
The wrapping code looks like this::
class_<FilePos>("FilePos")
.def(self + int()) // __add__
.def(int() + self) // __radd__
.def(self - int()) // __sub__
.def(self - self) // __sub__
.def(self += int()) // __iadd__
.def(self -= int()) // __isub__
.def(self < self); // __lt__
;
The magic is performed using a simplified application of "expression
templates" [VELD1995]_, a technique originally developed by for
optimization of high-performance matrix algebra expressions. The
essence is that instead of performing the computation immediately,
operators are overloaded to construct a type *representing* the
computation. In matrix algebra, dramatic optimizations are often
available when the structure of an entire expression can be taken into
account, rather than processing each operation "greedily".
Boost.Python uses the same technique to build an appropriate Python
callable object based on an expression involving ``self``, which is
then added to the class.
Inheritance
===========
C++ inheritance relationships can be represented to Boost.Python by adding
an optional ``bases<...>`` argument to the ``class_<...>`` template
parameter list as follows::
class_<Derived, bases<Base1,Base2> >("Derived")
...
This has two effects:
1. When the ``class_<...>`` is created, Python type objects
corresponding to ``Base1`` and ``Base2`` are looked up in the BPL
registry, and are used as bases for the new Python ``Derived`` type
object [#mi]_, so methods exposed for the Python ``Base1`` and
``Base2`` types are automatically members of the ``Derived`` type.
Because the registry is global, this works correctly even if
``Derived`` is exposed in a different module from either of its
bases.
2. C++ conversions from ``Derived`` to its bases are added to the
Boost.Python registry. Thus wrapped C++ methods expecting (a
pointer or reference to) an object of either base type can be
called with an object wrapping a ``Derived`` instance. Wrapped
member functions of class ``T`` are treated as though they have an
implicit first argument of ``T&``, so these conversions are
necessary to allow the base class methods to be called for derived
objects.
Of course it's possible to derive new Python classes from wrapped C++
class instances. Because Boost.Python uses the new-style class
system, that works very much as for the Python built-in types. There
is one significant detail in which it differs: the built-in types
generally establish their invariants in their ``__new__`` function, so
that derived classes do not need to call ``__init__`` on the base
class before invoking its methods :
>>> class L(list):
... def __init__(self):
... pass
...
>>> L().reverse()
>>>
Because C++ object construction is a one-step operation, C++ instance
data cannot be constructed until the arguments are available, in the
``__init__`` function:
>>> class D(SomeBPLClass):
... def __init__(self):
... pass
...
>>> D().some_bpl_method()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: bad argument type for built-in operation
This happened because Boost.Python couldn't find instance data of type
``SomeBPLClass`` within the ``D`` instance; ``D``'s ``__init__``
function masked construction of the base class. It could be corrected
by either removing ``D``'s ``__init__`` function or having it call
``SomeBPLClass.__init__(...)`` explicitly.
Virtual Functions
=================
Deriving new types in Python from extension classes is not very
interesting unless they can be used polymorphically from C++. In
other words, Python method implementations should appear to override
the implementation of C++ virtual functions when called *through base
class pointers/references from C++*. Since the only way to alter the
behavior of a virtual function is to override it in a derived class,
the user must build a special derived class to dispatch a polymorphic
class' virtual functions::
//
// interface to wrap:
//
class Base
{
public:
virtual int f(std::string x) { return 42; }
virtual ~Base();
};
int calls_f(Base const& b, std::string x) { return b.f(x); }
//
// Wrapping Code
//
// Dispatcher class
struct BaseWrap : Base
{
// Store a pointer to the Python object
BaseWrap(PyObject* self_) : self(self_) {}
PyObject* self;
// Default implementation, for when f is not overridden
int f_default(std::string x) { return this->Base::f(x); }
// Dispatch implementation
int f(std::string x) { return call_method<int>(self, "f", x); }
};
...
def("calls_f", calls_f);
class_<Base, BaseWrap>("Base")
.def("f", &Base::f, &BaseWrap::f_default)
;
Now here's some Python code which demonstrates:
>>> class Derived(Base):
... def f(self, s):
... return len(s)
...
>>> calls_f(Base(), 'foo')
42
>>> calls_f(Derived(), 'forty-two')
9
Things to notice about the dispatcher class:
* The key element which allows overriding in Python is the
``call_method`` invocation, which uses the same global type
conversion registry as the C++ function wrapping does to convert its
arguments from C++ to Python and its return type from Python to C++.
* Any constructor signatures you wish to wrap must be replicated with
an initial ``PyObject*`` argument
* The dispatcher must store this argument so that it can be used to
invoke ``call_method``
* The ``f_default`` member function is needed when the function being
exposed is not pure virtual; there's no other way ``Base::f`` can be
called on an object of type ``BaseWrap``, since it overrides ``f``.
Admittedly, this formula is tedious to repeat, especially on a project
with many polymorphic classes; that it is necessary reflects
limitations in C++'s compile-time reflection capabilities. Several
efforts are underway to write front-ends for Boost.Python which can
generate these dispatchers (and other wrapping code) automatically.
If these are successful it will mark a move away from wrapping
everything directly in pure C++ for many of our users.
---------------
Serialization
---------------
*Serialization* is the process of converting objects in memory to a
form that can be stored on disk or sent over a network connection. The
serialized object (most often a plain string) can be retrieved and
converted back to the original object. A good serialization system will
automatically convert entire object hierarchies. Python's standard
``pickle`` module is such a system. It leverages the language's strong
runtime introspection facilities for serializing practically arbitrary
user-defined objects. With a few simple and unintrusive provisions this
powerful machinery can be extended to also work for wrapped C++ objects.
Here is an example::
#include <string>
struct World
{
World(std::string a_msg) : msg(a_msg) {}
std::string greet() const { return msg; }
std::string msg;
};
#include <boost/python.hpp>
using namespace boost::python;
struct World_picklers : pickle_suite
{
static tuple
getinitargs(World const& w) { return make_tuple(w.greet()); }
};
BOOST_PYTHON_MODULE(hello)
{
class_<World>("World", init<std::string>())
.def("greet", &World::greet)
.def_pickle(World_picklers())
;
}
Now let's create a ``World`` object and put it to rest on disk::
>>> import hello
>>> import pickle
>>> a_world = hello.World("howdy")
>>> pickle.dump(a_world, open("my_world", "w"))
In a potentially *different script* on a potentially *different
computer* with a potentially *different operating system*::
>>> import pickle
>>> resurrected_world = pickle.load(open("my_world", "r"))
>>> resurrected_world.greet()
'howdy'
Of course the ``cPickle`` module can also be used for faster
processing.
Boost.Python's ``pickle_suite`` fully supports the ``pickle`` protocol
defined in the standard Python documentation. There is a one-to-one
correspondence between the standard pickling methods (``__getinitargs__``,
``__getstate__``, ``__setstate__``) and the functions defined by the
user in the class derived from ``pickle_suite`` (``getinitargs``,
``getstate``, ``setstate``). The ``class_::def_pickle()`` member function
is used to establish the Python bindings for all user-defined functions
simultaneously. Correct signatures for these functions are enforced at
compile time. Non-sensical combinations of the three pickle functions
are also rejected at compile time. These measures are designed to
help the user in avoiding obvious errors.
Enabling serialization of more complex C++ objects requires a little
more work than is shown in the example above. Fortunately the
``object`` interface (see next section) greatly helps in keeping the
code manageable.
------------------
Object interface
------------------
Experienced extension module authors will be familiar with the 'C' view
of Python objects, the ubiquitous ``PyObject*``. Most if not all Python
'C' API functions involve ``PyObject*`` as arguments or return type. A
major complication is the raw reference counting interface presented to
the 'C' programmer. E.g. some API functions return *new references* and
others return *borrowed references*. It is up to the extension module
writer to properly increment and decrement reference counts. This
quickly becomes cumbersome and error prone, especially if there are
multiple execution paths.
Boost.Python provides a type ``object`` which is essentially a high
level wrapper around ``PyObject*``. ``object`` automates reference
counting as much as possible. It also provides the facilities for
converting arbitrary C++ types to Python objects and vice versa.
This significantly reduces the learning effort for prospective
extension module writers.
Creating an ``object`` from any other type is extremely simple::
object o(3);
``object`` has templated interactions with all other types, with
automatic to-python conversions. It happens so naturally that it's
easily overlooked.
The ``extract<T>`` class template can be used to convert Python objects
to C++ types::
double x = extract<double>(o);
All registered user-defined conversions are automatically accessible
through the ``object`` interface. With reference to the ``World`` class
defined in previous examples::
object as_python_object(World("howdy"));
World back_as_c_plus_plus_object = extract<World>(as_python_object);
If a C++ type cannot be converted to a Python object an appropriate
exception is thrown at runtime. Similarly, an appropriate exception is
thrown if a C++ type cannot be extracted from a Python object.
``extract<T>`` provides facilities for avoiding exceptions if this is
desired.
The ``object::attr()`` member function is available for accessing
and manipulating attributes of Python objects. For example::
object planet(World());
planet.attr("set")("howdy");
``planet.attr("set")`` returns a callable ``object``. ``"howdy"`` is
converted to a Python string object which is then passed as an argument
to the ``set`` method.
The ``object`` type is accompanied by a set of derived types
that mirror the Python built-in types such as ``list``, ``dict``,
``tuple``, etc. as much as possible. This enables convenient
manipulation of these high-level types from C++::
dict d;
d["some"] = "thing";
d["lucky_number"] = 13;
list l = d.keys();
This almost looks and works like regular Python code, but it is pure C++.
=================
Thinking hybrid
=================
For many applications runtime performance considerations are very
important. This is particularly true for most scientific applications.
Often the performance considerations dictate the use of a compiled
language for the core algorithms. Traditionally the decision to use a
particular programming language is an exclusive one. Because of the
practical and mental difficulties of combining different languages many
systems are written in just one language. This is quite unfortunate
because the price payed for runtime performance is typically a
significant overhead due to static typing. For example, our experience
shows that developing maintainable C++ code is typically much more
time-consuming and requires much more hard-earned working experience
than developing useful Python code. A related observation is that many
compiled packages are augmented by some type of rudimentary scripting
layer. These ad hoc solutions clearly show that many times a compiled
language alone does not get the job done. On the other hand it is also
clear that a pure Python implementation is too slow for numerically
intensive production code.
Boost.Python enables us to *think hybrid* when developing new
applications. Python can be used for rapidly prototyping a
new application. Python's ease of use and the large pool of standard
libraries give us a head start on the way to a first working system. If
necessary, the working procedure can be used to discover the
rate-limiting algorithms. To maximize performance these can be
reimplemented in C++, together with the Boost.Python bindings needed to
tie them back into the existing higher-level procedure.
Of course, this *top-down* approach is less attractive if it is clear
from the start that many algorithms will eventually have to be
implemented in a compiled language. Fortunately Boost.Python also
enables us to pursue a *bottom-up* approach. We have used this approach
very successfully in the development of a toolbox for scientific
applications (scitbx) that we will describe elsewhere. The toolbox
started out mainly as a library of C++ classes with Boost.Python
bindings, and for a while the growth was mainly concentrated on the C++
parts. However, as the toolbox is becoming more complete, more and more
newly added functionality can be implemented in Python. We expect this
trend to continue, as illustrated qualitatively in this figure:
.. image:: python_cpp_mix.png
This figure shows the ratio of newly added C++ and Python code over
time as new algorithms are implemented. We expect this ratio to level
out near 70% Python. The increasing ability to solve new problems
mostly with the easy-to-use Python language rather than a necessarily
more arcane statically typed language is the return on the investment
of learning how to use Boost.Python. The ability to solve some problems
entirely using only Python will enable a larger group of people to
participate in the rapid development of new applications.
=============
Conclusions
=============
The examples in this paper illustrate that Boost.Python enables
seamless interoperability between C++ and Python. Importantly, this is
achieved without introducing a third syntax: the Python/C++ interface
definitions are written in pure C++. This avoids any problems with
parsing the C++ code to be interfaced to Python, yet the interface
definitions are concise and maintainable. Freed from most of the
development-time penalties of crossing a language boundary, software
designers can take full advantage of two rich and complimentary
language environments. In practice it turns out that some things are
very difficult to do with pure Python/C (e.g. an efficient array
library with an intuitive interface in the compiled language) and
others are very difficult to do with pure C++ (e.g. serialization).
If one has the luxury of being able to design a software system as a
hybrid system from the ground up there are many new ways of avoiding
road blocks in one language or the other.
.. I'm not ready to give up on all of this quite yet
.. Perhaps one day we'll have a language with the simplicity and
expressive power of Python and the compile-time muscle of C++. Being
able to take advantage of all of these facilities without paying the
mental and development-time penalties of crossing a language barrier
would bring enormous benefits. Until then, interoperability tools
like Boost.Python can help lower the barrier and make the benefits of
both languages more accessible to both communities.
===========
Footnotes
===========
.. [#mi] For hard-core new-style class/extension module writers it is
worth noting that the normal requirement that all extension classes
with data form a layout-compatible single-inheritance chain is
lifted for Boost.Python extension classes. Clearly, either
``Base1`` or ``Base2`` has to occupy a different offset in the
``Derived`` class instance. This is possible because the wrapped
part of BPL extension class instances is never assumed to have a
fixed offset within the wrapper.
===========
Citations
===========
.. [VELD1995] T. Veldhuizen, "Expression Templates," C++ Report,
Vol. 7 No. 5 June 1995, pp. 26-31.
http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html

View File

@@ -1,190 +0,0 @@
/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date$
:version: $Revision$
:copyright: This stylesheet has been placed in the public domain.
boostinspect:nolicense
Default cascading style sheet for the HTML output of Docutils.
*/
.first {
margin-top: 0 }
.last {
margin-bottom: 0 }
a.toc-backref {
text-decoration: none ;
color: black }
dd {
margin-bottom: 0.5em }
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em }
div.footer, div.header {
font-size: smaller }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr {
width: 75% }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.line-block {
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option-argument {
font-style: italic }
span.pre {
white-space: pre }
span.problematic {
color: red }
table {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.citation {
border-left: solid thin gray ;
padding-left: 0.5ex }
table.docinfo {
margin: 2em 4em }
table.footnote {
border-left: solid thin black ;
padding-left: 0.5ex }
td, th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
th.docinfo-name, th.field-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap }
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
font-size: 100% }
tt {
background-color: #eeeeee }
ul.auto-toc {
list-style-type: none }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -1,63 +0,0 @@
/* Copyright David Abrahams 2006. Distributed under the Boost
Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
H1
{
FONT-SIZE: 200%
COLOR: #00007f
}
H2
{
FONT-SIZE: 150%;
}
H3
{
FONT-SIZE: 125%;
}
H4
{
FONT-SIZE: 108%;
}
BODY
{
FONT-SIZE: 100%;
BACKGROUND-COLOR: #ffffff
}
PRE
{
MARGIN-LEFT: 2pc;
FONT-SIZE: 80%;
BACKGROUND-COLOR: #dfffff
}
CODE
{
FONT-SIZE: 95%;
white-space: pre
}
.index
{
TEXT-ALIGN: left
}
.page-index
{
TEXT-ALIGN: left
}
.definition
{
TEXT-ALIGN: left
}
.footnote
{
FONT-SIZE: 66%;
VERTICAL-ALIGN: super;
TEXT-DECORATION: none
}
.function-semantics
{
CLEAR: left
}
.metafunction-semantics
{
CLEAR: left
}

View File

@@ -1,636 +1,180 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
<title>Boost C++ Libraries: Boost.Python Build and Test HOWTO</title>
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
</head>
<body>
<div class="document" id="logo-boost-python-build-and-test-howto">
<h1 class="title"><a class="reference external" href="../index.html"><img alt="Boost C++ Libraries:" class="boost-logo" src="../../../boost.png" /></a> Boost.Python Build and Test HOWTO</h1>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at -->
<!-- http://www.boost.org/LICENSE_1_0.txt) -->
<div class="contents sidebar small topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="auto-toc simple">
<li><a class="reference internal" href="#requirements" id="id25">1&nbsp;&nbsp;&nbsp;Requirements</a></li>
<li><a class="reference internal" href="#background" id="id26">2&nbsp;&nbsp;&nbsp;Background</a></li>
<li><a class="reference internal" href="#no-install-quickstart" id="id27">3&nbsp;&nbsp;&nbsp;No-Install Quickstart</a><ul class="auto-toc">
<li><a class="reference internal" href="#basic-procedure" id="id28">3.1&nbsp;&nbsp;&nbsp;Basic Procedure</a></li>
<li><a class="reference internal" href="#in-case-of-trouble" id="id29">3.2&nbsp;&nbsp;&nbsp;In Case of Trouble</a></li>
<li><a class="reference internal" href="#in-case-everything-seemed-to-work" id="id30">3.3&nbsp;&nbsp;&nbsp;In Case Everything Seemed to Work</a></li>
<li><a class="reference internal" href="#modifying-the-example-project" id="id31">3.4&nbsp;&nbsp;&nbsp;Modifying the Example Project</a></li>
</ul>
</li>
<li><a class="reference internal" href="#installing-boost-python-on-your-system" id="id32">4&nbsp;&nbsp;&nbsp;Installing Boost.Python on your System</a></li>
<li><a class="reference internal" href="#configuring-boost-build" id="id33">5&nbsp;&nbsp;&nbsp;Configuring Boost.Build</a><ul class="auto-toc">
<li><a class="reference internal" href="#python-configuration-parameters" id="id34">5.1&nbsp;&nbsp;&nbsp;Python Configuration Parameters</a></li>
<li><a class="reference internal" href="#examples" id="id35">5.2&nbsp;&nbsp;&nbsp;Examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#choosing-a-boost-python-library-binary" id="id36">6&nbsp;&nbsp;&nbsp;Choosing a Boost.Python Library Binary</a><ul class="auto-toc">
<li><a class="reference internal" href="#the-dynamic-binary" id="id37">6.1&nbsp;&nbsp;&nbsp;The Dynamic Binary</a></li>
<li><a class="reference internal" href="#the-static-binary" id="id38">6.2&nbsp;&nbsp;&nbsp;The Static Binary</a></li>
</ul>
</li>
<li><a class="reference internal" href="#include-issues" id="id39">7&nbsp;&nbsp;&nbsp;<tt class="docutils literal"><span class="pre">#include</span></tt> Issues</a></li>
<li><a class="reference internal" href="#python-debugging-builds" id="id40">8&nbsp;&nbsp;&nbsp;Python Debugging Builds</a></li>
<li><a class="reference internal" href="#testing-boost-python" id="id41">9&nbsp;&nbsp;&nbsp;Testing Boost.Python</a></li>
<li><a class="reference internal" href="#notes-for-mingw-and-cygwin-with-mno-cygwin-gcc-users" id="id42">10&nbsp;&nbsp;&nbsp;Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users</a></li>
</ul>
</div>
<div class="section" id="requirements">
<h1><a class="toc-backref" href="#id25">1&nbsp;&nbsp;&nbsp;Requirements</a></h1>
<p>Boost.Python requires <a class="reference external" href="http://www.python.org/2.2">Python 2.2</a><a class="footnote-reference" href="#id22" id="id2"><sup>1</sup></a> <em>or</em> <a class="reference external" href="http://www.python.org"><em>newer</em></a>.</p>
</div>
<div class="section" id="background">
<h1><a class="toc-backref" href="#id26">2&nbsp;&nbsp;&nbsp;Background</a></h1>
<p>There are two basic models for combining C++ and Python:</p>
<ul class="simple">
<li><a class="reference external" href="http://www.python.org/doc/current/ext/intro.html">extending</a>, in which the end-user launches the Python interpreter
executable and imports Python “extension modules” written in C++.
Think of taking a library written in C++ and giving it a Python
interface so Python programmers can use it. From Python, these
modules look just like regular Python modules.</li>
<li><a class="reference external" href="http://www.python.org/doc/current/ext/embedding.html">embedding</a>, in which the end-user launches a program written
in C++ that in turn invokes the Python interpreter as a library
subroutine. Think of adding scriptability to an existing
application.</li>
</ul>
<p>The key distinction between extending and embedding is the location
of the C++ <tt class="docutils literal"><span class="pre">main()</span></tt> function: in the Python interpreter executable,
or in some other program, respectively. Note that even when
embedding Python in another program, <a class="reference external" href="http://www.python.org/doc/current/ext/extending-with-embedding.html">extension modules are often
the best way to make C/C++ functionality accessible to Python
code</a>, so the use of extension modules is really at the heart of
both models.</p>
<p>Except in rare cases, extension modules are built as
dynamically-loaded libraries with a single entry point, which means
you can change them without rebuilding either the other extension
modules or the executable containing <tt class="docutils literal"><span class="pre">main()</span></tt>.</p>
</div>
<div class="section" id="no-install-quickstart">
<span id="quickstart"></span><h1><a class="toc-backref" href="#id27">3&nbsp;&nbsp;&nbsp;No-Install Quickstart</a></h1>
<p>There is no need to “install Boost” in order to get started using
Boost.Python. These instructions use <a class="reference external" href="../../../tools/build/index.html">Boost.Build</a> projects,
which will build those binaries as soon as they're needed. Your
first tests may take a little longer while you wait for
Boost.Python to build, but doing things this way will save you from
worrying about build intricacies like which library binaries to use
for a specific compiler configuration and figuring out the right
compiler options to use yourself.</p>
<!-- .. raw:: html
<meta name="generator" content="HTML Tidy, see www.w3.org">
<div style="width:50%"> -->
<div class="note">
<p class="first admonition-title">Note</p>
<p>Of course it's possible to use other build systems to
build Boost.Python and its extensions, but they are not
officially supported by Boost. Moreover <strong>99% of all “I can't
build Boost.Python” problems come from trying to use another
build system</strong> without first following these instructions.</p>
<p>If you want to use another system anyway, we suggest that you
follow these instructions, and then invoke <tt class="docutils literal"><span class="pre">bjam</span></tt> with the</p>
<pre class="literal-block">
<tt class="docutils literal"><span class="pre">-a</span> <span class="pre">-o</span></tt><em>filename</em>
</pre>
<p class="last">options to dump the build commands it executes to a file, so
you can see what your alternate build system needs to do.</p>
</div>
<!-- .. raw:: html
<title>Building an Extension Module</title>
</div> -->
<div class="section" id="basic-procedure">
<h2><a class="toc-backref" href="#id28">3.1&nbsp;&nbsp;&nbsp;Basic Procedure</a></h2>
<ol class="arabic">
<li><p class="first">Get Boost; see sections 1 and 2 [<a class="reference external" href="../../../more/getting_started/unix-variants.html#get-boost">Unix/Linux</a>, <a class="reference external" href="../../../more/getting_started/windows.html#get-boost">Windows</a>] of the
Boost <a class="reference external" href="../../../more/getting_started/index.html">Getting Started Guide</a>.</p>
</li>
<li><p class="first">Get the <tt class="docutils literal"><span class="pre">bjam</span></tt> build driver. See section 5 [<a class="reference external" href="../../../more/getting_started/unix-variants.html#prepare-to-use-a-boost-library-binary">Unix/Linux</a>,
<a class="reference external" href="../../../more/getting_started/windows.html#prepare-to-use-a-boost-library-binary">Windows</a>] of the Boost <a class="reference external" href="../../../more/getting_started/index.html">Getting Started Guide</a>.</p>
</li>
<li><p class="first">cd into the <tt class="docutils literal"><span class="pre">libs/python/example/quickstart/</span></tt> directory of your
Boost installation, which contains a small example project.</p>
</li>
<li><p class="first">Invoke <tt class="docutils literal"><span class="pre">bjam</span></tt>. Replace the “<tt class="docutils literal"><span class="pre">stage</span></tt>“ argument from the
example invocation from section 5 of the <a class="reference external" href="../../../more/getting_started/index.html">Getting Started
Guide</a> with “<tt class="docutils literal"><span class="pre">test</span></tt>,“ to build all the test targets. Also add
the argument “<tt class="docutils literal"><span class="pre">--verbose-test</span></tt>” to see the output generated by
the tests when they are run.</p>
<p>On Windows, your <tt class="docutils literal"><span class="pre">bjam</span></tt> invocation might look something like:</p>
<pre class="literal-block">
C:\boost_1_34_0\…\quickstart&gt; <strong>bjam toolset=msvc --verbose-test test</strong>
</pre>
<p>and on Unix variants, perhaps,</p>
<pre class="literal-block">
~/boost_1_34_0/…/quickstart$ <strong>bjam toolset=gcc --verbose-test test</strong>
</pre>
</li>
</ol>
<div class="admonition-note-to-windows-users admonition">
<p class="first admonition-title">Note to Windows Users</p>
<p class="last">For the sake of concision, the rest of this guide will use
unix-style forward slashes in pathnames instead of the
backslashes with which you may be more familiar. The forward
slashes should work everywhere except in <a class="reference external" href="../../../more/getting_started/windows.html#command-prompt">Command Prompt</a>
windows, where you should use backslashes.</p>
</div>
<p>If you followed this procedure successfully, you will have built an
extension module called <tt class="docutils literal"><span class="pre">extending</span></tt> and tested it by running a
Python script called <tt class="docutils literal"><span class="pre">test_extending.py</span></tt>. You will also have
built and run a simple application called <tt class="docutils literal"><span class="pre">embedding</span></tt> that embeds
python.</p>
</div>
<div class="section" id="in-case-of-trouble">
<h2><a class="toc-backref" href="#id29">3.2&nbsp;&nbsp;&nbsp;In Case of Trouble</a></h2>
<p>If you're seeing lots of compiler and/or linker error messages,
it's probably because Boost.Build is having trouble finding your
Python installation. You might want to pass the
<tt class="docutils literal"><span class="pre">--debug-configuration</span></tt> option to <tt class="docutils literal"><span class="pre">bjam</span></tt> the first few times
you invoke it, to make sure that Boost.Build is correctly locating
all the parts of your Python installation. If it isn't, consider
<a class="reference internal" href="#configuring-boost-build">Configuring Boost.Build</a> as detailed below.</p>
<p>If you're still having trouble, Someone on one of the following
mailing lists may be able to help:</p>
<ul class="simple">
<li>The <a class="reference external" href="http://www.boost.org/more/mailing_lists.htm#jamboost">Boost.Build mailing list</a> for issues related to Boost.Build</li>
<li>The Python <a class="reference external" href="http://www.boost.org/more/mailing_lists.htm#cplussig">C++ Sig</a> for issues specifically related to Boost.Python</li>
</ul>
</div>
<div class="section" id="in-case-everything-seemed-to-work">
<h2><a class="toc-backref" href="#id30">3.3&nbsp;&nbsp;&nbsp;In Case Everything Seemed to Work</a></h2>
<p>Rejoice! If you're new to Boost.Python, at this point it might be
a good idea to ignore build issues for a while and concentrate on
learning the library by going through the <a class="reference external" href="tutorial/index.html">tutorial</a> and perhaps
some of the <a class="reference external" href="v2/reference.html">reference documentation</a>, trying out what you've
learned about the API by modifying the quickstart project.</p>
</div>
<div class="section" id="modifying-the-example-project">
<h2><a class="toc-backref" href="#id31">3.4&nbsp;&nbsp;&nbsp;Modifying the Example Project</a></h2>
<p>If you're content to keep your extension module forever in one
source file called <a class="reference external" href="../example/quickstart/extending.cpp"><tt class="docutils literal"><span class="pre">extending.cpp</span></tt></a>, inside your Boost
distribution, and import it forever as <tt class="docutils literal"><span class="pre">extending</span></tt>, then you can
stop here. However, it's likely that you will want to make a few
changes. There are a few things you can do without having to learn
<a class="reference external" href="../../../tools/build/index.html">Boost.Build</a> in depth.</p>
<p>The project you just built is specified in two files in the current
directory: <a class="reference external" href="../example/quickstart/boost-build.jam"><tt class="docutils literal"><span class="pre">boost-build.jam</span></tt></a>, which tells <tt class="docutils literal"><span class="pre">bjam</span></tt> where it can
find the interpreted code of the Boost build system, and
<a class="reference external" href="../example/quickstart/Jamroot"><tt class="docutils literal"><span class="pre">Jamroot</span></tt></a>, which describes the targets you just built. These
files are heavily commented, so they should be easy to modify.
Take care, however, to preserve whitespace. Punctuation such as
<tt class="docutils literal"><span class="pre">;</span></tt> will not be recognized as intended by <tt class="docutils literal"><span class="pre">bjam</span></tt> if it is not
surrounded by whitespace.</p>
<div class="section" id="relocate-the-project">
<h3>Relocate the Project</h3>
<p>You'll probably want to copy this project elsewhere so you can
change it without modifying your Boost distribution. To do that,
simply</p>
<ol class="loweralpha simple">
<li>copy the entire <tt class="docutils literal"><span class="pre">libs/python/example/quickstart/</span></tt> directory
into a new directory.</li>
<li>In the new copies of <a class="reference external" href="../example/quickstart/boost-build.jam"><tt class="docutils literal"><span class="pre">boost-build.jam</span></tt></a> and <a class="reference external" href="../example/quickstart/Jamroot"><tt class="docutils literal"><span class="pre">Jamroot</span></tt></a>, locate
the relative path near the top of the file that is clearly
marked by a comment, and edit that path so that it refers to the
same directory your Boost distribution as it referred to when
the file was in its original location in the
<tt class="docutils literal"><span class="pre">libs/python/example/quickstart/</span></tt> directory.</li>
</ol>
<p>For example, if you moved the project from
<tt class="docutils literal"><span class="pre">/home/dave/boost_1_34_0/libs/python/example/quickstart</span></tt> to
<tt class="docutils literal"><span class="pre">/home/dave/my-project</span></tt>, you could change the first path in
<a class="reference external" href="../example/quickstart/boost-build.jam"><tt class="docutils literal"><span class="pre">boost-build.jam</span></tt></a> from</p>
<pre class="literal-block">
<strong>../../../..</strong>/tools/build/v2
</pre>
<p>to</p>
<pre class="literal-block">
<strong>/home/dave/boost_1_34_0</strong>/tools/build/v2
</pre>
<p>and change the first path in <a class="reference external" href="../example/quickstart/Jamroot"><tt class="docutils literal"><span class="pre">Jamroot</span></tt></a> from</p>
<pre class="literal-block">
<strong>../../../..</strong>
</pre>
<p>to</p>
<pre class="literal-block">
<strong>/home/dave/boost_1_34_0</strong>
</pre>
</div>
<div class="section" id="add-new-or-change-names-of-existing-source-files">
<h3>Add New or Change Names of Existing Source Files</h3>
<p>The names of additional source files involved in building your
extension module or embedding application can be listed in
<a class="reference external" href="../example/quickstart/Jamroot"><tt class="docutils literal"><span class="pre">Jamroot</span></tt></a> right alongside <tt class="docutils literal"><span class="pre">extending.cpp</span></tt> or <tt class="docutils literal"><span class="pre">embedding.cpp</span></tt>
respectively. Just be sure to leave whitespace around each
filename:</p>
<pre class="literal-block">
… file1.cpp file2.cpp file3.cpp …
</pre>
<p>Naturally, if you want to change the name of a source file you can
tell Boost.Build about it by editing the name in <a class="reference external" href="../example/quickstart/Jamroot"><tt class="docutils literal"><span class="pre">Jamroot</span></tt></a>.</p>
</div>
<div class="section" id="change-the-name-of-your-extension-module">
<h3>Change the Name of your Extension Module</h3>
<p>The name of the extension module is determined by two things:</p>
<ol class="arabic simple">
<li>the name in <a class="reference external" href="../example/quickstart/Jamroot"><tt class="docutils literal"><span class="pre">Jamroot</span></tt></a> immediately following <tt class="docutils literal"><span class="pre">python-extension</span></tt>, and</li>
<li>the name passed to <tt class="docutils literal"><span class="pre">BOOST_PYTHON_MODULE</span></tt> in <a class="reference external" href="../example/quickstart/extending.cpp"><tt class="docutils literal"><span class="pre">extending.cpp</span></tt></a>.</li>
</ol>
<p>To change the name of the extension module from <tt class="docutils literal"><span class="pre">extending</span></tt> to
<tt class="docutils literal"><span class="pre">hello</span></tt>, you'd edit <a class="reference external" href="../example/quickstart/Jamroot"><tt class="docutils literal"><span class="pre">Jamroot</span></tt></a>, changing</p>
<pre class="literal-block">
python-extension <strong>extending</strong> : extending.cpp ;
</pre>
<p>to</p>
<pre class="literal-block">
python-extension <strong>hello</strong> : extending.cpp ;
</pre>
<p>and you'd edit extending.cpp, changing</p>
<pre class="literal-block">
BOOST_PYTHON_MODULE(<strong>extending</strong>)
</pre>
<p>to</p>
<pre class="literal-block">
BOOST_PYTHON_MODULE(<strong>hello</strong>)
</pre>
</div>
</div>
</div>
<div class="section" id="installing-boost-python-on-your-system">
<h1><a class="toc-backref" href="#id32">4&nbsp;&nbsp;&nbsp;Installing Boost.Python on your System</a></h1>
<p>Since Boost.Python is a separately-compiled (as opposed to
<a class="reference external" href="../../../more/getting_started/windows.html#header-only-libraries">header-only</a>) library, its user relies on the services of a
Boost.Python library binary.</p>
<p>If you need a regular installation of the Boost.Python library
binaries on your system, the Boost <a class="reference external" href="../../../more/getting_started/index.html">Getting Started Guide</a> will
walk you through the steps of creating one. If building binaries
from source, you might want to supply the <tt class="docutils literal"><span class="pre">--with-python</span></tt>
argument to <tt class="docutils literal"><span class="pre">bjam</span></tt> (or the <tt class="docutils literal"><span class="pre">--with-libraries=python</span></tt> argument
to <tt class="docutils literal"><span class="pre">configure</span></tt>), so only the Boost.Python binary will be built,
rather than all the Boost binaries.</p>
</div>
<div class="section" id="configuring-boost-build">
<h1><a class="toc-backref" href="#id33">5&nbsp;&nbsp;&nbsp;Configuring Boost.Build</a></h1>
<p>As described in the <a class="reference external" href="http://www.boost.orgdoc/html/bbv2/advanced.html#bbv2.advanced.configuration">Boost.Build reference manual</a>, a file called
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> in your home directory<a class="footnote-reference" href="#home-dir" id="id11"><sup>6</sup></a> is used to
specify the tools and libraries available to the build system. You
may need to create or edit <tt class="docutils literal"><span class="pre">user-config.jam</span></tt> to tell Boost.Build
how to invoke Python, <tt class="docutils literal"><span class="pre">#include</span></tt> its headers, and link with its
libraries.</p>
<div class="admonition-users-of-unix-variant-oses admonition">
<p class="first admonition-title">Users of Unix-Variant OSes</p>
<p class="last">If you are using a unix-variant OS and you ran Boost's
<tt class="docutils literal"><span class="pre">configure</span></tt> script, it may have generated a
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> for you.<a class="footnote-reference" href="#overwrite" id="id13"><sup>4</sup></a> If your <tt class="docutils literal"><span class="pre">configure</span></tt>/<tt class="docutils literal"><span class="pre">make</span></tt> sequence was successful and Boost.Python binaries
were built, your <tt class="docutils literal"><span class="pre">user-config.jam</span></tt> file is probably already
correct.</p>
</div>
<p>If you have one fairly “standard” python installation for your
platform, you might not need to do anything special to describe it. If
you haven't configured python in <tt class="docutils literal"><span class="pre">user-config.jam</span></tt> (and you don't
specify <tt class="docutils literal"><span class="pre">--without-python</span></tt> on the Boost.Build command line),
Boost.Build will automatically execute the equivalent of</p>
<pre class="literal-block">
import toolset : using ;
using python ;
</pre>
<p>which automatically looks for Python in the most likely places.
However, that only happens when using the Boost.Python project file
(e.g. when referred to by another project as in the <a class="reference internal" href="#quickstart">quickstart</a>
method). If instead you are linking against separately-compiled
Boost.Python binaries, you should set up a <tt class="docutils literal"><span class="pre">user-config.jam</span></tt> file
with at least the minimal incantation above.</p>
<div class="section" id="python-configuration-parameters">
<h2><a class="toc-backref" href="#id34">5.1&nbsp;&nbsp;&nbsp;Python Configuration Parameters</a></h2>
<p>If you have several versions of Python installed, or Python is
installed in an unusual way, you may want to supply any or all of
the following optional parameters to <tt class="docutils literal"><span class="pre">using</span> <span class="pre">python</span></tt>.</p>
<dl class="docutils">
<dt>version</dt>
<dd>the version of Python to use. Should be in Major.Minor
format, for example, <tt class="docutils literal"><span class="pre">2.3</span></tt>. Do not include the subminor
version (i.e. <em>not</em> <tt class="docutils literal"><span class="pre">2.5.1</span></tt>). If you have multiple Python
versions installed, the version will usually be the only
configuration argument required.</dd>
<dt>cmd-or-prefix</dt>
<dd>preferably, a command that invokes a Python interpreter.
Alternatively, the installation prefix for Python libraries and
header files. Only use the alternative formulation if there is
no appropriate Python executable available.</dd>
<dt>includes</dt>
<dd>the <tt class="docutils literal"><span class="pre">#include</span></tt> paths for Python headers. Normally the correct
path(s) will be automatically deduced from <tt class="docutils literal"><span class="pre">version</span></tt> and/or
<tt class="docutils literal"><span class="pre">cmd-or-prefix</span></tt>.</dd>
<dt>libraries</dt>
<dd>the path to Python library binaries. On MacOS/Darwin,
you can also pass the path of the Python framework. Normally the
correct path(s) will be automatically deduced from <tt class="docutils literal"><span class="pre">version</span></tt>
and/or <tt class="docutils literal"><span class="pre">cmd-or-prefix</span></tt>.</dd>
<dt>condition</dt>
<dd>if specified, should be a set of Boost.Build
properties that are matched against the build configuration when
Boost.Build selects a Python configuration to use. See examples
below for details.</dd>
<dt>extension-suffix</dt>
<dd>A string to append to the name of extension
modules before the true filename extension. You almost certainly
don't need to use this. Usually this suffix is only used when
targeting a Windows debug build of Python, and will be set
automatically for you based on the value of the
<a class="reference internal" href="#python-debugging"><tt class="docutils literal"><span class="pre">&lt;python-debugging&gt;</span></tt></a> feature. However, at least one Linux
distribution (Ubuntu Feisty Fawn) has a specially configured
<a class="reference external" href="https://wiki.ubuntu.com/PyDbgBuilds">python-dbg</a> package that claims to use such a suffix.</dd>
</dl>
</div>
<div class="section" id="examples">
<h2><a class="toc-backref" href="#id35">5.2&nbsp;&nbsp;&nbsp;Examples</a></h2>
<p>Note that in the examples below, case and <em>especially whitespace</em> are
significant.</p>
<ul>
<li><p class="first">If you have both python 2.5 and python 2.4 installed,
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> might contain:</p>
<pre class="literal-block">
using python : 2.5 ; # Make both versions of Python available
<div>
<h1><img width="277" height="86" align="center" src=
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Building an
Extension Module</h1>
using python : 2.4 ; # To build with python 2.4, add python=2.4
# to your command line.
</pre>
<p>The first version configured (2.5) becomes the default. To build
against python 2.4, add <tt class="docutils literal"><span class="pre">python=2.4</span></tt> to the <tt class="docutils literal"><span class="pre">bjam</span></tt> command line.</p>
</li>
<li><p class="first">If you have python installed in an unusual location, you might
supply the path to the interpreter in the <tt class="docutils literal"><span class="pre">cmd-or-prefix</span></tt>
parameter:</p>
<pre class="literal-block">
using python : : /usr/local/python-2.6-beta/bin/python ;
</pre>
</li>
<li><p class="first">If you have a separate build of Python for use with a particular
toolset, you might supply that toolset in the <tt class="docutils literal"><span class="pre">condition</span></tt>
parameter:</p>
<pre class="literal-block">
using python ; # use for most toolsets
<p>The build process for Boost is currently undergoing some evolution,
and, it is to be hoped, improvement. The following facts may help:
# Use with Intel C++ toolset
using python
: # version
: c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
: # includes
: # libraries
: &lt;toolset&gt;intel # condition
;
</pre>
</li>
<li><p class="first">If you have downloaded the Python sources and built both the
normal and the “<a class="reference internal" href="#id19">python debugging</a>” builds from source on
Windows, you might see:</p>
<pre class="literal-block">
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python ;
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python_d
: # includes
: # libs
: &lt;python-debugging&gt;on ;
</pre>
</li>
<li><p class="first">You can set up your user-config.jam so a bjam built under Windows
can build/test both Windows and <a class="reference external" href="http://cygwin.com">Cygwin</a> python extensions. Just pass
<tt class="docutils literal"><span class="pre">&lt;target-os&gt;cygwin</span></tt> in the <tt class="docutils literal"><span class="pre">condition</span></tt> parameter
for the cygwin python installation:</p>
<pre class="literal-block">
# windows installation
using python ;
<hr>
Makefiles for various platforms and a Visual Studio project
reside in the Boost subdirectory <tt>libs/python/build</tt>.
Build targets include:
# cygwin installation
using python : : c:\\cygwin\\bin\\python2.5 : : : &lt;target-os&gt;cygwin ;
</pre>
<p>when you put target-os=cygwin in your build request, it should build
with the cygwin version of python:<a class="footnote-reference" href="#flavor" id="id15"><sup>5</sup></a></p>
<blockquote>
<p>bjam target-os=cygwin toolset=gcc</p>
</blockquote>
<p>This is supposed to work the other way, too (targeting windows
python with a <a class="reference external" href="http://cygwin.com">Cygwin</a> bjam) but it seems as though the support in
Boost.Build's toolsets for building that way is broken at the
time of this writing.</p>
</li>
<li><p class="first">Note that because of <a class="reference external" href="http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection">the way Boost.Build currently selects target
alternatives</a>, you might have be very explicit in your build
requests. For example, given:</p>
<pre class="literal-block">
using python : 2.5 ; # a regular windows build
using python : 2.4 : : : : &lt;target-os&gt;cygwin ;
</pre>
<p>building with</p>
<pre class="literal-block">
bjam target-os=cygwin
</pre>
<p>will yield an error. Instead, you'll need to write:</p>
<pre class="literal-block">
bjam target-os=cygwin/python=2.4
</pre>
</li>
</ul>
</div>
</div>
<div class="section" id="choosing-a-boost-python-library-binary">
<h1><a class="toc-backref" href="#id36">6&nbsp;&nbsp;&nbsp;Choosing a Boost.Python Library Binary</a></h1>
<p>If—instead of letting Boost.Build construct and link with the right
libraries automatically—you choose to use a pre-built Boost.Python
library, you'll need to think about which one to link with. The
Boost.Python binary comes in both static and dynamic flavors. Take
care to choose the right flavor for your application.<a class="footnote-reference" href="#naming" id="id17"><sup>2</sup></a></p>
<div class="section" id="the-dynamic-binary">
<h2><a class="toc-backref" href="#id37">6.1&nbsp;&nbsp;&nbsp;The Dynamic Binary</a></h2>
<p>The dynamic library is the safest and most-versatile choice:</p>
<ul class="simple">
<li>A single copy of the library code is used by all extension
modules built with a given toolset.<a class="footnote-reference" href="#toolset-specific" id="id18"><sup>3</sup></a></li>
<li>The library contains a type conversion registry. Because one
registry is shared among all extension modules, instances of a
class exposed to Python in one dynamically-loaded extension
module can be passed to functions exposed in another such module.</li>
</ul>
</div>
<div class="section" id="the-static-binary">
<h2><a class="toc-backref" href="#id38">6.2&nbsp;&nbsp;&nbsp;The Static Binary</a></h2>
<p>It might be appropriate to use the static Boost.Python library in
any of the following cases:</p>
<ul class="simple">
<li>You are <a class="reference external" href="http://www.python.org/doc/current/ext/intro.html">extending</a> python and the types exposed in your
dynamically-loaded extension module don't need to be used by any
other Boost.Python extension modules, and you don't care if the
core library code is duplicated among them.</li>
<li>You are <a class="reference external" href="http://www.python.org/doc/current/ext/embedding.html">embedding</a> python in your application and either:<ul>
<li>You are targeting a Unix variant OS other than MacOS or AIX,
where the dynamically-loaded extension modules can “see” the
Boost.Python library symbols that are part of the executable.</li>
<li>Or, you have statically linked some Boost.Python extension
modules into your application and you don't care if any
dynamically-loaded Boost.Python extension modules are able to
use the types exposed by your statically-linked extension
modules (and vice-versa).</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="section" id="include-issues">
<h1><a class="toc-backref" href="#id39">7&nbsp;&nbsp;&nbsp;<tt class="docutils literal"><span class="pre">#include</span></tt> Issues</a></h1>
<ol class="arabic simple">
<li>If you should ever have occasion to <tt class="docutils literal"><span class="pre">#include</span> <span class="pre">&quot;python.h&quot;</span></tt>
directly in a translation unit of a program using Boost.Python,
use <tt class="docutils literal"><span class="pre">#include</span> <span class="pre">&quot;boost/python/detail/wrap_python.hpp&quot;</span></tt> instead.
It handles several issues necessary for use with Boost.Python,
one of which is mentioned in the next section.</li>
<li>Be sure not to <tt class="docutils literal"><span class="pre">#include</span></tt> any system headers before
<tt class="docutils literal"><span class="pre">wrap_python.hpp</span></tt>. This restriction is actually imposed by
Python, or more properly, by Python's interaction with your
operating system. See
<a class="reference external" href="http://docs.python.org/ext/simpleExample.html">http://docs.python.org/ext/simpleExample.html</a> for details.</li>
</ol>
</div>
<div class="section" id="python-debugging-builds">
<span id="id19"></span><span id="python-debugging"></span><h1><a class="toc-backref" href="#id40">8&nbsp;&nbsp;&nbsp;Python Debugging Builds</a></h1>
<p>Python can be built in a special “python debugging” configuration
that adds extra checks and instrumentation that can be very useful
for developers of extension modules. The data structures used by
the debugging configuration contain additional members, so <strong>a
Python executable built with python debugging enabled cannot be
used with an extension module or library compiled without it, and
vice-versa.</strong></p>
<p>Since pre-built “python debugging” versions of the Python
executable and libraries are not supplied with most distributions
of Python,<a class="footnote-reference" href="#get-debug-build" id="id20"><sup>7</sup></a> and we didn't want to force our users
to build them, Boost.Build does not automatically enable python
debugging in its <tt class="docutils literal"><span class="pre">debug</span></tt> build variant (which is the default).
Instead there is a special build property called
<tt class="docutils literal"><span class="pre">python-debugging</span></tt> that, when used as a build property, will
define the right preprocessor symbols and select the right
libraries to link with.</p>
<p>On unix-variant platforms, the debugging versions of Python's data
structures will only be used if the symbol <tt class="docutils literal"><span class="pre">Py_DEBUG</span></tt> is defined.
On many windows compilers, when extension modules are built with
the preprocessor symbol <tt class="docutils literal"><span class="pre">_DEBUG</span></tt>, Python defaults to force
linking with a special debugging version of the Python DLL. Since
that symbol is very commonly used even when Python is not present,
Boost.Python temporarily undefines _DEBUG when Python.h
is #included from <tt class="docutils literal"><span class="pre">boost/python/detail/wrap_python.hpp</span></tt> - unless
<tt class="docutils literal"><span class="pre">BOOST_DEBUG_PYTHON</span></tt> is defined. The upshot is that if you want
“python debugging”and you aren't using Boost.Build, you should make
sure <tt class="docutils literal"><span class="pre">BOOST_DEBUG_PYTHON</span></tt> is defined, or python debugging will be
suppressed.</p>
</div>
<div class="section" id="testing-boost-python">
<h1><a class="toc-backref" href="#id41">9&nbsp;&nbsp;&nbsp;Testing Boost.Python</a></h1>
<p>To run the full test suite for Boost.Python, invoke <tt class="docutils literal"><span class="pre">bjam</span></tt> in the
<tt class="docutils literal"><span class="pre">libs/python/test</span></tt> subdirectory of your Boost distribution.</p>
</div>
<div class="section" id="notes-for-mingw-and-cygwin-with-mno-cygwin-gcc-users">
<h1><a class="toc-backref" href="#id42">10&nbsp;&nbsp;&nbsp;Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users</a></h1>
<p>If you are using a version of Python prior to 2.4.1 with a MinGW
prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will need to
create a MinGW-compatible version of the Python library; the one
shipped with Python will only work with a Microsoft-compatible
linker. Follow the instructions in the “Non-Microsoft” section of
the “Building Extensions: Tips And Tricks” chapter in <a class="reference external" href="http://www.python.org/doc/current/inst/index.html">Installing
Python Modules</a> to create <tt class="docutils literal"><span class="pre">libpythonXX.a</span></tt>, where <tt class="docutils literal"><span class="pre">XX</span></tt>
corresponds to the major and minor version numbers of your Python
installation.</p>
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="id22" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[1]</a></td><td>Note that although we tested earlier versions of
Boost.Python with Python 2.2, and we don't <em>think</em> we've done
anything to break compatibility, this release of Boost.Python
may not have been tested with versions of Python earlier than
2.4, so we're not 100% sure that python 2.2 and 2.3 are
supported.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="naming" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id17">[2]</a></td><td><p class="first">Information about how to identify the
static and dynamic builds of Boost.Python:</p>
<ul class="simple">
<li><a class="reference external" href="../../../more/getting_started/windows.html#library-naming">on Windows</a></li>
<li><a class="reference external" href="../../../more/getting_started/unix-variants.html#library-naming">on Unix variants</a></li>
</ul>
</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="toolset-specific" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id18">[3]</a></td><td>Because of the way most *nix platforms
share symbols among dynamically-loaded objects, I'm not certain
that extension modules built with different compiler toolsets
will always use different copies of the Boost.Python library
when loaded into the same Python instance. Not using different
libraries could be a good thing if the compilers have compatible
ABIs, because extension modules built with the two libraries
would be interoperable. Otherwise, it could spell disaster,
since an extension module and the Boost.Python library would
have different ideas of such things as class layout. I would
appreciate someone doing the experiment to find out what
happens.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="overwrite" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id13">[4]</a></td><td><tt class="docutils literal"><span class="pre">configure</span></tt> overwrites the existing
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> in your home directory
(if any) after making a backup of the old version.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="flavor" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id15">[5]</a></td><td>Note that the <tt class="docutils literal"><span class="pre">&lt;target-os&gt;cygwin</span></tt> feature is
different from the <tt class="docutils literal"><span class="pre">&lt;flavor&gt;cygwin</span></tt> subfeature of the <tt class="docutils literal"><span class="pre">gcc</span></tt>
toolset, and you might need handle both explicitly if you also
have a MinGW GCC installed.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="home-dir" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id11">[6]</a></td><td><p class="first">Windows users, your home directory can be
found by typing:</p>
<pre class="literal-block">
ECHO %HOMEDRIVE%%HOMEPATH%
</pre>
<p class="last">into a <a class="reference external" href="../../../more/getting_started/windows.html#command-prompt">command prompt</a> window.</p>
</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="get-debug-build" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id20">[7]</a></td><td>On Unix and similar platforms, a debugging
python and associated libraries are built by adding
<tt class="docutils literal"><span class="pre">--with-pydebug</span></tt> when configuring the Python build. On
Windows, the debugging version of Python is generated by
the &quot;Win32 Debug&quot; target of the Visual Studio project in the
PCBuild subdirectory of a full Python source code distribution.
</td></tr>
</tbody>
</table>
</div>
</div>
<div class="footer">
<hr class="footer" />
<a class="reference external" href="./building.rst">View document source</a>.
Generated on: 2007-07-02 13:46 UTC.
Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
<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>.
</div>
</body>
</html>
<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 &lt;<a href=
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a>&gt;</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>&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided ``as is'' without
express or implied warranty, and with no claim as to its suitability for
any purpose.
<p>Updated: Apr 17, 2001 (R.W. Grosse-Kunstleve)
</div>

View File

@@ -1,680 +0,0 @@
.. Copyright David Abrahams 2006. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at
.. http://www.boost.org/LICENSE_1_0.txt)
==============================================
|(logo)|__ Boost.Python Build and Test HOWTO
==============================================
.. |(logo)| image:: ../../../boost.png
:alt: Boost C++ Libraries:
:class: boost-logo
__ ../index.html
.. section-numbering::
:depth: 2
.. contents:: Contents
:depth: 2
:class: sidebar small
.. |newer| replace:: *newer*
Requirements
============
Boost.Python requires `Python 2.2`_ [#2.2]_ *or* |newer|__.
.. _Python 2.2: http://www.python.org/2.2
__ http://www.python.org
Background
==========
There are two basic models for combining C++ and Python:
- extending_, in which the end-user launches the Python interpreter
executable and imports Python “extension modules” written in C++.
Think of taking a library written in C++ and giving it a Python
interface so Python programmers can use it. From Python, these
modules look just like regular Python modules.
- embedding_, in which the end-user launches a program written
in C++ that in turn invokes the Python interpreter as a library
subroutine. Think of adding scriptability to an existing
application.
.. _extending: http://www.python.org/doc/current/ext/intro.html
.. _embedding: http://www.python.org/doc/current/ext/embedding.html
The key distinction between extending and embedding is the location
of the C++ ``main()`` function: in the Python interpreter executable,
or in some other program, respectively. Note that even when
embedding Python in another program, `extension modules are often
the best way to make C/C++ functionality accessible to Python
code`__, so the use of extension modules is really at the heart of
both models.
__ http://www.python.org/doc/current/ext/extending-with-embedding.html
Except in rare cases, extension modules are built as
dynamically-loaded libraries with a single entry point, which means
you can change them without rebuilding either the other extension
modules or the executable containing ``main()``.
.. _quickstart:
No-Install Quickstart
=====================
There is no need to “install Boost” in order to get started using
Boost.Python. These instructions use Boost.Build_ projects,
which will build those binaries as soon as they're needed. Your
first tests may take a little longer while you wait for
Boost.Python to build, but doing things this way will save you from
worrying about build intricacies like which library binaries to use
for a specific compiler configuration and figuring out the right
compiler options to use yourself.
.. .. raw:: html
<div style="width:50%">
.. Note:: Of course it's possible to use other build systems to
build Boost.Python and its extensions, but they are not
officially supported by Boost. Moreover **99% of all “I can't
build Boost.Python” problems come from trying to use another
build system** without first following these instructions.
If you want to use another system anyway, we suggest that you
follow these instructions, and then invoke ``bjam`` with the
.. parsed-literal::
``-a -o``\ *filename*
options to dump the build commands it executes to a file, so
you can see what your alternate build system needs to do.
.. .. raw:: html
</div>
.. _Boost.Build: ../../../tools/build/index.html
Basic Procedure
---------------
1. Get Boost; see sections 1 and 2 [`Unix/Linux`__, `Windows`__\ ] of the
Boost `Getting Started Guide`_.
__ ../../../more/getting_started/unix-variants.html#get-boost
__ ../../../more/getting_started/windows.html#get-boost
2. Get the ``bjam`` build driver. See section 5 [`Unix/Linux`__,
`Windows`__\ ] of the Boost `Getting Started Guide`_.
__ ../../../more/getting_started/unix-variants.html#prepare-to-use-a-boost-library-binary
__ ../../../more/getting_started/windows.html#prepare-to-use-a-boost-library-binary
3. cd into the ``libs/python/example/quickstart/`` directory of your
Boost installation, which contains a small example project.
4. Invoke ``bjam``. Replace the “\ ``stage``\ “ argument from the
example invocation from section 5 of the `Getting Started
Guide`_ with “\ ``test``\ ,“ to build all the test targets. Also add
the argument “\ ``--verbose-test``\ ” to see the output generated by
the tests when they are run.
On Windows, your ``bjam`` invocation might look something like:
.. parsed-literal::
C:\\boost_1_34_0\\…\\quickstart> **bjam toolset=msvc --verbose-test test**
and on Unix variants, perhaps,
.. parsed-literal::
~/boost_1_34_0/…/quickstart$ **bjam toolset=gcc --verbose-test test**
.. Admonition:: Note to Windows Users
For the sake of concision, the rest of this guide will use
unix-style forward slashes in pathnames instead of the
backslashes with which you may be more familiar. The forward
slashes should work everywhere except in `Command Prompt`_
windows, where you should use backslashes.
.. _Command Prompt: ../../../more/getting_started/windows.html#command-prompt
If you followed this procedure successfully, you will have built an
extension module called ``extending`` and tested it by running a
Python script called ``test_extending.py``. You will also have
built and run a simple application called ``embedding`` that embeds
python.
.. _Getting Started Guide: ../../../more/getting_started/index.html
In Case of Trouble
------------------
If you're seeing lots of compiler and/or linker error messages,
it's probably because Boost.Build is having trouble finding your
Python installation. You might want to pass the
``--debug-configuration`` option to ``bjam`` the first few times
you invoke it, to make sure that Boost.Build is correctly locating
all the parts of your Python installation. If it isn't, consider
`Configuring Boost.Build`_ as detailed below.
If you're still having trouble, Someone on one of the following
mailing lists may be able to help:
* The `Boost.Build mailing list`__ for issues related to Boost.Build
* The Python `C++ Sig`__ for issues specifically related to Boost.Python
__ http://www.boost.org/more/mailing_lists.htm#jamboost
__ http://www.boost.org/more/mailing_lists.htm#cplussig
In Case Everything Seemed to Work
---------------------------------
Rejoice! If you're new to Boost.Python, at this point it might be
a good idea to ignore build issues for a while and concentrate on
learning the library by going through the tutorial_ and perhaps
some of the `reference documentation`_, trying out what you've
learned about the API by modifying the quickstart project.
.. _reference documentation: v2/reference.html
.. _tutorial: tutorial/index.html
Modifying the Example Project
-----------------------------
If you're content to keep your extension module forever in one
source file called |extending.cpp|_, inside your Boost
distribution, and import it forever as ``extending``, then you can
stop here. However, it's likely that you will want to make a few
changes. There are a few things you can do without having to learn
Boost.Build_ in depth.
The project you just built is specified in two files in the current
directory: |boost-build.jam|_, which tells ``bjam`` where it can
find the interpreted code of the Boost build system, and
|Jamroot|_, which describes the targets you just built. These
files are heavily commented, so they should be easy to modify.
Take care, however, to preserve whitespace. Punctuation such as
``;`` will not be recognized as intended by ``bjam`` if it is not
surrounded by whitespace.
.. |boost-build.jam| replace:: ``boost-build.jam``
.. _boost-build.jam: ../example/quickstart/boost-build.jam
.. |Jamroot| replace:: ``Jamroot``
.. _Jamroot: ../example/quickstart/Jamroot
.. |extending.cpp| replace:: ``extending.cpp``
.. _extending.cpp: ../example/quickstart/extending.cpp
Relocate the Project
....................
You'll probably want to copy this project elsewhere so you can
change it without modifying your Boost distribution. To do that,
simply
a. copy the entire ``libs/python/example/quickstart/`` directory
into a new directory.
b. In the new copies of |boost-build.jam|_ and |Jamroot|_, locate
the relative path near the top of the file that is clearly
marked by a comment, and edit that path so that it refers to the
same directory your Boost distribution as it referred to when
the file was in its original location in the
``libs/python/example/quickstart/`` directory.
For example, if you moved the project from
``/home/dave/boost_1_34_0/libs/python/example/quickstart`` to
``/home/dave/my-project``, you could change the first path in
|boost-build.jam|_ from
.. parsed-literal::
**../../../..**\ /tools/build/v2
to
.. parsed-literal::
**/home/dave/boost_1_34_0**\ /tools/build/v2
and change the first path in |Jamroot|_ from
.. parsed-literal::
**../../../..**
to
.. parsed-literal::
**/home/dave/boost_1_34_0**
Add New or Change Names of Existing Source Files
................................................
The names of additional source files involved in building your
extension module or embedding application can be listed in
|Jamroot|_ right alongside ``extending.cpp`` or ``embedding.cpp``
respectively. Just be sure to leave whitespace around each
filename::
… file1.cpp file2.cpp file3.cpp …
Naturally, if you want to change the name of a source file you can
tell Boost.Build about it by editing the name in |Jamroot|_.
Change the Name of your Extension Module
........................................
The name of the extension module is determined by two things:
1. the name in |Jamroot|_ immediately following ``python-extension``, and
2. the name passed to ``BOOST_PYTHON_MODULE`` in |extending.cpp|_.
To change the name of the extension module from ``extending`` to
``hello``, you'd edit |Jamroot|_, changing
.. parsed-literal::
python-extension **extending** : extending.cpp ;
to
.. parsed-literal::
python-extension **hello** : extending.cpp ;
and you'd edit extending.cpp, changing
.. parsed-literal::
BOOST_PYTHON_MODULE(\ **extending**\ )
to
.. parsed-literal::
BOOST_PYTHON_MODULE(\ **hello**\ )
Installing Boost.Python on your System
======================================
Since Boost.Python is a separately-compiled (as opposed to
`header-only`_) library, its user relies on the services of a
Boost.Python library binary.
.. _header-only: ../../../more/getting_started/windows.html#header-only-libraries
If you need a regular installation of the Boost.Python library
binaries on your system, the Boost `Getting Started Guide`_ will
walk you through the steps of creating one. If building binaries
from source, you might want to supply the ``--with-python``
argument to ``bjam`` (or the ``--with-libraries=python`` argument
to ``configure``), so only the Boost.Python binary will be built,
rather than all the Boost binaries.
Configuring Boost.Build
=======================
As described in the `Boost.Build reference manual`__, a file called
``user-config.jam`` in your home directory [#home-dir]_ is used to
specify the tools and libraries available to the build system. You
may need to create or edit ``user-config.jam`` to tell Boost.Build
how to invoke Python, ``#include`` its headers, and link with its
libraries.
__ http://www.boost.orgdoc/html/bbv2/advanced.html#bbv2.advanced.configuration
.. Admonition:: Users of Unix-Variant OSes
If you are using a unix-variant OS and you ran Boost's
``configure`` script, it may have generated a
``user-config.jam`` for you. [#overwrite]_ If your ``configure``\
/\ ``make`` sequence was successful and Boost.Python binaries
were built, your ``user-config.jam`` file is probably already
correct.
If you have one fairly “standard” python installation for your
platform, you might not need to do anything special to describe it. If
you haven't configured python in ``user-config.jam`` (and you don't
specify ``--without-python`` on the Boost.Build command line),
Boost.Build will automatically execute the equivalent of ::
import toolset : using ;
using python ;
which automatically looks for Python in the most likely places.
However, that only happens when using the Boost.Python project file
(e.g. when referred to by another project as in the quickstart_
method). If instead you are linking against separately-compiled
Boost.Python binaries, you should set up a ``user-config.jam`` file
with at least the minimal incantation above.
Python Configuration Parameters
-------------------------------
If you have several versions of Python installed, or Python is
installed in an unusual way, you may want to supply any or all of
the following optional parameters to ``using python``.
version
the version of Python to use. Should be in Major.Minor
format, for example, ``2.3``. Do not include the subminor
version (i.e. *not* ``2.5.1``). If you have multiple Python
versions installed, the version will usually be the only
configuration argument required.
cmd-or-prefix
preferably, a command that invokes a Python interpreter.
Alternatively, the installation prefix for Python libraries and
header files. Only use the alternative formulation if there is
no appropriate Python executable available.
includes
the ``#include`` paths for Python headers. Normally the correct
path(s) will be automatically deduced from ``version`` and/or
``cmd-or-prefix``.
libraries
the path to Python library binaries. On MacOS/Darwin,
you can also pass the path of the Python framework. Normally the
correct path(s) will be automatically deduced from ``version``
and/or ``cmd-or-prefix``.
condition
if specified, should be a set of Boost.Build
properties that are matched against the build configuration when
Boost.Build selects a Python configuration to use. See examples
below for details.
extension-suffix
A string to append to the name of extension
modules before the true filename extension. You almost certainly
don't need to use this. Usually this suffix is only used when
targeting a Windows debug build of Python, and will be set
automatically for you based on the value of the
|python-debugging|_ feature. However, at least one Linux
distribution (Ubuntu Feisty Fawn) has a specially configured
`python-dbg`__ package that claims to use such a suffix.
.. |python-debugging| replace:: ``<python-debugging>``
__ https://wiki.ubuntu.com/PyDbgBuilds
Examples
--------
Note that in the examples below, case and *especially whitespace* are
significant.
- If you have both python 2.5 and python 2.4 installed,
``user-config.jam`` might contain::
using python : 2.5 ; # Make both versions of Python available
using python : 2.4 ; # To build with python 2.4, add python=2.4
# to your command line.
The first version configured (2.5) becomes the default. To build
against python 2.4, add ``python=2.4`` to the ``bjam`` command line.
- If you have python installed in an unusual location, you might
supply the path to the interpreter in the ``cmd-or-prefix``
parameter::
using python : : /usr/local/python-2.6-beta/bin/python ;
- If you have a separate build of Python for use with a particular
toolset, you might supply that toolset in the ``condition``
parameter::
using python ; # use for most toolsets
# Use with Intel C++ toolset
using python
: # version
: c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
: # includes
: # libraries
: <toolset>intel # condition
;
- If you have downloaded the Python sources and built both the
normal and the “\ `python debugging`_\ ” builds from source on
Windows, you might see::
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python ;
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python_d
: # includes
: # libs
: <python-debugging>on ;
- You can set up your user-config.jam so a bjam built under Windows
can build/test both Windows and Cygwin_ python extensions. Just pass
``<target-os>cygwin`` in the ``condition`` parameter
for the cygwin python installation::
# windows installation
using python ;
# cygwin installation
using python : : c:\\cygwin\\bin\\python2.5 : : : <target-os>cygwin ;
when you put target-os=cygwin in your build request, it should build
with the cygwin version of python: [#flavor]_
bjam target-os=cygwin toolset=gcc
This is supposed to work the other way, too (targeting windows
python with a Cygwin_ bjam) but it seems as though the support in
Boost.Build's toolsets for building that way is broken at the
time of this writing.
- Note that because of `the way Boost.Build currently selects target
alternatives`__, you might have be very explicit in your build
requests. For example, given::
using python : 2.5 ; # a regular windows build
using python : 2.4 : : : : <target-os>cygwin ;
building with ::
bjam target-os=cygwin
will yield an error. Instead, you'll need to write::
bjam target-os=cygwin/python=2.4
.. _Cygwin: http://cygwin.com
__ http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection
Choosing a Boost.Python Library Binary
======================================
If—instead of letting Boost.Build construct and link with the right
libraries automatically—you choose to use a pre-built Boost.Python
library, you'll need to think about which one to link with. The
Boost.Python binary comes in both static and dynamic flavors. Take
care to choose the right flavor for your application. [#naming]_
The Dynamic Binary
------------------
The dynamic library is the safest and most-versatile choice:
- A single copy of the library code is used by all extension
modules built with a given toolset. [#toolset-specific]_
- The library contains a type conversion registry. Because one
registry is shared among all extension modules, instances of a
class exposed to Python in one dynamically-loaded extension
module can be passed to functions exposed in another such module.
The Static Binary
-----------------
It might be appropriate to use the static Boost.Python library in
any of the following cases:
- You are extending_ python and the types exposed in your
dynamically-loaded extension module don't need to be used by any
other Boost.Python extension modules, and you don't care if the
core library code is duplicated among them.
- You are embedding_ python in your application and either:
- You are targeting a Unix variant OS other than MacOS or AIX,
where the dynamically-loaded extension modules can “see” the
Boost.Python library symbols that are part of the executable.
- Or, you have statically linked some Boost.Python extension
modules into your application and you don't care if any
dynamically-loaded Boost.Python extension modules are able to
use the types exposed by your statically-linked extension
modules (and vice-versa).
``#include`` Issues
===================
1. If you should ever have occasion to ``#include "python.h"``
directly in a translation unit of a program using Boost.Python,
use ``#include "boost/python/detail/wrap_python.hpp"`` instead.
It handles several issues necessary for use with Boost.Python,
one of which is mentioned in the next section.
2. Be sure not to ``#include`` any system headers before
``wrap_python.hpp``. This restriction is actually imposed by
Python, or more properly, by Python's interaction with your
operating system. See
http://docs.python.org/ext/simpleExample.html for details.
.. _python-debugging:
.. _python debugging:
Python Debugging Builds
=======================
Python can be built in a special “python debugging” configuration
that adds extra checks and instrumentation that can be very useful
for developers of extension modules. The data structures used by
the debugging configuration contain additional members, so **a
Python executable built with python debugging enabled cannot be
used with an extension module or library compiled without it, and
vice-versa.**
Since pre-built “python debugging” versions of the Python
executable and libraries are not supplied with most distributions
of Python, [#get-debug-build]_ and we didn't want to force our users
to build them, Boost.Build does not automatically enable python
debugging in its ``debug`` build variant (which is the default).
Instead there is a special build property called
``python-debugging`` that, when used as a build property, will
define the right preprocessor symbols and select the right
libraries to link with.
On unix-variant platforms, the debugging versions of Python's data
structures will only be used if the symbol ``Py_DEBUG`` is defined.
On many windows compilers, when extension modules are built with
the preprocessor symbol ``_DEBUG``, Python defaults to force
linking with a special debugging version of the Python DLL. Since
that symbol is very commonly used even when Python is not present,
Boost.Python temporarily undefines _DEBUG when Python.h
is #included from ``boost/python/detail/wrap_python.hpp`` - unless
``BOOST_DEBUG_PYTHON`` is defined. The upshot is that if you want
“python debugging”and you aren't using Boost.Build, you should make
sure ``BOOST_DEBUG_PYTHON`` is defined, or python debugging will be
suppressed.
Testing Boost.Python
====================
To run the full test suite for Boost.Python, invoke ``bjam`` in the
``libs/python/test`` subdirectory of your Boost distribution.
Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users
=======================================================
If you are using a version of Python prior to 2.4.1 with a MinGW
prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will need to
create a MinGW-compatible version of the Python library; the one
shipped with Python will only work with a Microsoft-compatible
linker. Follow the instructions in the “Non-Microsoft” section of
the “Building Extensions: Tips And Tricks” chapter in `Installing
Python Modules`__ to create ``libpythonXX.a``, where ``XX``
corresponds to the major and minor version numbers of your Python
installation.
__ http://www.python.org/doc/current/inst/index.html
-----------------------------
.. [#2.2] Note that although we tested earlier versions of
Boost.Python with Python 2.2, and we don't *think* we've done
anything to break compatibility, this release of Boost.Python
may not have been tested with versions of Python earlier than
2.4, so we're not 100% sure that python 2.2 and 2.3 are
supported.
.. [#naming] Information about how to identify the
static and dynamic builds of Boost.Python:
* `on Windows`__
* `on Unix variants`__
__ ../../../more/getting_started/windows.html#library-naming
__ ../../../more/getting_started/unix-variants.html#library-naming
.. [#toolset-specific] Because of the way most \*nix platforms
share symbols among dynamically-loaded objects, I'm not certain
that extension modules built with different compiler toolsets
will always use different copies of the Boost.Python library
when loaded into the same Python instance. Not using different
libraries could be a good thing if the compilers have compatible
ABIs, because extension modules built with the two libraries
would be interoperable. Otherwise, it could spell disaster,
since an extension module and the Boost.Python library would
have different ideas of such things as class layout. I would
appreciate someone doing the experiment to find out what
happens.
.. [#overwrite] ``configure`` overwrites the existing
``user-config.jam`` in your home directory
(if any) after making a backup of the old version.
.. [#flavor] Note that the ``<target-os>cygwin`` feature is
different from the ``<flavor>cygwin`` subfeature of the ``gcc``
toolset, and you might need handle both explicitly if you also
have a MinGW GCC installed.
.. [#home-dir] Windows users, your home directory can be
found by typing::
ECHO %HOMEDRIVE%%HOMEPATH%
into a `command prompt`_ window.
.. [#get-debug-build] On Unix and similar platforms, a debugging
python and associated libraries are built by adding
``--with-pydebug`` when configuring the Python build. On
Windows, the debugging version of Python is generated by
the "Win32 Debug" target of the Visual Studio project in the
PCBuild subdirectory of a full Python source code distribution.

231
doc/comparisons.html Normal file
View File

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

336
doc/cross_module.html Normal file
View 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&lt;double&gt;&amp; x, const std::vector&lt;double&gt;&amp; y) : m_x(x), m_y(y) {}
const std::vector&lt;double&gt;&amp; x() const { return m_x; }
const std::vector&lt;double&gt;&amp; y() const { return m_y; }
double correlation();
private:
std::vector&lt;double&gt; m_x;
std::vector&lt;double&gt; 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&lt;double&gt;</tt> is exposed to Python in the usual
way with the <tt>class_builder&lt;&gt;</tt> template. To also enable the
automatic conversion of <tt>std::vector&lt;double&gt;</tt> function
arguments or return values in other Boost.Python C++ modules, the
converters that convert a <tt>std::vector&lt;double&gt;</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 &lt;boost/python/cross_module.hpp&gt;
//...
class_builder&lt;std::vector&lt;double&gt; &gt; v_double(std_vector_module, &quot;double&quot;);
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&lt;&gt;</tt> template.
For example:
<pre>
#include &lt;boost/python/cross_module.hpp&gt;
//...
import_converters&lt;std::vector&lt;double&gt; &gt; v_double_converters(&quot;std_vector&quot;, &quot;double&quot;);
</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&lt;&gt;</tt> template instantiations</h2>
<tt>import_converts&lt;&gt;</tt> can be viewed as a drop-in replacement
for <tt>class_wrapper&lt;&gt;</tt>, and the recommendations for the
placement of <tt>class_wrapper&lt;&gt;</tt> template instantiations
also apply to to <tt>import_converts&lt;&gt;</tt>. In particular, it is
important that an instantiation of <tt>class_wrapper&lt;&gt;</tt> is
visible to any code which wraps a C++ function with a <tt>T</tt>,
<tt>T*</tt>, const <tt>T&amp;</tt>, etc. parameter or return value.
Therefore you may want to group all <tt>class_wrapper&lt;&gt;</tt> and
<tt>import_converts&lt;&gt;</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&lt;store&gt; py_store(your_module, &quot;store&quot;);
export_converters_noncopyable(py_store);
</pre>
The corresponding <tt>import_converters&lt;&gt;</tt> statement does not
need any special attention:
<pre>
import_converters&lt;store&gt; py_store(&quot;noncopyable_export&quot;, &quot;store&quot;);
</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 &quot;foo.py&quot;, 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 &lt;vector&gt;</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&lt;&gt;</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&lt;X&gt;::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&lt;&gt;</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>
&copy; 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
View File

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

120
doc/enums.html Normal file
View File

@@ -0,0 +1,120 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Wrapping enums
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
Wrapping enums
</h1>
<p>Because there is in general no way to deduce that a value of arbitrary type T
is an enumeration constant, the Boost Python Library cannot automatically
convert enum values to and from Python. To handle this case, you need to decide
how you want the enum to show up in Python (since Python doesn't have
enums). Once you have done that, you can write some simple
<code>from_python()</code> and <code>to_python()</code> functions.
<p>If you are satisfied with a Python int as a way to represent your enum
values, we provide a shorthand for these functions. You just need to cause
<code>boost::python::enum_as_int_converters&lt;EnumType&gt;</code> to be
instantiated, where
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
<ol>
<li>Explicit instantiation:
<blockquote><pre>
template class boost::python::enum_as_int_converters&lt;my_enum&gt;;
</blockquote></pre>
Some buggy C++ implementations require a class to be instantiated in the same
namespace in which it is defined. In that case, the simple incantation above becomes:
<blockquote>
<pre>
...
} // close my_namespace
// drop into namespace python and explicitly instantiate
namespace boost { namespace python {
template class enum_as_int_converters&lt;my_enum_type&gt;;
}} // namespace boost::python
namespace my_namespace { // re-open my_namespace
...
</pre>
</blockquote>
<li>If you have such an implementation, you may find this technique more convenient
<blockquote><pre>
// instantiate as base class in any namespace
struct EnumTypeConverters
: boost::python::enum_as_int_converters&lt;EnumType&gt;
{
};
</blockquote></pre>
</ol>
<p>Either of the above is equivalent to the following declarations:
<blockquote><pre>
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
MyEnumType from_python(PyObject* x, boost::python::type&lt;MyEnumType&gt;)
{
return static_cast&lt;MyEnum&gt;(
from_python(x, boost::python::type&lt;long&gt;()));
}
MyEnumType from_python(PyObject* x, boost::python::type&lt;const MyEnumType&amp;&gt;)
{
return static_cast&lt;MyEnum&gt;(
from_python(x, boost::python::type&lt;long&gt;()));
}
PyObject* to_python(MyEnumType x)
{
return to_python(static_cast&lt;long&gt;(x));
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
</pre></blockquote>
<p>This technique defines the conversions of
<code>MyEnumType</code> in terms of the conversions for the built-in
<code>long</code> type.
You may also want to add a bunch of lines like this to your module
initialization. These bind the corresponding enum values to the appropriate
names so they can be used from Python:
<blockquote><pre>
mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
...
</pre></blockquote>
You can also add these to an extension class definition, if your enum happens to
be local to a class and you want the analogous interface in Python:
<blockquote><pre>
my_class_builder.add(boost::python::to_python(enum_value_1), "enum_value_1");
my_class_builder.add(boost::python::to_python(enum_value_2), "enum_value_2");
...
</pre></blockquote>
<p>
Next: <a href="pointers.html">Pointers and Smart Pointers</a>
Previous: <a href="building.html">Building an Extension Module</a>
Up: <a href="index.html">Top</a>
<p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided ``as
is'' without express or implied warranty, and with no claim as to
its suitability for any purpose.
<p>
Updated: Mar 6, 2001
</div>

82
doc/example1.html Normal file
View File

@@ -0,0 +1,82 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
A Simple Example
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
"c++boost.gif (8819 bytes)">
</h1>
<h1>
A Simple Example
</h1>
<p>
Suppose we have the following C++ API which we want to expose in
Python:
<blockquote>
<pre>
#include &lt;string&gt;
namespace { // Avoid cluttering the global namespace.
// A couple of simple C++ functions that we want to expose to Python.
std::string greet() { return "hello, world"; }
int square(int number) { return number * number; }
}
</pre>
</blockquote>
<p>
Here is the C++ code for a python module called <tt>getting_started1</tt>
which exposes the API.
<blockquote>
<pre>
#include &lt;boost/python/class_builder.hpp&gt;
namespace python = boost::python;
BOOST_PYTHON_MODULE_INIT(getting_started1)
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("getting_started1");
// Add regular functions to the module.
this_module.def(greet, "greet");
this_module.def(square, "square");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}
</pre>
</blockquote>
<p>
That's it! If we build this shared library and put it on our <code>
PYTHONPATH</code> we can now access our C++ functions from
Python.
<blockquote>
<pre>
&gt;&gt;&gt; import getting_started1
&gt;&gt;&gt; print getting_started1.greet()
hello, world
&gt;&gt;&gt; number = 11
&gt;&gt;&gt; print number, '*', number, '=', getting_started1.square(number)
11 * 11 = 121
</pre>
<p>
Next: <a href="exporting_classes.html">Exporting Classes</a>
Previous: <a href="comparisons.html">Comparisons with other systems</a> Up:
<a href="index.html">Top</a>
<p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided "as is" without
express or implied warranty, and with no claim as to its suitability
for any purpose.
<p>
Updated: Mar 6, 2000
</div>

144
doc/exporting_classes.html Normal file
View 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 &lt;iostream&gt;
#include &lt;string&gt;
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class hello
{
public:
hello(const std::string&amp; country) { this-&gt;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&amp; 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 &lt;boost/python/class_builder.hpp&gt;
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&lt;hello&gt; hello_class(this_module, "hello");
// Add the __init__ function.
hello_class.def(python::constructor&lt;std::string&gt;());
// Add a regular member function.
hello_class.def(&amp;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>
&gt;&gt;&gt; from getting_started2 import *
&gt;&gt;&gt; hi = hello('California')
&gt;&gt;&gt; hi.greet()
'Hello from California'
&gt;&gt;&gt; invite(hi)
'Hello from California! Please come soon!'
&gt;&gt;&gt; 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&lt;</tt><i>params</i><tt>&gt;</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>
&gt;&gt;&gt; class wordy(hello):
... def greet(self):
... return hello.greet(self) + ', where the weather is fine'
...
&gt;&gt;&gt; hi2 = wordy('Florida')
&gt;&gt;&gt; hi2.greet()
'Hello from Florida, where the weather is fine'
&gt;&gt;&gt; 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>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided "as is" without
express or implied warranty, and with no claim as to its suitability
for any purpose.
<p>
Updated: Mar 6, 2001
</div>

73
doc/extending.html Normal file
View File

@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
A Brief Introduction to writing Python extension modules
</title>
<h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
</h1>
<h1>
A Brief Introduction to writing Python extension modules
</h1>
<p>
Interfacing any language to Python involves building a module which can
be loaded by the Python interpreter, but which isn't written in Python.
This is known as an <em>extension module</em>. Many of the <a href=
"http://www.python.org/doc/current/lib/lib.html">built-in Python
libraries</a> are constructed in 'C' this way; Python even supplies its
<a href="http://www.python.org/doc/current/lib/types.html">fundamental
types</a> using the same mechanism. An extension module can be statically
linked with the Python interpreter, but it more commonly resides in a
shared library or DLL.
<p>
As you can see from <a href=
"http://www.python.org/doc/current/ext/ext.html"> The Python Extending
and Embedding Tutorial</a>, writing an extension module normally means
worrying about
<ul>
<li>
<a href="http://www.python.org/doc/current/ext/refcounts.html">
maintaining reference counts</a>
<li>
<a href="http://www.python.org/doc/current/ext/callingPython.html"> how
to call back into Python</a>
<li>
<a href="http://www.python.org/doc/current/ext/parseTuple.html">
function argument parsing and typechecking</a>
</ul>
This last item typically occupies a great deal of code in an extension
module. Remember that Python is a completely dynamic language. A callable
object receives its arguments in a tuple; it is up to that object to extract
those arguments from the tuple, check their types, and raise appropriate
exceptions. There are numerous other tedious details that need to be
managed; too many to mention here. The Boost Python Library is designed to
lift most of that burden.<br>
<br>
<p>
Another obstacle that most people run into eventually when extending
Python is that there's no way to make a true Python class in an extension
module. The typical solution is to create a new Python type in the
extension module, and then write an additional module in 100% Python. The
Python module defines a Python class which dispatches to an instance of
the extension type, which it contains. This allows users to write
subclasses of the class in the Python module, almost as though they were
sublcassing the extension type. Aside from being tedious, it's not really
the same as having a true class, because there's no way for the user to
override a method of the extension type which is called from the
extension module. Boost.Python solves this problem by taking advantage of <a
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
feature</a> to provide objects which look, walk, and hiss almost exactly
like regular Python classes. Boost.Python classes are actually cleaner than
Python classes in some subtle ways; a more detailed discussion will
follow (someday).</p>
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
href="index.html">Top</a> </p>
<p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided "as is" without
express or implied warranty, and with no claim as to its suitability for
any purpose.</p>

View File

@@ -1,184 +1,166 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
The Boost Python Library (Boost.Python)
</title>
<h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
align="center" height="86"><br>The Boost Python Library (Boost.Python)
</h1>
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Python</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Python</h1>
<h2 align="center">Index</h2>
</td>
<h2>Synopsis</h2>
<p>
Use the Boost Python Library to quickly and easily export a C++ library to <a
href="http://www.python.org">Python</a> such that the Python interface is
very similar to the C++ interface. It is designed to be minimally
intrusive on your C++ design. In most cases, you should not have to alter
your C++ classes in any way in order to use them with Boost.Python. The system
<em>should</em> simply ``reflect'' your C++ classes and functions into
Python. The major features of Boost.Python include support for:
<ul>
<li><a href="inheritance.html">Subclassing extension types in Python</a>
<li><a href="overriding.html">Overriding virtual functions in Python</a>
<li><a href="overloading.html">[Member] function Overloading</a>
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
</ul>
among others.
<td align="right">
<h2>Supported Platforms</h2>
<p>Boost.Python is known to have been tested in the following configurations:
<form method="get" action="http://www.google.com/custom">
<p>
<span id= "search-choice">
Search
<select name="hq" id="hq">
<option label="All Documentation" value=
"site:www.boost.org inurl:www.boost.org/libs/python/doc">
All Documentation
</option>
<option label="Tutorial" value=
"site:www.boost.org inurl:www.boost.org/libs/python/doc/tutorial">
Tutorial
</option>
<option label="Reference" value=
"site:www.boost.org inurl:www.boost.org/libs/python/doc/v2">
Reference
</option>
</select>
<br>
</span>
<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.
<span id="search-text">
<input type="text" name="q" id="q" size="31" maxlength="255" alt="Search Text" />
</span>
<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)
<br>
<span id= "google">
<a href= "http://www.google.com/search">
<img src="../../../more/google_logo_25wht.gif" alt="Google" border="0" /></a>Powered
</span>
<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>
<span id="go">
<input type="image" name="search" src="../../../more/space.gif" alt="Search" id="search-button" />
</span>
<li>Against Python 1.5.2 using the following compiler/library:
<br>
<input type="hidden" name="cof" value= "LW:277;L:http://www.boost.org/boost.png;LH:86;AH:center;GL:0;S:http://www.boost.org;AWFID:9b83d16ce652ed5a;" />
<input type="hidden" name="sa" value= "Google Search" />
<input type="hidden" name= "domains" value= "www.boost.org;mail.python.org" /></p>
</form>
<ul>
<li><a
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
</td>
</tr>
<tr>
<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>
</tr>
</table>
<hr>
<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>
<h2>Synopsis</h2>
Welcome to version 2 of <b>Boost.Python</b>, a C++ library which enables
seamless interoperability between C++ and the <a href=
"http://www.python.org">Python</a> programming language. The new version
has been rewritten from the ground up, with a more convenient and
flexible interface, and many new capabilities, including support for:
<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>]
<ul>
<li>References and Pointers</li>
<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 Boost.Python)
</ul>
</ul>
<li>Globally Registered Type Coercions</li>
<h2>Credits</h2>
<ul>
<li><a href="../../../people/dave_abrahams.htm">David Abrahams</a> originated
and wrote most of the library, and continues to coordinate development.
<li>Automatic Cross-Module Type Conversions</li>
<li>Efficient Function Overloading</li>
<li>C++ to Python Exception Translation</li>
<li>Default Arguments</li>
<li>Keyword Arguments</li>
<li>Manipulating Python objects in C++</li>
<li>Exporting C++ Iterators as Python Iterators</li>
<li>Documentation Strings</li>
</ul>
The development of these features was funded in part by grants to <a
href="http://www.boost-consulting.com">Boost Consulting</a> from the <a
href="http://www.llnl.gov/">Lawrence Livermore National Laboratories</a>
and by the <a href="http://cci.lbl.gov/">Computational Crystallography
Initiative</a> at Lawrence Berkeley National Laboratories.
<hr>
<h2>Contents</h2>
<dl class="index">
<dt><a href="tutorial/index.html">Tutorial Introduction</a></dt>
<dt><a href="building.html">Building and Testing</a></dt>
<dt><a href="v2/reference.html">Reference Manual</a></dt>
<dt>Suites:</dt>
<dd>
<ul>
<li><a href="v2/pickle.html">Pickle</a></li>
<li><a href="v2/indexing.html">Indexing</a></li>
</ul>
</dd>
<dt><a href="v2/configuration.html">Configuration Information</a></dt>
<dt><a href="v2/platforms.html">Known Working Platforms and
Compilers</a></dt>
<dt><a href="v2/definitions.html">Definitions</a></dt>
<dt><a href="projects.html">Projects using Boost.Python</a></dt>
<dt><a href="support.html">Support Resources</a></dt>
<dt><a href="v2/faq.html">Frequently Asked Questions (FAQs)</a></dt>
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
had independently developed a similar system. When he discovered Boost.Python,
he generously contributed countless hours of coding and much insight into
improving it. He is responsible for an early version of the support for <a
href="overloading.html">function overloading</a> and wrote the support for
<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.
<dt><a href="http://www.language-binding.net/pyplusplus/pyplusplus.html">Py++ Boost.Python code generator</a></dt>
<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.
<dt><a href="../pyste/index.html">Pyste Boost.Python code generator (no longer maintained)</a></dt>
<li>The members of the boost mailing list and the Python community
supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans,
Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott took the
brave step of trying to use Boost.Python while it was still in early
stages of development.
<dt><a href="internals.html">Internals Documentation</a></dt>
<li>The development of Boost.Python wouldn't have been possible without
the generous support of <a href="http://www.dragonsys.com/">Dragon
Systems/Lernout and Hauspie, Inc</a> who supported its development as an
open-source project.
</ul>
<dt><a href="news.html">News/Change Log</a></dt>
<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 Boost.Python and other
systems for extending Python</a>
<li><a href="example1.html">A Simple Example</a>
<li><a href="exporting_classes.html">Exporting Classes</a>
<li><a href="overriding.html">Overridable Virtual Functions</a>
<li><a href="overloading.html">Function Overloading</a>
<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 an Extension Module</a>
<li><a href="pickle.html">Pickle Support</a>
<li><a href="cross_module.html">Cross-Extension-Module Dependencies</a>
<li><a href="enums.html">Wrapping Enums</a>
<li><a href="pointers.html">Pointers and Smart Pointers</a>
<li><a href="data_structures.txt">Internal Data Structures</a>
</ol>
<dt><a href="../todo.html">TODO list</a></dt>
<p>
Documentation is a major ongoing project; assistance is greatly
appreciated! In the meantime, useful examples of every Boost.Python feature should
be evident in the regression test files <code>test/comprehensive.[<a
href="../test/comprehensive.py">py</a>/<a
href="../test/comprehensive.hpp">hpp</a>/<a
href="../test/comprehensive.cpp">cpp</a>]</code>
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
<p>
Questions should be directed to <a href=
"http://www.yahoogroups.com/list/boost">the boost mailing list</a>.
<dt><a href="v2/acknowledgments.html">Acknowledgments</a></dt>
</dl>
<hr>
<h2>Articles</h2>
&quot;<a href="PyConDC_2003/bpl.html">Building Hybrid
Systems With Boost Python</a>&quot;, by Dave Abrahams and Ralf
W. Grosse-Kunstleve (<a href="PyConDC_2003/bpl.pdf">PDF</a>)
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
26 August, 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003.</i></p>
</body>
</html>
<p>
&copy; Copyright David Abrahams 2001. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided ``as is'' without
express or implied warranty, and with no claim as to its suitability for
any purpose.
<p>
Updated: Mar 6, 2001

173
doc/inheritance.html Normal file
View File

@@ -0,0 +1,173 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Inheritance
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Inheritance
</h1>
<h2>Inheritance in Python</h2>
<p>
Boost.Python extension classes support single and multiple-inheritance in
Python, just like regular Python classes. You can arbitrarily mix
built-in Python classes with extension classes in a derived class'
tuple of bases. Whenever a Boost.Python extension class is among the bases for a
new class in Python, the result is an extension class:
<blockquote>
<pre>
&gt;&gt;&gt; class MyPythonClass:
... def f(): return 'MyPythonClass.f()'
...
&gt;&gt;&gt; import my_extension_module
&gt;&gt;&gt; class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
... '''This is an extension class'''
... pass
...
&gt;&gt;&gt; x = Derived()
&gt;&gt;&gt; x.f()
'MyPythonClass.f()'
&gt;&gt;&gt; x.g()
'MyExtensionClass.g()'
</pre>
</blockquote>
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
<p>
Boost.Python also allows us to represent C++ inheritance relationships so that
wrapped derived classes may be passed where values, pointers, or
references to a base class are expected as arguments. The
<code>declare_base</code> member function of
<code>class_builder&lt;&gt;</code> is used to establish the relationship
between base and derived classes:
<blockquote>
<pre>
#include &lt;memory&gt; // for std::auto_ptr&lt;&gt;
struct Base {
virtual ~Base() {}
virtual const char* name() const { return "Base"; }
};
struct Derived : Base {
Derived() : x(-1) {}
virtual const char* name() const { return "Derived"; }
int x;
};
std::auto_ptr&lt;Base&gt; derived_as_base() {
return std::auto_ptr&lt;Base&gt;(new Derived);
}
const char* get_name(const Base& b) {
return b.name();
}
int get_derived_x(const Derived& d) {
return d.x;
}
<hr>
#include &lt;boost/python/class_builder.hpp&gt;
// namespace alias for code brevity
namespace python = boost::python;
BOOST_PYTHON_MODULE_INIT(my_module)
{
    try
    {
       python::module_builder my_module("my_module");
       python::class_builder&lt;Base&gt; base_class(my_module, "Base");
       base_class.def(python::constructor&lt;void&gt;());
       python::class_builder&lt;Derived&gt; derived_class(my_module, "Derived");
       derived_class.def(python::constructor&lt;void&gt;());
<b>// Establish the inheritance relationship between Base and Derived
derived_class.declare_base(base_class);</b>
my_module.def(derived_as_base, "derived_as_base");
my_module.def(get_name, "get_name");
my_module.def(get_derived_x, "get_derived_x");
    }
    catch(...)
    {
       python::handle_exception();    // Deal with the exception for Python
    }
}
</pre>
</blockquote>
<p>
Then, in Python:
<blockquote>
<pre>
&gt;&gt;&gt; from my_module import *
&gt;&gt;&gt; base = Base()
&gt;&gt;&gt; derived = Derived()
&gt;&gt;&gt; get_name(base)
'Base'
</pre>
</blockquote>
<i>objects of wrapped class Derived may be passed where Base is expected</i>
<blockquote>
<pre>
&gt;&gt;&gt; get_name(derived)
'Derived'
</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>
&gt;&gt;&gt; get_derived_x(derived_as_base())
-1
</pre>
</blockquote>
<h2>Inheritance Without Virtual Functions</h2>
<p>
If for some reason your base class has no virtual functions but you still want
to represent the inheritance relationship between base and derived classes,
pass the special symbol <code>boost::python::without_downcast</code> as the 2nd parameter
to <code>declare_base</code>:
<blockquote>
<pre>
struct Base2 {};
struct Derived2 { int f(); };
<hr>
...
   python::class_builder&lt;Base&gt; base2_class(my_module, "Base2");
   base2_class.def(python::constructor&lt;void&gt;());
   python::class_builder&lt;Derived2&gt; derived2_class(my_module, "Derived2");
   derived2_class.def(python::constructor&lt;void&gt;());
derived_class.declare_base(base_class, <b>python::without_downcast</b>);
</pre>
</blockquote>
<p>This approach will allow <code>Derived2</code> objects to be passed where
<code>Base2</code> is expected, but does not attempt to implicitly convert (downcast)
smart-pointers to <code>Base2</code> into <code>Derived2</code> pointers,
references, or values.
<p>
Next: <a href="special.html">Special Method and Operator Support</a>
Previous: <a href="overloading.html">Function Overloading</a>
Up: <a href="index.html">Top</a>
<p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided "as is" without
express or implied warranty, and with no claim as to its suitability
for any purpose.
<p>
Updated: Nov 26, 2000
</div>

View File

@@ -1,186 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
<title>Boost.Python Internals Boost</title>
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
</head>
<body>
<div class="document" id="boost-python-internals-logo">
<h1 class="title"><a class="reference" href="index.html">Boost.Python</a> Internals <a class="reference" href="../../../index.htm"><img alt="Boost" src="../../../boost.png" /></a></h1>
<div class="section" id="a-conversation-between-brett-calcott-and-david-abrahams">
<h1><a name="a-conversation-between-brett-calcott-and-david-abrahams">A conversation between Brett Calcott and David Abrahams</a></h1>
<table class="field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams and Brett Calcott 2003. See
accompanying <a class="reference" href="../../../LICENSE_1_0.txt">license</a> for terms of use.</td>
</tr>
</tbody>
</table>
<p>In both of these cases, I'm quite capable of reading code - but the
thing I don't get from scanning the source is a sense of the
architecture, both structurally, and temporally (er, I mean in what
order things go on).</p>
<ol class="arabic">
<li><p class="first">What happens when you do the following:</p>
<pre class="literal-block">
struct boring {};
...etc...
class_&lt;boring&gt;(&quot;boring&quot;)
;
</pre>
</li>
</ol>
<p>There seems to be a fair bit going on.</p>
<blockquote>
<ul class="simple">
<li>Python needs a new ClassType to be registered.</li>
<li>We need to construct a new type that can hold our boring struct.</li>
<li>Inward and outward converters need to be registered for the type.</li>
</ul>
</blockquote>
<p>Can you gesture in the general direction where these things are done?</p>
<blockquote>
<p>I only have time for a &quot;off-the-top-of-my-head&quot; answer at the moment;
I suggest you step through the code with a debugger after reading this
to see how it works, fill in details, and make sure I didn't forget
anything.</p>
<blockquote>
<p>A new (Python) subclass of Boost.Python.Instance (see
libs/python/src/object/class.cpp) is created by invoking
Boost.Python.class, the metatype:</p>
<pre class="literal-block">
&gt;&gt;&gt; boring = Boost.Python.class(
... 'boring'
... , bases_tuple # in this case, just ()
... , {
... '__module__' : module_name
... , '__doc__' : doc_string # optional
... }
... )
</pre>
<p>A handle to this object is stuck in the m_class_object field
of the registration associated with <tt class="literal"><span class="pre">typeid(boring)</span></tt>. The
registry will keep that object alive forever, even if you
wipe out the 'boring' attribute of the extension module
(probably not a good thing).</p>
<p>Because you didn't specify <tt class="literal"><span class="pre">class&lt;boring,</span> <span class="pre">non_copyable,</span>
<span class="pre">...&gt;</span></tt>, a to-python converter for boring is registered which
copies its argument into a value_holder held by the the
Python boring object.</p>
<p>Because you didn't specify <tt class="literal"><span class="pre">class&lt;boring</span> <span class="pre">...&gt;(no_init)</span></tt>,
an <tt class="literal"><span class="pre">__init__</span></tt> function object is added to the class
dictionary which default-constructs a boring in a
value_holder (because you didn't specify some smart pointer
or derived wrapper class as a holder) held by the Python
boring object.</p>
<p><tt class="literal"><span class="pre">register_class_from_python</span></tt> is used to register a
from-python converter for <tt class="literal"><span class="pre">shared_ptr&lt;boring&gt;</span></tt>.
<tt class="literal"><span class="pre">boost::shared_ptr</span></tt>s are special among smart pointers
because their Deleter argument can be made to manage the
whole Python object, not just the C++ object it contains, no
matter how the C++ object is held.</p>
<p>If there were any <tt class="literal"><span class="pre">bases&lt;&gt;</span></tt>, we'd also be registering the
relationship between these base classes and boring in the
up/down cast graph (<tt class="literal"><span class="pre">inheritance.[hpp/cpp]</span></tt>).</p>
<p>In earlier versions of the code, we'd be registering lvalue
from-python converters for the class here, but now
from-python conversion for wrapped classes is handled as a
special case, before consulting the registry, if the source
Python object's metaclass is the Boost.Python metaclass.</p>
<p>Hmm, that from-python converter probably ought to be handled
the way class converters are, with no explicit conversions
registered.</p>
</blockquote>
</blockquote>
<ol class="arabic" start="2">
<li><p class="first">Can you give a brief overview of the data structures that are
present in the registry</p>
<blockquote>
<p>The registry is simple: it's just a map from typeid -&gt;
registration (see boost/python/converter/registrations.hpp).
<tt class="literal"><span class="pre">lvalue_chain</span></tt> and <tt class="literal"><span class="pre">rvalue_chain</span></tt> are simple endogenous
linked lists.</p>
<p>If you want to know more, just ask.</p>
<p>If you want to know about the cast graph, ask me something specific in
a separate message.</p>
</blockquote>
<p>and an overview of the process that happens as a type makes its
way from c++ to python and back again.</p>
</li>
</ol>
<blockquote>
<p>Big subject. I suggest some background reading: look for relevant
info in the LLNL progress reports and the messages they link to.
Also,</p>
<blockquote>
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a></p>
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-December/003115.html">http://mail.python.org/pipermail/c++-sig/2002-December/003115.html</a></p>
<p><a class="reference" href="http://aspn.activestate.com/ASPN/Mail/Message/1280898">http://aspn.activestate.com/ASPN/Mail/Message/1280898</a></p>
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-July/001755.html">http://mail.python.org/pipermail/c++-sig/2002-July/001755.html</a></p>
</blockquote>
<p>from c++ to python:</p>
<blockquote>
<p>It depends on the type and the call policies in use or, for
<tt class="literal"><span class="pre">call&lt;&gt;(...)</span></tt>, <tt class="literal"><span class="pre">call_method&lt;&gt;(...)</span></tt>, or <tt class="literal"><span class="pre">object(...)</span></tt>, if
<tt class="literal"><span class="pre">ref</span></tt> or <tt class="literal"><span class="pre">ptr</span></tt> is used. There are also two basic
categories to to-python conversion, &quot;return value&quot; conversion
(for Python-&gt;C++ calls) and &quot;argument&quot; conversion (for
C++-&gt;Python calls and explicit <tt class="literal"><span class="pre">object()</span></tt> conversions). The
behavior of these two categories differs subtly in various ways
whose details I forget at the moment. You can probably find
the answers in the above references, and certainly in the code.</p>
<p>The &quot;default&quot; case is by-value (copying) conversion, which uses
to_python_value as a to-python converter.</p>
<blockquote>
<p>Since there can sensibly be only one way to convert any type
to python (disregarding the idea of scoped registries for the
moment), it makes sense that to-python conversions can be
handled by specializing a template. If the type is one of
the types handled by a built-in conversion
(builtin_converters.hpp), the corresponding template
specialization of to_python_value gets used.</p>
<p>Otherwise, to_python_value uses the <tt class="literal"><span class="pre">m_to_python</span></tt>
function in the registration for the C++ type.</p>
</blockquote>
<p>Other conversions, like by-reference conversions, are only
available for wrapped classes, and are requested explicitly by
using <tt class="literal"><span class="pre">ref(...)</span></tt>, <tt class="literal"><span class="pre">ptr(...)</span></tt>, or by specifying different
CallPolicies for a call, which can cause a different to-python
converter to be used. These conversions are never registered
anywhere, though they do need to use the registration to find
the Python class corresponding to the C++ type being referred
to. They just build a new Python instance and stick the
appropriate Holder instance in it.</p>
</blockquote>
<p>from python to C++:</p>
<blockquote>
<p>Once again I think there is a distinction between &quot;return value&quot;
and &quot;argument&quot; conversions, and I forget exactly what that is.</p>
<p>What happens depends on whether an lvalue conversion is needed
(see <a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a>)
All lvalue conversions are also registered in a type's rvalue
conversion chain, since when an rvalue will do, an lvalue is
certainly good enough.</p>
<p>An lvalue conversion can be done in one step (just get me the
pointer to the object - it can be <tt class="literal"><span class="pre">NULL</span></tt> if no conversion is
possible) while an rvalue conversion requires two steps to
support wrapped function overloading and multiple converters for
a given C++ target type: first tell me if a conversion is
possible, then construct the converted object as a second step.</p>
</blockquote>
</blockquote>
</div>
</div>
<hr class="footer"/>
<div class="footer">
<a class="reference" href="internals.rst">View document source</a>.
Generated on: 2003-09-12 14:51 UTC.
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
</div>
</body>
</html>

View File

@@ -1,182 +0,0 @@
===================================
Boost.Python_ Internals |(logo)|__
===================================
.. |(logo)| image:: ../../../boost.png
:alt: Boost
:class: boost-logo
__ ../../../index.htm
.. _`Boost.Python`: index.html
.. _license: ../../../LICENSE_1_0.txt
-------------------------------------------------------
A conversation between Brett Calcott and David Abrahams
-------------------------------------------------------
:copyright: Copyright David Abrahams and Brett Calcott 2003. See
accompanying license_ for terms of use.
In both of these cases, I'm quite capable of reading code - but the
thing I don't get from scanning the source is a sense of the
architecture, both structurally, and temporally (er, I mean in what
order things go on).
1) What happens when you do the following::
struct boring {};
...etc...
class_<boring>("boring")
;
There seems to be a fair bit going on.
- Python needs a new ClassType to be registered.
- We need to construct a new type that can hold our boring struct.
- Inward and outward converters need to be registered for the type.
Can you gesture in the general direction where these things are done?
I only have time for a "off-the-top-of-my-head" answer at the moment;
I suggest you step through the code with a debugger after reading this
to see how it works, fill in details, and make sure I didn't forget
anything.
A new (Python) subclass of Boost.Python.Instance (see
libs/python/src/object/class.cpp) is created by invoking
Boost.Python.class, the metatype::
>>> boring = Boost.Python.class(
... 'boring'
... , bases_tuple # in this case, just ()
... , {
... '__module__' : module_name
... , '__doc__' : doc_string # optional
... }
... )
A handle to this object is stuck in the m_class_object field
of the registration associated with ``typeid(boring)``. The
registry will keep that object alive forever, even if you
wipe out the 'boring' attribute of the extension module
(probably not a good thing).
Because you didn't specify ``class<boring, non_copyable,
...>``, a to-python converter for boring is registered which
copies its argument into a value_holder held by the the
Python boring object.
Because you didn't specify ``class<boring ...>(no_init)``,
an ``__init__`` function object is added to the class
dictionary which default-constructs a boring in a
value_holder (because you didn't specify some smart pointer
or derived wrapper class as a holder) held by the Python
boring object.
``register_class_from_python`` is used to register a
from-python converter for ``shared_ptr<boring>``.
``boost::shared_ptr``\ s are special among smart pointers
because their Deleter argument can be made to manage the
whole Python object, not just the C++ object it contains, no
matter how the C++ object is held.
If there were any ``bases<>``, we'd also be registering the
relationship between these base classes and boring in the
up/down cast graph (``inheritance.[hpp/cpp]``).
In earlier versions of the code, we'd be registering lvalue
from-python converters for the class here, but now
from-python conversion for wrapped classes is handled as a
special case, before consulting the registry, if the source
Python object's metaclass is the Boost.Python metaclass.
Hmm, that from-python converter probably ought to be handled
the way class converters are, with no explicit conversions
registered.
2) Can you give a brief overview of the data structures that are
present in the registry
The registry is simple: it's just a map from typeid ->
registration (see boost/python/converter/registrations.hpp).
``lvalue_chain`` and ``rvalue_chain`` are simple endogenous
linked lists.
If you want to know more, just ask.
If you want to know about the cast graph, ask me something specific in
a separate message.
and an overview of the process that happens as a type makes its
way from c++ to python and back again.
Big subject. I suggest some background reading: look for relevant
info in the LLNL progress reports and the messages they link to.
Also,
http://mail.python.org/pipermail/c++-sig/2002-May/001023.html
http://mail.python.org/pipermail/c++-sig/2002-December/003115.html
http://aspn.activestate.com/ASPN/Mail/Message/1280898
http://mail.python.org/pipermail/c++-sig/2002-July/001755.html
from c++ to python:
It depends on the type and the call policies in use or, for
``call<>(...)``, ``call_method<>(...)``, or ``object(...)``, if
``ref`` or ``ptr`` is used. There are also two basic
categories to to-python conversion, "return value" conversion
(for Python->C++ calls) and "argument" conversion (for
C++->Python calls and explicit ``object()`` conversions). The
behavior of these two categories differs subtly in various ways
whose details I forget at the moment. You can probably find
the answers in the above references, and certainly in the code.
The "default" case is by-value (copying) conversion, which uses
to_python_value as a to-python converter.
Since there can sensibly be only one way to convert any type
to python (disregarding the idea of scoped registries for the
moment), it makes sense that to-python conversions can be
handled by specializing a template. If the type is one of
the types handled by a built-in conversion
(builtin_converters.hpp), the corresponding template
specialization of to_python_value gets used.
Otherwise, to_python_value uses the ``m_to_python``
function in the registration for the C++ type.
Other conversions, like by-reference conversions, are only
available for wrapped classes, and are requested explicitly by
using ``ref(...)``, ``ptr(...)``, or by specifying different
CallPolicies for a call, which can cause a different to-python
converter to be used. These conversions are never registered
anywhere, though they do need to use the registration to find
the Python class corresponding to the C++ type being referred
to. They just build a new Python instance and stick the
appropriate Holder instance in it.
from python to C++:
Once again I think there is a distinction between "return value"
and "argument" conversions, and I forget exactly what that is.
What happens depends on whether an lvalue conversion is needed
(see http://mail.python.org/pipermail/c++-sig/2002-May/001023.html)
All lvalue conversions are also registered in a type's rvalue
conversion chain, since when an rvalue will do, an lvalue is
certainly good enough.
An lvalue conversion can be done in one step (just get me the
pointer to the object - it can be ``NULL`` if no conversion is
possible) while an rvalue conversion requires two steps to
support wrapped function overloading and multiple converters for
a given C++ target type: first tell me if a conversion is
possible, then construct the converted object as a second step.

View File

@@ -1,335 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st September 2004), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="boost.css">
<title>Boost.Python - News/Change Log</title>
</head>
<body link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
<h2 align="center">News/Change Log</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt>Current SVN</dt>
<dd>
<ul>
<li>Pythonic signatures are now automatically appended to the
docstrings.
<li>Use <a href="v2/docstring_options.html"
><code>docstring_options.hpp</code></a> header
control the content of docstrings.
<li>This new feature increases the size of the modules by about 14%.
If this is not acceptable it can be turned off by defining the macro
BOOST_PYTHON_NO_PY_SIGNATURES. Modules compiled with and without the macro
defined are compatible.
</li>
<li> If BOOST_PYTHON_NO_PY_SIGNATURES is undefined, this version defines the
macro BOOST_PYTHON_SUPPORTS_PY_SIGNATURES. This allows writing code that will compile
with older version of Boost.Python (see <a href="v2/pytype_function.html#examples">here</a>).
</li>
<li>By defining BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE, and at a cost
of another 14% size increase, proper pythonic type is generated for the "self"
parameter of the __init__ methods.
</li>
<li> To support this new feature changes were made to the
<a href="v2/to_python_converter.html"><code>to_python_converter.hpp</code></a>,
<a href="v2/default_call_policies.html"><code>default_call_policies</code></a>,
<a href="v2/ResultConverter.html"><code>ResultConverter</code></a>,
<a href="v2/CallPolicies.html"><code>CallPolicies</code></a> and some others.
Efforts were made not to have interface breaking changes.
</li>
</ul>
</dd>
<dt>12 May 2007 - 1.34.0 release</dt>
<dd>
<ul>
<li>C++ signatures are now automatically appended to the
docstrings.
<li>New <a href="v2/docstring_options.html"
><code>docstring_options.hpp</code></a> header to
control the content of docstrings.
<li>Support for converting <code>void*</code> to/from python,
with <code><a
href="v2/opaque.html">opaque_pointer_converter</a></code>
as the return value policy. Thanks to Niall Douglas for the
initial patch.
</ul>
</dd>
<dt>19 October 2005 - 1.33.1 release</dt>
<dd>
<ul>
<li><code>wrapper&lt;T&gt;</code> can now be used as expected with a
held type of <i>some-smart-pointer</i><code>&lt;T&gt;</code></li>
<li>The build now assumes Python 2.4 by default, rather than 2.2</li>
<li>Support Python that's built without Unicode support</li>
<li>Support for wrapping classes with overloaded address-of
(<code>&amp;</code>) operators</li>
</ul>
</dd>
<dt>14 August 2005 - 1.33 release</dt>
<dd>
<ul>
<li>Support for docstrings on nonstatic properties.</li>
<li>We now export the client-provided docstrings for
<code>init&lt;optional&lt;&gt; &gt;</code> and
<i>XXX</i><code>_FUNCTION_OVERLOADS()</code> for only the last
overload.</li>
<li>Fixed some support for Embedded VC++ 4</li>
<li>Better support for rvalue from-python conversions of shared_ptr:
always return a pointer that holds the owning python object *unless*
the python object contains a NULL shared_ptr holder of the right
type.</li>
<li>Support for exposing <code>vector&lt;T*&gt;</code> with the
indexing suite.</li>
<li>Support for GCC-3.3 on MacOS.</li>
<li>updated visual studio project build file to include two new files
(slice.cpp and wrapper.cpp)</li>
<li>Added search feature to the index page.</li>
<li>Numerous fixes to the tutorial</li>
<li>Numerous workarounds for MSVC 6 and 7, GCC 2.96, and EDG
2.45</li>
</ul>
</dd>
<dt>11 March 2005</dt>
<dd>
<ul>
<li>Added a hack that will fool PyDoc into working with Boost.Python,
thanks to Nick Rasmussen</li>
</ul>
</dd>
<dt>19 November 2004 - 1.32 release</dt>
<dd>
<ul>
<li>Updated to use the Boost Software License.</li>
<li>A new, <a href=
"tutorial/doc/html/python/exposing.html#python.class_virtual_functions">
better method of wrapping classes with virtual functions</a> has been
implemented.</li>
<li>Support for upcoming GCC symbol export control features have been
folded in, thanks to Niall Douglas.</li>
<li>Improved support for <code>std::auto_ptr</code>-like types.</li>
<li>The Visual C++ bug that makes top-level <i>cv-qualification</i>
of function parameter types part of the function type has been worked
around.</li>
<li>Components used by other libraries have been moved out of
<code>python/detail</code> and into <code>boost/detail</code> to
improve dependency relationships.</li>
<li>Miscellaneous bug fixes and compiler workarounds.</li>
</ul>
</dd>
<dt>8 Sept 2004</dt>
<dd>Support for Python's Bool type, thanks to <a href=
"mailto:dholth-at-fastmail.fm">Daniel Holth</a>.</dd>
<dt>11 Sept 2003</dt>
<dd>
<ul>
<li>Changed the response to multiple to-python converters being
registered for the same type from a hard error into warning;
Boost.Python now reports the offending type in the message.</li>
<li>Added builtin <code>std::wstring</code> conversions</li>
<li>Added <code>std::out_of_range</code> =&gt; Python
<code>IndexError</code> exception conversion, thanks to <a href=
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li>
</ul>
</dd>
<dt>9 Sept 2003</dt>
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd>
<dt>constructors which take a range of characters, allowing strings
containing nul (<code>'\0'</code>) characters.</dt>
<dt>8 Sept 2003</dt>
<dd>Added the ability to create methods from function objects (with an
<code>operator()</code>); see the <a href=
"v2/make_function.html#make_function-spec">make_function</a> docs for
more info.</dd>
<dt>10 August 2003</dt>
<dd>Added the new <code>properties</code> unit tests contributed by
<a href="mailto:romany-at-actimize.com">Roman Yakovenko</a> and
documented <code>add_static_property</code> at his urging.</dd>
<dt>1 August 2003</dt>
<dd>
Added the new <code>arg</code> class contributed by <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a> which supplies the
ability to wrap functions that can be called with ommitted arguments in
the middle:
<pre>
void f(int x = 0, double y = 3.14, std::string z = std::string("foo"));
BOOST_PYTHON_MODULE(test)
{
def("f", f
, (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
}
</pre>And in Python:
<pre>
&gt;&gt;&gt; import test
&gt;&gt;&gt; f(0, z = "bar")
&gt;&gt;&gt; f(z = "bar", y = 0.0)
</pre>Thanks, Nikolay!
</dd>
<dt>22 July 2003</dt>
<dd>Killed the dreaded "bad argument type for builtin operation" error.
Argument errors now show the actual and expected argument types!</dd>
<dt>19 July 2003</dt>
<dd>Added the new <code><a href=
"v2/return_arg.html">return_arg</a></code> policy from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
<dt>18 March, 2003</dt>
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
Gan&szlig;auge</a> has contributed <a href=
"v2/opaque.html">opaque pointer support</a>.<br>
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
Oliveira</a> has contributed the exciting <a href=
"../pyste/index.html">Pyste</a> ("Pie-steh") package.</dd>
<dt>24 February 2003</dt>
<dd>Finished improved support for <code>boost::shared_ptr</code>. Now any
wrapped object of C++ class <code>X</code> can be converted automatically
to <code>shared_ptr&lt;X&gt;</code>, regardless of how it was wrapped.
The <code>shared_ptr</code> will manage the lifetime of the Python object
which supplied the <code>X</code>, rather than just the <code>X</code>
object itself, and when such a <code>shared_ptr</code> is converted back
to Python, the original Python object will be returned.</dd>
<dt>19 January 2003</dt>
<dd>Integrated <code>staticmethod</code> support from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
<dt>29 December 2002</dt>
<dd>Added Visual Studio project file and instructions from Brett Calcott.
Thanks, Brett!</dd>
<dt>20 December 2002</dt>
<dd>Added automatic downcasting for pointers, references, and smart
pointers to polymorphic class types upon conversion to python</dd>
<dt>18 December 2002</dt>
<dd>Optimized from_python conversions for wrapped classes by putting the
conversion logic in the shared library instead of registering separate
converters for each class in each extension module</dd>
<dt>19 November 2002</dt>
<dd>Removed the need for users to cast base class member function
pointers when used as arguments to <a href=
"v2/class.html#class_-spec-modifiers">add_property</a></dd>
<dt>13 December 2002</dt>
<dd>Allow exporting of <a href=
"v2/enum.html#enum_-spec"><code>enum_</code></a> values into enclosing
<a href="v2/scope.html#scope-spec"><code>scope</code></a>.<br>
Fixed unsigned integer conversions to deal correctly with numbers that
are out-of-range of <code>signed long</code>.</dd>
<dt>14 November 2002</dt>
<dd>Auto-detection of class data members wrapped with <a href=
"v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd>
<dt>13 November 2002</dt>
<dd>Full Support for <code>std::auto_ptr&lt;&gt;</code> added.</dd>
<dt>October 2002</dt>
<dd>Ongoing updates and improvements to tutorial documentation</dd>
<dt>10 October 2002</dt>
<dd>Boost.Python V2 is released!</dd>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
19 November 2004
<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003.</i></p>
</body>
</html>

155
doc/overloading.html Normal file
View File

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

215
doc/overriding.html Normal file
View File

@@ -0,0 +1,215 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Overridable Virtual Functions</title>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
<h1>Overridable Virtual Functions</h1>
<p>
In the <a href="exporting_classes.html">previous example</a> we exposed a simple
C++ class in Python and showed that we could write a subclass. We even
redefined one of the functions in our derived class. Now we will learn
how to make the function behave virtually <em>when called from C++</em>.
<h2><a name="overriding_example">Example</a></h2>
<p>In this example, it is assumed that <code>hello::greet()</code> is a virtual
member function:
<blockquote><pre>
class hello
{
public:
hello(const std::string&amp; country) { this-&gt;country = country; }
<b>virtual</b> std::string greet() const { return "Hello from " + country; }
    virtual ~hello(); // Good practice
...
};
</pre></blockquote>
<p>
We'll need a derived class<a href="#why_derived">*</a> to help us
dispatch the call to Python. In our derived class, we need the following
elements:
<ol>
<li><a name="derived_1">A</a> <code>PyObject*</code> data member (usually
called <tt>self</tt>) that holds a pointer to the Python object corresponding
to our C++ <tt>hello</tt> instance.
<li><a name="derived_2">For</a> each exposed constructor of the
base class <tt>T</tt>, a constructor which takes the same parameters preceded by an initial
<code>PyObject*</code> argument. The initial argument should be stored in the <tt>self</tt> data
member described above.
<li><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*,&nbsp;const&nbsp;T&amp;)</tt>.
<li><a name="derived_4">An</a> implementation of each virtual function you may
wish to override in Python which uses
<tt>callback&lt</tt><i>return-type</i><tt>&gt;::call_method(self,&nbsp;&quot;</tt><i>name</i><tt>&quot;,&nbsp;</tt><i>args...</i><tt>)</tt> to call
the Python override.
<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
a reference or pointer to the <tt>T</tt> as the first parameter and which
forwards any additional parameters neccessary to the <i>default</i>
implementation of the virtual function. See also <a href="#private">this
note</a> if the base class virtual function is private.
</ol>
<blockquote><pre>
struct hello_callback : hello
{
// hello constructor storing initial self_ parameter
hello_callback(PyObject* self_, const std::string&amp; x) // <a href="#derived_2">2</a>
: hello(x), self(self_) {}
// In case hello is returned by-value from a wrapped function
hello_callback(PyObject* self_, const hello&amp; x) // <a href="#derived_3">3</a>
: hello(x), self(self_) {}
// Override greet to call back into Python
std::string greet() const // <a href="#derived_4">4</a>
{ return boost::python::callback&lt;std::string&gt;::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:
PyObject* self; // <a href="#derived_1">1</a>
};
</pre></blockquote>
<p>
Finally, we add <tt>hello_callback</tt> to the <tt>
class_builder&lt;&gt;</tt> declaration in our module initialization
function, and when we define the function, we must tell Boost.Python about the default
implementation:
<blockquote><pre>
// Create the <a name=
"hello_class">Python type object</a> for our extension class
boost::python::class_builder&lt;hello<strong>,hello_callback&gt;</strong> hello_class(hello, "hello");
// Add a virtual member function
hello_class.def(&amp;hello::greet, "greet", &amp;<b>hello_callback::default_greet</b>);
</pre></blockquote>
<p>
Now our Python subclass of <tt>hello</tt> behaves as expected:
<blockquote><pre>
&gt;&gt;&gt; class wordy(hello):
... def greet(self):
... return hello.greet(self) + ', where the weather is fine'
...
&gt;&gt;&gt; hi2 = wordy('Florida')
&gt;&gt;&gt; hi2.greet()
'Hello from Florida, where the weather is fine'
&gt;&gt;&gt; invite(hi2)
'Hello from Florida, where the weather is fine! Please come soon!'
</pre></blockquote>
<p>
<a name="why_derived">*</a>You may ask, "Why do we need this derived
class? This could have been designed so that everything gets done right
inside of <tt>hello</tt>." One of the goals of Boost.Python is to be
minimally intrusive on an existing C++ design. In principle, it should be
possible to expose the interface for a 3rd party library without changing
it. To unintrusively hook into the virtual functions so that a Python
override may be called, we must use a derived class.
<h2>Pure Virtual Functions</h2>
<p>
A pure virtual function with no implementation is actually a lot easier to
deal with than a virtual function with a default implementation. First of
all, you obviously don't need to <a href="#default_implementation"> supply
a default implementation</a>. Secondly, you don't need to call
<tt>def()</tt> on the <tt>extension_class&lt;&gt;</tt> instance
for the virtual function. In fact, you wouldn't <em>want</em> to: if the
corresponding attribute on the Python class stays undefined, you'll get an
<tt>AttributeError</tt> in Python when you try to call the function,
indicating that it should have been implemented. For example:
<blockquote>
<pre>
struct baz {
<strong>virtual</strong> int pure(int) = 0;
int calls_pure(int x) { return pure(x) + 1000; }
};
struct baz_callback {
int pure(int x) { boost::python::callback&lt;int&gt;::call_method(m_self, "pure", x); }
};
BOOST_PYTHON_MODULE_INIT(foobar)
{
try
{
boost::python::module_builder foobar("foobar");
boost::python::class_builder&lt;baz,baz_callback&gt; baz_class("baz");
baz_class.def(&amp;baz::calls_pure, "calls_pure");
}
catch(...)
{
boost::python::handle_exception(); // Deal with the exception for Python
}
}
</pre>
</blockquote>
<p>
Now in Python:
<blockquote>
<pre>
&gt;&gt;&gt; from foobar import baz
&gt;&gt;&gt; x = baz()
&gt;&gt;&gt; x.pure(1)
Traceback (innermost last):
File "&lt;stdin&gt;", line 1, in ?
AttributeError: pure
&gt;&gt;&gt; x.calls_pure(1)
Traceback (innermost last):
File "&lt;stdin&gt;", line 1, in ?
AttributeError: pure
&gt;&gt;&gt; class mumble(baz):
... def pure(self, x): return x + 1
...
&gt;&gt;&gt; y = mumble()
&gt;&gt;&gt; y.pure(99)
100
&gt;&gt;&gt; y.calls_pure(99)
1100
</pre></blockquote>
<a name="private"><h2>Private Non-Pure Virtual Functions</h2></a>
<p>This is one area where some minor intrusiveness on the wrapped library is
required. Once it has been overridden, the only way to call the base class
implementation of a private virtual function is to make the derived class a
friend of the base class. You didn't hear it from me, but most C++
implementations will allow you to change the declaration of the base class in
this limited way without breaking binary compatibility (though it will certainly
break the <a
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
<hr>
<p>
Next: <a href="overloading.html">Function Overloading</a>
Previous: <a href="exporting_classes.html">Exporting Classes</a>
Up: <a href="index.html">Top</a>
<p>
&copy; Copyright David Abrahams 2001. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided "as is" without
express or implied warranty, and with no claim as to its suitability for
any purpose.
<p>
Updated: Mar 21, 2001

272
doc/pickle.html Normal file
View 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&lt;your_class&gt; 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&lt;your_class&gt; 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>
&copy; 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>

148
doc/pointers.html Normal file
View File

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

View File

@@ -1,222 +0,0 @@
.. Copyright David Abrahams 2006. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at
.. http://www.boost.org/LICENSE_1_0.txt)
How Runtime Polymorphism is expressed in Boost.Python:
-----------------------------------------------------
struct A { virtual std::string f(); virtual ~A(); };
std::string call_f(A& x) { return x.f(); }
struct B { virtual std::string f() { return "B"; } };
struct Bcb : B
{
Bcb(PyObject* self) : m_self(self) {}
virtual std::string f() { return call_method<std::string>(m_sef, "f"); }
static std::string f_default(B& b) { return b.B::f(); }
PyObject* m_self;
};
struct C : B
{
virtual std::string f() { return "C"; }
};
>>> class D(B):
... def f():
... return 'D'
...
>>> class E(B): pass
...
When we write, "invokes B::f non-virtually", we mean:
void g(B& x) { x.B::f(); }
This will call B::f() regardless of the dynamic type of x. Any other
way of invoking B::f, including through a function pointer, is a
"virtual invocation", and will call the most-derived override of f().
Case studies
C++\Python class
\___A_____B_____C_____D____E___
|
A | 1
|
B | 2 3
|
Bcb | 4 5 6
|
C | 7 8
|
1. Simple case
2. Python A holds a B*. Probably won't happen once we have forced
downcasting.
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: A.f invokes A::f() (virtually or otherwise)
3. Python B holds a B*.
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: B.f invokes B::f (virtually or otherwise)
4. B constructed from Python
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: B.f invokes B::f non-virtually. Bcb::f invokes B::f
non-virtually.
Question: Does it help if we arrange for Python B construction to
build a true B object? Then this case doesn't arise.
5. D is a Python class derived from B
Requires:
x.f() -> 'D'
call_f(x) -> 'D'
Implies: Bcb::f must invoke call_method to look up the Python
method override, otherwise call_f wouldn't work.
6. E is like D, but doesn't override f
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: B.f invokes B::f non-virtually. If it were virtual, x.f()
would cause infinite recursion, because we've already
determined that Bcb::f must invoke call_method to look up
the Python method override.
7. Python B object holds a C*
Requires:
x.f() -> 'C'
call_f(x) -> 'C'
Implies: B.f invokes B::f virtually.
8. C object constructed from Python
Requires:
x.f() -> 'C'
call_f(x) -> 'C'
Implies: nothing new.
------
Total implications:
2: A.f invokes A::f() (virtually or otherwise)
3: B.f invokes B::f (virtually or otherwise)
4: B.f invokes B::f non-virtually. Bcb::f invokes B::f non-virtually
6: B.f invokes B::f non-virtually.
7: B.f invokes B::f virtually.
5: Bcb::f invokes call_method to look up the Python method
Though (4) is avoidable, clearly 6 and 7 are not, and they
conflict. The implication is that B.f must choose its behavior
according to the type of the contained C++ object. If it is Bcb, a
non-virtual call to B::f must occur. Otherwise, a virtual call to B::f
must occur. This is essentially the same scheme we had with
Boost.Python v1.
Note: in early versions of Boost.Python v1, we solved this problem by
introducing a new Python class in the hierarchy, so that D and E
actually derive from a B', and B'.f invokes B::f non-virtually, while
B.f invokes B::f virtually. However, people complained about the
artificial class in the hierarchy, which was revealed when they tried
to do normal kinds of Python introspection.
-------
Assumption: we will have a function which builds a virtual function
dispatch callable Python object.
make_virtual_function(pvmf, default_impl, call_policies, dispatch_type)
Pseudocode:
Get first argument from Python arg tuple
if it contains dispatch_type
call default_impl
else
call through pvmf
Open questions:
1. What about Python multiple inheritance? Do we have the right
check in the if clause above?
A: Not quite. The correct test looks like:
Deduce target type of pvmf, i.e. T in R(T::*)(A1...AN).
Find holder in first argument which holds T
if it holds dispatch_type...
2. Can we make this more efficient?
The current "returning" mechanism will look up a holder for T
again. I don't know if we know how to avoid that.
OK, the solution involves reworking the call mechanism. This is
neccesary anyway in order to enable wrapping of function objects.
It can result in a reduction in the overall amount of source code,
because returning<> won't need to be specialized for every
combination of function and member function... though it will still
need a void specialization. We will still need a way to dispatch to
member functions through a regular function interface. mem_fn is
almost the right tool, but it only goes up to 8
arguments. Forwarding is tricky if you don't want to incur copies.
I think the trick is to use arg_from_python<T>::result_type for each
argument to the forwarder.
Another option would be to use separate function, function object,
and member function dispatchers. Once you know you have a member
function, you don't need cv-qualified overloads to call it.
Hmm, while we're at this, maybe we should solve the write-back
converter problem. Can we do it? Maybe not. Ralf doesn't want to
write special write-back functions here, does he? He wants the
converter to do the work automatically. We could add
cleanup/destructor registration. That would relieve the client from
having accessible destructors for types which are being converted by
rvalue. I'm not sure that this will really save any code,
however. It rather depends on the linker, doesn't it? I wonder if
this can be done in a backwards-compatible fashion by generating the
delete function when it's not supplied?

View File

@@ -1,466 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st September 2004), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html">
<link rel="stylesheet" type="text/css" href="boost.css">
<title>Boost.Python - Projects using Boost.Python</title>
</head>
<body link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
<h2 align="center">Projects using Boost.Python</h2>
</td>
</tr>
</table>
<hr>
<h2>Introduction</h2>
<p>This is a partial list of projects using Boost.Python. If you are using
Boost.Python as your Python/C++ binding solution, we'd be proud to list
your project on this page. Just <a href=
"mailto:c++-sig@python.org">post</a> a short description of your project
and how Boost.Python helps you get the job done, and we'll add it to this
page .</p>
<hr>
<h3>Data Analysis</h3>
<dl class="page-index">
<dt><b><a href="http://www.neuralynx.com">NeuraLab</a></b></dt>
<dd>Neuralab is a data analysis environment specifically tailored for
neural data from <a href="http://www.neuralynx.com">Neuralynx</a>
acquisition systems. Neuralab combines presentation quality graphics, a
numerical analysis library, and the <a href=
"http://www.python.org">Python</a> scripting engine in a single
application. With Neuralab, Neuralynx users can perform common analysis
tasks with just a few mouse clicks. More advanced users can create custom
Python scripts, which can optionally be assigned to menus and mouse
clicks.</dd>
</dl>
<dl class="page-index">
<dt><b>TSLib</b> - <a href="http://www.fortressinv.com">Fortress
Investment Group LLC</a></dt>
<dd>
Fortress Investment Group has contracted <a href=
"http://www.boost-consulting.com">Boost Consulting</a> to develop core
internal financial analysis tools in C++ and to prepare Python bindings
for them using Boost.Python.
<p>Tom Barket of Fortress writes:</p>
<blockquote>
We have a large C++ analytical library specialized for research in
finance and economics, built for speed and mission critical
stability. Yet Python offers us the flexibility to test out new ideas
quickly and increase the productivity of our time versus working in
C++. There are several key features which make Python stand out. Its
elegance, stability, and breadth of resources on the web are all
valuable, but the most important is its extensibility, due to its
open source transparency. Boost.Python makes Python extensibility
extremely simple and straightforward, yet preserves a great deal of
power and control.
</blockquote>
</dd>
</dl>
<h3>Educational</h3>
<dl class="page-index">
<dt><a href="http://edu.kde.org/kig"><b>Kig</b></a></dt>
<dd>
<p>KDE Interactive Geometry is a high-school level educational tool,
built for the KDE desktop. It is a nice tool to let students work with
geometrical constructions. It is meant to be the most intuitive, yet
featureful application of its kind.</p>
<p>Versions after 0.6.x (will) support objects built by the user
himself in the Python language. The exporting of the relevant internal
API's were done using Boost.Python, which made the process very
easy.</p>
</dd>
</dl>
<h3>Enterprise Software</h3>
<dl class="page-index">
<dt><b><a href="http://openwbem.sourceforge.net">OpenWBEM</a></b></dt>
<dd>
The OpenWBEM project is an effort to develop an open-source
implementation of Web Based Enterprise Management suitable for
commercial and non-commercial application
<p><a href="mailto:dnuffer@sco.com">Dan Nuffer</a> writes:</p>
<blockquote>
I'm using Boost.Python to wrap the client API of OpenWBEM.This will
make it easier to do rapid prototyping, testing, and scripting when
developing management solutions that use WBEM.
</blockquote>
</dd>
<dt><b><a href="http://www.transversal.com">Metafaq</a></b></dt>
<dd>
Metafaq, from <a href="http://www.transversal.com">Transversal,
Inc.</a>, is an enterprise level online knowledge base management
system.
<p><a href="mailto:ben.young-at-transversal.com">Ben Young</a>
writes:</p>
<blockquote>
Boost.Python is used in an automated process to generate python
bindings to our api which is exposed though multiple backends and
frontends. This allows us to write quick tests and bespoke scripts to
perform one off tasks without having to go through the full
compilation cycle.
</blockquote>
</dd>
</dl>
<h3>Games</h3>
<dl>
<dt><b><a href="http://www.firaxis.com">Civilization IV</a></b></dt>
</dl>
<blockquote>
&ldquo;The fourth game in the PC strategy series that has sold over five
million copies, Sid Meier's Civilization IV is a bold step forward for
the franchise, with spectacular new 3D graphics and all-new single and
multiplayer content. Civilization IV will also set a new standard for
user-modification, allowing gamers to create their own add-ons using
Python and XML.
<p>Sid Meier's Civilization IV will be released for PC in late 2005. For
more information please visit <a href=
"http://www.firaxis.com">http://www.firaxis.com</a> or write <a href=
"mailto:kgilmore@firaxis.com">kgilmore@firaxis.com</a>&rdquo;</p>
</blockquote>
<p>Boost.Python is used as the interface layer between the C++ game code
and Python. Python is used for many purposes in the game, including map
generation, interface screens, game events, tools, tutorials, etc. Most
high-level game operations have been exposed to Python in order to give
modders the power they need to customize the game.</p>
<blockquote>
-Mustafa Thamer, Civ4 Lead Programmer
</blockquote>
<dl class="page-index">
<dt><b><a href="http://vegastrike.sourceforge.net">Vega
Strike</a></b></dt>
<dd>
<a href="http://vegastrike.sourceforge.net">Vega Strike</a> is the 3D
Space Simulator that allows you to trade and bounty hunt in a vast
universe. Players face dangers, decisions, piracy, and aliens.
<p><a href="http://vegastrike.sourceforge.net">Vega Strike</a> has
decided to base its scripting on python, using boost as the layer
between the class hierarchy in python and the class hierarchy in C++.
The result is a very flexible scripting system that treats units as
native python classes when designing missions or writing AI's.</p>
<p>A large economic and planetary simulation is currently being run in
the background in python and the results are returned back into C++ in
the form of various factions' spaceships appearing near worlds that
they are simulated to be near in python if the player is in the general
neighborhood.</p>
</dd>
</dl>
<h3>Graphics</h3>
<dl class="page-index">
<dt><b><a href="http://sourceforge.net/projects/pyosg">OpenSceneGraph
Bindings</a></b></dt>
<dd><a href="mailto:gideon@computer.org">Gideon May</a> has created a set
of bindings for <a href=
"http://www.openscenegraph.org">OpenSceneGraph</a>, a cross-platform
C++/OpenGL library for the real-time visualization.<br>
&nbsp;</dd>
<dt><b><a href=
"http://www.slac.stanford.edu/grp/ek/hippodraw/index.html">HippoDraw</a></b></dt>
<dd>
HippoDraw is a data analysis environment consisting of a canvas upon
which graphs such as histograms, scattter plots, etc, are prsented. It
has a highly interactive GUI interface, but some things you need to do
with scripts. HippoDraw can be run as Python extension module so that
all the manipulation can be done from either Python or the GUI.
<p>Before the web page came online, <a href=
"mailto:Paul_Kunz@SLAC.Stanford.EDU">Paul F. Kunz</a> wrote:</p>
<blockquote>
Don't have a web page for the project, but the organization's is
<a href=
"http://www.slac.stanford.edu">http://www.slac.stanford.edu</a> (the
first web server site in America, I installed it).
</blockquote>Which was just too cool a piece of trivia to omit.<br>
&nbsp;
</dd>
<dt><a href="http://www.iplt.org"><b>IPLT</b></a></dt>
<dd>
<a href="mailto:ansgar.philippsen-at-unibas.ch">Ansgar Philippsen</a>
writes:
<blockquote>
IPLT is an image processing library and toolbox for the structural
biology electron microscopy community. I would call it a
budding/evolving project, since it is currently not in production
stage, but rather under heavy development. Python is used as the main
scripting/interaction level, but also for rapid prototyping, since
the underlying C++ class library is pretty much fully exposed via
boost.python (at least the high-level interface). The combined power
of C++ and Python for this project turned out to be just awesome.
</blockquote><br>
&nbsp;
</dd>
<dt><a href=
"http://www.procoders.net/pythonmagick"><b>PythonMagick</b></a></dt>
<dd>PythonMagick binds the <a href=
"http://www.graphicsmagick.org">GraphicsMagick</a> image manipulation
library to Python.<br>
&nbsp;</dd>
<dt><a href="http://www.vpython.org"><b>VPython</b></a></dt>
<dd>
<a href="mailto:Bruce_Sherwood-at-ncsu.edu">Bruce Sherwood</a> writes:
<blockquote>
VPython is an extension for Python that makes it easy to create
navigable 3D animations, which are generated as a side effect of
computational code. VPython is used in education for various
purposes, including teaching physics and programming, but it has also
been used by research scientists to visualize systems or data in 3D.
</blockquote><br>
&nbsp;
</dd>
</dl>
<h3>Scientific Computing</h3>
<dl class="page index">
<dt><a href="http://camfr.sourceforge.net"><b>CAMFR</b></a></dt>
<dd>
CAMFR is a photonics and electromagnetics modelling tool. Python is
used for computational steering.
<p><a href="mailto:Peter.Bienstman@rug.ac.be">Peter Bienstman</a>
writes:</p>
<blockquote>
Thanks for providing such a great tool!
</blockquote>
</dd>
<dt><a href="http://cctbx.sourceforge.net"><b>cctbx - Computational
Crystallography Toolbox</b></a></dt>
<dd>
Computational Crystallography is concerned with the derivation of
atomic models of crystal structures, given experimental X-ray
diffraction data. The cctbx is an open-source library of fundamental
algorithms for crystallographic computations. The core algorithms are
implemented in C++ and accessed through higher-level Python interfaces.
<p>The cctbx grew together with Boost.Python and is designed from the
ground up as a hybrid Python/C++ system. With one minor exception,
run-time polymorphism is completely handled by Python. C++ compile-time
polymorphism is used to implement performance critical algorithms. The
Python and C++ layers are seamlessly integrated using Boost.Python.</p>
<p>The SourceForge cctbx project is organized in modules to facilitate
use in non-crystallographic applications. The scitbx module implements
a general purpose array family for scientific applications and pure C++
ports of FFTPACK and the L-BFGS quasi-Newton minimizer.</p>
</dd>
<dt><a href="http://www.llnl.gov/CASC/emsolve"><b>EMSolve</b></a></dt>
<dd>EMSolve is a provably stable, charge conserving, and energy
conserving solver for Maxwell's equations.<br>
&nbsp;</dd>
<dt><b><a href="http://cern.ch/gaudi">Gaudi</a></b> and <b><a href=
"http://cern.ch/Gaudi/RootPython/">RootPython</a></b></dt>
<dd>
Gaudi is a framework for particle physics collision data processing
applications developed in the context of the LHCb and ATLAS experiments
at CERN.
<p><a href="mailto:Pere.Mato@cern.ch">Pere Mato Vila</a> writes:</p>
<blockquote>
We are using Boost.Python to provide scripting/interactive capability
to our framework. We have a module called "GaudiPython" implemented
using Boost.Python that allows the interaction with any framework
service or algorithm from python. RootPython also uses Boost.Python
to provide a generic "gateway" between the <a href=
"http://root.cern.ch">ROOT</a> framework and python
<p>Boost.Python is great. We managed very quickly to interface our
framework to python, which is great language. We are trying to
facilitate to our physicists (end-users) a rapid analysis application
development environment based on python. For that, Boost.Python plays
and essential role.</p>
</blockquote>
</dd>
<dt><b><a href="http://www.esss.com.br">ESSS</a></b></dt>
<dd>
ESSS (Engineering Simulation and Scientific Software) is a company that
provides engineering solutions and acts in the brazilian and
south-american market providing products and services related to
Computational Fluid Dynamics and Image Analysis.
<p><a href="mailto:bruno@esss.com.br">Bruno da Silva de Oliveira</a>
writes:</p>
<blockquote>
Recently we moved our work from working exclusively with C++ to an
hybrid-language approach, using Python and C++, with Boost.Python
providing the layer between the two. The results are great so far!
</blockquote>
<p>Two projects have been developed so far with this technology:</p>
<p><b><a href=
"http://www.esss.com.br/index.php?pg=dev_projetos">Simba</a></b>
provides 3D visualization of geological formations gattered from the
simulation of the evolution of oil systems, allowing the user to
analyse various aspects of the simulation, like deformation, pressure
and fluids, along the time of the simulation.</p>
<p><b><a href=
"http://www.esss.com.br/index.php?pg=dev_projetos">Aero</a></b> aims to
construct a CFD with brazilian technology, which involves various
companies and universities. ESSS is responsible for various of the
application modules, including GUI and post-processing of results.</p>
</dd>
<dt><b><a href="http://polybori.sourceforge.net/">PolyBoRi</a></b></dt>
<dd>
<p><a href="mailto:brickenstein@mfo.de"
>Michael Brickenstein</a> writes:</p>
<blockquote>
<p>The core of PolyBoRi is a C++ library, which provides
high-level data types for Boolean polynomials and monomials,
exponent vectors, as well as for the underlying polynomial
rings and subsets of the powerset of the Boolean variables. As
a unique approach, binary decision diagrams are used as
internal storage type for polynomial structures. On top of
this C++-library we provide a Python interface. This allows
parsing of complex polynomial systems, as well as sophisticated
and extendable strategies for Gr&ouml;bner basis computation.
Boost.Python has helped us to create this interface in a
very clean way.</p>
</blockquote>
</dd>
<dt><b><a href="http://www.rationaldiscovery.com">Rational Discovery
LLC</a></b></dt>
<dd>
Rational Discovery provides computational modeling, combinatorial
library design and custom software development services to the
pharmaceutical, biotech and chemical industries. We do a substantial
amount of internal research to develop new approaches for applying
machine-learning techniques to solve chemical problems. Because we're a
small organization and chemistry is a large and complex field, it is
essential that we be able to quickly and easily prototype and test new
algorithms.
<p>For our internal software, we implement core data structures in C
and expose them to Python using Boost.Python. Algorithm development is
done in Python and then translated to C if required (often it's not).
This hybrid development approach not only greatly increases our
productivity, but it also allows "non-developers" (people without C
experience) to take part in method development. Learning C is a
daunting task, but "Python fits your brain." (Thanks to Bruce Eckel for
the quote.)</p>
</dd>
</dl>
<h3>Systems Libraries</h3>
<dl>
<dt><a href="http://itamarst.org/software"><b>Fusion</b></a></dt>
<dd>
<p>Fusion is a library that supports implementing protocols in C++ for
use with Twisted, allowing control over memory allocation strategies,
fast method calls internally, etc.. Fusion supports TCP, UDP and
multicast, and is implemented using the Boost.Python python
bindings.</p>
<p>Fusion is licensed under the MIT license, and available for download
from <a href=
"http://itamarst.org/software">http://itamarst.org/software</a>.</p>
</dd>
</dl>
<h3>Tools</h3>
<dl>
<dt><a href="http://www.jayacard.org"><b>Jayacard</b></a></dt>
<dd>
Jayacard aims at developing a secure portable open source operating
system for contactless smart cards and a complete suite of high quality
development tools to ease smart card OS and application development.
<p>The core of the smart card reader management is written in C++ but
all the development tools are written in the friendly Python language.
Boost plays the fundamental role of binding the tools to our core smart
card reader library.</p>
</dd>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
29 May, 2008</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2008.</i></p>
</body>
</html>

905
doc/special.html Normal file
View File

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

View File

@@ -1,74 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="boost.css">
<title>Boost.Python - Support Resources</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
<h2 align="center">Support Resources</h2>
</td>
</tr>
</table>
<hr>
<h2>Synopsis</h2>
<p>This is a list of available resources for support with Boost.Python
problems and feature requests. <b>Please try to resist emailing the
Boost.Python developers directly for support.</b> Use the following
resources instead; the developers are listening!</p>
<hr>
<dl class="page-index">
<dt><b><a href="http://www.boost-consulting.com">Boost
Consulting</a></b> - Commercial support, development, training, and
distribution for all the Boost libraries, from the people who brought
you Boost.Python.<br>
&nbsp;</dt>
<dt><b><a href=
"http://www.boost.org/more/mailing_lists.htm#cplussig">The Python
C++-sig</a></b> mailing list is a forum for discussing Python/C++
interoperability, and Boost.Python in particular. Post your
Boost.Python questions here.<br>
&nbsp;</dt>
<dt>The <b>Boost.Python <a href=
"http://www.python.org/cgi-bin/moinmoin/boost_2epython">Wiki
Pages</a></b> established by Mike Rovner as part of the <a href=
"http://www.python.org/cgi-bin/moinmoin">PythonInfo Wiki</a> serves as
a forum to gather peoples' experience and as a cookbook.<br>
&nbsp;</dt>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
12 Sept, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2003.</i></p>
</body>
</html>

View File

@@ -1,20 +0,0 @@
# Copyright Joel de Guzman 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
project boost/libs/python/doc/tutorial/doc ;
import boostbook : boostbook ;
using quickbook ;
path-constant images : html ;
boostbook tutorial
:
tutorial.qbk
:
<xsl:param>boost.root=../../../../../..
<xsl:param>boost.libraries=../../../../../../libs/libraries.htm
<xsl:param>html.stylesheet=../../../../../../doc/html/boostbook.css
<format>pdf:<xsl:param>img.src.path=$(images)/
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/python/doc/tutorial/doc/html
;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 658 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 370 B

View File

@@ -1,151 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Chapter 1. python 2.0</title>
<link rel="stylesheet" href="../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="index.html" title="Chapter 1. python 1.0">
<link rel="next" href="python/hello.html" title=" Building Hello World">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/html/images/next.png" alt="Next"></a></div>
<div class="chapter" lang="en">
<div class="titlepage"><div>
<div><h2 class="title">
<a name="python"></a>Chapter 1. python 1.0</h2></div>
<div><div class="author"><h3 class="author">
<span class="firstname">Joel</span> <span class="surname">de Guzman</span>
</h3></div></div>
<div><div class="author"><h3 class="author">
<span class="firstname">David</span> <span class="surname">Abrahams</span>
</h3></div></div>
<div><p class="copyright">Copyright © 2002-2005 Joel
de Guzman, David Abrahams</p></div>
<div><div class="legalnotice">
<a name="id457106"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></div>
</div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl>
<dt><span class="section"><a href="index.html#python.quickstart">QuickStart</a></span></dt>
<dt><span class="section"><a href="python/hello.html"> Building Hello World</a></span></dt>
<dt><span class="section"><a href="python/exposing.html"> Exposing Classes</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="python/exposing.html#python.constructors">Constructors</a></span></dt>
<dt><span class="section"><a href="python/exposing.html#python.class_data_members">Class Data Members</a></span></dt>
<dt><span class="section"><a href="python/exposing.html#python.class_properties">Class Properties</a></span></dt>
<dt><span class="section"><a href="python/exposing.html#python.inheritance">Inheritance</a></span></dt>
<dt><span class="section"><a href="python/exposing.html#python.class_virtual_functions">Class Virtual Functions</a></span></dt>
<dt><span class="section"><a href="python/exposing.html#python.virtual_functions_with_default_implementations">Virtual Functions with Default Implementations</a></span></dt>
<dt><span class="section"><a href="python/exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="python/functions.html">Functions</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="python/functions.html#python.call_policies">Call Policies</a></span></dt>
<dt><span class="section"><a href="python/functions.html#python.overloading">Overloading</a></span></dt>
<dt><span class="section"><a href="python/functions.html#python.default_arguments">Default Arguments</a></span></dt>
<dt><span class="section"><a href="python/functions.html#python.auto_overloading">Auto-Overloading</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="python/object.html"> Object Interface</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="python/object.html#python.basic_interface">Basic Interface</a></span></dt>
<dt><span class="section"><a href="python/object.html#python.derived_object_types">Derived Object types</a></span></dt>
<dt><span class="section"><a href="python/object.html#python.extracting_c___objects">Extracting C++ objects</a></span></dt>
<dt><span class="section"><a href="python/object.html#python.enums">Enums</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="python/embedding.html">Embedding</a></span></dt>
<dd><dl><dt><span class="section"><a href="python/embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></dd>
<dt><span class="section"><a href="python/iterators.html">Iterators</a></span></dt>
<dt><span class="section"><a href="python/exception.html"> Exception Translation</a></span></dt>
<dt><span class="section"><a href="python/techniques.html"> General Techniques</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="python/techniques.html#python.creating_packages">Creating Packages</a></span></dt>
<dt><span class="section"><a href="python/techniques.html#python.extending_wrapped_objects_in_python">Extending Wrapped Objects in Python</a></span></dt>
<dt><span class="section"><a href="python/techniques.html#python.reducing_compiling_time">Reducing Compiling Time</a></span></dt>
</dl></dd>
</dl>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.quickstart"></a>QuickStart</h2></div></div></div>
<p>
The Boost Python Library is a framework for interfacing Python and C++. It
allows you to quickly and seamlessly expose C++ classes functions and objects
to Python, and vice-versa, using no special tools -- just your C++ compiler.
It is designed to wrap C++ interfaces non-intrusively, so that you should not
have to change the C++ code at all in order to wrap it, making Boost.Python
ideal for exposing 3rd-party libraries to Python. The library's use of advanced
metaprogramming techniques simplifies its syntax for users, so that wrapping
code takes on the look of a kind of declarative interface definition language
(IDL).
</p>
<a name="quickstart.hello_world"></a><h2>
<a name="id386707"></a>
Hello World
</h2>
<p>
Following C/C++ tradition, let's start with the "hello, world". A
C++ Function:
</p>
<pre class="programlisting"><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">greet</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="string">"hello, world"</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
can be exposed to Python by writing a Boost.Python wrapper:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello_ext</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
<span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="identifier">greet</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
That's it. We're done. We can now build this as a shared library. The resulting
DLL is now visible to Python. Here's a sample Python session:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello_ext</span>
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
<span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
</pre>
<p>
</p>
<div class="blockquote"><blockquote class="blockquote">
<p>
</p>
<p>
<span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World
module from start to finish...</b></span></em></span>
</p>
<p>
</p>
</blockquote></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: November 22, 2008 at 03:24:11 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/html/images/next.png" alt="Next"></a></div>
</body>
</html>

View File

@@ -1,277 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Embedding</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="object.html" title=" Object Interface">
<link rel="next" href="iterators.html" title="Iterators">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="object.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.embedding"></a>Embedding</h2></div></div></div>
<div class="toc"><dl><dt><span class="section"><a href="embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></div>
<p>
By now you should know how to use Boost.Python to call your C++ code from Python.
However, sometimes you may need to do the reverse: call Python code from the
C++-side. This requires you to <span class="emphasis"><em>embed</em></span> the Python interpreter
into your C++ program.
</p>
<p>
Currently, Boost.Python does not directly support everything you'll need when
embedding. Therefore you'll need to use the <a href="http://www.python.org/doc/current/api/api.html" target="_top">Python/C
API</a> to fill in the gaps. However, Boost.Python already makes embedding
a lot easier and, in a future version, it may become unnecessary to touch the
Python/C API at all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span>
</p>
<a name="embedding.building_embedded_programs"></a><h2>
<a name="id472330"></a>
Building embedded programs
</h2>
<p>
To be able to embed python into your programs, you have to link to both Boost.Python's
as well as Python's own runtime library.
</p>
<p>
Boost.Python's library comes in two variants. Both are located in Boost's
<tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On Windows, the
variants are called <tt class="literal">boost_python.lib</tt> (for release builds)
and <tt class="literal">boost_python_debug.lib</tt> (for debugging). If you can't
find the libraries, you probably haven't built Boost.Python yet. See <a href="../../../../building.html" target="_top">Building and Testing</a> on how to do this.
</p>
<p>
Python's library can be found in the <tt class="literal">/libs</tt> subdirectory
of your Python directory. On Windows it is called pythonXY.lib where X.Y is
your major Python version number.
</p>
<p>
Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be added
to your include path.
</p>
<p>
In a Jamfile, all the above boils down to:
</p>
<pre class="programlisting">projectroot c:\projects\embedded_program ; # location of the program
# bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
exe embedded_program # name of the executable
: #sources
embedded_program.cpp
: # requirements
&lt;find-library&gt;boost_python &lt;library-path&gt;c:\boost\libs\python
$(PYTHON_PROPERTIES)
&lt;library-path&gt;$(PYTHON_LIB_PATH)
&lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ;
</pre>
<a name="embedding.getting_started"></a><h2>
<a name="id472435"></a>
Getting started
</h2>
<p>
Being able to build is nice, but there is nothing to build yet. Embedding the
Python interpreter into one of your C++ programs requires these 4 steps:
</p>
<div class="orderedlist"><ol type="1">
<li>
#include <tt class="literal">&lt;boost/python.hpp&gt;</tt>
</li>
<li>
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>()
to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt>
module.
</li>
<li>
Call other Python C API routines to use the interpreter.
</li>
</ol></div>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top"><p>
<span class="bold"><b>Note that at this time you must not call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
to stop the interpreter. This may be fixed in a future version of boost.python.</b></span>
</p></td></tr>
</table></div>
<p>
(Of course, there can be other C++ code between all of these steps.)
</p>
<div class="blockquote"><blockquote class="blockquote">
<p>
</p>
<p>
<span class="emphasis"><em><span class="bold"><b>Now that we can embed the interpreter in
our programs, lets see how to put it to use...</b></span></em></span>
</p>
<p>
</p>
</blockquote></div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
<p>
As you probably already know, objects in Python are reference-counted. Naturally,
the <tt class="literal">PyObject</tt>s of the Python C API are also reference-counted.
There is a difference however. While the reference-counting is fully automatic
in Python, the Python C API requires you to do it <a href="http://www.python.org/doc/current/c-api/refcounting.html" target="_top">by
hand</a>. This is messy and especially hard to get right in the presence
of C++ exceptions. Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a>
and <a href="../../../../v2/object.html" target="_top">object</a> class templates to
automate the process.
</p>
<a name="using_the_interpreter.running_python_code"></a><h2>
<a name="id472601"></a>
Running Python code
</h2>
<p>
Boost.python provides three related functions to run Python code from C++.
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">eval</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">expression</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
<span class="identifier">object</span> <span class="identifier">exec</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">code</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
<span class="identifier">object</span> <span class="identifier">exec_file</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">filename</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
</pre>
<p>
eval evaluates the given expression and returns the resulting value. exec
executes the given code (typically a set of statements) returning the result,
and exec_file executes the code contained in the given file.
</p>
<p>
The <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters are
Python dictionaries containing the globals and locals of the context in which
to run the code. For most intents and purposes you can use the namespace
dictionary of the <tt class="literal"><span class="underline">_main</span>_</tt>
module for both parameters.
</p>
<p>
Boost.python provides a function to import a module:
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">import</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
</pre>
<p>
import imports a python module (potentially loading it into the running process
first), and returns it.
</p>
<p>
Let's import the <tt class="literal"><span class="underline">_main</span>_</tt>
module and run some Python code in its namespace:
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"hello = file('hello.txt', 'w')\n"</span>
<span class="string">"hello.write('Hello world!')\n"</span>
<span class="string">"hello.close()"</span><span class="special">,</span>
<span class="identifier">main_namespace</span><span class="special">);</span>
</pre>
<p>
This should create a file called 'hello.txt' in the current directory containing
a phrase that is well-known in programming circles.
</p>
<a name="using_the_interpreter.manipulating_python_objects"></a><h2>
<a name="id473185"></a>
Manipulating Python objects
</h2>
<p>
Often we'd like to have a class to manipulate Python objects. But we have
already seen such a class above, and in the <a href="object.html" target="_top">previous
section</a>: the aptly named <tt class="literal">object</tt> class and its
derivatives. We've already seen that they can be constructed from a <tt class="literal">handle</tt>.
The following examples should further illustrate this fact:
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"result = 5 ** 2"</span><span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">);</span>
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
</pre>
<p>
Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
module's namespace. Then we assign 5 squared to the result variable and read
this variable from the dictionary. Another way to achieve the same result
is to use eval instead, which returns the result directly:
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5 ** 2"</span><span class="special">);</span>
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span>
</pre>
<a name="using_the_interpreter.exception_handling"></a><h2>
<a name="id473554"></a>
Exception handling
</h2>
<p>
If an exception occurs in the evaluation of the python expression, <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>
is thrown:
</p>
<pre class="programlisting"><span class="keyword">try</span>
<span class="special">{</span>
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5/0"</span><span class="special">);</span>
<span class="comment">// execution will never get here:
</span> <span class="keyword">int</span> <span class="identifier">five_divided_by_zero</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&amp;)</span>
<span class="special">{</span>
<span class="comment">// handle the exception in some way
</span><span class="special">}</span>
</pre>
<p>
The <tt class="literal">error_already_set</tt> exception class doesn't carry any
information in itself. To find out more about the Python exception that occurred,
you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception
handling functions</a> of the Python C API in your catch-statement. This
can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a>
to print the exception's traceback to the console, or comparing the type
of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
exceptions</a>:
</p>
<pre class="programlisting"><span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&amp;)</span>
<span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">PyErr_ExceptionMatches</span><span class="special">(</span><span class="identifier">PyExc_ZeroDivisionError</span><span class="special">))</span>
<span class="special">{</span>
<span class="comment">// handle ZeroDivisionError specially
</span> <span class="special">}</span>
<span class="keyword">else</span>
<span class="special">{</span>
<span class="comment">// print all other errors to stderr
</span> <span class="identifier">PyErr_Print</span><span class="special">();</span>
<span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
(To retrieve even more information from the exception you can use some of
the other exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="object.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -1,63 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title> Exception Translation</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="iterators.html" title="Iterators">
<link rel="next" href="techniques.html" title=" General Techniques">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.exception"></a> Exception Translation</h2></div></div></div>
<p>
All C++ exceptions must be caught at the boundary with Python code. This boundary
is the point where C++ meets Python. Boost.Python provides a default exception
handler that translates selected standard exceptions, then gives up:
</p>
<pre class="programlisting"><span class="keyword">raise</span> <span class="identifier">RuntimeError</span><span class="special">,</span> <span class="string">'unidentifiable C++ Exception'</span>
</pre>
<p>
Users may provide custom translation. Here's an example:
</p>
<pre class="programlisting"><span class="identifier">struct</span> <span class="identifier">PodBayDoorException</span><span class="special">;</span>
<span class="identifier">void</span> <span class="identifier">translator</span><span class="special">(</span><span class="identifier">PodBayDoorException</span> <span class="identifier">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">PyErr_SetString</span><span class="special">(</span><span class="identifier">PyExc_UserWarning</span><span class="special">,</span> <span class="string">"I'm sorry Dave..."</span><span class="special">);</span>
<span class="special">}</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">kubrick</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">register_exception_translator</span><span class="special">&lt;</span>
<span class="identifier">PodBayDoorException</span><span class="special">&gt;(</span><span class="identifier">translator</span><span class="special">);</span>
<span class="special">...</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -1,605 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title> Exposing Classes</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="hello.html" title=" Building Hello World">
<link rel="next" href="functions.html" title="Functions">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="hello.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.exposing"></a> Exposing Classes</h2></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="exposing.html#python.constructors">Constructors</a></span></dt>
<dt><span class="section"><a href="exposing.html#python.class_data_members">Class Data Members</a></span></dt>
<dt><span class="section"><a href="exposing.html#python.class_properties">Class Properties</a></span></dt>
<dt><span class="section"><a href="exposing.html#python.inheritance">Inheritance</a></span></dt>
<dt><span class="section"><a href="exposing.html#python.class_virtual_functions">Class Virtual Functions</a></span></dt>
<dt><span class="section"><a href="exposing.html#python.virtual_functions_with_default_implementations">Virtual Functions with Default Implementations</a></span></dt>
<dt><span class="section"><a href="exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
</dl></div>
<p>
Now let's expose a C++ class to Python.
</p>
<p>
Consider a C++ class/struct that we want to expose to Python:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">World</span>
<span class="special">{</span>
<span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
<span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
Here, we wrote a C++ class wrapper that exposes the member functions <tt class="literal">greet</tt>
and <tt class="literal">set</tt>. Now, after building our module as a shared library,
we may use our class <tt class="literal">World</tt> in Python. Here's a sample Python
session:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="string">'howdy'</span><span class="special">)</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
<span class="string">'howdy'</span>
</pre>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.constructors"></a>Constructors</h3></div></div></div>
<p>
Our previous example didn't have any explicit constructors. Since <tt class="literal">World</tt>
is declared as a plain struct, it has an implicit default constructor. Boost.Python
exposes the default constructor by default, which is why we were able to
write
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
</pre>
<p>
We may wish to wrap a class with a non-default constructor. Let us build
on our previous example:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">World</span>
<span class="special">{</span>
<span class="identifier">World</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">):</span> <span class="identifier">msg</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)</span> <span class="special">{}</span> <span class="comment">// added constructor
</span> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
This time <tt class="literal">World</tt> has no default constructor; our previous
wrapping code would fail to compile when the library tried to expose it.
We have to tell <tt class="literal">class_&lt;World&gt;</tt> about the constructor
we want to expose instead.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
<span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
<tt class="literal">init&lt;std::string&gt;()</tt> exposes the constructor taking
in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").
</p>
<p>
We can expose additional constructors by passing more <tt class="literal">init&lt;...&gt;</tt>s
to the <tt class="literal">def()</tt> member function. Say for example we have
another World constructor taking in two doubles:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
<span class="special">;</span>
</pre>
<p>
On the other hand, if we do not wish to expose any constructors at all, we
may use <tt class="literal">no_init</tt> instead:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Abstract</span><span class="special">&gt;(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
</pre>
<p>
This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
method which always raises a Python RuntimeError exception.
</p>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.class_data_members"></a>Class Data Members</h3></div></div></div>
<p>
Data members may also be exposed to Python so that they can be accessed as
attributes of the corresponding Python class. Each data member that we wish
to be exposed may be regarded as <span class="bold"><b>read-only</b></span>
or <span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Var</span>
<span class="special">{</span>
<span class="identifier">Var</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">name</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">name</span><span class="special">),</span> <span class="identifier">value</span><span class="special">()</span> <span class="special">{}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="identifier">name</span><span class="special">;</span>
<span class="keyword">float</span> <span class="identifier">value</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
Our C++ <tt class="literal">Var</tt> class and its data members can be exposed
to Python:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Var</span><span class="special">&gt;(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">name</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def_readwrite</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span>
</pre>
<p>
Then, in Python, assuming we have placed our Var class inside the namespace
hello as we did before:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">Var</span><span class="special">(</span><span class="string">'pi'</span><span class="special">)</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span><span class="special">,</span> <span class="string">'is around'</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span>
<span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
</pre>
<p>
Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span>
while <tt class="literal">value</tt> is exposed as <span class="bold"><b>read-write</b></span>.
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">'e'</span> <span class="comment"># can't change name
</span><span class="identifier">Traceback</span> <span class="special">(</span><span class="identifier">most</span> <span class="identifier">recent</span> <span class="identifier">call</span> <span class="identifier">last</span><span class="special">):</span>
<span class="identifier">File</span> <span class="string">"&lt;stdin&gt;"</span><span class="special">,</span> <span class="identifier">line</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">in</span> #
<span class="identifier">AttributeError</span><span class="special">:</span> <span class="identifier">can</span>#<span class="identifier">t</span> <span class="identifier">set</span> <span class="identifier">attribute</span>
</pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.class_properties"></a>Class Properties</h3></div></div></div>
<p>
In C++, classes with public data members are usually frowned upon. Well designed
classes that take advantage of encapsulation hide the class' data members.
The only way to access the class' data is through access (getter/setter)
functions. Access functions expose class properties. Here's an example:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Num</span>
<span class="special">{</span>
<span class="identifier">Num</span><span class="special">();</span>
<span class="keyword">float</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">float</span> <span class="identifier">value</span><span class="special">);</span>
<span class="special">...</span>
<span class="special">};</span>
</pre>
<p>
However, in Python attribute access is fine; it doesn't neccessarily break
encapsulation to let users handle attributes directly, because the attributes
can just be a different syntax for a method call. Wrapping our <tt class="literal">Num</tt>
class using Boost.Python:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Num</span><span class="special">&gt;(</span><span class="string">"Num"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">set</span><span class="special">);</span>
</pre>
<p>
And at last, in Python:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">Num</span><span class="special">()</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span>
<span class="special">(</span><span class="number">3.14</span><span class="special">,</span> <span class="number">3.14</span><span class="special">)</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!
</span></pre>
<p>
Take note that the class property <tt class="literal">rovalue</tt> is exposed as
<span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
setter member function is not passed in:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
</pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.inheritance"></a>Inheritance</h3></div></div></div>
<p>
In the previous examples, we dealt with classes that are not polymorphic.
This is not often the case. Much of the time, we will be wrapping polymorphic
classes and class hierarchies related by inheritance. We will often have
to write Boost.Python wrappers for classes that are derived from abstract
base classes.
</p>
<p>
Consider this trivial inheritance structure:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span> <span class="special">{</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">();</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
</pre>
<p>
And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt>
object instances:
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">b</span><span class="special">(</span><span class="identifier">Base</span><span class="special">*);</span>
<span class="keyword">void</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">*);</span>
<span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span>
</pre>
<p>
We've seen how we can wrap the base class <tt class="literal">Base</tt>:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="comment">/*...*/</span>
<span class="special">;</span>
</pre>
<p>
Now we can inform Boost.Python of the inheritance relationship between <tt class="literal">Derived</tt>
and its base class <tt class="literal">Base</tt>. Thus:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"Derived"</span><span class="special">)</span>
<span class="comment">/*...*/</span>
<span class="special">;</span>
</pre>
<p>
Doing so, we get some things for free:
</p>
<div class="orderedlist"><ol type="1">
<li>
Derived automatically inherits all of Base's Python methods (wrapped C++
member functions)
</li>
<li>
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt>
objects which have been passed to Python via a pointer or reference to
<tt class="literal">Base</tt> can be passed where a pointer or reference to
<tt class="literal">Derived</tt> is expected.
</li>
</ol></div>
<p>
Now, we will expose the C++ free functions <tt class="literal">b</tt> and <tt class="literal">d</tt>
and <tt class="literal">factory</tt>:
</p>
<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span>
<span class="identifier">def</span><span class="special">(</span><span class="string">"d"</span><span class="special">,</span> <span class="identifier">d</span><span class="special">);</span>
<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
</pre>
<p>
Note that free function <tt class="literal">factory</tt> is being used to generate
new instances of class <tt class="literal">Derived</tt>. In such cases, we use
<tt class="literal">return_value_policy&lt;manage_new_object&gt;</tt> to instruct
Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
in a new Python <tt class="literal">Base</tt> object until the the Python object
is destroyed. We will see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
policies</a> later.
</p>
<pre class="programlisting"><span class="comment">// Tell Python to take ownership of factory's result
</span><span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">,</span>
<span class="identifier">return_value_policy</span><span class="special">&lt;</span><span class="identifier">manage_new_object</span><span class="special">&gt;());</span>
</pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div>
<p>
In this section, we will learn how to make functions behave polymorphically
through virtual functions. Continuing our example, let us add a virtual function
to our <tt class="literal">Base</tt> class:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span>
<span class="special">{</span>
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
One of the goals of Boost.Python is to be minimally intrusive on an existing
C++ design. In principle, it should be possible to expose the interface for
a 3rd party library without changing it. It is not ideal to add anything
to our class <tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when
you have a virtual function that's going to be overridden in Python and called
polymorphically <span class="bold"><b>from C++</b></span>, we'll need to
add some scaffoldings to make things work properly. What we'll do is write
a class wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt>
that will unintrusively hook into the virtual functions so that a Python
override may be called:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">)();</span>
<span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>,
we also multiply- inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
the job of wrapping classes that are meant to overridden in Python, easier.
</p>
<div class="sidebar">
<p>
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span>
</p>
<p>
If you are using Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt> as:
</p>
<p>
<tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
</p>
</div>
<p>
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt>
in effect calls the corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.
</p>
<p>
Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">pure_virtual</span><span class="special">(&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span>
<span class="special">;</span>
</pre>
<p>
<tt class="computeroutput"><span class="identifier">pure_virtual</span></tt> signals Boost.Python
that the function <tt class="computeroutput"><span class="identifier">f</span></tt> is a
pure virtual function.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top">
<p>
<span class="bold"><b>member function and methods</b></span>
</p>
<p>
Python, like many object oriented languages uses the term <span class="bold"><b>methods</b></span>.
Methods correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
</p>
</td></tr>
</table></div>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
<p>
We've seen in the previous section how classes with pure virtual functions
are wrapped using Boost.Python's <a href="../../../../v2/wrapper.html" target="_top">class
wrapper</a> facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual
functions instead, the mechanism is a bit different.
</p>
<p>
Recall that in the <a href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous
section</a>, we wrapped a class with a pure virtual function that we then
implemented in C++, or Python classes derived from it. Our base class:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span>
<span class="special">{</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
had a pure virtual function <tt class="literal">f</tt>. If, however, its member
function <tt class="literal">f</tt> was not declared as pure virtual:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span>
<span class="special">{</span>
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
We wrap it this way:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">override</span> <span class="identifier">f</span> <span class="special">=</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">))</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">();</span> <span class="comment">// *note*
</span> <span class="keyword">return</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">default_f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span> <span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now,
we have to check if there is an override for <tt class="computeroutput"><span class="identifier">f</span></tt>.
If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.
</p>
<div class="sidebar">
<p>
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span>
</p>
<p>
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:
</p>
<p>
<tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special">&lt;</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*&gt;(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
</p>
</div>
<p>
Finally, exposing:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span>
<span class="special">;</span>
</pre>
<p>
Take note that we expose both <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
to its default implementation <tt class="literal">default_f</tt>. There's a special
<tt class="literal">def</tt> function for this purpose.
</p>
<p>
In Python, the results would be as expected:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span> <span class="special">=</span> <span class="identifier">Base</span><span class="special">()</span>
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">class</span> <span class="identifier">Derived</span><span class="special">(</span><span class="identifier">Base</span><span class="special">):</span>
<span class="special">...</span> <span class="keyword">def</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
<span class="special">...</span> <span class="keyword">return</span> <span class="number">42</span>
<span class="special">...</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
</pre>
<p>
Calling <tt class="literal">base.f()</tt>:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
<span class="number">0</span>
</pre>
<p>
Calling <tt class="literal">derived.f()</tt>:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
<span class="number">42</span>
</pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
<a name="class_operators_special_functions.python_operators"></a><h2>
<a name="id462548"></a>
Python Operators
</h2>
<p>
C is well known for the abundance of operators. C++ extends this to the extremes
by allowing operator overloading. Boost.Python takes advantage of this and
makes it easy to wrap C++ operator-powered classes.
</p>
<p>
Consider a file position class <tt class="literal">FilePos</tt> and a set of operators
that take on FilePos instances:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">FilePos</span> <span class="special">{</span> <span class="comment">/*...*/</span> <span class="special">};</span>
<span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
<span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
<span class="keyword">int</span> <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
<span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
<span class="identifier">FilePos</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">+=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">);</span>
<span class="identifier">FilePos</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">-=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">);</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
</pre>
<p>
The class and the various operators can be mapped to Python rather easily
and intuitively:
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">FilePos</span><span class="special">&gt;(</span><span class="string">"FilePos"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __add__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="keyword">int</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __radd__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __sub__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __sub__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+=</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __iadd__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-=</span> <span class="identifier">other</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">&lt;</span> <span class="identifier">self</span><span class="special">);</span> <span class="comment">// __lt__
</span></pre>
<p>
The code snippet above is very clear and needs almost no explanation at all.
It is virtually the same as the operators' signatures. Just take note that
<tt class="literal">self</tt> refers to FilePos object. Also, not every class
<tt class="literal">T</tt> that you might need to interact with in an operator
expression is (cheaply) default-constructible. You can use <tt class="literal">other&lt;T&gt;()</tt>
in place of an actual <tt class="literal">T</tt> instance when writing "self
expressions".
</p>
<a name="class_operators_special_functions.special_methods"></a><h2>
<a name="id463302"></a>
Special Methods
</h2>
<p>
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python
supports all of the standard special method names supported by real Python
class instances. A similar set of intuitive interfaces can also be used to
wrap C++ functions that correspond to these Python <span class="emphasis"><em>special functions</em></span>.
Example:
</p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">Rational</span>
<span class="special">{</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">operator</span> <span class="keyword">double</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> <span class="special">};</span>
<span class="identifier">Rational</span> <span class="identifier">pow</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">,</span> <span class="identifier">Rational</span><span class="special">);</span>
<span class="identifier">Rational</span> <span class="identifier">abs</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">);</span>
<span class="identifier">ostream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">ostream</span><span class="special">&amp;,</span><span class="identifier">Rational</span><span class="special">);</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;(</span><span class="string">"Rational"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">float_</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __float__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">pow</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">other</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;))</span> <span class="comment">// __pow__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">abs</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __abs__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __str__
</span> <span class="special">;</span>
</pre>
<p>
Need we say more?
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top"><p>
What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt>? Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt> requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt> to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt>
is used by the method defined by <tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.
</p></td></tr>
</table></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="hello.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -1,589 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Functions</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="exposing.html" title=" Exposing Classes">
<link rel="next" href="object.html" title=" Object Interface">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.functions"></a>Functions</h2></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="functions.html#python.call_policies">Call Policies</a></span></dt>
<dt><span class="section"><a href="functions.html#python.overloading">Overloading</a></span></dt>
<dt><span class="section"><a href="functions.html#python.default_arguments">Default Arguments</a></span></dt>
<dt><span class="section"><a href="functions.html#python.auto_overloading">Auto-Overloading</a></span></dt>
</dl></div>
<p>
In this chapter, we'll look at Boost.Python powered functions in closer detail.
We will see some facilities to make exposing C++ functions to Python safe from
potential pifalls such as dangling pointers and references. We will also see
facilities that will make it even easier for us to expose C++ functions that
take advantage of C++ features such as overloading and default arguments.
</p>
<div class="blockquote"><blockquote class="blockquote">
<p>
</p>
<p>
<span class="emphasis"><em>Read on...</em></span>
</p>
<p>
</p>
</blockquote></div>
<p>
But before you do, you might want to fire up Python 2.2 or later and type
<tt class="literal">&gt;&gt;&gt; import this</tt>.
</p>
<pre class="programlisting">&gt;&gt;&gt; import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than <span class="bold"><b>right</b></span> now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
</pre>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.call_policies"></a>Call Policies</h3></div></div></div>
<p>
In C++, we often deal with arguments and return types such as pointers and
references. Such primitive types are rather, ummmm, low level and they really
don't tell us much. At the very least, we don't know the owner of the pointer
or the referenced object. No wonder languages such as Java and Python never
deal with such low level entities. In C++, it's usually considered a good
practice to use smart pointers which exactly describe ownership semantics.
Still, even good C++ interfaces use raw references and pointers sometimes,
so Boost.Python must deal with them. To do this, it may need your help. Consider
the following C++ function:
</p>
<pre class="programlisting"><span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">);</span>
</pre>
<p>
How should the library wrap this function? A naive approach builds a Python
X object around result reference. This strategy might or might not work out.
Here's an example where it didn't
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> <span class="preprocessor"># x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">y</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span>
</pre>
<p>
What's the problem?
</p>
<p>
Well, what if f() was implemented as shown below:
</p>
<pre class="programlisting"><span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">y</span><span class="special">.</span><span class="identifier">z</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
The problem is that the lifetime of result X&amp; is tied to the lifetime
of y, because the f() returns a reference to a member of the y object. This
idiom is is not uncommon and perfectly acceptable in the context of C++.
However, Python users should not be able to crash the system just by using
our C++ interface. In this case deleting y will invalidate the reference
to X. We have a dangling reference.
</p>
<p>
Here's what's happening:
</p>
<div class="orderedlist"><ol type="1">
<li>
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
and a pointer to <tt class="literal">z</tt>
</li>
<li>
A reference to <tt class="literal">y.x</tt> is returned
</li>
<li>
<tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference
</li>
<li>
<tt class="literal">x.some_method()</tt> is called
</li>
<li><span class="bold"><b>BOOM!</b></span></li>
</ol></div>
<p>
We could copy result into a new object:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">).</span><span class="identifier">set</span><span class="special">(</span><span class="number">42</span><span class="special">)</span> <span class="comment"># Result disappears
</span><span class="special">&gt;&gt;&gt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="comment"># No crash, but still bad
</span><span class="number">3.14</span>
</pre>
<p>
This is not really our intent of our C++ interface. We've broken our promise
that the Python interface should reflect the C++ interface as closely as
possible.
</p>
<p>
Our problems do not end there. Suppose Y is implemented as follows:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Y</span>
<span class="special">{</span>
<span class="identifier">X</span> <span class="identifier">x</span><span class="special">;</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">z_value</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">z</span><span class="special">-&gt;</span><span class="identifier">value</span><span class="special">();</span> <span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
Notice that the data member <tt class="literal">z</tt> is held by class Y using
a raw pointer. Now we have a potential dangling pointer problem inside Y:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> <span class="preprocessor"># y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">z</span> <span class="preprocessor"># Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span>
</pre>
<p>
For reference, here's the implementation of <tt class="literal">f</tt> again:
</p>
<pre class="programlisting"><span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">y</span><span class="special">.</span><span class="identifier">z</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
Here's what's happening:
</p>
<div class="orderedlist"><ol type="1">
<li>
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
and a pointer to <tt class="literal">z</tt>
</li>
<li>
A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt>
</li>
<li>
A reference to <tt class="literal">y.x</tt> is returned
</li>
<li>
<tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer
</li>
<li>
<tt class="literal">y.z_value()</tt> is called
</li>
<li>
<tt class="literal">z-&gt;value()</tt> is called
</li>
<li><span class="bold"><b>BOOM!</b></span></li>
</ol></div>
<a name="call_policies.call_policies"></a><h2>
<a name="id465291"></a>
Call Policies
</h2>
<p>
Call Policies may be used in situations such as the example detailed above.
In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
are our friends:
</p>
<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span>
<span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span>
<span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="special">&gt;());</span>
</pre>
<p>
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
ask?
</p>
<pre class="programlisting"><span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span>
</pre>
<p>
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&amp;
y</tt>, is the owner of the returned reference: <tt class="literal">X&amp;</tt>.
The "<tt class="literal">1</tt>" simply specifies the first argument.
In short: "return an internal reference <tt class="literal">X&amp;</tt> owned
by the 1st argument <tt class="literal">Y&amp; y</tt>".
</p>
<pre class="programlisting"><span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span>
</pre>
<p>
Informs Boost.Python that the lifetime of the argument indicated by ward
(i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&amp;
y</tt>).
</p>
<p>
It is also important to note that we have defined two policies above. Two
or more policies can be composed by chaining. Here's the general syntax:
</p>
<pre class="programlisting"><span class="identifier">policy1</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span>
<span class="identifier">policy2</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span>
<span class="identifier">policy3</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span>
</pre>
<p>
Here is the list of predefined call policies. A complete reference detailing
these can be found <a href="../../../../v2/reference.html#models_of_call_policies" target="_top">here</a>.
</p>
<div class="itemizedlist"><ul type="disc">
<li>
<span class="bold"><b>with_custodian_and_ward</b></span>: Ties lifetimes
of the arguments
</li>
<li>
<span class="bold"><b>with_custodian_and_ward_postcall</b></span>: Ties
lifetimes of the arguments and results
</li>
<li>
<span class="bold"><b>return_internal_reference</b></span>: Ties lifetime
of one argument to that of result
</li>
<li>
<span class="bold"><b>return_value_policy&lt;T&gt; with T one of:</b></span><div class="itemizedlist"><ul type="circle">
<li>
<span class="bold"><b>reference_existing_object</b></span>: naive (dangerous)
approach
</li>
<li>
<span class="bold"><b>copy_const_reference</b></span>: Boost.Python
v1 approach
</li>
<li>
<span class="bold"><b>copy_non_const_reference</b></span>:
</li>
<li>
<span class="bold"><b>manage_new_object</b></span>: Adopt a pointer
and hold the instance
</li>
</ul></div>
</li>
</ul></div>
<div class="sidebar">
<p>
<span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><b>Remember the Zen, Luke:</b></span>
</p>
<p>
"Explicit is better than implicit"
</p>
<p>
"In the face of ambiguity, refuse the temptation to guess"
</p>
</div>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.overloading"></a>Overloading</h3></div></div></div>
<p>
The following illustrates a scheme for manually wrapping an overloaded member
functions. Of course, the same technique can be applied to wrapping overloaded
non-member functions.
</p>
<p>
We have here our C++ class:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span>
<span class="special">{</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">b</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">c</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">;</span>
<span class="special">};</span>
<span class="special">};</span>
</pre>
<p>
Class X has 4 overloaded functions. We will start by introducing some member
function pointer variables:
</p>
<pre class="programlisting"><span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx3</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx4</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
</pre>
<p>
With these in hand, we can proceed to define and wrap this for Python:
</p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx3</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx4</span><span class="special">)</span>
</pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
<p>
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
pointers carry no default argument info. Take a function <tt class="literal">f</tt>
with default arguments:
</p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span> <span class="special">=</span> <span class="number">3.14</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="special">=</span> <span class="string">"hello"</span><span class="special">);</span>
</pre>
<p>
But the type of a pointer to the function <tt class="literal">f</tt> has no information
about its default arguments:
</p>
<pre class="programlisting"><span class="keyword">int</span><span class="special">(*</span><span class="identifier">g</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*)</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">;</span> <span class="comment">// defaults lost!
</span></pre>
<p>
When we pass this function pointer to the <tt class="literal">def</tt> function,
there is no way to retrieve the default arguments:
</p>
<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// defaults lost!
</span></pre>
<p>
Because of this, when wrapping C++ code, we had to resort to manual wrapping
as outlined in the <a href="functions.html#python.overloading" title="Overloading">previous section</a>,
or writing thin wrappers:
</p>
<pre class="programlisting"><span class="comment">// write "thin wrappers"
</span><span class="keyword">int</span> <span class="identifier">f1</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">f2</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">);</span> <span class="special">}</span>
<span class="comment">/*...*/</span>
<span class="comment">// in module init
</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// all arguments
</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f2</span><span class="special">);</span> <span class="comment">// two arguments
</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f1</span><span class="special">);</span> <span class="comment">// one argument
</span></pre>
<p>
When you want to wrap functions (or member functions) that either:
</p>
<div class="itemizedlist"><ul type="disc">
<li>
have default arguments, or
</li>
<li>
are overloaded with a common sequence of initial arguments
</li>
</ul></div>
<a name="default_arguments.boost_python_function_overloads"></a><h2>
<a name="id467317"></a>
BOOST_PYTHON_FUNCTION_OVERLOADS
</h2>
<p>
Boost.Python now has a way to make it easier. For instance, given a function:
</p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">c</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">3</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
</pre>
<p>
The macro invocation:
</p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
</pre>
<p>
will automatically create the thin wrappers for us. This macro will create
a class <tt class="literal">foo_overloads</tt> that can be passed on to <tt class="literal">def(...)</tt>.
The third and fourth macro argument are the minimum arguments and maximum
arguments, respectively. In our <tt class="literal">foo</tt> function the minimum
number of arguments is 1 and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
function will automatically add all the foo variants for us:
</p>
<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span>
</pre>
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
<a name="id467632"></a>
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
</h2>
<p>
Objects here, objects there, objects here there everywhere. More frequently
than anything else, we need to expose member functions of our classes to
Python. Then again, we have the same inconveniences as before when default
arguments or overloads with a common sequence of initial arguments come into
play. Another macro is provided to make this a breeze.
</p>
<p>
Like <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
may be used to automatically create the thin wrappers for wrapping member
functions. Let's have an example:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">george</span>
<span class="special">{</span>
<span class="keyword">void</span>
<span class="identifier">wack_em</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span> <span class="special">=</span> <span class="char">'x'</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
The macro invocation:
</p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">george_overloads</span><span class="special">,</span> <span class="identifier">wack_em</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
</pre>
<p>
will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt>
member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
the third and fourth macro argument). The thin wrappers are all enclosed
in a class named <tt class="literal">george_overloads</tt> that can then be used
as an argument to <tt class="literal">def(...)</tt>:
</p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"wack_em"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span>
</pre>
<p>
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads
reference</a> for details.
</p>
<a name="default_arguments.init_and_optional"></a><h2>
<a name="id467992"></a>
init and optional
</h2>
<p>
A similar facility is provided for class constructors, again, with default
arguments or a sequence of overloads. Remember <tt class="literal">init&lt;...&gt;</tt>?
For example, given a class X with a constructor:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span>
<span class="special">{</span>
<span class="identifier">X</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">b</span> <span class="special">=</span> <span class="char">'D'</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">c</span> <span class="special">=</span> <span class="string">"constructor"</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">0.0</span><span class="special">);</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
</pre>
<p>
You can easily add this constructor to Boost.Python in one shot:
</p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
</pre>
<p>
Notice the use of <tt class="literal">init&lt;...&gt;</tt> and <tt class="literal">optional&lt;...&gt;</tt>
to signify the default (optional arguments).
</p>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
<p>
It was mentioned in passing in the previous section that <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>
and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> can also be
used for overloaded functions and member functions with a common sequence
of initial arguments. Here is an example:
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
<span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
</pre>
<p>
Like in the previous section, we can generate thin wrappers for these overloaded
functions in one-shot:
</p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
</pre>
<p>
Then...
</p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="special">(</span><span class="keyword">void</span><span class="special">(*)(</span><span class="keyword">bool</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">))</span><span class="number">0</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span>
</pre>
<p>
Notice though that we have a situation now where we have a minimum of zero
(0) arguments and a maximum of 3 arguments.
</p>
<a name="auto_overloading.manual_wrapping"></a><h2>
<a name="id468767"></a>
Manual Wrapping
</h2>
<p>
It is important to emphasize however that <span class="bold"><b>the overloaded
functions must have a common sequence of initial arguments</b></span>. Otherwise,
our scheme above will not work. If this is not the case, we have to wrap
our functions <a href="functions.html#python.overloading" title="Overloading">manually</a>.
</p>
<p>
Actually, we can mix and match manual wrapping of overloaded functions and
automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
and its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following
up on our example presented in the section <a href="functions.html#python.overloading" title="Overloading">on
overloading</a>, since the first 4 overload functins have a common sequence
of initial arguments, we can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
to automatically wrap the first three of the <tt class="literal">def</tt>s and
manually wrap just the last. Here's how we'll do this:
</p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">xf_overloads</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
</pre>
<p>
Create a member function pointers as above for both X::f overloads:
</p>
<pre class="programlisting"><span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
</pre>
<p>
Then...
</p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">,</span> <span class="identifier">xf_overloads</span><span class="special">());</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -1,218 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title> Building Hello World</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="../index.html" title="Chapter 1. python 1.0">
<link rel="next" href="exposing.html" title=" Exposing Classes">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
<a name="hello.from_start_to_finish"></a><h2>
<a name="id388718"></a>
From Start To Finish
</h2>
<p>
Now the first thing you'd want to do is to build the Hello World module and
try it for yourself in Python. In this section, we will outline the steps necessary
to achieve that. We will use the build tool that comes bundled with every boost
distribution: <span class="bold"><b>bjam</b></span>.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top">
<p>
<span class="bold"><b>Building without bjam</b></span>
</p>
<p>
Besides bjam, there are of course other ways to get your module built. What's
written here should not be taken as "the one and only way". There
are of course other build tools apart from <tt class="literal">bjam</tt>.
</p>
<p>
Take note however that the preferred build tool for Boost.Python is bjam.
There are so many ways to set up the build incorrectly. Experience shows
that 90% of the "I can't build Boost.Python" problems come from
people who had to use a different tool.
</p>
</td></tr>
</table></div>
<p>
We will skip over the details. Our objective will be to simply create the hello
world module and run it in Python. For a complete reference to building Boost.Python,
check out: <a href="../../../../building.html" target="_top">building.html</a>. After
this brief <span class="emphasis"><em>bjam</em></span> tutorial, we should have built the DLLs
and run a python program using the extension.
</p>
<p>
The tutorial example can be found in the directory: <tt class="literal">libs/python/example/tutorial</tt>.
There, you can find:
</p>
<div class="itemizedlist"><ul type="disc">
<li>
hello.cpp
</li>
<li>
hello.py
</li>
<li>
Jamroot
</li>
</ul></div>
<p>
The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The
<tt class="literal">Jamroot</tt> is a minimalist <span class="emphasis"><em>bjam</em></span> script
that builds the DLLs for us. Finally, <tt class="literal">hello.py</tt> is our Python
program that uses the extension in <tt class="literal">hello.cpp</tt>.
</p>
<p>
Before anything else, you should have the bjam executable in your boost directory
or somewhere in your path such that <tt class="literal">bjam</tt> can be executed
in the command line. Pre-built Boost.Jam executables are available for most
platforms. The complete list of Bjam executables can be found <a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.
</p>
<a name="hello.let_s_jam_"></a><h2>
<a name="id387300"></a>
Let's Jam!
</h2>
<p>
<span class="inlinemediaobject"><img src="../images/jam.png" alt="jam"></span>
</p>
<p>
<a href="../../../../../example/tutorial/Jamroot" target="_top">Here</a> is our minimalist
Jamroot file. Simply copy the file and tweak <tt class="literal">use-project boost</tt>
to where your boost root directory is and your OK.
</p>
<p>
The comments contained in the Jamrules file above should be sufficient to get
you going.
</p>
<a name="hello.running_bjam"></a><h2>
<a name="id387357"></a>
Running bjam
</h2>
<p>
<span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
interpreter.
</p>
<div class="blockquote"><blockquote class="blockquote">
<p>
</p>
<p>
Start it up.
</p>
<p>
</p>
</blockquote></div>
<p>
A file called user-config.jam in your home directory is used to configure your
tools. In Windows, your home directory can be found by typing:
</p>
<pre class="programlisting">ECHO %HOMEDRIVE%%HOMEPATH%
</pre>
<p>
into a command prompt window. Your file should at least have the rules for
your compiler and your python installation. A specific example of this on Windows
would be:
</p>
<pre class="programlisting"># MSVC configuration
using msvc : 8.0 ;
# Python configuration
using python : 2.4 : C:/dev/tools<span class="emphasis"><em>Python</em></span> ;
</pre>
<p>
The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools.
The second rule provides information on Python, its version and where it is
located. The above assumes that the Python installation is in <tt class="literal">C:/dev/tools/Python/</tt>.
If you have one fairly "standard" python installation for your platform,
you might not need to do this.
</p>
<p>
Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt>
where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamroot"</tt>
is situated.
</p>
<p>
Finally:
</p>
<pre class="programlisting"><span class="identifier">bjam</span>
</pre>
<p>
It should be building now:
</p>
<pre class="programlisting">cd C:\dev\boost\libs\python\example\tutorial
bjam
...patience...
...found 1101 targets...
...updating 35 targets...
</pre>
<p>
And so on... Finally:
</p>
<pre class="programlisting">Creating library <span class="emphasis"><em>path-to-boost_python.dll</em></span>
Creating library <span class="emphasis"><em>path-to-'''hello_ext'''.exp</em></span>
**passed** ... hello.test
...updated 35 targets...
</pre>
<p>
Or something similar. If all is well, you should now have built the DLLs and
run the Python program.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top"><p>
Starting from Boost 1.35, bjam erases the generated executables (e.g. pyd
file) after the test has concluded to conserve disk space. To keep bjam from
doing that, pass --preserve-test-targets to bjam.
</p></td></tr>
</table></div>
<div class="blockquote"><blockquote class="blockquote">
<p>
</p>
<p>
<span class="bold"><b>There you go... Have fun!</b></span>
</p>
<p>
</p>
</blockquote></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -1,199 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Iterators</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="embedding.html" title="Embedding">
<link rel="next" href="exception.html" title=" Exception Translation">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.iterators"></a>Iterators</h2></div></div></div>
<p>
In C++, and STL in particular, we see iterators everywhere. Python also has
iterators, but these are two very different beasts.
</p>
<p>
<span class="bold"><b>C++ iterators:</b></span>
</p>
<div class="itemizedlist"><ul type="disc">
<li>
C++ has 5 type categories (random-access, bidirectional, forward, input,
output)
</li>
<li>
There are 2 Operation categories: reposition, access
</li>
<li>
A pair of iterators is needed to represent a (first/last) range.
</li>
</ul></div>
<p>
<span class="bold"><b>Python Iterators:</b></span>
</p>
<div class="itemizedlist"><ul type="disc">
<li>
1 category (forward)
</li>
<li>
1 operation category (next())
</li>
<li>
Raises StopIteration exception at end
</li>
</ul></div>
<p>
The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y
in x...</b></span></tt> is as follows:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">__iter__</span><span class="special">()</span> <span class="comment"># get iterator
</span><span class="keyword">try</span><span class="special">:</span>
<span class="keyword">while</span> <span class="number">1</span><span class="special">:</span>
<span class="identifier">y</span> <span class="special">=</span> <span class="identifier">iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">()</span> <span class="comment"># get each item
</span> <span class="special">...</span> <span class="comment"># process y
</span><span class="keyword">except</span> <span class="identifier">StopIteration</span><span class="special">:</span> <span class="keyword">pass</span> <span class="comment"># iterator exhausted
</span></pre>
<p>
Boost.Python provides some mechanisms to make C++ iterators play along nicely
as Python iterators. What we need to do is to produce appropriate <tt class="computeroutput"><span class="identifier">__iter__</span></tt> function from C++ iterators that
is compatible with the Python iteration protocol. For example:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">get_iterator</span> <span class="special">=</span> <span class="identifier">iterator</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;();</span>
<span class="identifier">object</span> <span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">get_iterator</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">first</span> <span class="special">=</span> <span class="identifier">iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">();</span>
</pre>
<p>
Or for use in class_&lt;&gt;:
</p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"__iter__"</span><span class="special">,</span> <span class="identifier">iterator</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
</pre>
<p>
<span class="bold"><b>range</b></span>
</p>
<p>
We can create a Python savvy iterator using the range function:
</p>
<div class="itemizedlist"><ul type="disc">
<li>
range(start, finish)
</li>
<li>
range&lt;Policies,Target&gt;(start, finish)
</li>
</ul></div>
<p>
Here, start/finish may be one of:
</p>
<div class="itemizedlist"><ul type="disc">
<li>
member data pointers
</li>
<li>
member function pointers
</li>
<li>
adaptable function object (use Target parameter)
</li>
</ul></div>
<p>
<span class="bold"><b>iterator</b></span>
</p>
<div class="itemizedlist"><ul type="disc"><li>
iterator&lt;T, Policies&gt;()
</li></ul></div>
<p>
Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
calls <tt class="literal">range</tt> with &amp;T::begin, &amp;T::end.
</p>
<p>
Let's put this into action... Here's an example from some hypothetical bogon
Particle accelerator code:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">f</span> <span class="special">=</span> <span class="identifier">Field</span><span class="special">()</span>
<span class="keyword">for</span> <span class="identifier">x</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">pions</span><span class="special">:</span>
<span class="identifier">smash</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span>
<span class="keyword">for</span> <span class="identifier">y</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">bogons</span><span class="special">:</span>
<span class="identifier">count</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span>
</pre>
<p>
Now, our C++ Wrapper:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;(</span><span class="string">"Field"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"pions"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_end</span><span class="special">))</span>
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"bogons"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
</pre>
<p>
<span class="bold"><b>stl_input_iterator</b></span>
</p>
<p>
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
we wish to go the other way, though: we'd like to pass a Python sequence to
an STL algorithm or use it to initialize an STL container. We need to make
a Python iterator look like an STL iterator. For that, we use <tt class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special">&lt;&gt;</span></tt>.
Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">list_assign</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">o</span><span class="special">)</span> <span class="special">{</span>
<span class="comment">// Turn a Python sequence into an STL input range
</span> <span class="identifier">stl_input_iterator</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">o</span><span class="special">),</span> <span class="identifier">end</span><span class="special">;</span>
<span class="identifier">l</span><span class="special">.</span><span class="identifier">assign</span><span class="special">(</span><span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">// Part of the wrapper for list&lt;int&gt;
</span><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"list_int"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"assign"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">list_assign</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;)</span>
<span class="comment">// ...
</span> <span class="special">;</span>
</pre>
<p>
Now in Python, we can assign any integer sequence to <tt class="computeroutput"><span class="identifier">list_int</span></tt>
objects:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">x</span> <span class="special">=</span> <span class="identifier">list_int</span><span class="special">();</span>
<span class="identifier">x</span><span class="special">.</span><span class="identifier">assign</span><span class="special">([</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">])</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -1,338 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title> Object Interface</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="functions.html" title="Functions">
<link rel="next" href="embedding.html" title="Embedding">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="functions.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.object"></a> Object Interface</h2></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="object.html#python.basic_interface">Basic Interface</a></span></dt>
<dt><span class="section"><a href="object.html#python.derived_object_types">Derived Object types</a></span></dt>
<dt><span class="section"><a href="object.html#python.extracting_c___objects">Extracting C++ objects</a></span></dt>
<dt><span class="section"><a href="object.html#python.enums">Enums</a></span></dt>
</dl></div>
<p>
Python is dynamically typed, unlike C++ which is statically typed. Python variables
may hold an integer, a float, list, dict, tuple, str, long etc., among other
things. In the viewpoint of Boost.Python and C++, these Pythonic variables
are just instances of class <tt class="literal">object</tt>. We will see in this
chapter how to deal with Python objects.
</p>
<p>
As mentioned, one of the goals of Boost.Python is to provide a bidirectional
mapping between C++ and Python while maintaining the Python feel. Boost.Python
C++ <tt class="literal">object</tt>s are as close as possible to Python. This should
minimize the learning curve significantly.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/python.png" alt="python"></span>
</p>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
<p>
Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the
intricacies of dealing with <tt class="literal">PyObject</tt>s such as managing
reference counting are handled by the <tt class="literal">object</tt> class. C++
object interoperability is seamless. Boost.Python C++ <tt class="literal">object</tt>s
can in fact be explicitly constructed from any C++ object.
</p>
<p>
To illustrate, this Python code snippet:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">def</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">):</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">y</span> <span class="special">==</span> <span class="string">'foo'</span><span class="special">):</span>
<span class="identifier">x</span><span class="special">[</span><span class="number">3</span><span class="special">:</span><span class="number">7</span><span class="special">]</span> <span class="special">=</span> <span class="string">'bar'</span>
<span class="keyword">else</span><span class="special">:</span>
<span class="identifier">x</span><span class="special">.</span><span class="identifier">items</span> <span class="special">+=</span> <span class="identifier">y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span> <span class="identifier">x</span><span class="special">)</span>
<span class="keyword">return</span> <span class="identifier">x</span>
<span class="keyword">def</span> <span class="identifier">getfunc</span><span class="special">():</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">;</span>
</pre>
<p>
Can be rewritten in C++ using Boost.Python facilities this way:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">object</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">y</span> <span class="special">==</span> <span class="string">"foo"</span><span class="special">)</span>
<span class="identifier">x</span><span class="special">.</span><span class="identifier">slice</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">7</span><span class="special">)</span> <span class="special">=</span> <span class="string">"bar"</span><span class="special">;</span>
<span class="keyword">else</span>
<span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"items"</span><span class="special">)</span> <span class="special">+=</span> <span class="identifier">y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">x</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">object</span> <span class="identifier">getfunc</span><span class="special">()</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">object</span><span class="special">(</span><span class="identifier">f</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
Apart from cosmetic differences due to the fact that we are writing the code
in C++, the look and feel should be immediately apparent to the Python coder.
</p>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
<p>
Boost.Python comes with a set of derived <tt class="literal">object</tt> types
corresponding to that of Python's:
</p>
<div class="itemizedlist"><ul type="disc">
<li>
list
</li>
<li>
dict
</li>
<li>
tuple
</li>
<li>
str
</li>
<li>
long_
</li>
<li>
enum
</li>
</ul></div>
<p>
These derived <tt class="literal">object</tt> types act like real Python types.
For instance:
</p>
<pre class="programlisting"><span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">==&gt;</span> <span class="string">"1"</span>
</pre>
<p>
Wherever appropriate, a particular derived <tt class="literal">object</tt> has
corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
has a <tt class="literal">keys()</tt> method:
</p>
<pre class="programlisting"><span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span>
</pre>
<p>
<tt class="literal">make_tuple</tt> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
Example:
</p>
<pre class="programlisting"><span class="identifier">make_tuple</span><span class="special">(</span><span class="number">123</span><span class="special">,</span> <span class="char">'D'</span><span class="special">,</span> <span class="string">"Hello, World"</span><span class="special">,</span> <span class="number">0.0</span><span class="special">);</span>
</pre>
<p>
In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments
to functions, subtype matching is required. For example, when a function
<tt class="literal">f</tt>, as declared below, is wrapped, it will only accept
instances of Python's <tt class="literal">str</tt> type and subtypes.
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">object</span> <span class="identifier">n2</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"upper"</span><span class="special">)();</span> <span class="comment">// NAME = name.upper()
</span> <span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span> <span class="comment">// better
</span> <span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
In finer detail:
</p>
<pre class="programlisting"><span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span>
</pre>
<p>
Illustrates that we provide versions of the str type's methods as C++ member
functions.
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
</pre>
<p>
Demonstrates that you can write the C++ equivalent of <tt class="literal">"format"
% x,y,z</tt> in Python, which is useful since there's no easy way to
do that in std C++.
</p>
<div class="sidebar"><p>
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>Beware</b></span> the common pitfall
of forgetting that the constructors of most of Python's mutable types make
copies, just as in Python.
</p></div>
<p>
Python:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">dict</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special">)</span> <span class="comment"># copies x.__dict__
</span><span class="special">&gt;&gt;&gt;</span> <span class="identifier">d</span><span class="special">[</span><span class="string">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span> <span class="comment"># modifies the copy
</span></pre>
<p>
C++:
</p>
<pre class="programlisting"><span class="identifier">dict</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span> <span class="comment">// copies x.__dict__
</span><span class="identifier">d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies the copy
</span></pre>
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
<a name="id470756"></a>
class_&lt;T&gt; as objects
</h2>
<p>
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_&lt;T&gt;</tt>
may also be one of these types! The following code snippet wraps the class
(type) object.
</p>
<p>
We can use this to create wrapped instances. Example:
</p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">vec345</span> <span class="special">=</span> <span class="special">(</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&gt;(</span><span class="string">"Vec2"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"length"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">length</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"angle"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">angle</span><span class="special">)</span>
<span class="special">)(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">4.0</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">vec345</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">)</span> <span class="special">==</span> <span class="number">5.0</span><span class="special">);</span>
</pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
<p>
At some point, we will need to get C++ values out of object instances. This
can be achieved with the <tt class="literal">extract&lt;T&gt;</tt> function. Consider
the following:
</p>
<pre class="programlisting"><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">);</span> <span class="comment">// compile error
</span></pre>
<p>
In the code above, we got a compiler error because Boost.Python <tt class="literal">object</tt>
can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what
we wanted to do above can be achieved by writing:
</p>
<pre class="programlisting"><span class="keyword">double</span> <span class="identifier">l</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">));</span>
<span class="identifier">Vec2</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;(</span><span class="identifier">o</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">l</span> <span class="special">==</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">length</span><span class="special">());</span>
</pre>
<p>
The first line attempts to extract the "length" attribute of the
Boost.Python <tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span>
the <tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt>.
</p>
<p>
Take note that we said "attempt to" above. What if the Boost.Python
<tt class="literal">object</tt> does not really hold a <tt class="literal">Vec2</tt>
type? This is certainly a possibility considering the dynamic nature of Python
<tt class="literal">object</tt>s. To be on the safe side, if the C++ type can't
be extracted, an appropriate exception is thrown. To avoid an exception,
we need to test for extractibility:
</p>
<pre class="programlisting"><span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;</span> <span class="identifier">x</span><span class="special">(</span><span class="identifier">o</span><span class="special">);</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">check</span><span class="special">())</span> <span class="special">{</span>
<span class="identifier">Vec2</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
</pre>
<p>
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <tt class="literal">extract&lt;T&gt;</tt>
facility in fact solves the mutable copying problem:
</p>
<pre class="programlisting"><span class="identifier">dict</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">dict</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span>
<span class="identifier">d</span><span class="special">[</span><span class="string">"whatever"</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies x.__dict__ !
</span></pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.enums"></a>Enums</h3></div></div></div>
<p>
Boost.Python has a nifty facility to capture and wrap C++ enums. While Python
has no <tt class="literal">enum</tt> type, we'll often want to expose our C++ enums
to Python as an <tt class="literal">int</tt>. Boost.Python's enum facility makes
this easy while taking care of the proper conversions from Python's dynamic
typing to C++'s strong static typing (in C++, ints cannot be implicitly converted
to enums). To illustrate, given a C++ enum:
</p>
<pre class="programlisting"><span class="keyword">enum</span> <span class="identifier">choice</span> <span class="special">{</span> <span class="identifier">red</span><span class="special">,</span> <span class="identifier">blue</span> <span class="special">};</span>
</pre>
<p>
the construct:
</p>
<pre class="programlisting"><span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">choice</span><span class="special">&gt;(</span><span class="string">"choice"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span>
<span class="special">;</span>
</pre>
<p>
can be used to expose to Python. The new enum type is created in the current
<tt class="literal">scope()</tt>, which is usually the current module. The snippet
above creates a Python class derived from Python's <tt class="literal">int</tt>
type which is associated with the C++ type passed as its first parameter.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top">
<p>
<span class="bold"><b>what is a scope?</b></span>
</p>
<p>
The scope is a class that has an associated global Python object which
controls the Python namespace in which new extension classes and wrapped
functions will be defined as attributes. Details can be found <a href="../../../../v2/scope.html" target="_top">here</a>.
</p>
</td></tr>
</table></div>
<p>
You can access those values in Python as
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span>
<span class="identifier">my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span>
</pre>
<p>
where my_module is the module where the enum is declared. You can also create
a new scope around a class:
</p>
<p>
</p>
<pre class="programlisting"><span class="identifier">scope</span> <span class="identifier">in_X</span> <span class="special">=</span> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;(</span><span class="string">"X"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span> <span class="special">...</span> <span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span> <span class="special">...</span> <span class="special">)</span>
<span class="special">;</span>
<span class="comment">// Expose X::nested as X.nested
</span><span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">nested</span><span class="special">&gt;(</span><span class="string">"nested"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span>
<span class="special">;</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="functions.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -1,452 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title> General Techniques</title>
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="exception.html" title=" Exception Translation">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="exception.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.techniques"></a> General Techniques</h2></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="techniques.html#python.creating_packages">Creating Packages</a></span></dt>
<dt><span class="section"><a href="techniques.html#python.extending_wrapped_objects_in_python">Extending Wrapped Objects in Python</a></span></dt>
<dt><span class="section"><a href="techniques.html#python.reducing_compiling_time">Reducing Compiling Time</a></span></dt>
</dl></div>
<p>
Here are presented some useful techniques that you can use while wrapping code
with Boost.Python.
</p>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.creating_packages"></a>Creating Packages</h3></div></div></div>
<p>
A Python package is a collection of modules that provide to the user a certain
functionality. If you're not familiar on how to create packages, a good introduction
to them is provided in the <a href="http://www.python.org/doc/current/tut/node8.html" target="_top">Python
Tutorial</a>.
</p>
<p>
But we are wrapping C++ code, using Boost.Python. How can we provide a nice
package interface to our users? To better explain some concepts, let's work
with an example.
</p>
<p>
We have a C++ library that works with sounds: reading and writing various
formats, applying filters to the sound data, etc. It is named (conveniently)
<tt class="literal">sounds</tt>. Our library already has a neat C++ namespace hierarchy,
like so:
</p>
<pre class="programlisting"><span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span>
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">io</span>
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">filters</span>
</pre>
<p>
We would like to present this same hierarchy to the Python user, allowing
him to write code like this:
</p>
<pre class="programlisting"><span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
<span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(...)</span> <span class="comment"># echo is a C++ function
</span></pre>
<p>
The first step is to write the wrapping code. We have to export each module
separately with Boost.Python, like this:
</p>
<pre class="programlisting"><span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">core</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">core</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span> <span class="identifier">namespace</span> <span class="special">*/</span>
<span class="special">...</span>
<span class="special">}</span>
<span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">io</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">io</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">io</span> <span class="identifier">namespace</span> <span class="special">*/</span>
<span class="special">...</span>
<span class="special">}</span>
<span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">filters</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">filters</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">filters</span> <span class="identifier">namespace</span> <span class="special">*/</span>
<span class="special">...</span>
<span class="special">}</span>
</pre>
<p>
Compiling these files will generate the following Python extensions: <tt class="literal">core.pyd</tt>,
<tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top"><p>
The extension <tt class="literal">.pyd</tt> is used for python extension modules,
which are just shared libraries. Using the default for your system, like
<tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt> for Windows,
works just as well.
</p></td></tr>
</table></div>
<p>
Now, we create this directory structure for our Python package:
</p>
<pre class="programlisting">sounds/
__init__.py
core.pyd
filters.pyd
io.pyd
</pre>
<p>
The file <tt class="literal">__init__.py</tt> is what tells Python that the directory
<tt class="literal">sounds/</tt> is actually a Python package. It can be a empty
file, but can also perform some magic, that will be shown later.
</p>
<p>
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt>
into his <a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
and fire up the interpreter:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">io</span>
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">sound</span> <span class="special">=</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">.</span><span class="identifier">open</span><span class="special">(</span><span class="string">'file.mp3'</span><span class="special">)</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">new_sound</span> <span class="special">=</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">,</span> <span class="number">1.0</span><span class="special">)</span>
</pre>
<p>
Nice heh?
</p>
<p>
This is the simplest way to create hierarchies of packages, but it is not
very flexible. What if we want to add a <span class="emphasis"><em>pure</em></span> Python
function to the filters package, for instance, one that applies 3 filters
in a sound object at once? Sure, you can do this in C++ and export it, but
why not do so in Python? You don't have to recompile the extension modules,
plus it will be easier to write it.
</p>
<p>
If we want this flexibility, we will have to complicate our package hierarchy
a little. First, we will have to change the name of the extension modules:
</p>
<p>
</p>
<pre class="programlisting"><span class="comment">/* file core.cpp */</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_core</span><span class="special">)</span>
<span class="special">{</span>
<span class="special">...</span>
<span class="comment">/* export everything in the sounds::core namespace */</span>
<span class="special">}</span>
</pre>
<p>
Note that we added an underscore to the module name. The filename will have
to be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same
to the other extension modules. Now, we change our package hierarchy like
so:
</p>
<pre class="programlisting">sounds/
__init__.py
core/
__init__.py
<span class="underline">core.pyd
filters/
\</span>_init__.py
<span class="underline">filters.pyd
io/
\</span>_init__.py
_io.pyd
</pre>
<p>
Note that we created a directory for each extension module, and added a __init__.py
to each one. But if we leave it that way, the user will have to access the
functions in the core module with this syntax:
</p>
<p>
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(...)</span>
</pre>
<p>
which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
can be accessed directly by the user. So, all we have to do is bring the
entire namespace from <tt class="literal">_core.pyd</tt> to <tt class="literal">core/__init__.py</tt>.
So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:
</p>
<pre class="programlisting"><span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span>
</pre>
<p>
We do the same for the other packages. Now the user accesses the functions
and classes in the extension modules like before:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(...)</span>
</pre>
<p>
with the additional benefit that we can easily add pure Python functions
to any module, in a way that the user can't tell the difference between a
C++ function and a Python function. Let's add a <span class="emphasis"><em>pure</em></span>
Python function, <tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt>
package. This function applies both the <tt class="literal">echo</tt> and <tt class="literal">noise</tt>
filters in sequence in the given <tt class="literal">sound</tt> object. We create
a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our
function:
</p>
<pre class="programlisting"><span class="keyword">import</span> <span class="identifier">_filters</span>
<span class="keyword">def</span> <span class="identifier">echo_noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">):</span>
<span class="identifier">s</span> <span class="special">=</span> <span class="identifier">_filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span>
<span class="identifier">s</span> <span class="special">=</span> <span class="identifier">_filters</span><span class="special">.</span><span class="identifier">noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span>
<span class="keyword">return</span> <span class="identifier">s</span>
</pre>
<p>
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:
</p>
<pre class="programlisting"><span class="keyword">from</span> <span class="identifier">echo_noise</span> <span class="keyword">import</span> <span class="identifier">echo_noise</span>
</pre>
<p>
And that's it. The user now accesses this function like any other function
from the <tt class="literal">filters</tt> package:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo_noise</span><span class="special">(...)</span>
</pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div>
<p>
Thanks to Python's flexibility, you can easily add new methods to a class,
even after it was already created:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">class</span> <span class="identifier">C</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span> <span class="keyword">pass</span>
<span class="special">&gt;&gt;&gt;</span>
<span class="special">&gt;&gt;&gt;</span> <span class="comment"># a regular function
</span><span class="special">&gt;&gt;&gt;</span> <span class="keyword">def</span> <span class="identifier">C_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span> <span class="keyword">return</span> <span class="string">'A C instance!'</span>
<span class="special">&gt;&gt;&gt;</span>
<span class="special">&gt;&gt;&gt;</span> <span class="comment"># now we turn it in a member function
</span><span class="special">&gt;&gt;&gt;</span> <span class="identifier">C</span><span class="special">.</span><span class="identifier">__str__</span> <span class="special">=</span> <span class="identifier">C_str</span>
<span class="special">&gt;&gt;&gt;</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">C</span><span class="special">()</span>
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">c</span>
<span class="identifier">A</span> <span class="identifier">C</span> <span class="identifier">instance</span><span class="special">!</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">C_str</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span>
<span class="identifier">A</span> <span class="identifier">C</span> <span class="identifier">instance</span><span class="special">!</span>
</pre>
<p>
Yes, Python rox. <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span>
</p>
<p>
We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class <tt class="literal">point</tt> in C++:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">point</span> <span class="special">{...};</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span>
<span class="special">}</span>
</pre>
<p>
If we are using the technique from the previous session, <a href="techniques.html#python.creating_packages" title="Creating Packages">Creating
Packages</a>, we can code directly into <tt class="literal">geom/__init__.py</tt>:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">from</span> <span class="identifier">_geom</span> <span class="keyword">import</span> <span class="special">*</span>
<span class="comment"># a regular function
</span><span class="keyword">def</span> <span class="identifier">point_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
<span class="keyword">return</span> <span class="identifier">str</span><span class="special">((</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">self</span><span class="special">.</span><span class="identifier">y</span><span class="special">))</span>
<span class="comment"># now we turn it into a member function
</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">__str__</span> <span class="special">=</span> <span class="identifier">point_str</span>
</pre>
<p>
<span class="bold"><b>All</b></span> point instances created from C++ will
also have this member function! This technique has several advantages:
</p>
<div class="itemizedlist"><ul type="disc">
<li>
Cut down compile times to zero for these additional functions
</li>
<li>
Reduce the memory footprint to virtually zero
</li>
<li>
Minimize the need to recompile
</li>
<li>
Rapid prototyping (you can move the code to C++ if required without changing
the interface)
</li>
</ul></div>
<p>
You can even add a little syntactic sugar with the use of metaclasses. Let's
create a special metaclass that "injects" methods in other classes.
</p>
<pre class="programlisting"><span class="comment"># The one Boost.Python uses for all wrapped classes.
</span><span class="comment"># You can use here any class exported by Boost instead of "point"
</span><span class="identifier">BoostPythonMetaclass</span> <span class="special">=</span> <span class="identifier">point</span><span class="special">.</span><span class="identifier">__class__</span>
<span class="keyword">class</span> <span class="identifier">injector</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span>
<span class="keyword">class</span> <span class="identifier">__metaclass__</span><span class="special">(</span><span class="identifier">BoostPythonMetaclass</span><span class="special">):</span>
<span class="keyword">def</span> <span class="identifier">__init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">,</span> <span class="identifier">dict</span><span class="special">):</span>
<span class="keyword">for</span> <span class="identifier">b</span> <span class="keyword">in</span> <span class="identifier">bases</span><span class="special">:</span>
<span class="keyword">if</span> <span class="identifier">type</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span> <span class="keyword">not</span> <span class="keyword">in</span> <span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">type</span><span class="special">):</span>
<span class="keyword">for</span> <span class="identifier">k</span><span class="special">,</span><span class="identifier">v</span> <span class="keyword">in</span> <span class="identifier">dict</span><span class="special">.</span><span class="identifier">items</span><span class="special">():</span>
<span class="identifier">setattr</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">k</span><span class="special">,</span><span class="identifier">v</span><span class="special">)</span>
<span class="keyword">return</span> <span class="identifier">type</span><span class="special">.</span><span class="identifier">__init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">,</span> <span class="identifier">dict</span><span class="special">)</span>
<span class="comment"># inject some methods in the point foo
</span><span class="keyword">class</span> <span class="identifier">more_point</span><span class="special">(</span><span class="identifier">injector</span><span class="special">,</span> <span class="identifier">point</span><span class="special">):</span>
<span class="keyword">def</span> <span class="identifier">__repr__</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
<span class="keyword">return</span> <span class="string">'Point(x=%s, y=%s)'</span> <span class="special">%</span> <span class="special">(</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">self</span><span class="special">.</span><span class="identifier">y</span><span class="special">)</span>
<span class="keyword">def</span> <span class="identifier">foo</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
<span class="keyword">print</span> <span class="string">'foo!'</span>
</pre>
<p>
Now let's see how it got:
</p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">point</span><span class="special">()</span>
<span class="identifier">Point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">10</span><span class="special">,</span> <span class="identifier">y</span><span class="special">=</span><span class="number">10</span><span class="special">)</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">point</span><span class="special">().</span><span class="identifier">foo</span><span class="special">()</span>
<span class="identifier">foo</span><span class="special">!</span>
</pre>
<p>
Another useful idea is to replace constructors with factory functions:
</p>
<pre class="programlisting"><span class="identifier">_point</span> <span class="special">=</span> <span class="identifier">point</span>
<span class="keyword">def</span> <span class="identifier">point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">0</span><span class="special">,</span> <span class="identifier">y</span><span class="special">=</span><span class="number">0</span><span class="special">):</span>
<span class="keyword">return</span> <span class="identifier">_point</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">)</span>
</pre>
<p>
In this simple case there is not much gained, but for constructurs with many
overloads and/or arguments this is often a great simplification, again with
virtually zero memory footprint and zero compile-time overhead for the keyword
support.
</p>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div>
<p>
If you have ever exported a lot of classes, you know that it takes quite
a good time to compile the Boost.Python wrappers. Plus the memory consumption
can easily become too high. If this is causing you problems, you can split
the class_ definitions in multiple files:
</p>
<p>
</p>
<pre class="programlisting"><span class="comment">/* file point.cpp */</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">export_point</span><span class="special">()</span>
<span class="special">{</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span>
<span class="special">}</span>
<span class="comment">/* file triangle.cpp */</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">export_triangle</span><span class="special">()</span>
<span class="special">{</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">&gt;(</span><span class="string">"triangle"</span><span class="special">)...;</span>
<span class="special">}</span>
</pre>
<p>
Now you create a file <tt class="literal">main.cpp</tt>, which contains the <tt class="literal">BOOST_PYTHON_MODULE</tt>
macro, and call the various export functions inside it.
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">export_point</span><span class="special">();</span>
<span class="keyword">void</span> <span class="identifier">export_triangle</span><span class="special">();</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">export_point</span><span class="special">();</span>
<span class="identifier">export_triangle</span><span class="special">();</span>
<span class="special">}</span>
</pre>
<p>
Compiling and linking together all this files produces the same result as
the usual approach:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">&gt;(</span><span class="string">"triangle"</span><span class="special">)...;</span>
<span class="special">}</span>
</pre>
<p>
but the memory is kept under control.
</p>
<p>
This method is recommended too if you are developing the C++ library and
exporting it to Python at the same time: changes in a class will only demand
the compilation of a single cpp, instead of the entire wrapper code.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top"><p>
If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
take a look at the <tt class="literal">--multiple</tt> option, that generates
the wrappers in various files as demonstrated here.
</p></td></tr>
</table></div>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td colspan="2" align="left" valign="top"><p>
This method is useful too if you are getting the error message <span class="emphasis"><em>"fatal
error C1204:Compiler limit:internal structure overflow"</em></span>
when compiling a large source file, as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.
</p></td></tr>
</table></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="exception.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
</head>
<body>
Automatic redirection failed, click this
<a href="doc/html/index.html">link</a> &nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>

62
doc/under-the-hood.html Normal file
View File

@@ -0,0 +1,62 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
A Peek Under the Hood
</title>
<h1>
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
</h1>
<h1>
A Peek Under the Hood
</h1>
<p>
Declaring a <code>class_builder&lt;T&gt;</code> causes the instantiation
of an <code>extension_class&lt;T&gt;</code> to which it forwards all
member function calls and which is doing most of the real work.
<code>extension_class&lt;T&gt;</code> is a subclass of <code>
PyTypeObject</code>, the <code> struct</code> which Python's 'C' API uses
to describe a type. <a href="example1.html#world_class">An instance of the
<code>extension_class&lt;&gt;</code></a> becomes the Python type object
corresponding to <code>hello::world</code>. When we <a href=
"example1.html#add_world_class">add it to the module</a> it goes into the
module's dictionary to be looked up under the name "world".
<p>
Boost.Python uses C++'s template argument deduction mechanism to determine the
types of arguments to functions (except constructors, for which we must
<a href="example1.html#Constructor_example">provide an argument list</a>
because they can't be named in C++). Then, it calls the appropriate
overloaded functions <code>PyObject*
to_python(</code><em>S</em><code>)</code> and <em>
S'</em><code>from_python(PyObject*,
type&lt;</code><em>S</em><code>&gt;)</code> which convert between any C++
type <em>S</em> and a <code>PyObject*</code>, the type which represents a
reference to any Python object in its 'C' API. The <a href=
"example1.html#world_class"><code>extension_class&lt;T&gt;</code></a>
template defines a whole raft of these conversions (for <code>T, T*,
T&amp;, std::auto_ptr&lt;T&gt;</code>, etc.), using the same inline
friend function technique employed by <a href=
"http://www.boost.org/libs/utility/operators.htm">the boost operators
library</a>.
<p>
Because the <code>to_python</code> and <code>from_python</code> functions
for a user-defined class are defined by <code>
extension_class&lt;T&gt;</code>, it is important that an instantiation of
<code> extension_class&lt;T&gt;</code> is visible to any code which wraps
a C++ function with a <code>T, T*, const T&amp;</code>, etc. parameter or
return value. In particular, you may want to create all of the classes at
the top of your module's init function, then <code>def</code> the member
functions later to avoid problems with inter-class dependencies.
<p>
Next: <a href="building.html">Building a Module with Boost.Python</a>
Previous: <a href="special.html">Special Method and Operator Support</a>
Up: <a href="index.html">Top</a>
<p>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided "as is" without
express or implied warranty, and with no claim as to its suitability for
any purpose.
<p>
Updated: Nov 26, 2000

View File

@@ -1,166 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - April 2002 Progress Report</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">April 2002 Progress Report</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="index">
<dt><a href="#accomplishments">Accomplishments</a></dt>
<dl class="index">
<dt><a href="#arity">Arbitrary Arity Support</a></dt>
<dt><a href="#callbacks">New Callback Interface</a></dt>
<dt><a href="#policies">Call Policies for Construtors</a></dt>
<dt><a href="#bugs">Real Users, Real Bugs</a></dt>
<dt><a href="#insights">New Insights</a></dt>
<dt><a href="#v1">Boost.Python V1 Maintenance</a></dt>
</dl>
<dt><a href="#missing">What's Missing</a></dt>
</dl>
<h2><a name="accomplishments">Accomplishments</a></h2>
April was a short month as far as Boost.Python was concerned, since
the spring ISO C++ Committee Meeting (and associated vacation)
occupied me for the 2nd half of the month. However, a suprising amount
of work got done...
<h3><a name="arity">Arbitrary Arity Support</a></h3>
I began using the <a
href="../../../preprocessor/doc/index.html">Boost.Preprocessor</a>
metaprogramming library to generate support for functions and member
functions of arbitrary arity, which was, to say the least, quite an
adventure. The feedback cycle resulting from my foray into
Boost.Preprocessor resulted in several improvements to the library,
most notably in its documentation.
<p>
Boost.Python now supports calls of up to 17 arguments on most
compilers. Because most EDG-based compilers have dismal preprocessor
performance, I had to &quot;manually&quot; expand the metaprograms for
arities from zero to fifteen arguments, and EDG-based compilers with
<code>__EDG_VERSION__&nbsp;&lt;=&nbsp;245</code> only support 15
arguments by default. If some crazy program finds a need for more than
the default arity support, users can increase the base support by
setting the <code>BOOST_PYTHON_MAX_ARITY</code> preprocessor symbol.
<h3><a name="callbacks">New Callback Interface</a></h3>
I mentioned in <a href="Mar2002.html">last month's report</a> that I
wasn't pleased with the interface for the interface for calling into
Python, so now it has been redesigned. The new interface is outlined
in <a
href="http://mail.python.org/pipermail/c++-sig/2002-April/000953.html">this
message</a> (though the GCC 2.95.3 bugs have been fixed).
<h3><a name="policies">Call Policies for Constructors</a></h3>
On April 2nd, I <a
href="http://mail.python.org/pipermail/c++-sig/2002-April/000916.html">announced</a>
support for the use of call policies with constructors.
<h3><a name="bugs">Real Users, Real Bugs</a></h3>
At least two people outside of Kull began actually using Boost.Python
v2 in earnest this month. Peter Bienstman and Pearu Pearson both
provided valuable real-world bug reports that helped me to improve the
library's robustness.
<h3><a name="insights">New Insights</a></h3>
<a
href="http://mail.python.org/pipermail/c++-sig/2002-May/001010.html"
>Answering some of Pearu's questions</a> about explicitly converting
objects between Python and C++ actually led me to a new understanding
of the role of the current conversion facilities. In Boost.Python v1,
all conversions between Python and C++ were handled by a single family
of functions, called <code>to_python()</code> and
<code>from_python()</code>. Since the primary role of Boost.Python is
to wrap C++ functions in Python, I used these names for the first kind
of converters I needed: those that extract C++ objects to be used as
function arguments and which C++ function return values to
Python. The better-considered approach in Boost.Python v2 uses a
completely different mechanism for conversions used when calling
Python from C++, as in wrapped virtual function implementations. I
usually think of this as a &quot;callback&quot;, as in &quot;calling
back into Python&quot;, and I named the converters used in callbacks
accordingly: <code>to_python_callback</code> and
<code>from_python_callback</code>. However, as it turns out, the
behavior of the &quot;callback&quot; converters is the appropriate one
for users who want to explicitly extract a C++ value from a Python
object, or create a Python object from a C++ value. The upshot is that
it probably makes sense to change the name of the existing <code>to_python</code> and
<code>from_python</code> so those names are available for the
user-friendly explicit converters.
<p>
<a
href="http://mail.python.org/pipermail/c++-sig/2002-May/001013.html">Another
of Pearu's questions</a> pushes momentum further in the direction of a
more-sophisticated overloading mechanism than the current
simple-minded &quot;first match&quot; approach, as I suggested <a
href="Mar2002.html#implicit_conversions">last month</a>.
<h3><a name="v1">Boost.Python V1 Maintenance</a></h3>
As much as I'm looking forward to retiring Boost.Python v1, a
significant amount of effort has been being spent dealing with support
problems; the saying that code rots when left alone is true, and
Boost.Python is no exception. Eventually it became obvious to me that
we were going to have to invest some effort in keeping V1 healthy
while working on V2. Ralf and I have expanded support for various
compilers and stabilized the V1 codebase considerably. We discarded
the obsolete Visual Studio projects which were causing so much
confusion. Still to do before the next Boost release:
<ol>
<li>Update the build/test documentation with detailed instructions for
configuring various toolsets.
<li>Provide some links to Boost.Python v2 to let people know what's
coming.
</ol>
<h2><a name="missing">What's Missing</a></h2>
Last month I announced that I would implement the following which are
not yet complete:
<ol>
<li>Document all implemented features
<li>Implement conversions for <code>char</code> types. This is
implemented but not tested, so we have to assume it doesn't work.
</ol>
These are my first priority for this month (especially the
documentation).
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -1,165 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Boost.Python - CallPolicies Concept</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">CallPolicies Concept</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#composition">CallPolicies Composition</a></dt>
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#CallPolicies-concept">CallPolicies Concept</a></dt>
</dl>
</dd>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>Models of the CallPolicies concept are used to specialize the behavior
of Python callable objects generated by Boost.Python to wrapped C++
objects like function and member function pointers, providing three
behaviors:</p>
<ol>
<li><code>precall</code> - Python argument tuple management before the
wrapped object is invoked</li>
<li><code>result_converter</code> - C++ return value handling</li>
<li><code>postcall</code> - Python argument tuple and result management
after the wrapped object is invoked</li>
<li><code>extract_return_type</code> - metafunction for extracting the return type from a given signature type sequence</li>
</ol>
<h2><a name="composition"></a>CallPolicies Composition</h2>
In order to allow the use of multiple models of CallPolicies in the same
callable object, Boost.Python's CallPolicies class templates provide a
chaining interface which allows them to be recursively composed. This
interface takes the form of an optional template parameter,
<code>Base</code> which defaults to <a href=
"default_call_policies.html#default_call_policies-spec"><code>default_call_policies</code></a>.
By convention, the <code>precall</code> function of the <code>Base</code>
is invoked <i>after</i> the <code>precall</code> function supplied by the
outer template, and the <code>postcall</code> function of the
<code>Base</code> is invoked <i>before</i> the <code>postcall</code>
function of the outer template. If a <code>result_converter</code> is
supplied by the outer template, it <i>replaces</i> any
<code>result_converter</code> supplied by the <code>Base</code>. For an
example, see <a href=
"return_internal_reference.html#return_internal_reference-spec"><code>return_internal_reference</code></a>.
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
<h3><a name="CallPolicies-concept"></a>CallPolicies Concept</h3>
<p>In the table below, <code><b>x</b></code> denotes an object whose type
<code><b>P</b></code> is a model of CallPolicies, <code><b>a</b></code>
denotes a <code>PyObject*</code> pointing to a Python argument tuple
object, and <code><b>r</b></code> denotes a <code>PyObject*</code>
referring to a "preliminary" result object.</p>
<table summary="CallPolicies expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Type</b></td>
<td><b>Result/Semantics</b></td>
</tr>
<tr>
<td valign="top"><code>x.precall(a)</code></td>
<td>convertible to <code>bool</code></td>
<td>returns <code>false</code> and <code><a href=
"http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71">PyErr_Occurred</a>()&nbsp;!=&nbsp;0</code>
upon failure, <code>true</code> otherwise.</td>
</tr>
<tr>
<td valign="top"><code>P::result_converter</code></td>
<td>A model of <a href=
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
<td>An MPL unary <a href=
"../../../mpl/doc/refmanual/metafunction-class.html">Metafunction
Class</a> used produce the "preliminary" result object.</td>
</tr>
<tr>
<td valign="top"><code>x.postcall(a, r)</code></td>
<td>convertible to <code>PyObject*</code></td>
<td>0 <code>0</code> and <code><a href=
"http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71">PyErr_Occurred</a>()&nbsp;!=&nbsp;0</code>
upon failure. Must "conserve references" even in the event of an
exception. In other words, if <code>r</code> is not returned, its
reference count must be decremented; if another existing object is
returned, its reference count must be incremented.</td>
</tr>
<tr>
<td valign="top"><code>P::extract_return_type</code></td>
<td>A model of <a href=
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a>.</td>
<td>An MPL unary <a href=
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a> used extract the return type from a given signature. By default it is derived from mpl::front.</td>
</tr>
</table>
Models of CallPolicies are required to be <a href=
"../../../utility/CopyConstructible.html">CopyConstructible</a>.
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
<p>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.</p>
</body>
</html>

View File

@@ -1,74 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Boost.Python - Dereferenceable Concept</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Dereferenceable Concept</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
<dl class="page-index">
<dt><a href="#Dereferenceable-concept">Dereferenceable Concept</a></dt>
</dl>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>Instances of a Dereferenceable type can be used like a pointer to access an lvalue.
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
<h3><a name="Dereferenceable-concept"></a>Dereferenceable Concept</h3>
<p>In the table below, <code><b>T</b></code> is a model of
Dereferenceable, and <code><b>x</b></code> denotes an object of
type <code>T</code>. In addition, all pointers are Dereferenceable.
<table summary="Dereferenceable expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Result</b></td>
<td><b>Operational Semantics</b></td>
</tr>
<tr>
<td><code>get_pointer(x)</code></td>
<td>convertible to <code><a href="pointee.html#pointee-spec">pointee</a>&lt;T&gt;::type*</code>
<td><code>&amp;*x</code>, or a null pointer
</tr>
<tr>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
18 December, 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003. </i>
<p>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.
</body>
</html>

View File

@@ -1,96 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Boost.Python - Extractor Concept</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Extractor Concept</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
<dl class="page-index">
<dt><a href="#Extractor-concept">Extractor Concept</a></dt>
</dl>
<dt><a href="#notes">Notes</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>An Extractor is a class which Boost.Python can use to extract C++
objects from Python objects, and is typically used by facilities that
define <code>from_python</code> conversions for
&quot;traditional&quot; Python extension types.
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
<h3><a name="Extractor-concept"></a>Extractor Concept</h3>
<p>In the table below, <code><b>X</b></code> denotes a model of
Extractor and <code><b>a</b></code> denotes an instance of a Python
object type.
<table summary="Extractor expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Type</b></td>
<td><b>Semantics</b></td>
</tr>
<tr>
<td valign="top"><code>X::execute(a)</code></td>
<td>non-void
<td>Returns the C++ object being extracted. The
<code>execute</code> function must not be overloaded.
</tr>
<tr>
<td valign="top"><code>&amp;a.ob_type</code>
<td><code><a
href="http://www.python.org/doc/2.2/ext/dnt-type-methods.html">PyTypeObject</a>**</code>
<td>Points to the <code>ob_type</code> field of an object which is
layout-compatible with <code>PyObject</code>
</tr>
</tr>
</table>
<h2><a name="notes"></a>Notes</h2>
Informally, an Extractor's <code>execute</code> member must be a
non-overloaded static function whose single argument is a Python
object type. Acceptable Python object types include those publicly (and
unambiguously) derived from <code>PyObject</code>, and POD types which
are layout-compatible with PyObject.
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002. </i>
<p>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.
</body>
</html>

View File

@@ -1,74 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Boost.Python - Holder Concept</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">HolderGenerator Concept</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
<dl class="page-index">
<dt><a href="#HolderGenerator-concept">HolderGenerator Concept</a></dt>
</dl>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>A HolderGenerator is a unary metafunction class which returns types
suitable for holding instances of its argument in a wrapped C++ class
instance.
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
<h3><a name="HolderGenerator-concept"></a>HolderGenerator Concept</h3>
<p>In the table below, <code><b>G</b></code> denotes an type which
models HolderGenerator, and <code><b>X</b></code> denotes a class
type.
<table summary="Holder expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Requirements</b></td>
</tr>
<tr>
<td valign="top"><code>G::apply&lt;X&gt;::type</code></td>
<td>A concrete subclass of <a
href="instance_holder.html#instance_holder-spec">instance_holder</a>
which can hold objects of type <code>X</code>.
</tr>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002. </i>
<p>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.
</body>
</html>

View File

@@ -1,229 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - June 2002 Progress Report</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">June 2002 Progress Report</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="index">
<dt><a href="#intro">Introduction</a></dt>
<dt><a href="#handle"><code>handle&lt;T&gt;</code></a></dt>
<dt><a href="#object"><code>object</code></a></dt>
<dl class="index">
<dt><a href="#operators"><code>object</code> operators</a></dt>
<dt><a href="#conversions"><code>object</code> conversions</a></dt>
</dl>
<dt><a href="#list"><code>list</code></a></dt>
<dt><a href="#numerics"><code>Numerics</code></a></dt>
<dt><a href="#community">Community</a></dt>
<dt><a href="#next">What's Next</a></dt>
</dl>
<h2><a name="intro">Introduction</a></h2>
July was mostly focused on allowing expressive manipulation of
individual Python objects, or what Ralf Grosse-Kunstleve calls
&quot;Writing Python in C++&quot;. The work began with this <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001311.html">posting</a>,
which outlines the issues and intention.
<h2><a name="handle"><code>handle&lt;T&gt;</code></a></h2>
The most basic element needed was a replacement for the
<code>reference&lt;&gt;</code> class template and the
<code>ref</code> typedef from Boost.Python v1, a simple smart
pointer to a Python object. The old v1 typedef
&quot;<code>ref</code>&quot; (for
<code>reference&lt;PyObject&gt;</code>) had to be retired because I
thought it would be too confusing given the importance of <code><a
href="../../../bind/ref.html">boost::ref</a>()</code> to this
library. I began a <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001311.html">discussion</a>of
possible names, and it was eventually <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001337.html">decided</a>
to rename <code>reference</code> to <code>handle</code> and supply a
default argument so that <code>ref</code> could be spelled
<code>handle&lt;&gt;</code> without an additional typedef. There
were also some interface changes to make it safer and more-efficient
to interface with the raw
<code>PyObject*</code>s forced on us by Python's 'C' API. A
discussion of those protocols can be found <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001401.html">here</a>.
<h2><a name="handle"><code>object</code></a></h2>
It is intended that users will seldom need or want to work with
<code>handle&lt;&gt;</code>; its major distinguishing features are
that it gives direct access to the underlying object representation
through <code>operator*</code> and <code>operator-&gt;</code>, and
that can be <code>NULL</code>, both sources of danger. Instead the
library provides a class called <code>object</code>, which
encapsulates a valid Python object and provides a similar interface to
Python's.
<h3><a name="operators"><code>object</code> operators</a></h3>
The first challenge was to provide support for object manipulations
using a Python-like syntax, mostly in the form of operator overloads:
<table border="1">
<tr><th>Python <th>C++
<tr>
<td><code>y = x.foo</code> <td><code>y = x.attr(&quot;foo&quot;);
<tr>
<td><code>x.foo = 1</code> <td><code>x.attr(&quot;foo&quot;) = 1;
<tr>
<td><code>y = x[z]</code> <td><code>y = x[z];
<tr>
<td><code>x[z] = 1</code> <td><code>x[z] = 1;
<tr>
<td><code>y = x[3:-1]</code> <td><code>y = x.slice(3,-1);
<tr>
<td><code>y = x[3:]</code> <td><code>y = x.slice(3,_);
<tr>
<td><code>y = x[:-2]</code> <td><code>y = x.slice(_,-2);
<tr>
<td><code>z = x(1, y)</code> <td><code>z = x(1, y);
<tr>
<td><code>z = x.f(1, y)</code> <td><code>z = x.attr(&quot;f&quot;)(1, y);
<tr>
<td><code>not x</code> <td><code>!x
<tr>
<td><code>x and y</code> <td><code>x and y
</table>
I'm still a unsatisfied with the interface for attribute access. There
original proposal used a syntax like this one:
<pre>
y = x._(&quot;foo&quot;);
x._(&quot;foo&quot;) = 1;
</pre>
which was only marginally better than what we've got. Niki Spahiev
then <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001447.html">pointed
out</a> a potential conflict with the macro which GNU Gettext <a
href="http://www.gnu.org/manual/gettext/html_mono/gettext.html#SEC6">suggests</a>
people define. This unfortunate state of affairs forced us into using
<code>attr</code> instead. I'd still like to find a better interface,
but the lack of overloadable C++ operators which aren't already used
in Python is an obstacle. The comma operator is still a possibility,
but it has the wrong precedence:
<pre>
y = x,&quot;foo&quot; // error
x,&quot;foo&quot; = 1; // error
y = (x,&quot;foo&quot;); // ok
(x,&quot;foo&quot;) = 1; // ok
</pre>
Well, I guess we could consider adding that to the interface without
removing <code>attr()</code>, to see how it plays out...
<h3><a name="operators"><code>object</code> conversions</a></h3>
The <code>object</code> class also provided an opportunity to replace
Boost.Python v1's <code>to_python()</code> as a user-level
interface. Instead, <code>object</code> has a templated constructor
which can be used to convert any C++ object to Python using the same
underlying mechanisms used for the arguments to <code><a
href="call.html">call</a>&lt;&gt;</code>.
<p>Incidentally, the implementation of operator and conversion support
for object uncovered an inordinate number of compiler bugs in our
targeted platforms. It was a lot more &quot;interesting&quot; than it
should have been.
<h2><a name="list"><code>list</code></a></h2>
With <code>object</code> implemented, it was time to begin replacing
the ad-hoc implementations of <code>list</code>, <code>string</code>,
and <code>dictionary</code> supplied by Boost.Python v1 with something
more robust. I started with <code>list</code> as an example. Because
<code>object</code> already provides all of the requisite operators,
publicly deriving <code>list</code> from object seemed like a good
choice. The remaining issues were what do do about the one-argument
list constructor (which in Python attempts to convert its argument to
a list), and how to deal converting with <code>list</code> arguments
to wrapped functions. Some of the issues are laid out in <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001551.html">this
thread</a>. Ultimately, it was decided that <code>list(x)</code>
should do the same thing in C++ as in Python (conversion), while
<code>list</code> arguments should only match Python
<code>list</code>s (and <code>list</code> subclasses). The
implementation worked well, and provided a <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001586.html">roadmap</a>
for the protocol to be used for implementation of the other built-in
types.
<h2><a name="numerics">Numerics</a></h2>
Support for C++ <code>long long</code> and <code>unsigned long
long</code>
(and <code>__int64</code> on MSVC) to/from python conversions was
added this month. We also improved handling of numeric overflows when
converting, e.g., a Python int to a type with a more limited range of
representation.
<h2><a name="community">Community</a></h2>
<ul>
<li>Ralf W. Grosse-Kunstleve and Nick Sauter have implemented
<a href="http://cci.lbl.gov/boost/">multiplatform nightly
build-and-test</a> runs for Boost.Python V2 at LBL.
<li>Dave Hawkes has made significant progress on generating the
Python <a
href="http://mail.python.org/pipermail/c++-sig/2002-June/001503.html">built-in
function and API wrappers</a>
<li>Achim Domma has agreed to take up the job of implementing the
<code>str</code>, <code>dict</code>, and <code>tuple</code> classes.
</ul>
Deep thanks to all the Boost.Python contributors! This project
wouldn't be possible without your participation.
<h2><a name="next">What's Next</a></h2>
As I write this we are already well into the month of July, so I
suggest you consult the <a
href="http://mail.python.org/pipermail/c++-sig/2002-July/">Mailing
List Archive</a> if you want to know what's been happening. Otherwise
you'll just have to wait till next month (hopefully the beginning).
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -1,237 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - March 2002 Progress Report</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">March 2002 Progress Report</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="index">
<dt><a href="#accomplishments">Accomplishments</a></dt>
<dl class="index">
<dt><a href="#calling_python">Calling Python from C++</a></dt>
<dt><a href="#virtual_functions">Virtual Functions</a></dt>
<dt><a href="#abstract_classes">Abstract Classes</a></dt>
<dt><a href="#implicit_conversions">C++ Implicit Conversions</a></dt>
<dt><a href="#data_members">C++ Data Members</a></dt>
<dt><a href="#miscellaneous">Miscellaneous</a></dt>
</dl>
<dt><a href="#future">The Near future</a></dt>
<dt><a href="#notes">Notes</a></dt>
</dl>
<h2><a name="accomplishments">Accomplishments</a></h2>
March was mostly devoted to the reimplementation of features from
Boost.Python v1, and some new features. Re-examination of the features
from Boost.Python v1 allowed me to make significant improvements.
<h3><a name="calling_python">Calling Python from C++</a></h3>
The ability to call Python from C++ is crucial for virtual function
support. Implementing this feature well for V2 proved to be more
interesting than I expected. You can review most of the relevant
design decisions
<a href="callbacks.txt">here</a>.
<p>
One point which <i>isn't</i> emphasized in that document is that there
are subtle differences in the way <code>from_python</code> conversions
work when used for C++ function arguments and Python function return
values. In particular, while <code>T const&amp;</code> arguments may
invoke rvalue converters, a reference-to-const return value requires
an lvalue converter, since a temporary conversion result would leave
the returned reference dangling.
<p>I'm not particularly pleased with the current callback interface,
since it usually results in constructs like:
<pre>
<u>return returning</u>&lt;X&amp;&gt;::call(f, obj);
</pre>
However, I think the following may be possible and I plan to investigate:
<pre>
return apply&lt;X&amp;&gt;(f, obj);
</pre>
I'm open to suggestion for better names (and syntaxes)!
<h3><a name="virtual_functions">Virtual Functions</a></h3>
Once Python callbacks were implemented, it was just a short step to
implementing virtual functions. Python extension class exposing a C++
class whose virtual functions are overridable in Python must actually
hold a C++ instance of a class <i>derived</i> from the one exposed to
Python. Needing some way for users to specify that class, I added an
optional template argument to <code>value_holder_generator</code> and
<code>pointer_holder_generator&lt;&gt;</code> to specify the class
actually held. This move began to put pressure on the
<code>class_&lt;&gt;</code> interface, since the need for the user to
produce complicated instantations of
<code>class_&lt;&gt;</code> was increased:
<pre>
class&lt;Foo, bases&lt;&gt;, value_holder_generator&lt;Foo_callback&gt; &gt;(&quot;Foo&quot;)
.def(&quot;hello&quot;, &amp;Foo::hello)
...
</pre>
<h3><a name="abstract_classes">Abstract Classes</a></h3>
Normally when a C++ class is exposed to Python, the library registers
a conversion function which allows users to wrap functions returning
values of that type. Naturally, these return values are temporaries,
so the conversion function must make a copy in some
dynamically-allocated storage (a &quot;holder&quot;) which is managed
by the corresponding Python object.
<p>Unfortunately, in the case of abstract classes (and other types
without a publicly-accessible copy constructor), instantiating this
conversion function causes a compilation error. In order to support
non-copyable classes, there had to be some way to prevent the library
from trying to instantiate the conversion function. The only practical
approach I could think of was to add an additional template parameter
to the <code>class_&lt;&gt;</code> interface. When the number of
template parameters with useful defaults begins to grow, it is often
hard to choose an order which allows users to take advantage of the
defaults.
<p>
This was the straw that broke the
<code>class_&lt;&gt;</code> interface's back and caused the redesign
whose outcome is detailed <a
href="http://mail.python.org/pipermail/c++-sig/2002-March/000892.html">here</a>.
The approach allows the user to supply the optional parameters in an
arbitrary order. It was inspired by the use of <a
href="../../../utility/iterator_adaptors.htm#named_tempalte_parameters">named
template parameters</a> in the <a
href="../../../utility/iterator_adaptors.htm">Boost Iterator Adaptor
Library</a>, though in this case it is possible to deduce the meaning
of the template parameters entirely from their type properties,
resulting in a simpler interface. Although the move from a
policy-based design to what resembles a configuration DSL usually
implies a loss of flexibility, in this case I think any costs are far
outweighed by the advantages.
<p>Note: working around the limitations of the various compilers I'm
supporting was non-trivial, and resulted in a few messy implementation
details. It might be a good idea to switch to a more-straightforward
approach once Metrowerks CodeWarrior Pro8 is released.
<h3><a name="implicit_conversions">C++ Implicit Conversions</a></h3>
Support for C++ implicit conversion involves creating
<code>from_python</code> converters for a type <code>U</code> which in
turn use <code>from_python</code> converters registered for a type
<code>T</code> where there exists a implicit conversion from
<code>T</code> to <code>U</code>. The current implementation is
subject to two inefficiencies:
<ol>
<li>Because an rvalue <code>from_python</code> converter produces two
pieces of data (a function and a <code>void*</code>) from its
<code>convertible()</code> function, we end up calling the function
for <code>T</code> twice: once when the converter is looked up in the
registry, and again when the conversion is actually performed.
<li>A vector is used to mark the "visited" converters, preventing
infinite recursion as <code>T</code> to
<code>U</code> and <code>U</code> to <code>T</code> converters
continually search through one-another.
</ol>
I consider the former to be a minor issue. The second may or may not
prove to be computationally significant, but I believe that
architecturally, it points toward a need for more sophisticated
overload resolution. It may be that we want CLOS-style multimethod
dispatching along with C++ style rules that prevent more than one
implicit conversion per argument.
<h3><a name="data_members">C++ Data Members</a></h3>
To supply the ability to directly access data members, I was able to
hijack the new Python <a
href="http://www.python.org/2.2/descrintro.html#property">property</a>
type. I had hoped that I would also be able to re-use the work of <a
href="make_function.html">make_function</a> to create callable python
objects from C++ functions which access a data member of a given
class. C++ facilities for specifying data member pointer non-type
template arguments require the user to explicitly specify the type of
the data member and this under-utilized feature is also not
well-implemented on all compilers, so passing the member pointer as a
runtime value is the only practical approach. The upshot is that any
such entity would actually have to be a function <i>object</i>, and I
haven't implemented automatic wrapping of C++ callable function
objects yet, so there is less re-use in the implementation than I'd
like. I hope to implement callable object wrapping and refactor this
code one day. I also hope to implement static data member support,
for which Python's property will not be an appropriate descriptor.
<h3><a name="miscellaneous">Miscellaneous</a></h3>
<ul>
<li>Moved <code>args&lt;&gt;</code> and <code>bases&lt;&gt;</code> from unnamed namespace to <code>boost::python</code> in their own header files.
<li>Convert <code>NULL</code> pointers returned from wrapped C++ functions to <code>None</code>.
<li>Improved some compile-time error checks.
<li>Eliminated <code>boost/python/detail/eval.hpp</code> in favor of
more-general <code>boost/mpl/apply.hpp</code>.
<li>General code cleanup and refactoring.
<li>Works with Microsoft Visual C++ 7.0
<li>Warning suppression for many compilers
<li>Elegant interface design for exporting <code>enum</code> types.
</ul>
<hr>
<h2><a name="future">The Near Future</a></h2>
Before April 15th I plan to
<ol>
<li>Document all implemented features
<li>Implement a <code>CallPolicy</code> interface for constructors of wrapped
classes
<li>Implement conversions for <code>char</code> types.
<li>Implement automated code generation for all headers containing
families of overloaded functions to handle arbitrary arity.
</ol>
I also hope to implement a mechanism for generating conversions
between arbitrary Python sequences and C++ containers, if time permits
(and others haven't already done it)!
<h2><a name="notes">Notes</a></h2>
The older version of KCC used by Kull is generating lots of warnings
about a construct I use to instantiate static members of various class
templates. I'm thinking of moving to an idiom which uses a function
template to suppress it, but worry about bloating the size of debug
builds. Since KCC users may be moving to GCC, I'm not sure that it's
worth doing anything about it.
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -1,311 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - May 2002 Progress Report</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">May 2002 Progress Report</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="index">
<dt><a href="#intro">Introduction</a></dt>
<dt><a href="#features">New Features</a></dt>
<dl>
<dt><a href="#aix_shared">Shared Library Support for AIX</a><dd>
<dt><a href="#class_enhancements">Class Enhancements</a><dd>
<dl>
<dt><a href="#operators">Operators</a><dd>
<dt><a href="#iterators">Iterators</a><dd>
<dt><a href="#properties">Properties</a><dd>
<dt><a href="#setattr">setattr</a><dd>
<dt><a href="#module">__module__ Attribute</a><dd>
</dl>
<dt><a href="#back_reference">back_reference</a><dd>
</dl>
<dt><a href="#documentation">Documentation</a></dt>
<dt><a href="#misc">Miscellaneous</a></dt>
<dl class="index">
<dt><a href="#converters">Converters</a></dt>
<dt><a href="#checkins">Checkins Mailing List</a></dt>
<dt><a href="#shared">Shared Libraries</a></dt>
</dl>
<dt><a href="#next">What's Next</a></dt>
</dl>
<h2><a name="intro">Introduction</a></h2>
Aside from library development, work on Boost.Python in May was
focused on reducing the support burden. In recent weeks, responding to
requests for support, espcially surrounding building the library, had
begun to impede progress on development. There was a major push to
release a stable 1.28.0 of Boost, including documentation of <a
href="../../../../tools/build/v1/build_system.htm">Boost.Build</a> and specific
<a href="../building.html">instructions</a> for building Boost.Python
v1. The documentation for Boost.Python v2 was also updated as
described <a href="#documentation">here</a>.
<h2><a name="features">New Features</a></h2>
<h3><a name="aix_shared">Shared Library Support for AIX</a></h3>
The Kull group required the ability to build and test Boost.Python
extensions on AIX, a platform with &quot;creatively designed&quot;
shared library semantics. Making this work was a multi-pronged
effort, involving changes to Boost.Build and some great research by
Martin Casado which uncovered the key mechanism required to allow
shared libraries to use functions from the Python executable. The
current solution used in Boost.Build relies on a <a
href="../../../../tools/build/v1/gen_aix_import_file.py">Python
Script</a> as part of the build process. This is not a problem for
Boost.Python, as Python will be available. However, the commands
issued by the script are so simple that a 100%-pure-Boost.Jam
solution is surely possible. Linking on AIX is sufficiently
interesting to have skewed the Boost.Python development schedule a
bit.
<h3><a name="class_enhancements">Class Enhancements</a></h3>
<h4><a name="operators">Operators</a></h4>
Support for exposing C++ operators and functions as the corresponding
Python special methods was added. Thinking that the Boost.Python
v1 interface was a little too esoteric (especially the use of
<code>left_operand&lt;...&gt;/right_operand&lt;...&gt;</code> for
asymmetric operands), I introduced a simple form of <a
href="http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">expression
templates</a> which allow users to simply write the expressions that
should be wrapped, as in this <a href="operators.html#examples">example</a>.
<h4><a name="iterators">Iterators</a></h4>
Python iterator support as required by the Kull project resulted in a
highly flexible interface allowing:
<dl>
<dt>Direct exposure of a class' <code>begin()</code> and
<code>end()</code> functions:
<pre>
...
.def(&quot;__iter__&quot;, iterator&lt;list_int&gt;())
</pre>
<dd>
<dt>Creation of iterators from member functions...
<pre>
...
.def(&quot;__iter__&quot;
, range(&amp;my_class::x_begin, &amp;my_class::x_end))
)
</pre>
<dd>
<dt>...and member data:
<pre>
...
.def(&quot;__iter__&quot;
, range(&amp;std::pair&lt;char*,char*&gt;::first, &amp;std::pair&lt;char*,char*&gt;::second))
)
</pre>
<dd>
<dt>The ability to specify <a
href="CallPolicies.html">CallPolicies</a>, e.g. to prevent copying of
heavyweight values:
<pre>
...
.def(&quot;__iter__&quot;,
, range&lt;return_value_policy&lt;copy_non_const_reference&gt; &gt;(
&amp;my_sequence&lt;heavy&gt;::begin
, &amp;my_sequence&lt;heavy&gt;::end))
</pre>
<dd>
</dl>
<h4><a name="properties">Properties</a></h4>
The Kull iteration interfaces also required the ability to iterate
over a sequence specified by an instance's attribute:
<pre>
&gt;&gt;&gt; f = field()
&gt;&gt;&gt; for e in f.elements:
... print e,
</pre>
This forced the exposure of the <a
href="http://www.python.org/2.2/descrintro.html#property"><code>property</code></a>
interface used internally to implement the data member exposure
facility described in <a
href="Mar2002.html#data_members">March</a>. Properties are an
incredibly useful idiom, so it's good to be able to provide them
at little new development cost.
<h4><a name="setattr">setattr</a></h4>
<code>class_&lt;&gt;</code> acquired a <code>setattr</code> member
function which allows users to easily add new Python objects as class
attributes.
<h4><a name="module">__module__ Attribute</a></h4>
Ralf Grosse-Kunstleve has been working on pickling support for v2. To
make it work correctly, he had to make sure that a class'
<code>__module__</code> attribute was set correctly.
<h3><a name="back_reference"><code>back_reference</code></a></h3>
The new <code>back_reference&lt;T&gt;</code> template can be used as a
function parameter when the user needs access to both a <code>T</code>
argument and to the Python object which manages it. The function will
only match in the overload resolution process if it would match the
same function signature with <code>T</code> substituted for
<code>back_reference&lt;T&gt;</code>. This feature is not yet
documented.
<h2><a name="documentation">Documentation</a></h2>
In a major effort to prepare Boost.Python v2 to replace v1, many pages
of new reference documentation were added:
<blockquote>
<dl>
<dt><a href="CallPolicies.html">CallPolicies.html</a><dd>
<dt><a href="Dereferenceable.html">Dereferenceable.html</a><dd>
<dt><a href="Extractor.html">Extractor.html</a><dd>
<dt><a href="HolderGenerator.html">HolderGenerator.html</a><dd>
<dt><a href="ResultConverter.html">ResultConverter.html</a><dd>
<dt><a href="call_method.html">call_method.html</a><dd>
<dt><a href="callbacks.html">callbacks.html</a><dd>
<dt><a href="data_members.html">data_members.html</a><dd>
<dt><a href="has_back_reference.html">has_back_reference.html</a><dd>
<dt><a href="implicit.html">implicit.html</a><dd>
<dt><a href="instance_holder.html">instance_holder.html</a><dd>
<dt><a href="operators.html">operators.html</a><dd>
<dt><a href="ptr.html">ptr.html</a><dd>
<dt><a href="type_id.html">type_id.html</a><dd>
<dt><a href="with_custodian_and_ward.html">with_custodian_and_ward.html</a><dd>
</dl>
</blockquote>
Major updates were made to the following pages:
<blockquote>
<dl>
<dt><a href="call.html">call.html</a><dd> <dt>updated<dd>
<dt><a href="class.html">class.html</a><dd>
<dt><a href="reference.html">reference.html</a><dd>
</dl>
</blockquote>
As usual, careful documentation forces one to consider the
interface again, and there were many interface changes
associated with this effort, including the elevation of the
following components from implementation detail to
first-class library citizen:
<blockquote>
<dl>
<dt>type_id.hpp<dd>
<dt>pointee.hpp<dd>
<dt>lvalue_from_pytype.hpp<dd></dl>
</dl>
</blockquote>
<h2><a name="misc">Miscellaneous</a></h2>
<h3><a name="converters">Converters</a></h3>
It appears that the world of C++ &lt;==&gt; Python conversion rules is
an endlessly-rich area of exploration. Completing the conversions for
<code>char</code> and <code>char const*</code> types, as described at
the end of <a href="Apr2002.html#missing">April's report</a>,
uncovered some interesting new shades to the problem. It turns out to
be worth distinguishing mutable and immutable lvalue conversions,
because despite the fact that Python doesn't understand
<code>const</code>, it does understand immutability (c.f. Python
strings, which expose an immutable <code>char</code> pointer). It is
also worth recognizing types which represent lvalue <i>sequences</i>,
to prevent Python <code>&quot;foobar&quot;</code> from being silently
truncated to C++ <code>'f'</code>. More details on this insight can be
found in the mailing list <a
href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">
archive</a>. I don't plan to do anything about this immediately, but I
do think it's the right direction to go in the long run.
<h3><a name="checkins">Checkins Mailing List</a></h3>
In order to better coordinate changes made by multiple developers, I
enabled <a
href="http://sourceforge.net/docman/display_doc.php?docid=772&group_id=1">syncmail</a>
for the Boost.Python CVS trees, and established an associated <a
href="http://lists.sourceforge.net/lists/listinfo/boost-python-cvs">mailing
list</a>. Subscribe to this list to receive notices of each new
checkin.
<h3><a name="shared">Shared Libraries</a></h3>
Beyond the vagaries of dynamic linking on AIX, I have been
participating in a more-general discussion of dynamic linking for
C++. Needless to say, C++ dynamic linking is of critical importance to
Boost.Python: all extension modules are normally built as shared
libraries, and Boost.Python extension modules share a common library
as well.
In fact, there are at least two separate conversations. One
in the C++ standard extensions mailing list concerns what can be
standardized for C++ and shared libraries; the other, mostly on the <a
href="http://gcc.gnu.org/ml/gcc/">gcc</a> mailing list, concerns the
behavior of GCC on Posix/ELF platforms.
Some of the GCC threads are here:
<blockquote>
<a
href="http://gcc.gnu.org/ml/gcc/2002-05/msg02002.html">http://gcc.gnu.org/ml/gcc/2002-05/msg02002.html</a><br>
<a
href="http://gcc.gnu.org/ml/gcc/2002-05/msg02945.html">http://gcc.gnu.org/ml/gcc/2002-05/msg02945.html</a><br>
<a href="http://gcc.gnu.org/ml/gcc/2002-05/msg01758.html">http://gcc.gnu.org/ml/gcc/2002-05/msg01758.html</a>
</blockquote>
<h2><a name="next">What's Next</a></h2>
Development is focused on what's needed to be able to retire
Boost.Python v1. At the moment, that means deciding the user-friendly
interfaces for to_/from_python conversion, and formally exposing the
Python object smart pointers and object wrapper classes. Quite a few
questions have also been showing up recently about how to embed Python
with Boost.Python, and how to link with it statically; the solutions
to these issues will probably have to be formalized before long.
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -1,153 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - ObjectWrapper Concept</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">ObjectWrapper and TypeWrapper Concepts</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#ObjectWrapper-concept">ObjectWrapper Concept</a></dt>
<dt><a href="#TypeWrapper-concept">TypeWrapper Concept</a></dt>
</dl>
</dd>
<dt><a href="#caveat">Caveat</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>This page defines two concepts used to describe classes which manage a
Python objects, and which are intended to support usage with a
Python-like syntax.</p>
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
<h3><a name="ObjectWrapper-concept"></a>ObjectWrapper Concept</h3>
Models of the ObjectWrapper concept have <a href=
"object.html#object-spec">object</a> as a publicly-accessible base class,
and are used to supply special construction behavior and/or additional
convenient functionality through (often templated) member functions.
Except when the return type <code>R</code> is itself an <a href=
"#TypeWrapper-concept">TypeWrapper</a>, a member function invocation of
the form
<pre>
x.<i>some_function</i>(<i>a<small>1</small>, a<small>2</small>,...a<small>n</small></i>)
</pre>
always has semantics equivalent to:
<pre>
<a href=
"extract.html#extract-spec">extract</a>&lt;R&gt;(x.attr("<i>some_function</i>")(<a
href=
"object.html#object-spec-ctors">object</a>(<i>a<small>1</small></i>), <a
href=
"object.html#object-spec-ctors">object</a>(<i>a<small>2</small></i>),...<a
href="object.html#object-spec-ctors">object</a>(<i>a<small>n</small></i>)))()
</pre>
When the <code>R</code> is an <a href=
"#TypeWrapper-concept">TypeWrapper</a>, the result type may be
constructed by taking direct posession of:
<pre>
x.attr("<i>some_function</i>")(<a href=
"object.html#object-spec-ctors">object</a>(<i>a<small>1</small></i>), <a
href=
"object.html#object-spec-ctors">object</a>(<i>a<small>2</small></i>),...<a
href=
"object.html#object-spec-ctors">object</a>(<i>a<small>n</small></i>)).ptr()
</pre>
[see <a href="#caveat">caveat</a> below]
<h3><a name="TypeWrapper-concept"></a>TypeWrapper Concept</h3>
TypeWrapper is a refinement of ObjectWrapper which is associated with a
particular Python type <code>X</code>. For a given TypeWrapper
<code>T</code>, a valid constructor expression
<pre>
T(<i>a<small>1</small>, a<small>2</small>,...a<small>n</small></i>)
</pre>
builds a new <code>T</code> object managing the result of invoking
<code>X</code> with arguments corresponding to
<pre>
<a href=
"object.html#object-spec-ctors">object</a>(<i>a<small>1</small></i>), <a
href=
"object.html#object-spec-ctors">object</a>(<i>a<small>2</small></i>),...<a
href=
"object.html#object-spec-ctors">object</a>(<i>a<small>n</small></i>)
</pre>
When used as arguments to wrapped C++ functions, or as the template
parameter to <code><a
href="extract.html#extract-spec">extract</a>&lt;&gt;</code>, only
instances of the associated Python type will be considered a match.
<h3><a name="caveat">Caveat</a></h3>
The upshot of the special member function invocation rules when the
return type is a TypeWrapper is that it is possible for the returned
object to manage a Python object of an inappropriate type. This is not
usually a serious problem; the worst-case result is that errors will be
detected at runtime a little later than they might otherwise be. For an
example of how this can occur, note that the <code><a href=
"dict.html#dict-spec">dict</a></code> member function <code>items</code>
returns an object of type <code><a href=
"list.html#list-spec">list</a></code>. Now suppose the user defines this
<code>dict</code> subclass in Python:
<pre>
&gt;&gt;&gt; class mydict(dict):
... def items(self):
... return tuple(dict.items(self)) # return a tuple
</pre>
Since an instance of <code>mydict</code> is also an instance of
<code>dict</code>, when used as an argument to a wrapped C++ function,
<code><a href="dict.html#dict-spec">boost::python::dict</a></code> can
accept objects of Python type <code>mydict</code>. Invoking
<code>items()</code> on this object can result in an instance of <code><a
href="list.html#list-spec">boost::python::list</a></code> which actually
holds a Python tuple. Subsequent attempts to use list methods (e.g.
<code>append</code>, or any other mutating operation) on this object will
raise the same exception that would occur if you tried to do it from
Python.
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,124 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Boost.Python - ResultConverter Concept</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">ResultConverter Concept</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#ResultConverter-concept">ResultConverter Concept</a></dt>
<dt><a href="#ResultConverterGenerator-concept">ResultConverterGenerator Concept</a></dt>
</dl>
</dd>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>A ResultConverter for a type <code>T</code> is a type whose
instances can be used to convert C++ return values of type
<code>T</code> <code>to_python</code>. A ResultConverterGenerator is
an MPL unary metafunction class which, given the return type of a C++
function, returns a ResultConverter for that type. ResultConverters in
Boost.Python generally inspect library's registry of converters to
find a suitable converter, but converters which don't use the registry
are also possible.
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
<h3><a name="ResultConverter-concept"></a>ResultConverter Concept</h3>
<p>In the table below, <code><b>C</b></code> denotes a ResultConverter
type for a type <b><code>R</code></b> , <code><b>c</b></code> denotes
an object of type <code><b>C</b></code> , and <code><b>r</b></code>
denotes an object of type <code><b>R</b></code>.
<table summary="ResultConverter expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Type</b></td>
<td><b>Semantics</b></td>
</tr>
<tr>
<td valign="top"><code>C c;</code></td>
<td>
<td>Constructs a <code>C</code> object.
</tr>
<tr>
<td valign="top"><code>c.convertible()</code></td>
<td>convertible to <code>bool</code></td>
<td><code>false</code> iff no conversion from any <code>R</code> value
to a Python object is possible.</td>
</tr>
<tr>
<td valign="top"><code>c(r)</code></td>
<td>convertible to <code>PyObject*</code></td>
<td>A pointer to a Python object corresponding to <code>r</code>,
or <code>0</code> iff <code>r</code> could not be converted
<code>to_python</code>, in which case <a
href="http://www.python.org/doc/current/api/exceptionHandling.html#l2h-71">PyErr_Occurred</a>
should return non-zero.</td>
</tr>
<tr>
<td valign="top"><code>c.get_pytype()</code></td>
<td><code>PyTypeObject const*</code></td>
<td>A pointer to a Python Type object corresponding to result of the conversion,
or <code>0</code>. Used for documentation generation. If <code>0</code> is returned
the generated type in the documentation will be <b>object</b> .</td>
</tr>
</table>
<h3><a name="ResultConverterGenerator-concept"></a>ResultConverterGenerator Concept</h3>
<p>In the table below, <code><b>G</b></code> denotes a
ResultConverterGenerator type and <code><b>R</b></code> denotes a possible
C++ function return type.
<table summary="ResultConverterGenerator expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Requirements</b></td>
</tr>
<tr>
<td valign="top"><code>G::apply&lt;R&gt;::type</code></td>
<td>A ResultConverter type for <code>R</code>.</td>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
09 May, 2002 <!--Luann's birthday! -->
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002. </i>
<p>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.
</body>
</html>

View File

@@ -1,135 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - Acknowledgments</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Acknowledgments</h2>
</td>
</tr>
</table>
<hr>
<p><a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> is
the architect, designer, and implementor of <b>Boost.Python</b>.</p>
<p><a href="mailto:brett.calcott@paradise.net.nz">Brett Calcott</a>
contributed and maintains the Visual Studio project files and
documentation.</p>
<p><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
Ganßauge</a> supplied support for opaque pointer conversions,
complete with documentation and a regression test (and I didn't
even have to ask him for those)!
<p>Joel de Guzman implemented the <a href="overloads.html">default
argument support</a> and wrote the excellent <a href=
"../tutorial/index.html">tutorial documentation</a>.</p>
<p><a href="http://www.boost.org/people/ralf_w_grosse_kunstleve.htm">Ralf W.
Grosse-Kunstleve</a> implemented the <a href="pickle.html">pickle
support</a>, and has enthusiastically supported the library since its
birth, contributing to design decisions and providing invaluable
real-world insight into user requirements. Ralf has written some <a href=
"faq.html#question2">extensions</a> for converting C++ containers that I
hope will be incorporated into the library soon. He also implemented the
cross-module support in the first version of Boost.Python. More
importantly, Ralf makes sure nobody forgets the near-perfect synergy of
C++ and Python for solving the problems of large-scale software
construction.</p>
<p><a href="http://www.boost.org/people/aleksey_gurtovoy.htm">Aleksey Gurtovoy</a>
wrote an incredible C++ <a href="http://www.mywikinet.com/mpl">Template
Metaprogramming Library</a> which allows Boost.Python to perform much of
its compile-time magic. In addition, Aleksey very generously contributed
his time and deep knowledge of the quirks of various buggy compilers to
help us get around problems at crucial moments.</p>
<p><a href="http://www.boost.org/people/paul_mensonides.htm">Paul Mensonides</a>,
building on the work <a href="http://www.boost.org/people/vesa_karvonen.htm">Vesa
Karvonen</a>, wrote a similarly amazing <a href=
"../../../preprocessor/doc/index.html">Preprocessor Metaprogramming
Library</a>, and generously contributed the time and expertise to get it
working in the Boost.Python library, rewriting much of Boost.Python to
use the new preproccessor metaprogramming constructs and helping us to
work around buggy and slow C++ preprocessors.</p>
<p><a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
Oliveira</a> contributed the ingenious <a
href="../../pyste/index.html">Pyste</a> (&quot;Pie-Steh&quot;)
code generator.
<p><a href="mailto:nickm@sitius.com">Nikolay Mladenov</a> contributed
<code>staticmethod</code> support.</p>
<p>Martin Casado solved some sticky problems which allow us to build the
Boost.Python shared library for AIX's crazy dynamic linking model.</p>
<p><a href="mailto:achim@procoders.net">Achim Domma</a> contributed some
of the <a href="reference.html#object_wrappers">Object Wrappers</a> and
HTML templates for this documentation. Dave Hawkes contributed
inspiration for the use of the <code><a href=
"scope.html#scope-spec">scope</a></code> class to simplify module
definition syntax. Pearu Pearson wrote some of the test cases that are in
the current test suite.</p>
<p>The development of this version of Boost.Python was funded in part by
the <a href="http://www.llnl.gov/">Lawrence Livermore National
Laboratories</a> and by the <a href="http://cci.lbl.gov/">Computational
Crystallography Initiative</a> at Lawrence Berkeley National
Laboratories.</p>
<p><a href="http://kogs-www.informatik.uni-hamburg.de/~koethe/">Ullrich
Koethe</a> had independently developed a similar system. When he
discovered Boost.Python v1, he generously contributed countless hours of
coding and much insight into improving it. He is responsible for an early
version of the support for function overloading and wrote the support for
reflecting C++ inheritance relationships. He has helped to improve
error-reporting from both Python and C++ (we hope to do as well in v2
again soon), and has designed the original support for exposing numeric
operators, including a way to avoid explicit coercion by means of
overloading.</p>
<p>The members of the boost mailing list and the Python community
supplied invaluable early feedback. In particular, Ron Clarke, Mark
Evans, Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott
took the brave step of trying to use Boost.Python while it was still in
early stages of development.</p>
<p>The first version of Boost.Python would not have been possible without
the support of Dragon Systems, which supported its development and
release as a Boost library.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
26 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,199 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/args.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header &lt;boost/python/args.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#keyword-expression"><i>keyword-expressions</i></a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#arg-spec">class <code>arg</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#arg-synopsis">class <code>arg</code>
synopsis</a></dt>
<dt><a href="#arg-ctor">class <code>arg</code>
constructor</a></dt>
<dt><a href="#arg-operator">class <code>arg</code> template
<code>operator =</code></a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#keyword-expression-operators"><i>Keyword-expression</i>
operator <code>,</code></a></dt>
<dt><a href="#functions">Functions (deprecated)</a></dt>
<dd>
<dl class="page-index">
<dt><code><a href=
"#args-spec">args</a>(</code>...<code>)</code></dt>
</dl>
</dd>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Supplies a family of overloaded functions for specifying argument
keywords for wrapped C++ functions.</p>
<h2><a name="keyword-expression"></a><i>keyword-expressions</i></h2>
<p>A <b>keyword-expression</b> results in an object which holds a
sequence of <a href="definitions.html#ntbs">ntbs</a>es, and whose type
encodes the number of keywords specified. The <b>keyword-expression</b>
may contain default values for some or all of the keywords it holds</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="arg-spec"></a><code>class arg;</code></h3>
<p>The objects of class arg are keyword-expressions holding one keyword (
size one )</p>
<h4><a name="arg-synopsis"></a>Class <code>arg</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
struct arg
{
template &lt;class T&gt;
arg &amp;perator = (T const &amp;value);
explicit arg (char const *name){elements[0].name = name;}
};
}}
</pre>
<h4><a name="arg-ctor"></a>Class <code>arg</code> constructor</h4>
<pre>
arg(char const* name);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> The argument must be a <a href=
"definitions.html#ntbs">ntbs</a>.</dt>
<dt><b>Effects:</b> Constructs an <code>arg</code> object holding a
keyword with name <code>name</code>.</dt>
</dl>
<h4><a name="arg-operator"></a>Class <code>arg</code> operator =</h4>
<pre>
template &lt;class T&gt; arg &amp;operator = (T const &amp;value);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> The argument must convertible to python.</dt>
<dt><b>Effects:</b> Assigns default value for the keyword.</dt>
<dt><b>Returns:</b> Reference to <code>this</code>.</dt>
</dl>
<h2><a name="keyword-expression-operators"><i>Keyword-expression</i>
operator <code>,</code></a></h2>
<pre>
<i>keyword-expression</i> operator , (<i>keyword-expression</i>, const arg &amp;kw) const
<i>keyword-expression</i> operator , (<i>keyword-expression</i>, const char *name) const;
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> The argument <code>name</code> must be a <a href=
"definitions.html#ntbs">ntbs</a>.</dt>
<dt><b>Effects:</b> Extends the <i>keyword-expression</i> argument with
one more keyword.</dt>
<dt><b>Returns:</b> The extended <i>keyword-expression</i>.</dt>
</dl>
<h2><font color="#7F7F7F"><a name="functions"></a>Functions
(deprecated)</font></h2>
<h3><a name="args-spec"></a><code><font color=
"#7F7F7F">args</font>(</code>...<code>)</code></h3>
<pre>
<font color="#7F7F7F"> <i>unspecified1</i> args(char const*);
<i>unspecified2</i> args(char const*, char const*);
.
.
.
<i>unspecifiedN</i> args(char const*, char const*, ... char const*);
</font>
</pre>
<dl class="function-semantics">
<dt><font color="#7F7F7F"><b>Requires:</b> Every argument must be a <a
href="definitions.html#ntbs">ntbs</a>.</font></dt>
<dt><font color="#7F7F7F"><b>Returns:</b> an object representing a <a
href="#keyword-expression"><i>keyword-expression</i></a> encapsulating
the arguments passed.</font></dt>
</dl>
<h2><a name="examples"></a>Example</h2>
<pre>
#include &lt;boost/python/def.hpp&gt;
using namespace boost::python;
int f(double x, double y, double z=0.0, double w=1.0);
BOOST_PYTHON_MODULE(xxx)
{
def("f", f
, ( arg("x"), "y", arg("z")=0.0, arg("w")=1.0 )
);
}
</pre>
<p>Revised 01 August, 2003</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
</body>
</html>

View File

@@ -1,85 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;call.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header &lt;call.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#functions">Functions</a></dt>
<dl class="page-index">
<dt><a href="#call-spec">call</a></dt>
</dl>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>
<code>&lt;boost/python/call.hpp&gt;</code> defines the <a
href="#call-spec"><code>call</code></a> family of overloaded function
templates, used to invoke Python callable objects from C++.
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name="call-spec">template &lt;class R, class A1, class A2, ... class A<i>n</i>&gt;</a>
R call(PyObject* callable, A1 const&amp;, A2 const&amp;, ... A<i>n</i> const&amp;)
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>R</code> is a pointer type, reference
type, or a complete type with an accessible copy constructor</dt>
<dt><b>Effects:</b> Invokes <code>callable(a1,&nbsp;a2,&nbsp;...a<i>n</i>)</code> in
Python, where <code>a1</code>...<code>a<i>n</i></code> are the arguments to
<code>call()</code>, converted to Python objects.
<dt><b>Returns:</b> The result of the Python call, converted to the C++ type <code>R</code>.</dt>
</dt>
<dt><b>Rationale:</b> For a complete semantic description and
rationale, see <a href="callbacks.html">this page</a>.
</dt>
</dl>
<h2><a name="examples"></a>Example(s)</h2>
The following C++ function applies a Python callable object to its two
arguments and returns the result. If a Python exception is raised or
the result can't be converted to a <code>double</code>, an exception
is thrown.
<pre>
double apply2(PyObject* func, double x, double y)
{
return boost::python::call&lt;double&gt;(func, x, y);
}
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
9 May, 2002 <!-- Luann's birthday! -->
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -1,161 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;call_method.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header &lt;call_method.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#functions">Functions</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#call_method-spec">call_method</a></dt>
</dl>
</dd>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p><code>&lt;boost/python/call_method.hpp&gt;</code> defines the <a href=
"#call_method-spec"><code>call_method</code></a> family of overloaded
function templates, used to invoke callable attributes of Python objects
from C++.</p>
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name=
"call_method-spec">template &lt;class R, class A1, class A2, ... class A<i>n</i>&gt;</a>
R call_method(PyObject* self, char const* method, A1 const&amp;, A2 const&amp;, ... A<i>n</i> const&amp;)
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>R</code> is a pointer type, reference type,
or a complete type with an accessible copy constructor</dt>
<dt><b>Effects:</b> Invokes
<code>self.<i>method</i>(a1,&nbsp;a2,&nbsp;...a<i>n</i>)</code> in
Python, where <code>a1</code>...<code>a<i>n</i></code> are the
arguments to <code>call_method()</code>, converted to Python objects.
For a complete semantic description, see <a href="callbacks.html">this
page</a>.</dt>
<dt><b>Returns:</b> The result of the Python call, converted to the C++
type <code>R</code>.</dt>
<dt><b>Rationale:</b> <code>call_method</code> is critical to
implementing C++ virtual functions which are overridable in Python, as
shown by the example below.</dt>
</dl>
<h2><a name="examples"></a>Example(s)</h2>
The following C++ illustrates the use of <code>call_method</code> in
wrapping a class with a virtual function that can be overridden in
Python:
<h3>C++ Module Definition</h3>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/class.hpp&gt;
#include &lt;boost/utility.hpp&gt;
#include &lt;cstring&gt;
// class to be wrapped
class Base
{
public:
virtual char const* class_name() const { return "Base"; }
virtual ~Base();
};
bool is_base(Base* b)
{
return !std::strcmp(b-&gt;class_name(), "Base");
}
// Wrapper code begins here
using namespace boost::python;
// Callback class
class Base_callback : public Base
{
public:
Base_callback(PyObject* self) : m_self(self) {}
char const* class_name() const { return <b>call_method</b>&lt;char const*&gt;(m_self, "class_name"); }
char const* Base_name() const { return Base::class_name(); }
private:
PyObject* const m_self;
};
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
def("is_base", is_base);
class_&lt;Base,Base_callback, noncopyable&gt;("Base")
.def("class_name", &amp;Base_callback::Base_name)
;
}
</pre>
<h3>Python Code</h3>
<pre>
&gt;&gt;&gt; from my_module import *
&gt;&gt;&gt; class Derived(Base):
... def __init__(self):
... Base.__init__(self)
... def class_name(self):
... return self.__class__.__name__
...
&gt;&gt;&gt; is_base(Base()) # calls the class_name() method from C++
1
&gt;&gt;&gt; is_base(Derived())
0
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,254 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - Calling Python Functions and Methods</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Calling Python Functions and Methods</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#argument_handling">Argument Handling</a></dt>
<dt><a href="#result_handling">Result Handling</a></dt>
<dt><a href="#result_handling">Rationale</a></dt>
</dl>
<hr>
<h2><a name="introduction">Introduction</a></h2>
The simplest way to call a Python function from C++, given an <code><a
href="object.html#object-spec">object</a></code> instance <code>f</code>
holding the function, is simply to invoke its function call operator.
<pre>
f("tea", 4, 2) // In Python: f('tea', 4, 2)
</pre>
And of course, a method of an <code><a href=
"object.html#object-spec">object</a></code> instance <code>x</code> can
be invoked by using the function-call operator of the corresponding
attribute:
<pre>
x.attr("tea")(4, 2); // In Python: x.tea(4, 2)
</pre>
<p>If you don't have an <code>object</code> instance, Boost.Python
provides two families of function templates, <code><a href=
"call.html#call-spec">call</a></code> and <code><a href=
"call_method.html#call_method-spec">call_method</a></code>, for invoking
Python functions and methods respectively on <code>PyObject*</code>s. The
interface for calling a Python function object (or any Python callable
object) looks like:</p>
<pre>
call&lt;ResultType&gt;(callable_object, a1, a2... a<i>N</i>);
</pre>
Calling a method of a Python object is similarly easy:
<pre>
call_method&lt;ResultType&gt;(self_object, "<i>method-name</i>", a1, a2... a<i>N</i>);
</pre>
This comparitively low-level interface is the one you'll use when
implementing C++ virtual functions that can be overridden in Python.
<h2><a name="argument_handling">Argument Handling</a></h2>
<p>Arguments are converted to Python according to their type. By default,
the arguments <code>a1</code>...<code>a<i>N</i></code> are copied into
new Python objects, but this behavior can be overridden by the use of
<code><a href="ptr.html#ptr-spec">ptr()</a></code> and <a href=
"../../../bind/ref.html">ref()</a>:</p>
<pre>
class X : boost::noncopyable
{
...
};
void apply(PyObject* callable, X&amp; x)
{
// Invoke callable, passing a Python object which holds a reference to x
boost::python::call&lt;void&gt;(callable, boost::ref(x));
}
</pre>
In the table below, <code><b>x</b></code> denotes the actual argument
object and <code><b>cv</b></code> denotes an optional
<i>cv-qualification</i>: "<code>const</code>", "<code>volatile</code>",
or "<code>const volatile</code>".
<table border="1" summary="class_ template parameters">
<tr>
<th>Argument Type</th>
<th>Behavior</th>
</tr>
<tr>
<td><code>T cv&amp;</code><br>
<code>T cv</code></td>
<td>The Python argument is created by the same means used for the
return value of a wrapped C++ function returning <code>T</code>. When
<code>T</code> is a class type, that normally means <code>*x</code>
is copy-constructed into the new Python object.</td>
</tr>
<tr>
<td><code>T*</code></td>
<td>If <code>x&nbsp;==&nbsp;0</code>, the Python argument will be
<code><a href=
"http://www.python.org/doc/current/lib/bltin-null-object.html">None</a></code>.
Otherwise, the Python argument is created by the same means used for
the return value of a wrapped C++ function returning <code>T</code>.
When <code>T</code> is a class type, that normally means
<code>*x</code> is copy-constructed into the new Python object.</td>
</tr>
<tr>
<td><code><a href=
"../../../bind/ref.html">boost::reference_wrapper</a>&lt;T&gt;</code></td>
<td>The Python argument contains a pointer to, rather than a copy of,
<code>x.get()</code>. Note: failure to ensure that no Python code
holds a reference to the resulting object beyond the lifetime of
<code>*x.get()</code> <b>may result in a crash!</b></td>
</tr>
<tr>
<td><code><a href=
"ptr.html#pointer_wrapper-spec">pointer_wrapper</a>&lt;T&gt;</code></td>
<td>If <code>x.get()&nbsp;==&nbsp;0</code>, the Python argument will
be <code><a href=
"http://www.python.org/doc/current/lib/bltin-null-object.html">None</a></code>.
Otherwise, the Python argument contains a pointer to, rather than a
copy of, <code>*x.get()</code>. Note: failure to ensure that no
Python code holds a reference to the resulting object beyond the
lifetime of <code>*x.get()</code> <b>may result in a crash!</b></td>
</tr>
</table>
<h2><a name="result_handling">Result Handling</a></h2>
In general, <code>call&lt;ResultType&gt;()</code> and
<code>call_method&lt;ResultType&gt;()</code> return
<code>ResultType</code> by exploiting all lvalue and rvalue
<code>from_python</code> converters registered for ResultType and
returning a copy of the result. However, when <code>ResultType</code> is
a pointer or reference type, Boost.Python searches only for lvalue
converters. To prevent dangling pointers and references, an exception
will be thrown if the Python result object has only a single reference
count.
<h2><a name="rationale">Rationale</a></h2>
In general, to get Python arguments corresponding to
<code>a1</code>...<code>a<i>N</i></code>, a new Python object must be
created for each one; should the C++ object be copied into that Python
object, or should the Python object simply hold a reference/pointer to
the C++ object? In general, the latter approach is unsafe, since the
called function may store a reference to the Python object somewhere. If
the Python object is used after the C++ object is destroyed, we'll crash
Python.
<p>In keeping with the philosophy that users on the Python side shouldn't
have to worry about crashing the interpreter, the default behavior is to
copy the C++ object, and to allow a non-copying behavior only if the user
writes <code><a href="../../../bind/ref.html">boost::ref</a>(a1)</code>
instead of a1 directly. At least this way, the user doesn't get dangerous
behavior "by accident". It's also worth noting that the non-copying
("by-reference") behavior is in general only available for class types,
and will fail at runtime with a Python exception if used otherwise[<a
href="#1">1</a>].</p>
<p>However, pointer types present a problem: one approach is to refuse to
compile if any aN has pointer type: after all, a user can always pass
<code>*aN</code> to pass "by-value" or <code>ref(*aN)</code> to indicate
a pass-by-reference behavior. However, this creates a problem for the
expected null pointer to <code>None</code> conversion: it's illegal to
dereference a null pointer value.</p>
<p>The compromise I've settled on is this:</p>
<ol>
<li>The default behavior is pass-by-value. If you pass a non-null
pointer, the pointee is copied into a new Python object; otherwise the
corresponding Python argument will be None.</li>
<li>if you want by-reference behavior, use <code>ptr(aN)</code> if
<code>aN</code> is a pointer and <code>ref(aN)</code> otherwise. If a
null pointer is passed to <code>ptr(aN)</code>, the corresponding
Python argument will be <code>None</code>.</li>
</ol>
<p>As for results, we have a similar problem: if <code>ResultType</code>
is allowed to be a pointer or reference type, the lifetime of the object
it refers to is probably being managed by a Python object. When that
Python object is destroyed, our pointer dangles. The problem is
particularly bad when the <code>ResultType</code> is char const* - the
corresponding Python String object is typically uniquely-referenced,
meaning that the pointer dangles as soon as <code>call&lt;char
const*&gt;(...)</code> returns.</p>
<p>The old Boost.Python v1 deals with this issue by refusing to compile
any uses of <code>call&lt;char const*&gt;()</code>, but this goes both
too far and not far enough. It goes too far because there are cases where
the owning Python string object survives beyond the call (just for
instance, when it's the name of a Python class), and it goes not far
enough because we might just as well have the same problem with a
returned pointer or reference of any other type.</p>
<p>In Boost.Python v2 this is dealt with by:</p>
<ol>
<li>lifting the compile-time restriction on const char* callback
returns</li>
<li>detecting the case when the reference count on the result Python
object is 1 and throwing an exception inside of
<code>call&lt;U&gt;(...)</code> when <code>U</code> is a pointer or
reference type.</li>
</ol>
This should be acceptably safe because users have to explicitly specify a
pointer/reference for <code>U</code> in <code>call&lt;U&gt;</code>, and
they will be protected against dangles at runtime, at least long enough
to get out of the <code>call&lt;U&gt;(...)</code> invocation.
<hr>
<a name="1">[1]</a> It would be possible to make it fail at compile-time
for non-class types such as int and char, but I'm not sure it's a good
idea to impose this restriction yet.
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,92 +0,0 @@
.. Copyright David Abrahams 2006. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Here's the plan:
I aim to provide an interface similar to that of Boost.Python v1's
callback<>::call(...) for dealing with callbacks. The interface will
look like:
returning<ResultType>::call("method_name", self_object, a1, a2...);
or
returning<ResultType>::call(callable_object, a1, a2...);
ARGUMENT HANDLING
There is an issue concerning how to make Python objects from the
arguments a1...aN. A new Python object must be created; should the C++
object be copied into that Python object, or should the Python object
simply hold a reference/pointer to the C++ object? In general, the
latter approach is unsafe, since the called function may store a
reference to the Python object somewhere. If the Python object is used
after the C++ object is destroyed, we'll crash Python.
I plan to make the copying behavior the default, and to allow a
non-copying behavior if the user writes boost::ref(a1) instead of a1
directly. At least this way, the user doesn't get dangerous behavior "by
accident". It's also worth noting that the non-copying ("by-reference")
behavior is in general only available for class types, and will fail at
runtime with a Python exception if used otherwise**
However, pointer types present a problem: My first thought is to refuse
to compile if any aN has pointer type: after all, a user can always pass
*aN to pass "by-value" or ref(*aN) to indicate a pass-by-reference
behavior. However, this creates a problem for the expected NULL pointer
=> None conversion: it's illegal to dereference a null pointer value.
We could use another construct, say "ptr(aN)", to deal with null
pointers, but then what does it mean? We know what it does when aN is
NULL, but it might either have by-value or by-reference behavior when aN
is non-null.
The compromise I've settled on is this:
1. The default behavior is pass-by-value. If you pass a non-null
pointer, the pointee is copied into a new Python object; otherwise
the corresponding Python argument will be None.
2. if you want by-reference behavior, use ptr(aN) if aN is a pointer
and ref(aN) otherwise. If a null pointer is passed to ptr(aN), the
corresponding Python argument will be None.
RESULT HANDLING
As for results, we have a similar problem: if ResultType is allowed to
be a pointer or reference type, the lifetime of the object it refers to
is probably being managed by a Python object. When that Python object is
destroyed, our pointer dangles. The problem is particularly bad when the
ResultType is char const* - the corresponding Python String object is
typically uniquely-referenced, meaning that the pointer dangles as soon
as returning<char const*>::call() returns.
Boost.Python v1 deals with this issue by refusing to compile any uses of
callback<char const*>::call(), but IMO this goes both too far and not
far enough. It goes too far because there are cases where the owning
String object survives beyond the call (just for instance when it's the
name of a Python class), and it goes not far enough because we might
just as well have the same problem with any returned pointer or
reference.
I propose to address this in Boost.Python v2 by
1. lifting the compile-time restriction on const
char* callback returns
2. detecting the case when the reference count on the
result Python object is 1 and throwing an exception
inside of returning<U>::call() when U is a pointer or
reference type.
I think this is acceptably safe because users have to explicitly specify
a pointer/reference for U in returning<U>, and they will be protected
against dangles at runtime, at least long enough to get out of the
returning<U>::call() invocation.
-Dave
**It would be possible to make it fail at compile-time for non-class
types such as int and char, but I'm not sure it's a good idea to impose
this restriction yet.

View File

@@ -1,790 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st September 2004), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-latin-1-dos">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/class.hpp&gt;,
&lt;boost/python/class_fwd.hpp&gt;</title>
</head>
<body link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Headers &lt;boost/python/class.hpp&gt;,
&lt;boost/python/class_fwd.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#class_-spec">Class template
<code>class_</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#class_-spec-synopsis">Class <code>class_</code>
synopsis</a></dt>
<dt><a href="#class_-spec-ctors">Class <code>class_</code>
constructors</a></dt>
<dt><a href="#class_-spec-modifiers">Class <code>class_</code>
modifier functions</a></dt>
</dl>
</dd>
<dt><a href="#bases-spec">Class template <code>bases</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#bases-spec-synopsis">Class template
<code>bases</code> synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction" id="introduction"></a>Introduction</h2>
<p><code>&lt;boost/python/class.hpp&gt;</code> defines the interface
through which users expose their C++ classes to Python. It declares the
<code>class_</code> class template, which is parameterized on the class
type being exposed. It also exposes the <code>init</code>,
<code>optional</code> and <code>bases</code> utility class templates, which
are used in conjunction with <code>class_</code>.</p>
<p><code>&lt;boost/python/class_fwd.hpp&gt;</code> contains a forward
declaration of the <code>class_</code> class template.</p>
<h2><a name="classes" id="classes"></a>Classes</h2>
<h3><a name="class_-spec" id="class_-spec"></a>Class template
<code>class_&lt;T,&nbsp;<font color="#007F00">Bases,&nbsp;HeldType,
NonCopyable</font>&gt;</code></h3>
<p>Creates a Python class associated with the C++ type passed as its first
parameter. Although it has four template parameters, only the first one is
required. The three optional arguments can actually be supplied
<font color="#007F00"><b>in any order</b></font>; Boost.Python determines
the role of the argument from its type.<br>
<br></p>
<table border="1" summary="class_ template parameters">
<tr>
<th>Template Parameter</th>
<th>Requirements</th>
<th>Semantics</th>
<th>Default</th>
</tr>
<tr>
<td><code>T</code></td>
<td>A class type.</td>
<td>The class being wrapped</td>
</tr>
<tr>
<td><code><font color="#007F00">Bases</font></code></td>
<td>A specialization of <a href=
"#bases-spec"><code>bases&lt;</code>...<code>&gt;</code></a> which
specifies previously-exposed C++ base classes of <code>T</code><a href=
"#footnote_1">[1]</a>.</td>
<td>Registers <code>from_python</code> conversions from wrapped
<code>T</code> instances to each of its exposed direct and indirect
bases. For each polymorphic base <code>B</code>, registers conversions
from indirectly-held wrapped <code>B</code> instances to
<code>T</code>.</td>
<td><code><a href="#bases-spec">bases&lt;&gt;</a></code></td>
</tr>
<tr>
<td><code><font color="#007F00">HeldType</font></code></td>
<td>Must be <code>T</code>, a class derived from <code>T</code>, or a
<a href="Dereferenceable.html">Dereferenceable</a> type for which
<code><a href=
"pointee.html#pointee-spec">pointee</a>&lt;HeldType&gt;::type</code> is
<code>T</code> or a class derived from <code>T</code>.</td>
<td>Specifies the type that is actually embedded in a Python object
wrapping a <code>T</code> instance when <code>T</code>'s constructor is
called or when a <code>T</code> or <code>T*</code> is converted to
Python without the use of <a href=
"http://www.boost.org/libs/python/doc/v2/callbacks.html#argument_handling">
<code>ptr</code></a>, <a href=
"http://www.boost.org/libs/python/doc/v2/callbacks.html#argument_handling">
<code>ref</code></a>, or <a href="CallPolicies.html">Call Policies</a>
such as <code><a href=
"return_internal_reference.html">return_internal_reference</a></code>.
More details <a href="#HeldType">below</a>.</td>
<td><code>T</code></td>
</tr>
<tr>
<td><code><font color="#007F00">NonCopyable</font></code></td>
<td>If supplied, must be <a href=
"../../../utility/utility.htm#Class_noncopyable">boost::noncopyable</a>.</td>
<td>Suppresses automatic registration of <code>to_python</code>
conversions which copy <code>T</code> instances. Required when
<code>T</code> has no publicly-accessible copy constructor.</td>
<td>An unspecified type other than
<code>boost::noncopyable</code>.</td>
</tr>
</table>
<h4><a name="HeldType" id="HeldType">HeldType Semantics</a></h4>
<ol>
<li>If <code>HeldType</code> is derived from T, its exposed
constructor(s) must accept an initial <code>PyObject*</code> argument
which refers back to the Python object that contains the
<code>HeldType</code> instance, as shown in <a href=
"call_method.html#examples">this example</a>. This argument is not
included in the <em><a href=
"init.html#init-expressions">init-expression</a></em> passed to <a href=
"#class_-spec-modifiers"><code>def(init_expr)</code></a>, below, nor is
it passed explicitly by users when Python instances of <code>T</code> are
created. This idiom allows C++ virtual functions which will be overridden
in Python to access the Python object so the Python method can be
invoked. Boost.Python automatically registers additional converters which
allow wrapped instances of <code>T</code> to be passed to wrapped C++
functions expecting <code>HeldType</code> arguments.</li>
<li>Because Boost.Python will always allow wrapped instances of
<code>T</code> to be passed in place of <code>HeldType</code> arguments,
specifying a smart pointer for <code>HeldType</code> allows users to pass
Python <code>T</code> instances where a smart pointer-to-<code>T</code>
is expected. Smart pointers such as <code>std::auto_ptr&lt;&gt;</code> or
<code><a href=
"../../../smart_ptr/shared_ptr.htm">boost::shared_ptr&lt;&gt;</a></code>
which contain a nested type <code>element_type</code> designating the
referent type are automatically supported; additional smart pointer types
can be supported by specializing <a href=
"pointee.html#pointee-spec">pointee&lt;HeldType&gt;</a>.</li>
<li>As in case 1 above, when <code>HeldType</code> is a smart pointer to
a class derived from <code>T</code>, the initial <code>PyObject*</code>
argument must be supplied by all of <code>HeldType</code>'s exposed
constructors.</li>
<li>Except in cases 1 and 3, users may optionally specify that T itself
gets initialized with a similar initial <code>PyObject*</code> argument
by specializing <a href=
"has_back_reference.html#has_back_reference-spec">has_back_reference&lt;T&gt;</a>.</li>
</ol>
<h4><a name="class_-spec-synopsis" id="class_-spec-synopsis"></a>Class
template <code>class_</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
template &lt;class T
<font color="#007F00"> , class Bases = bases&lt;&gt;
, class HeldType = T
, class NonCopyable = <i>unspecified</i>
&gt;
</font> class class_ : public <a href="object.html#object-spec">object</a>
{
// Constructors with default __init__
class_(char const* name);
class_(char const* name, char const* docstring);
// Constructors, specifying non-default __init__
template &lt;class Init&gt;
class_(char const* name, Init);
template &lt;class Init&gt;
class_(char const* name, char const* docstring, Init);
// Exposing additional __init__ functions
template &lt;class Init&gt;
class_&amp; def(Init);
// defining methods
template &lt;class F&gt;
class_&amp; def(char const* name, F f);
template &lt;class Fn, class A1&gt;
class_&amp; def(char const* name, Fn fn, A1 const&amp;);
template &lt;class Fn, class A1, class A2&gt;
class_&amp; def(char const* name, Fn fn, A1 const&amp;, A2 const&amp;);
template &lt;class Fn, class A1, class A2, class A3&gt;
class_&amp; def(char const* name, Fn fn, A1 const&amp;, A2 const&amp;, A3 const&amp;);
// declaring method as static
class_&amp; staticmethod(char const* name);
// exposing operators
template &lt;<i>unspecified</i>&gt;
class_&amp; def(<a href=
"operators.html#operator_-spec">detail::operator_</a>&lt;unspecified&gt;);
// Raw attribute modification
template &lt;class U&gt;
class_&amp; setattr(char const* name, U const&amp;);
// exposing data members
template &lt;class D&gt;
class_&amp; def_readonly(char const* name, D T::*pm);
template &lt;class D&gt;
class_&amp; def_readwrite(char const* name, D T::*pm);
// exposing static data members
template &lt;class D&gt;
class_&amp; def_readonly(char const* name, D const&amp; d);
template &lt;class D&gt;
class_&amp; def_readwrite(char const* name, D&amp; d);
// property creation
template &lt;class Get&gt;
void add_property(char const* name, Get const&amp; fget, char const* doc=0);
template &lt;class Get, class Set&gt;
void add_property(
char const* name, Get const&amp; fget, Set const&amp; fset, char const* doc=0);
template &lt;class Get&gt;
void add_static_property(char const* name, Get const&amp; fget);
template &lt;class Get, class Set&gt;
void add_static_property(char const* name, Get const&amp; fget, Set const&amp; fset);
// pickle support
template &lt;typename PickleSuite&gt;
self&amp; def_pickle(PickleSuite const&amp;);
self&amp; enable_pickling();
};
}}
</pre>
<h4><a name="class_-spec-ctors" id="class_-spec-ctors"></a>Class template
<code>class_</code> constructors</h4>
<pre>
class_(char const* name);
class_(char const* name, char const* docstring);
template &lt;class Init&gt;
class_(char const* name, Init init_spec);
template &lt;class Init&gt;
class_(char const* name, char const* docstring, Init init_spec);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>. If <code>docstring</code> is supplied, it must be an
<a href="definitions.html#ntbs">ntbs</a>. If <code>init_spec</code> is
supplied, it must be either the special enumeration constant
<code>no_init</code> or an <a href=
"init.html#init-expressions">init-expression</a> compatible with
<code>T</code>.</dt>
<dt><b>Effects:</b> Constructs a <code>class_</code> object holding a
Boost.Python extension class named <code>name</code>. The
<code>name</code>d attribute of the <a href=
"scope.html#introduction">current scope</a> is bound to the new extension
class.</dt>
<dd>
<ul>
<li>If supplied, the value of <code>docstring</code> is bound to the
<code>__doc__</code> attribute of the extension class.</li>
<li>If <code>init_spec</code> is <code>no_init</code>, a special
<code>__init__</code> function is generated which always raises a
Python exception. Otherwise, <code>this-&gt;def(init_spec)</code> is
called.</li>
<li>If <code>init_spec</code> is not supplied,
<code>this-&gt;def(init&lt;&gt;())</code> is called.</li>
</ul>
</dd>
<dt><b>Rationale:</b>Allowing the user to specify constructor arguments
in the <code>class_&lt;&gt;</code> constructor helps her to avoid the
common run-time errors which result from invoking wrapped member
functions without having exposed an <code>__init__</code> function which
creates the requisite <code>T</code> instance. Types which are not
default-constructible will cause a compile-time error unless
<code>Init</code> is supplied. The user must always supply
<code>name</code> as there is currently no portable method to derive the
text of the class name from its type.</dt>
</dl>
<h4><a name="class_-spec-modifiers" id="class_-spec-modifiers"></a>Class
template <code>class_</code> modifier functions</h4>
<pre>
template &lt;class Init&gt;
class_&amp; def(Init init_expr);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>init_expr</code> is the result of an <a href=
"init.html#init-expressions">init-expression</a> compatible with
<code>T</code>.</dt>
<dt><b>Effects:</b> For each <a href="init.html#init-expressions">valid
prefix</a> <em>P</em> of <code>Init</code>, adds an
<code>__init__(</code>...<code>)</code> function overload to the
extension class accepting <em>P</em> as arguments. Each overload
generated constructs an object of <code>HeldType</code> according to the
semantics described <a href="#HeldType">above</a>, using a copy of
<code>init_expr</code>'s <a href="CallPolicies.html">call policies</a>.
If the longest <a href="init.html#init-expressions">valid prefix</a> of
<code>Init</code> contains <em>N</em> types and <code>init_expr</code>
holds <em>M</em> keywords, an initial sequence of the keywords are used
for all but the first <em>N</em> - <em>M</em> arguments of each
overload.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Allows users to easily expose a class' constructor
to Python.</dt>
</dl><br>
<pre>
template &lt;class F&gt;
class_&amp; def(char const* name, Fn fn);
template &lt;class Fn, class A1&gt;
class_&amp; def(char const* name, Fn fn, A1 const&amp; a1);
template &lt;class Fn, class A1, class A2&gt;
class_&amp; def(char const* name, Fn fn, A1 const&amp; a1, A2 const&amp; a2);
template &lt;class Fn, class A1, class A2, class A3&gt;
class_&amp; def(char const* name, Fn fn, A1 const&amp; a1, A2 const&amp; a2, A3 const&amp; a3);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>.</dt>
<dd>
<ul>
<li>If <code>a1</code> is the result of an <a href=
"overloads.html#overload-dispatch-expression"><em>overload-dispatch-expression</em></a>,
only the second form is allowed and fn must be a pointer to function
or pointer to member function whose <a href="definitions.html#arity">
arity</a> is the same as A1's <a href=
"overloads.html#overload-dispatch-expression"><em>maximum
arity</em></a>.
<dl>
<dt><b>Effects:</b> For each prefix <em>P</em> of
<code>Fn</code>'s sequence of argument types, beginning with the
one whose length is <code>A1</code>'s <a href=
"overloads.html#overload-dispatch-expression"><em>minimum
arity</em></a>, adds a
<code><em>name</em>(</code>...<code>)</code> method overload to
the extension class. Each overload generated invokes
<code>a1</code>'s call-expression with <em>P</em>, using a copy
of <code>a1</code>'s <a href="CallPolicies.html">call
policies</a>. If the longest valid prefix of <code>A1</code>
contains <em>N</em> types and <code>a1</code> holds <em>M</em>
keywords, an initial sequence of the keywords are used for all
but the first <em>N</em> - <em>M</em> arguments of each
overload.<br></dt>
</dl>
</li>
<li>Otherwise, a single method overload is built around fn, which
must not be null:
<ul>
<li>If fn is a function pointer, its first argument must be of
the form <code>U</code>, <code>U <em>cv</em>&amp;</code>, <code>U
<em>cv</em>*</code>, or <code>U <em>cv</em>* const&amp;</code>,
where <code>T*</code> is convertible to <code>U*</code>, and
<code>a1</code>-<code>a3</code>, if supplied, may be selected in
any order from the table below.</li>
<li>Otherwise, if fn is a member function pointer, its target
must be <code>T</code> or one of its public base classes, and
<code>a1</code>-<code>a3</code>, if supplied, may be selected in
any order from the table below.</li>
<li>Otherwise, <code>Fn</code> must be [derived from]
<code><a href="object.html#object-spec">object</a></code>, and
<code>a1-a2</code>, if supplied, may be selcted in any order from
the first two rows of the table below. To be useful,
<code>fn</code> should be <a href=
"http://www.python.org/doc/current/lib/built-in-funcs.html#l2h-6">
callable</a>.</li>
</ul>
<table border="1" summary="def() optional arguments">
<tr>
<th>Memnonic Name</th>
<th>Requirements/Type properties</th>
<th>Effects</th>
</tr>
<tr>
<td>docstring</td>
<td>Any <a href="definitions.html#ntbs">ntbs</a>.</td>
<td>Value will be bound to the <code>__doc__</code> attribute
of the resulting method overload. If an earlier overload
supplied a docstring, two newline characters and the new
docstring are appended to it.</td>
</tr>
<tr>
<td>policies</td>
<td>A model of <a href=
"CallPolicies.html">CallPolicies</a></td>
<td>A copy will be used as the call policies of the resulting
method overload.</td>
</tr>
<tr>
<td>keywords</td>
<td>The result of a <a href=
"args.html#keyword-expression"><em>keyword-expression</em></a>
specifying no more arguments than the <a href=
"definitions.html#arity">arity</a> of <code>fn</code>.</td>
<td>A copy will be used as the call policies of the resulting
method overload.</td>
</tr>
</table>
</li>
</ul>
</dd>
<dt><b>Returns:</b> <code>*this</code></dt>
</dl>
<pre>
class_&amp; staticmethod(char const* name);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>, and corresponds to a method whose overloads have all
been defined.</dt>
<dt><b>Effects:</b> Replaces the existing named attribute <i>x</i> with
the result of invoking <code>staticmethod(</code><i>x</i><code>)</code>
in Python. Specifies that the corresponding method is static and
therefore no object instance will be passed to it. This is equivalent to
the Python statement:</dt>
<dd>
<pre>
setattr(self, name, staticmethod(getattr(self, name)))
</pre>
</dd>
<dt><b>Note:</b> Attempting to invoke <code>def(name,...)</code> after
invoking <code>staticmethod(name)</code> will <a href=
"definitions.html#raise">raise</a> a RuntimeError.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>
</dl><br>
<pre>
template &lt;<i>unspecified</i>&gt;
class_&amp; def(<a href=
"operators.html#operator_-spec">detail::operator_</a>&lt;unspecified&gt;);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Adds a Python <a href=
"http://www.python.org/doc/ref/specialnames.html">special method</a> as
described <a href="operators.html">here</a>.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>
</dl>
<pre>
template &lt;class U&gt;
class_&amp; setattr(char const* name, U const&amp; u);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>.</dt>
<dt><b>Effects:</b> Converts u to Python and adds it to the attribute
dictionary of the extension class:</dt>
<dd>
<blockquote>
<code><a href=
"http://www.python.org/doc/current/api/object.html#l2h-166">PyObject_SetAttrString</a>(this-&gt;ptr(),
name, <a href=
"object.html#object-spec-ctors">object</a>(u).ptr());</code>
</blockquote>
</dd>
<dt><b>Returns:</b> <code>*this</code></dt>
</dl><br>
<pre>
template &lt;class Get&gt;
void add_property(char const* name, Get const&amp; fget, char const* doc=0);
template &lt;class Get, class Set&gt;
void add_property(
char const* name, Get const&amp; fget, Set const&amp; fset, char const* doc=0);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conform to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>.</dt>
<dt><b>Effects:</b> Creates a new Python <a href=
"http://www.python.org/2.2.2/descrintro.html#property"><code>property</code></a>
class instance, passing <code><a href=
"object.html#object-spec-ctors">object</a>(fget)</code> (and
<code><a href="object.html#object-spec-ctors">object</a>(fset)</code> in
the second form) with an (optional) docstring <code>doc</code> to its
constructor, then adds that property to the Python class object under
construction with the given attribute <code>name</code>.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Allows users to easily expose functions that can be
invoked from Python with attribute access syntax.</dt>
</dl><br>
<pre>
template &lt;class Get&gt;
void add_static_property(char const* name, Get const&amp; fget);
template &lt;class Get, class Set&gt;
void add_static_property(char const* name, Get const&amp; fget, Set const&amp; fset);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>.</dt>
<dt><b>Effects:</b> Creates a Boost.Python.StaticProperty object, passing
<code><a href="object.html#object-spec-ctors">object</a>(fget)</code>
(and <code><a href=
"object.html#object-spec-ctors">object</a>(fset)</code> in the second
form) to its constructor, then adds that property to the Python class
under construction with the given attribute <code>name</code>.
StaticProperty is a special subclass of Python's <a href=
"http://www.python.org/2.2.2/descrintro.html#property"><code>property</code></a>
class which can be called without an initial <code>self</code>
argument.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Allows users to easily expose functions that can be
invoked from Python with static attribute access syntax.</dt>
</dl><br>
<pre>
template &lt;class D&gt;
class_&amp; def_readonly(char const* name, D T::*pm, char const* doc=0);
template &lt;class D&gt;
class_&amp; def_readonly(char const* name, D const&amp; d);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>. <code>doc</code> is also an ntbs.</dt>
<dt><b>Effects:</b></dt>
<dd>
<pre>
this-&gt;add_property(name, <a href=
"data_members.html#make_getter-spec">make_getter</a>(pm), doc);
</pre>and
<pre>
this-&gt;add_static_property(name, <a href=
"data_members.html#make_getter-spec">make_getter</a>(d));
</pre>respectively.<br>
<br>
</dd>
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Allows users to easily expose a class' data member
or free variable such that it can be inspected from Python with a natural
syntax.</dt>
</dl>
<pre>
template &lt;class D&gt;
class_&amp; def_readwrite(char const* name, D T::*pm, char const* doc=0);
template &lt;class D&gt;
class_&amp; def_readwrite(char const* name, D&amp; d);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b></dt>
<dd>
<pre>
this-&gt;add_property(name, <a href=
"data_members.html#make_getter-spec">make_getter</a>(pm), <a href=
"data_members.html#make_setter-spec">make_setter</a>(pm), doc);
</pre>and
<pre>
this-&gt;add_static_property(name, <a href=
"data_members.html#make_getter-spec">make_getter</a>(d), <a href=
"data_members.html#make_setter-spec">make_setter</a>(d));
</pre>respectively.<br>
<br>
</dd>
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Allows users to easily expose a class' data or free
variable member such that it can be inspected and set from Python with a
natural syntax.</dt>
</dl>
<pre>
template &lt;typename PickleSuite&gt;
class_&amp; def_pickle(PickleSuite const&amp;);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> PickleSuite must be publically derived from <a href=
"pickle.html"><code>pickle_suite</code></a>.</dt>
<dt><b>Effects:</b> Defines a legal combination of the special attributes
and methods: <code>__getinitargs__</code>, <code>__getstate__</code>,
<code>__setstate__</code>, <code>__getstate_manages_dict__</code>,
<code>__safe_for_unpickling__</code>, <code>__reduce__</code></dt>
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Provides an <a href="pickle.html">easy to use
high-level interface</a> for establishing complete pickle support for the
wrapped class. The user is protected by compile-time consistency
checks.</dt>
</dl><br>
<pre>
class_&amp; enable_pickling();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Defines the <code>__reduce__</code> method and the
<code>__safe_for_unpickling__</code> attribute.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Light-weight alternative to
<code>def_pickle()</code>. Enables implementation of <a href=
"pickle.html">pickle support</a> from Python.</dt>
</dl><br>
<h3><a name="bases-spec" id="bases-spec"></a>Class template
<code>bases&lt;T1, T2,</code>...<code>TN&gt;</code></h3>
<p>An <a href="../../../mpl/doc/refmanual/forward-sequence.html">MPL
sequence</a> which can be used in
<code>class_&lt;</code>...<code>&gt;</code> instantiations indicate a list
of base classes.</p>
<h4><a name="bases-spec-synopsis" id="bases-spec-synopsis"></a>Class
template <code>bases</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
template &lt;T1 = <i>unspecified</i>,...T<i>n</i> = <i>unspecified</i>&gt;
struct bases
{};
}}
</pre>
<h2><a name="examples" id="examples"></a>Example(s)</h2>
<p>Given a C++ class declaration:</p>
<pre>
class Foo : public Bar, public Baz
{
public:
Foo(int x, char const* y);
Foo(double);
std::string const&amp; name() { return m_name; }
void name(char const*);
double value; // public data
private:
...
};
</pre>A corresponding Boost.Python extension class can be created with:
<pre>
using namespace boost::python;
class_&lt;Foo,bases&lt;Bar,Baz&gt; &gt;("Foo",
"This is Foo's docstring."
"It describes our Foo extension class",
init&lt;int,char const*&gt;(args("x","y"), "__init__ docstring")
)
.def(init&lt;double&gt;())
.def("get_name", &amp;Foo::get_name, return_internal_reference&lt;&gt;())
.def("set_name", &amp;Foo::set_name)
.def_readwrite("value", &amp;Foo::value)
;
</pre>
<hr>
<a name="footnote_1" id="footnote_1">[1]</a> By "previously-exposed" we
mean that the for each <code>B</code> in <code>bases</code>, an instance of
<code>class_&lt;B<font color="#007F00">, ...</font>&gt;</code> must have
already been constructed.
<pre>
class_&lt;Base&gt;("Base");
class_&lt;Derived, bases&lt;Base&gt; &gt;("Derived");
</pre>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
1 November, 2005 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,190 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - Configuration</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Configuration</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#app-defined">Application Defined Macros</a></dt>
<dt><a href="#lib-defined-impl">Library Defined Implementation
Macros</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p><b>Boost.Python</b> uses several configuration macros in <a href=
"http://www.boost.org/libs/config/config.htm">&lt;boost/config.hpp&gt;</a>,
as well as configuration macros meant to be supplied by the application.
These macros are documented here.</p>
<h2><a name="app-defined"></a>Application Defined Macros</h2>
<p>These are the macros that may be defined by an application using
<b>Boost.Python</b>. Note that if you extend a strict interpretation of
the C++ standard to cover dynamic libraries, using different values of
these macros when compiling different libraries (including extension
modules and the <b>Boost.Python</b> library itself) is a violation of the
<a href="definitions.html#ODR">ODR</a>. However, we know of no C++
implementations on which this particular violation is detectable or
causes any problems.</p>
<table summary="application defined macros" width="100%" cellpadding=
"10">
<tr>
<th align="left"><b>Macro</b></th>
<th><b>Default</b></th>
<th align="left"><b>Meaning</b></th>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_MAX_ARITY</code></td>
<td valign="top" align="center">15</td>
<td valign="top">The maximum <a href=
"definitions.html#arity">arity</a> of any function, member function,
or constructor to be wrapped, invocation of a <b>Boost.Python</b>
function wich is specified as taking arguments
<code>x1,&nbsp;x2,</code>...<code>X</code><i>n</i>. This includes, in
particular, callback mechanisms such as <code><a href=
"object.html#object-spec">object</a>::operator()(</code>...<code>)</code>
or <code><a href=
"call_method.html#call_method-spec">call_method</a>&lt;R&gt;(</code>...
<code>)</code>.</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_MAX_BASES</code></td>
<td valign="top" align="center">10</td>
<td valign="top">The maximum number of template arguments to the
<code><a href=
"class.html#bases-spec">bases</a>&lt;</code>...<code>&gt;</code>
class template, which is used to specify the bases of a wrapped C++
class..</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_STATIC_MODULE</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined, prevents your module initialization
function from being treated as an exported symbol on platforms which
support that distinction in-code</td>
</tr>
</table>
<h2><a name="lib-defined-impl"></a>Library Defined Implementation
Macros</h2>
<p>These macros are defined by <b>Boost.Python</b> and are implementation
details of interest only to implementors and those porting to new
platforms.</p>
<table summary="library defined implementation macros" width="100%"
cellpadding="10">
<tr>
<th align="left"><b>Macro</b></th>
<th><b>Default</b></th>
<th align="left"><b>Meaning</b></th>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_TYPE_ID_NAME</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined, this indicates that the type_info
comparison across shared library boundaries does not work on this
platform. In other words, if shared-lib-1 passes
<code>typeid(T)</code> to a function in shared-lib-2 which compares
it to <code>typeid(T)</code>, that comparison may return
<code>false</code>. If this macro is #defined, Boost.Python uses and
compares <code>typeid(T).name()</code> instead of using and comparing
the <code>std::type_info</code> objects directly.</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_NO_PY_SIGNATURES</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined for a module no pythonic signatures are generated
for the docstrings of the module functions, and no python type is associated with any
of the converters registered by the module. This also reduces the binary size of the
module by about 14% (gcc compiled).<br>
If defined for the boost_python runtime library, the default for the
<code>docstring_options.enable_py_signatures()</code> is set to <code>false</code>.
</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_SUPPORTS_PY_SIGNATURES</code></td>
<td valign="top" align="center"><i>defined if <code>BOOST_PYTHON_NO_PY_SIGNATURES</code> is undefined</i></td>
<td valign="top">This macro is defined to enable a smooth transition from older Boost.Python versions
which do not support pythonic signatures. For example usage see
<a href="pytype_function.html#examples">here</a>.
</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined the python type of <code>__init__</code> method "self" parameters
is properly generated, otherwise <code><b>object</b></code> is used. It is undefined
by default because it increases the binary size of the module by about 14% (gcc compiled).</td>
</tr>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
7 January, 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,149 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python -
&lt;boost/python/copy_const_reference.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header
&lt;boost/python/copy_const_reference.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#copy_const_reference-spec">Class
<code>copy_const_reference</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#copy_const_reference-spec-synopsis">Class
<code>copy_const_reference</code> synopsis</a></dt>
<dt><a href="#copy_const_reference-spec-metafunctions">Class
<code>copy_const_reference</code> metafunctions</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Example</a></dt>
</dl>
<hr>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="copy_const_reference-spec"></a>Class
<code>copy_const_reference</code></h3>
<p><code>copy_const_reference</code> is a model of <a href=
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>
which can be used to wrap C++ functions returning a reference-to-const
type such that the referenced value is copied into a new Python
object.</p>
<h4><a name="copy_const_reference-spec-synopsis"></a>Class
<code>copy_const_reference</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
struct copy_const_reference
{
template &lt;class T&gt; struct apply;
};
}}
</pre>
<h4><a name="copy_const_reference-spec-metafunctions"></a>Class
<code>copy_const_reference</code> metafunctions</h4>
<pre>
template &lt;class T&gt; struct apply
</pre>
<dl class="metafunction-semantics">
<dt><b>Requires:</b> <code>T</code> is <code>U const&amp;</code> for
some <code>U</code>.</dt>
<dt><b>Returns:</b> <code>typedef <a href=
"to_python_value.html#to_python_value-spec">to_python_value</a>&lt;T&gt;
type;</code></dt>
</dl>
<h2><a name="examples"></a>Example</h2>
<h3>C++ Module Definition</h3>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/class.hpp&gt;
#include &lt;boost/python/copy_const_reference.hpp&gt;
#include &lt;boost/python/return_value_policy.hpp&gt;
// classes to wrap
struct Bar { int x; }
struct Foo {
Foo(int x) : { b.x = x; }
Bar const&amp; get_bar() const { return b; }
private:
Bar b;
};
// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
class_&lt;Bar&gt;("Bar");
class_&lt;Foo&gt;("Foo", init&lt;int&gt;())
.def("get_bar", &amp;Foo::get_bar
, return_value_policy&lt;copy_const_reference&gt;())
;
}
</pre>
<h3>Python Code</h3>
<pre>
&gt;&gt;&gt; from my_module import *
&gt;&gt;&gt; f = Foo(3) # create a Foo object
&gt;&gt;&gt; b = f.get_bar() # make a copy of the internal Bar object
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,149 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python -
&lt;boost/python/copy_non_const_reference.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header
&lt;boost/python/copy_non_const_reference.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#copy_non_const_reference-spec">Class
<code>copy_non_const_reference</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#copy_non_const_reference-spec-synopsis">Class
<code>copy_non_const_reference</code> synopsis</a></dt>
<dt><a href=
"#copy_non_const_reference-spec-metafunctions">Class
<code>copy_non_const_reference</code> metafunctions</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Example</a></dt>
</dl>
<hr>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="copy_non_const_reference-spec"></a>Class
<code>copy_non_const_reference</code></h3>
<p><code>copy_non_const_reference</code> is a model of <a href=
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>
which can be used to wrap C++ functions returning a
reference-to-non-const type such that the referenced value is copied into
a new Python object.</p>
<h4><a name="copy_non_const_reference-spec-synopsis"></a>Class
<code>copy_non_const_reference</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
struct copy_non_const_reference
{
template &lt;class T&gt; struct apply;
};
}}
</pre>
<h4><a name="copy_non_const_reference-spec-metafunctions"></a>Class
<code>copy_non_const_reference</code> metafunctions</h4>
<pre>
template &lt;class T&gt; struct apply
</pre>
<dl class="metafunction-semantics">
<dt><b>Requires:</b> <code>T</code> is <code>U&amp;</code> for some
non-const <code>U</code>.</dt>
<dt><b>Returns:</b> <code>typedef <a href=
"to_python_value.html#to_python_value-spec">to_python_value</a>&lt;T&gt;
type;</code></dt>
</dl>
<h2><a name="examples"></a>Example</h2>
<p>C++ code:</p>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/class.hpp&gt;
#include &lt;boost/python/copy_non_const_reference.hpp&gt;
#include &lt;boost/python/return_value_policy.hpp&gt;
// classes to wrap
struct Bar { int x; }
struct Foo {
Foo(int x) : { b.x = x; }
Bar&amp; get_bar() { return b; }
private:
Bar b;
};
// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
class_&lt;Bar&gt;("Bar");
class_&lt;Foo&gt;("Foo", init&lt;int&gt;())
.def("get_bar", &amp;Foo::get_bar
, return_value_policy&lt;copy_non_const_reference&gt;())
;
}
</pre>
Python Code:
<pre>
&gt;&gt;&gt; from my_module import *
&gt;&gt;&gt; f = Foo(3) # create a Foo object
&gt;&gt;&gt; b = f.get_bar() # make a copy of the internal Bar object
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,229 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/data_members.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header
&lt;boost/python/data_members.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#functions">Functions</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#make_getter-spec">make_getter</a></dt>
<dt><a href="#make_setter-spec">make_setter</a></dt>
</dl>
</dd>
<dt><a href="#examples">Example</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p><code><a href="#make_getter-spec">make_getter</a>()</code> and
<code><a href="#make_setter-spec">make_setter</a>()</code> are the
functions used internally by <code>class_&lt;&gt;::<a href=
"class.html#class_-spec-modifiers">def_readonly</a></code> and
<code>class_&lt;&gt;::<a href=
"class.html#class_-spec-modifiers">def_readwrite</a></code> to produce
Python callable objects which wrap C++ data members.</p>
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name="make_getter-spec">template &lt;class C, class D&gt;</a>
<a href="object.html#object-spec">object</a> make_getter(D C::*pm);
template &lt;class C, class D, class Policies&gt;
<a href=
"object.html#object-spec">object</a> make_getter(D C::*pm, Policies const&amp; policies);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>Policies</code> is a model of <a href=
"CallPolicies.html">CallPolicies</a>.</dt>
<dt><b>Effects:</b> Creates a Python callable object which accepts a
single argument that can be converted <code>from_python</code> to
<code>C*</code>, and returns the corresponding member <code>D</code>
member of the <code>C</code> object, converted <code>to_python</code>.
If <code>policies</code> is supplied, it will be applied to the
function as described <a href="CallPolicies.html">here</a>. Otherwise,
the library attempts to determine whether <code>D</code> is a
user-defined class type, and if so uses <code><a href=
"return_internal_reference.html#return_internal_reference-spec">return_internal_reference</a>&lt;&gt;</code></dt>
<dt>for <code>Policies</code>. Note that this test may inappropriately
choose <code>return_internal_reference&lt;&gt;</code> in some cases
when <code>D</code> is a smart pointer type. This is a known
defect.</dt>
<dt><b>Returns:</b> An instance of <a href=
"object.html#object-spec">object</a> which holds the new Python
callable object.</dt>
</dl>
<pre>
template &lt;class D&gt;
<a href="object.html#object-spec">object</a> make_getter(D const&amp; d);
template &lt;class D, class Policies&gt;
<a href=
"object.html#object-spec">object</a> make_getter(D const&amp; d, Policies const&amp; policies);
template &lt;class D&gt;
<a href="object.html#object-spec">object</a> make_getter(D const* p);
template &lt;class D, class Policies&gt;
<a href=
"object.html#object-spec">object</a> make_getter(D const* p, Policies const&amp; policies);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>Policies</code> is a model of <a href=
"CallPolicies.html">CallPolicies</a>.</dt>
<dt><b>Effects:</b> Creates a Python callable object which accepts no
arguments and returns <code>d</code> or <code>*p</code>, converted
<code>to_python</code> on demand. If <code>policies</code> is supplied,
it will be applied to the function as described <a href=
"CallPolicies.html">here</a>. Otherwise, the library attempts to
determine whether <code>D</code> is a user-defined class type, and if
so uses <code><a href=
"reference_existing_object.html#reference_existing_object-spec">reference_existing_object</a></code></dt>
<dt>for <code>Policies</code>.</dt>
<dt><b>Returns:</b> An instance of <a href=
"object.html#object-spec">object</a> which holds the new Python
callable object.</dt>
</dl>
<pre>
<a name="make_setter-spec">template &lt;class C, class D&gt;</a>
<a href="object.html#object-spec">object</a> make_setter(D C::*pm);
template &lt;class C, class D, class Policies&gt;
<a href=
"object.html#object-spec">object</a> make_setter(D C::*pm, Policies const&amp; policies);
</pre>
<dl class="function*-semantics">
<dt><b>Requires:</b> <code>Policies</code> is a model of <a href=
"CallPolicies.html">CallPolicies</a>.</dt>
<dt><b>Effects:</b> Creates a Python callable object which, when called
from Python, expects two arguments which can be converted
<code>from_python</code> to <code>C*</code> and
<code>D&nbsp;const&amp;</code>, respectively, and sets the
corresponding <code>D</code> member of the <code>C</code> object. If
<code>policies</code> is supplied, it will be applied to the function
as described <a href="CallPolicies.html">here</a>.</dt>
<dt><b>Returns:</b> An instance of <a href=
"object.html#object-spec">object</a> which holds the new Python
callable object.</dt>
</dl>
<pre>
template &lt;class D&gt;
<a href="object.html#object-spec">object</a> make_setter(D&amp; d);
template &lt;class D, class Policies&gt;
<a href=
"object.html#object-spec">object</a> make_setter(D&amp; d, Policies const&amp; policies);
template &lt;class D&gt;
<a href="object.html#object-spec">object</a> make_setter(D* p);
template &lt;class D, class Policies&gt;
<a href=
"object.html#object-spec">object</a> make_setter(D* p, Policies const&amp; policies);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>Policies</code> is a model of <a href=
"CallPolicies.html">CallPolicies</a>.</dt>
<dt><b>Effects:</b> Creates a Python callable object which accepts one
argument, which is converted from Python to <code>D const&amp;</code>
and written into <code>d</code> or <code>*p</code>, respectively. If
<code>policies</code> is supplied, it will be applied to the function
as described <a href="CallPolicies.html">here</a>.</dt>
<dt><b>Returns:</b> An instance of <a href=
"object.html#object-spec">object</a> which holds the new Python
callable object.</dt>
</dl>
<h2><a name="examples"></a>Example</h2>
<p>The code below uses make_getter and make_setter to expose a data
member as functions:</p>
<pre>
#include &lt;boost/python/data_members.hpp&gt;
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/class.hpp&gt;
struct X
{
X(int x) : y(x) {}
int y;
};
using namespace boost::python;
BOOST_PYTHON_MODULE_INIT(data_members_example)
{
class_&lt;X&gt;("X", init&lt;int&gt;())
.def("get", make_getter(&amp;X::y))
.def("set", make_setter(&amp;X::y))
;
}
</pre>
It can be used this way in Python:
<pre>
&gt;&gt;&gt; from data_members_example import *
&gt;&gt;&gt; x = X(1)
&gt;&gt;&gt; x.get()
1
&gt;&gt;&gt; x.set(2)
&gt;&gt;&gt; x.get()
2
</pre>
<p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
5 August, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,191 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/def.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header &lt;boost/python/def.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#functions">Functions</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#def-spec">def</a></dt>
</dl>
</dd>
<dt><a href="#examples">Example</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p><code><a href="#def-spec">def</a>()</code> is the function which can
be used to expose C++ functions and callable objects as Python functions
in the current <code><a href="scope.html">scope</a></code>.</p>
<h2><a name="functions"></a>Functions</h2>
<a name="def-spec"></a>def
<pre>
template &lt;class F&gt;
void def(char const* name, F f);
template &lt;class Fn, class A1&gt;
void def(char const* name, Fn fn, A1 const&amp;);
template &lt;class Fn, class A1, class A2&gt;
void def(char const* name, Fn fn, A1 const&amp;, A2 const&amp;);
template &lt;class Fn, class A1, class A2, class A3&gt;
void def(char const* name, Fn fn, A1 const&amp;, A2 const&amp;, A3 const&amp;);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>name</code> is an <a href=
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
"http://www.python.org/doc/current/ref/identifiers.html">identifier
naming rules</a>.</dt>
<dd>
<ul>
<li>If <code>Fn</code> is [derived from] <code><a href=
"object.html#object-spec">object</a></code>, it will be added to
the current scope as a single overload. To be useful,
<code>fn</code> should be <a href=
"http://www.python.org/doc/current/lib/built-in-funcs.html#l2h-6">callable</a>.</li>
<li>
If <code>a1</code> is the result of an <a href=
"overloads.html#overload-dispatch-expression"><em>overload-dispatch-expression</em></a>,
only the second form is allowed and fn must be a pointer to
function or pointer to member function whose <a href=
"definitions.html#arity">arity</a> is the same as A1's <a href=
"overloads.html#overload-dispatch-expression"><em>maximum
arity</em></a>.
<dl>
<dt><b>Effects:</b> For each prefix <em>P</em> of
<code>Fn</code>'s sequence of argument types, beginning with
the one whose length is <code>A1</code>'s <a href=
"overloads.html#overload-dispatch-expression"><em>minimum
arity</em></a>, adds a
<code><em>name</em>(</code>...<code>)</code> function overload
to the <a href="scope.html">current scope</a>. Each overload
generated invokes <code>a1</code>'s call-expression with
<em>P</em>, using a copy of <code>a1</code>'s <a href=
"CallPolicies.html">call policies</a>. If the longest valid
prefix of <code>A1</code> contains <em>N</em> types and
<code>a1</code> holds <em>M</em> keywords, an initial sequence
of the keywords are used for all but the first
<em>N</em>&nbsp;-&nbsp;<em>M</em> arguments of each
overload.<br>
</dt>
</dl>
</li>
<li>Otherwise, fn must be a non-null function or member function
pointer, and a single function overload built around fn is added to
the <a href="scope.html">current scope</a>. If any of
<code>a1</code>-<code>a3</code> are supplied, they may be selected
in any order from the table below.</li>
</ul>
<table border="1" summary="def() optional arguments">
<tr>
<th>Memnonic Name</th>
<th>Requirements/Type properties</th>
<th>Effects</th>
</tr>
<tr>
<td>docstring</td>
<td>Any <a href="definitions.html#ntbs">ntbs</a>.</td>
<td>Value will be bound to the <code>__doc__</code> attribute of
the resulting method overload.</td>
</tr>
<tr>
<td>policies</td>
<td>A model of <a href="CallPolicies.html">CallPolicies</a></td>
<td>A copy will be used as the call policies of the resulting
method overload.</td>
</tr>
<tr>
<td>keywords</td>
<td>The result of a <a href=
"args.html#keyword-expression"><em>keyword-expression</em></a>
specifying no more arguments than the <a href=
"definitions.html#arity">arity</a> of <code>fn</code>.</td>
<td>A copy will be used as the call policies of the resulting
method overload.</td>
</tr>
</table>
</dd>
</dl>
<h2><a name="examples"></a>Example</h2>
<pre>
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/args.hpp&gt;
using namespace boost::python;
char const* foo(int x, int y) { return "foo"; }
BOOST_PYTHON_MODULE(def_test)
{
def("foo", foo, args("x", "y"), "foo's docstring");
}
</pre>
<p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
7 March, 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,137 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<meta name="generator" content="Microsoft FrontPage 5.0">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/def_visitor.hpp&gt;</title>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
<td valign="top">
<h1 align="center"><a href="../index.html"><font size="7">Boost.Python</font></a></h1>
<h2 align="center">Header &lt;boost/python/def_visitor.hpp&gt;</h2>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a>
<dt><a href="#classes">Classes</a>
<dd>
<dl class="page-index">
<dt><a href="#def_visitor-spec">Class <code>def_visitor</code></a>
<dd> <a href="#def_visitor-synopsis">Class <code>def_visitor</code>
synopsis</a></dd>
<dd> <a href="#def_visitor-requirements">Class <code>def_visitor</code>
requirements</a></dd>
</dl>
<dt><a href="#examples">Example</a>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p><code>&lt;boost/python/def_visitor.hpp&gt;</code> provides a generic visitation
interface through which the <a href="class.html">class_</a> <b>def</b> member
functionality can be extended non-intrusively to avoid cluttering the <a href="class.html">class_</a>
interface. It declares the <code>def_visitor&lt;T&gt; </code>class template,
which is parameterized on the derived type <tt>DerivedVisitor</tt>, which provides
the actual <b>def</b> functionality through its <b>visit</b> member functions.
<h2><a name="classes"></a>Classes</h2>
<h3><a name="def_visitor-spec"></a>Class template <code>def_visitor&lt;DerivedVisitor&gt;</code></h3>
<p>The class def_visitor is a base class paramaterized by its derived class. The
def_visitor class is a protocol class. Its derived class, DerivedVisitor, is
expected to have a member function visit. The def_visitor class is never instantiated
directly. Instead, an instance of its subclass, DerivedVisitor,&nbsp; is passed
on as an argument to the <a href="class.html">class_</a> def member function.
<h4>
<a name="def_visitor-synopsis" id="def_visitor-synopsis"></a>Class <code>def_visitor </code>synopsis</h4>
<pre>namespace boost { namespace python {
template &lt;class DerivedVisitor&gt;
class def_visitor {};
}</pre>
<h3><a name="def_visitor-requirements"></a><code>def_visitor </code>requirements</h3>
<p>The <span class="pre">client supplied class </span><span class="pre"></span><tt class="literal"><span class="pre">DerivedVisitor</span></tt>
template parameter is expected to:
<ul>
<li>be privately derived from def_visitor</li>
<li>grant friend access to class def_visitor_access</li>
<li>define either or both visit member functions listed in the table below:</li>
</ul>
<table border class="table">
<tr>
<td width="181" nowrap><b>Expression</b></td>
<td width="85"><b>Return Type</b></td>
<td width="330"><b>Requirements</b></td>
<td width="259"><b>Effects</b></td>
</tr>
<tr>
<td nowrap>visitor.visit(cls)</td>
<td>void</td>
<td>cls is an instance of a <a href="class.html">class_</a>&nbsp; being wrapped
to Python. visitor is a def_visitor derived class.</td>
<td>A call to cls.def(visitor) forwards to this member function.</td>
</tr>
<tr>
<td nowrap>visitor.visit(cls, name, options)</td>
<td>void</td>
<td>cls is a class_ instance, name is a C string. visitor is a def_visitor
derived class. options is a context specific optional argument.</td>
<td>A call to cls.def(name, visitor) or cls.def(name, visitor, options) forwards
to this member function. </td>
</tr>
</table>
<h2><a name="examples"></a>Example</h2>
<pre>class X {/*...*/};<br>
class my_def_visitor : boost::python::def_visitor&lt;my_def_visitor&gt;
{
friend class def_visitor_access;
template &lt;class classT&gt;
void visit(classT&amp; c) const
{
c
.def(&quot;foo&quot;, &amp;my_def_visitor::foo)
.def(&quot;bar&quot;, &amp;my_def_visitor::bar)
;
}
static void foo(X&amp; self);
static void bar(X&amp; self);
};
BOOST_PYTHON_MODULE(my_ext)
{
class_&lt;X&gt;(&quot;X&quot;)
.def(my_def_visitor())
;
}
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->27 August, 2003<!--webbot bot="Timestamp" endspan i-checksum="34484" -->
</p>
<p><i>&copy; Copyright Joel de Guzman 2003. </i> Distributed under the Boost
Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,173 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<meta name="generator" content="HTML Tidy, see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python -
&lt;boost/python/default_call_policies.hpp&gt;</title>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header
&lt;boost/python/default_call_policies.hpp&gt;</h2>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#classes">Classes</a>
<dd>
<dl class="page-index">
<dt><a href="#default_call_policies-spec">Class
<code>default_call_policies</code></a>
<dd>
<dl class="page-index">
<dt><a href="#default_call_policies-spec-synopsis">Class
<code>default_call_policies</code> synopsis</a>
<dt><a href="#default_call_policies-spec-statics">Class
<code>default_call_policies</code> static functions</a>
</dl>
<dt><a href="#default_result_converter-spec">Class
<code>default_result_converter</code></a>
<dd>
<dl class="page-index">
<dt><a href="#default_result_converter-spec-synopsis">Class
<code>default_result_converter</code> synopsis</a>
<dt><a href="#default_result_converter-spec-metafunctions">Class
<code>default_result_converter</code> metafunctions</a>
</dl>
</dl>
<dt><a href="#examples">Example</a>
</dl>
<hr>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="default_call_policies-spec"></a>Class
<code>default_call_policies</code></h3>
<p><code>default_call_policies</code> is a model of <a href=
"CallPolicies.html">CallPolicies</a> with no <code>precall</code> or
<code>postcall</code> behavior and a <code>result_converter</code> which
handles by-value returns. Wrapped C++ functions and member functions use
<code>default_call_policies</code> unless otherwise specified. You may find
it convenient to derive new models of <a href=
"CallPolicies.html">CallPolicies</a> from
<code>default_call_policies</code>.
<h4><a name="default_call_policies-spec-synopsis"></a>Class
<code>default_call_policies</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
struct default_call_policies
{
static bool precall(PyObject*);
static PyObject* postcall(PyObject*, PyObject* result);
typedef <a href=
"#default_result_converter-spec">default_result_converter</a> result_converter;
template &lt;class Sig&gt; struct extract_return_type : mpl::front&lt;Sig&gt;{};
};
}}
</pre>
<h4><a name="default_call_policies-spec-statics"></a>Class
<code>default_call_policies</code> static functions</h4>
<pre>
bool precall(PyObject*);
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> <code>true</code>
<dt><b>Throws:</b> nothing
</dl>
<pre>
PyObject* postcall(PyObject*, PyObject* result);
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> <code>result</code>
<dt><b>Throws:</b> nothing
</dl>
<h3><a name="default_result_converter-spec"></a>Class
<code>default_result_converter</code></h3>
<p><code>default_result_converter</code> is a model of <a href=
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a> which can be
used to wrap C++ functions returning non-pointer types, <code>char
const*</code>, and <code>PyObject*</code>, by-value.
<h4><a name="default_result_converter-spec-synopsis"></a>Class
<code>default_result_converter</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
struct default_result_converter
{
template &lt;class T&gt; struct apply;
};
}}
</pre>
<h4><a name="default_result_converter-spec-metafunctions"></a>Class
<code>default_result_converter</code> metafunctions</h4>
<pre>
template &lt;class T&gt; struct apply
</pre>
<dl class="metafunction-semantics">
<dt><b>Requires:</b> <code>T</code> is not a reference type. If
<code>T</code> is a pointer type, <code>T</code> is <code>const
char*</code> or <code>PyObject*</code>.
<dt><b>Returns:</b> <code>typedef <a href=
"to_python_value.html#to_python_value-spec">to_python_value</a>&lt;T
const&amp;&gt; type;</code>
</dl>
<h2><a name="examples"></a>Example</h2>
<p>This example comes from the Boost.Python implementation itself. Because
the <a href=
"return_value_policy.html#return_value_policy-spec">return_value_policy</a>
class template does not implement <code>precall</code> or
<code>postcall</code> behavior, its default base class is
<code>default_call_policies</code>:
<pre>
template &lt;class Handler, class Base = default_call_policies&gt;
struct return_value_policy : Base
{
typedef Handler result_converter;
};
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
11 June, 2007
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002.</i> Distributed under the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)</p>

View File

@@ -1,102 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - Definitions</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Definitions</h2>
</td>
</tr>
</table>
<hr>
<dl class="definitions">
<dt><b><a name="arity">arity</a>:</b> The number of arguments accepted
by a function or member function. Unless otherwise specified, the
hidden "<code>this</code>" argument to member functions is not counted
when specifying arity</dt>
<dd><br>
</dd>
<dt><b><a name="ntbs">ntbs</a>:</b> Null-Terminated Byte String, or
`C'-string. C++ string literals are <strong>ntbs</strong>es. An
<strong>ntbs</strong> must never be null.</dt>
<dd><br>
</dd>
<dt><b><a name="raise">raise</a>:</b> Exceptions in Python are
"raised", not "thrown", as they are in C++. When this documentation
says that some Python exception is "raised" in the context of C++ code,
it means that the corresponding Python exception is set via the <a
href=
"http://www.python.org/doc/current/api/exceptionHandling.html">Python/'C'
API</a>, and <code><a href=
"errors.html#throw_error_already_set-spec">throw_error_already_set</a>()</code>
is called.</dt>
<dd><br>
</dd>
<dt><b><a name="POD">POD</a>:</b> A technical term from the C++
standard. Short for "Plain Ol'Data": A POD-struct is an aggregate class
that has no non-static data members of type pointer to member,
non-POD-struct, non-POD-union (or array of such types) or reference,
and has no user-defined copy assign- ment operator and no user-defined
destructor. Similarly, a POD-union is an aggregate union that has no
non-static data members of type pointer to member, non-POD-struct,
non-POD-union (or array of such types) or reference, and has no
user-defined copy assignment operator and no user-defined destructor. A
POD class is a class that is either a POD-struct or a POD-union. An
aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members
(clause 11), no base classes (clause 10), and no virtual functions
(10.3).</dt>
<dd><br>
</dd>
<dt><b><a name="ODR">ODR</a>:</b> The &quot;One Definition
Rule&quot;, which says that any entity in a C++ program must have the same definition in all translation units (object files) which make up a program.
</dt>
<dd><br>
</dd>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,152 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/dict.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header &lt;boost/python/dict.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#dict-spec">Class <code>dict</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#dict-spec-synopsis">Class <code>dict</code>
synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Exposes a <a href=
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> for the Python
<a href=
"http://www.python.org/dev/doc/devel/lib/typesmapping.html">dict</a>
type.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="dict-spec"></a>Class <code>dict</code></h3>
<p>Exposes the <a href=
"http://www.python.org/dev/doc/devel/lib/typesmapping.html">mapping
protocol</a> of Python's built-in <code>dict</code> type. The semantics
of the constructors and member functions defined below can be fully
understood by reading the <a href=
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
definition. Since <code>dict</code> is publicly derived from <code><a
href="object.html#object-spec">object</a></code>, the public object
interface applies to <code>dict</code> instances as well.</p>
<h4><a name="dict-spec-synopsis"></a>Class <code>dict</code>
synopsis</h4>
<pre>
namespace boost { namespace python
{
class dict : public object
{
dict();
template&lt; class T &gt;
dict(T const &amp; data);
// modifiers
void clear();
dict copy();
template &lt;class T1, class T2&gt;
tuple popitem();
template &lt;class T&gt;
object setdefault(T const &amp;k);
template &lt;class T1, class T2&gt;
object setdefault(T1 const &amp; k, T2 const &amp; d);
void update(object_cref E);
template&lt; class T &gt;
void update(T const &amp; E);
// observers
list values() const;
object get(object_cref k) const;
template&lt;class T&gt;
object get(T const &amp; k) const;
object get(object_cref k, object_cref d) const;
object get(T1 const &amp; k, T2 const &amp; d) const;
bool has_key(object_cref k) const;
template&lt; class T &gt;
bool has_key(T const &amp; k) const;
list items() const;
object iteritems() const;
object iterkeys() const;
object itervalues() const;
list keys() const;
};
}}
</pre>
<h2><a name="examples"></a>Example</h2>
<pre>
using namespace boost::python;
dict swap_object_dict(object target, dict d)
{
dict result = extract&lt;dict&gt;(target.attr("__dict__"));
target.attr("__dict__") = d;
return result;
}
</pre>
<p>Revised 30 September, 2002</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>

View File

@@ -1,386 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1st September 2004), see www.w3.org">
<meta http-equiv="Content-Type" content=
"text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python -
&lt;boost/python/docstring_options.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%"
summary="header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width=
"277" alt="C++ Boost" src="../../../../boost.png" border=
"0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href=
"../index.html">Boost.Python</a></h1>
<h2 align="center">Header
&lt;boost/python/docstring_options.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#docstring_options-spec">Class
<code>docstring_options</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#docstring_options-spec-synopsis">Class
<code>docstring_options</code> synopsis</a></dt>
<dt><a href="#docstring_options-spec-ctors">Class
<code>docstring_options</code> constructors</a></dt>
<dt><a href="#docstring_options-spec-dtors">Class
<code>docstring_options</code> destructors</a></dt>
<dt><a href="#docstring_options-spec-modifiers">Class
<code>docstring_options</code> modifiers</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction" id=
"introduction"></a>Introduction</h2>
<p>Boost.Python supports user-defined docstrings with automatic
appending of C++ signatures. These features are enabled by
default. The <code>class docstring_options</code> is available to
selectively suppress the user-defined docstrings, signatures, or
both.</p>
<h2><a name="classes" id="classes"></a>Classes</h2>
<h3><a name="docstring_options-spec" id=
"docstring_options-spec"></a>Class
<code>docstring_options</code></h3>
<p>Controls the appearance of docstrings of wrapped functions and
member functions for the life-time of the instance. The instances
are noncopyable to eliminate the possibility of surprising side
effects.</p>
<h4><a name="docstring_options-spec-synopsis" id=
"docstring_options-spec-synopsis"></a>Class
<code>docstring_options</code> synopsis</h4>
<pre>
namespace boost { namespace python {
class docstring_options : boost::noncopyable
{
public:
docstring_options(bool show_all=true);
docstring_options(bool show_user_defined, bool show_signatures);
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
~docstring_options();
void
disable_user_defined();
void
enable_user_defined();
void
disable_signatures();
void
enable_signatures();
void
disable_py_signatures();
void
enable_py_signatures();
void
disable_cpp_signatures();
void
enable_cpp_signatures();
void
disable_all();
void
enable_all();
};
}}
</pre>
<h4><a name="docstring_options-spec-ctors" id=
"docstring_options-spec-ctors"></a>Class
<code>docstring_options</code> constructors</h4>
<pre>
docstring_options(bool show_all=true);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>docstring_options</code>
object which controls the appearance of function and
member-function docstrings defined in the code that follows. If
<code>show_all</code> is <code>true</code>, both the
user-defined docstrings and the automatically generated Python and C++
signatures are shown. If <code>show_all</code> is
<code>false</code> the <code>__doc__</code> attributes are
<code>None</code>.</dt>
</dl>
<pre>
docstring_options(bool show_user_defined, bool show_signatures);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>docstring_options</code>
object which controls the appearance of function and
member-function docstrings defined in the code that follows.
Iff <code>show_user_defined</code> is <code>true</code>, the
user-defined docstrings are shown. Iff
<code>show_signatures</code> is <code>true</code>, Python and C++
signatures are automatically added. If both
<code>show_user_defined</code> and <code>show_signatures</code>
are <code>false</code>, the <code>__doc__</code> attributes are
<code>None</code>.</dt>
</dl>
<pre>
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>docstring_options</code>
object which controls the appearance of function and
member-function docstrings defined in the code that follows.
Iff <code>show_user_defined</code> is <code>true</code>, the
user-defined docstrings are shown. Iff
<code>show_py_signatures</code> is <code>true</code>, Python
signatures are automatically added. Iff
<code>show_cpp_signatures</code> is <code>true</code>, C++
signatures are automatically added. If all parameters are
<code>false</code>, the <code>__doc__</code> attributes are
<code>None</code>.</dt>
</dl>
<h4><a name="docstring_options-spec-dtors" id=
"docstring_options-spec-dtors"></a>Class
<code>docstring_options</code> destructors</h4>
<pre>
~docstring_options();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Restores the previous state of the
docstring options. In particular, if
<code>docstring_options</code> instances are in nested C++
scopes the settings effective in the enclosing scope are
restored. If the last <code>docstring_options</code> instance
goes out of scope the default "all on" settings are
restored.</dt>
</dl>
<h4><a name="docstring_options-spec-modifiers" id=
"docstring_options-spec-modifiers"></a>Class
<code>docstring_options</code> modifier functions</h4>
<pre>
void disable_user_defined();
void enable_user_defined();
void disable_signatures();
void enable_signatures();
void disable_py_signatures();
void enable_py_signatures();
void disable_cpp_signatures();
void enable_cpp_signatures();
void disable_all();
void enable_all();
</pre>
<dl class="function-semantics">
<dt>These member functions dynamically change the appearance of
docstrings in the code that follows. The
<code>*_user_defined()</code> and <code>*_signatures()</code>
member functions are provided for fine-grained control. The
<code>*_all()</code> member functions are convenient shortcuts
to manipulate all settings simultaneously.</dt>
</dl>
<h2><a name="examples" id="examples"></a>Examples</h2>
<h4>Docstring options defined at compile time</h4>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/docstring_options.hpp&gt;
void foo() {}
BOOST_PYTHON_MODULE(demo)
{
using namespace boost::python;
docstring_options doc_options(DEMO_DOCSTRING_SHOW_ALL);
def("foo", foo, "foo doc");
}
</pre>If compiled with <code>-DDEMO_DOCSTRING_SHOW_ALL=true</code>:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo.__doc__
foo() -&gt; None : foo doc
C++ signature:
foo(void) -&gt; void
</pre>If compiled with
<code>-DDEMO_DOCSTRING_SHOW_ALL=false</code>:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo.__doc__
None
</pre>
<h4>Selective suppressions</h4>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/args.hpp&gt;
#include &lt;boost/python/docstring_options.hpp&gt;
int foo1(int i) { return i; }
int foo2(long l) { return static_cast&lt;int&gt;(l); }
int foo3(float f) { return static_cast&lt;int&gt;(f); }
int foo4(double d) { return static_cast&lt;int&gt;(d); }
BOOST_PYTHON_MODULE(demo)
{
using namespace boost::python;
docstring_options doc_options;
def("foo1", foo1, arg("i"), "foo1 doc");
doc_options.disable_user_defined();
def("foo2", foo2, arg("l"), "foo2 doc");
doc_options.disable_signatures();
def("foo3", foo3, arg("f"), "foo3 doc");
doc_options.enable_user_defined();
def("foo4", foo4, arg("d"), "foo4 doc");
doc_options.enable_py_signatures();
def("foo5", foo4, arg("d"), "foo5 doc");
doc_options.disable_py_signatures();
doc_options.enable_cpp_signatures();
def("foo6", foo4, arg("d"), "foo6 doc");
}
</pre>Python code:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo1.__doc__
foo1( (int)i) -&gt; int : foo1 doc
C++ signature:
foo1(int i) -&gt; int
&gt;&gt;&gt; print demo.foo2.__doc__
foo2( (int)l) -&gt; int :
C++ signature:
foo2(long l) -&gt; int
&gt;&gt;&gt; print demo.foo3.__doc__
None
&gt;&gt;&gt; print demo.foo4.__doc__
foo4 doc
&gt;&gt;&gt; print demo.foo5.__doc__
foo5( (float)d) -&gt; int : foo5 doc
&gt;&gt;&gt; print demo.foo6.__doc__
foo6 doc
C++ signature:
foo6(double d) -&gt; int
</pre>
<h4>Wrapping from multiple C++ scopes</h4>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/args.hpp&gt;
#include &lt;boost/python/docstring_options.hpp&gt;
int foo1(int i) { return i; }
int foo2(long l) { return static_cast&lt;int&gt;(l); }
int bar1(int i) { return i; }
int bar2(long l) { return static_cast&lt;int&gt;(l); }
namespace {
void wrap_foos()
{
using namespace boost::python;
// no docstring_options here
// -&gt; settings from outer C++ scope are in effect
def("foo1", foo1, arg("i"), "foo1 doc");
def("foo2", foo2, arg("l"), "foo2 doc");
}
void wrap_bars()
{
using namespace boost::python;
bool show_user_defined = true;
bool show_signatures = false;
docstring_options doc_options(show_user_defined, show_signatures);
def("bar1", bar1, arg("i"), "bar1 doc");
def("bar2", bar2, arg("l"), "bar2 doc");
}
}
BOOST_PYTHON_MODULE(demo)
{
boost::python::docstring_options doc_options(false);
wrap_foos();
wrap_bars();
}
</pre>Python code:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo1.__doc__
None
&gt;&gt;&gt; print demo.foo2.__doc__
None
&gt;&gt;&gt; print demo.bar1.__doc__
bar1 doc
&gt;&gt;&gt; print demo.bar2.__doc__
bar2 doc
</pre>
<h4>See also: <code>boost/libs/python/test/docstring.cpp</code>
and <code>docstring.py</code></h4>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
16 January, 2006
<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/ralf_w_grosse_kunstleve.htm">Ralf W.
Grosse-Kunstleve</a> 2006.</i></p>
</body>
</html>

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