Compare commits
1 Commits
boost-1.86
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
daa159a279 |
@@ -1,98 +0,0 @@
|
||||
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
|
||||
# distribute this software is granted provided this copyright notice appears
|
||||
# in all copies. This software is provided "as is" without express or implied
|
||||
# warranty, and with no claim as to its suitability for any purpose.
|
||||
#
|
||||
# Boost.Python library Jamfile
|
||||
|
||||
|
||||
# declare the location of this subproject relative to the root
|
||||
subproject libs/python/build ;
|
||||
|
||||
# bring in the rules for python
|
||||
import python ;
|
||||
|
||||
if [ check-python-config ]
|
||||
{
|
||||
|
||||
local bpl-linkflags ;
|
||||
|
||||
if $(UNIX) && ( $(OS) = AIX )
|
||||
{
|
||||
bpl-linkflags = <linkflags>"-e initlibboost_python" ;
|
||||
}
|
||||
|
||||
# Enabling intrinsics (/0i) or maximize speed (/02) seem to cause
|
||||
# internal compiler errors with this toolset.
|
||||
local msvc-stlport-workarounds
|
||||
= <optimization>off "<cxxflags>-Ogty -O1 -Gs" ;
|
||||
|
||||
local sources =
|
||||
numeric.cpp
|
||||
list.cpp
|
||||
long.cpp
|
||||
dict.cpp
|
||||
tuple.cpp
|
||||
str.cpp
|
||||
slice.cpp
|
||||
|
||||
aix_init_module.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_protocol.cpp
|
||||
object_operators.cpp
|
||||
wrapper.cpp
|
||||
exec.cpp
|
||||
import.cpp
|
||||
;
|
||||
|
||||
dll boost_python
|
||||
: ../src/$(sources)
|
||||
: $(BOOST_PYTHON_V2_PROPERTIES)
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
$(bpl-linkflags)
|
||||
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
||||
<darwin><*><linkflags>-bind_at_load
|
||||
<gcc-3_3-darwin><*><linkflags>-bind_at_load
|
||||
;
|
||||
|
||||
template extension
|
||||
: <dll>boost_python
|
||||
: <sysinclude>../../..
|
||||
;
|
||||
|
||||
lib boost_python
|
||||
: # sources
|
||||
../src/$(sources)
|
||||
|
||||
: # requirements
|
||||
$(BOOST_PYTHON_V2_PROPERTIES)
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
<define>BOOST_STATIC_LIB
|
||||
$(bpl-linkflags)
|
||||
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
||||
;
|
||||
|
||||
stage bin-stage : <dll>boost_python <lib>boost_python
|
||||
: <tag><debug>"_debug"
|
||||
<tag><debug-python>"_pydebug"
|
||||
:
|
||||
debug release
|
||||
;
|
||||
|
||||
install python lib
|
||||
: <dll>boost_python <lib>boost_python
|
||||
;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
import os ;
|
||||
import modules ;
|
||||
|
||||
import python ;
|
||||
|
||||
if [ python.configured ] {
|
||||
|
||||
|
||||
project boost/python
|
||||
: source-location ../src
|
||||
: requirements
|
||||
#<include>$(PYTHON_PATH)/include
|
||||
# $(lib_condition)<library-path>$(PYTHON_PATH)/libs
|
||||
# <link>shared:<library>$(PYTHON_LIB)
|
||||
# <define>$(defines)
|
||||
#: usage-requirements # requirement that will be propageted to *users* of this library
|
||||
# <include>$(PYTHON_PATH)/include
|
||||
|
||||
# We have a bug which causes us to conclude that conditionalized
|
||||
# properties in this section are not free.
|
||||
# $(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||
# <shared>true:<find-library>$(PYTHON_LIB)
|
||||
|
||||
# <library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||
# <library>$(PYTHON_LIB)
|
||||
;
|
||||
|
||||
lib boost_python
|
||||
:
|
||||
numeric.cpp
|
||||
list.cpp
|
||||
long.cpp
|
||||
dict.cpp
|
||||
tuple.cpp
|
||||
str.cpp
|
||||
slice.cpp
|
||||
|
||||
aix_init_module.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_protocol.cpp
|
||||
object_operators.cpp
|
||||
wrapper.cpp
|
||||
: <link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
<library>/python//python
|
||||
: <link>shared
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
ECHO "warning: Python location is not configured" ;
|
||||
ECHO "warning: the Boost.Python library won't be built" ;
|
||||
}
|
||||
@@ -1,890 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="boost_python" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=BOOST_PYTHON - WIN32 RELEASE
|
||||
!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 "boost_python.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 "boost_python.mak" CFG="BOOST_PYTHON - WIN32 RELEASE"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "boost_python - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "boost_python - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "boost_python - 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 "../bin-stage"
|
||||
# PROP Intermediate_Dir "release-obj"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BPL_EXPORTS" /YX /FD /Zm800 /Zm800 /Zm800 /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../../" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BOOST_PYTHON_DYNAMIC_LIB" /D "BOOST_PYTHON_SOURCE" /FD /Zm800 /Zm800 /Zm800 /Zm800 /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x1409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x1409 /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 /nologo /dll /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "boost_python - 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 "../bin-stage"
|
||||
# PROP Intermediate_Dir "debug-obj"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BPL_EXPORTS" /YX /FD /Zm800 /Zm800 /Zm800 /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /GR /GX /Zi /Od /I "../../../../" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BOOST_PYTHON_DYNAMIC_LIB" /D "BOOST_PYTHON_SOURCE" /FD /Zm800 /Zm800 /Zm800 /Zm800 /Zm800 /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x1409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x1409 /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 /nologo /dll /incremental:no /debug /machine:I386 /out:"../bin-stage/boost_python_debug.dll" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "boost_python - Win32 Release"
|
||||
# Name "boost_python - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\aix_init_module.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\converter\arg_to_python_base.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\converter\builtin_converters.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object\class.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\dict.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object\enum.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\errors.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\converter\from_python.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object\function.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object\inheritance.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object\iterator.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object\life_support.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\list.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\long.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\module.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\numeric.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object_operators.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object_protocol.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\object\pickle_support.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\converter\registry.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\slice.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\str.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\tuple.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\converter\type_id.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\wrapper.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Group "detail"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\aix_init_module.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\api_placeholder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\arg_tuple_size.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\borrowed_ptr.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\call_object.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\caller.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\char_array.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\config.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\construct.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\convertible.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\cv_category.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\decorated_type_id.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\def_helper.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\defaults_def.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\defaults_gen.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\dependent.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\destroy.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\exception_handler.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\force_instantiate.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\if_else.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\indirect_traits.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\make_keyword_range_fn.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\make_tuple.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\map_entry.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\member_function_cast.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\module_base.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\module_init.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\msvc_typeinfo.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\none.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\not_specified.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\operator_id.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\overloads_fwd.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\pointee.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\preprocessor.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\python22_fixed.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\raw_pyobject.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\referent_storage.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\result.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\returning.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\scope.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\string_literal.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\target.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\translate_exception.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\type_list.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\type_list_impl.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\type_list_impl_no_pts.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\type_list_utils.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\unwind_type.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\void_ptr.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\void_return.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\wrap_python.hpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "converter"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\arg_from_python.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\arg_to_python.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\arg_to_python_base.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\builtin_converters.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\constructor_function.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\convertible_function.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\from_python.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\implicit.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\obj_mgr_arg_from_python.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\object_manager.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\pointer_type_id.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\pyobject_traits.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\pyobject_type.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\pytype_arg_from_python.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\pytype_object_mgr_traits.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\registered.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\registered_pointee.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\registrations.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\registry.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\return_from_python.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\rvalue_from_python_data.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\converter\to_python_function_type.hpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "object"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\add_to_namespace.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\class.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\class_converters.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\class_detail.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\class_wrapper.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\construct.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\enum_base.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\find_instance.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\forward.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\function.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\function_handle.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\function_object.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\inheritance.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\instance.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\iterator.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\iterator_core.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\life_support.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\make_holder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\make_instance.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\pickle_support.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\pointer_holder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\py_function.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\select_holder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\value_holder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object\value_holder_fwd.hpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\arg_from_python.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\args.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\args_fwd.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\back_reference.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\base_type_traits.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\bases.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\borrowed.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\call.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\call_method.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\cast.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\class.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\class_fwd.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\copy_const_reference.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\copy_non_const_reference.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\data_members.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\def.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\default_call_policies.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\dict.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\enum.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\errors.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\exception_translator.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\extract.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\handle.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\handle_fwd.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\has_back_reference.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\implicit.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\init.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\instance_holder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\iterator.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\list.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\long.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\lvalue_from_pytype.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\make_function.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\manage_new_object.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\module.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\module_init.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\numeric.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_attributes.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_call.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_core.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_fwd.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_items.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_operators.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_protocol.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_protocol_core.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\object_slices.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\operators.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\operators2.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\other.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\overloads.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\pointee.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\proxy.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\ptr.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\refcount.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\reference_existing_object.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\return_internal_reference.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\return_value_policy.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\scope.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\self.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\signature.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\slice_nil.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\str.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\tag.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\to_python_converter.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\to_python_indirect.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\to_python_value.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\tuple.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\type_id.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\with_custodian_and_ward.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
|
||||
@@ -1,29 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "boost_python"=".\boost_python.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<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: “Building Hybrid Systems With Boost.Python”</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>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
This file has been moved to http://www.boost-consulting.com/writing/bpl.txt.
|
||||
@@ -1,908 +0,0 @@
|
||||
.. 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
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
:Author: David Goodger
|
||||
:Contact: goodger@users.sourceforge.net
|
||||
:date: $Date$
|
||||
:version: $Revision$
|
||||
:copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
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 }
|
||||
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
@@ -1,59 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,454 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - Building and Testing</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">Building and Testing</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="Reference">
|
||||
<dt><a href="#requirements">Requirements</a></dt>
|
||||
|
||||
<dt><a href="#building">Building Boost.Python</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="#configuration">Configuration</a></dt>
|
||||
|
||||
<dt><a href="#cygwin_configuration">Configuration for Cygwin GCC
|
||||
from a Windows prompt</a></dt>
|
||||
|
||||
<dt><a href="#results">Results</a></dt>
|
||||
|
||||
<dt><a href="#cygwin">Notes for Cygwin GCC Users</a></dt>
|
||||
|
||||
<dt><a href="#mingw">Notes for MinGW (and Cygwin with -mno-cygwin)
|
||||
GCC Users</a></dt>
|
||||
|
||||
<dt><a href="#testing">Testing</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#building_ext">Building your Extension Module</a></dt>
|
||||
|
||||
<dt><a href="#variants">Build Variants</a></dt>
|
||||
|
||||
<dt><a href="#VisualStudio">Building Using the Microsoft Visual Studio
|
||||
IDE</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="requirements">Requirements</a></h2>
|
||||
<b>Boost.Python</b> version 2 requires <a href=
|
||||
"http://www.python.org/2.2">Python 2.2</a> <i>or <a href=
|
||||
"http://www.python.org">newer</a></i>. An unsupported archive of
|
||||
Boost.Python version 1, which works with versions of Python since 1.5.2,
|
||||
is available <a href="../build/python_v1.zip">here</a>.
|
||||
|
||||
<h2><a name="building">Building Boost.Python</a></h2>
|
||||
|
||||
<p>Normally, Boost.Python extension modules must be linked with the
|
||||
<code>boost_python</code> shared library. In special circumstances you
|
||||
may want to link to a static version of the <code>boost_python</code>
|
||||
library, but if multiple Boost.Python extension modules are used
|
||||
together, it will prevent sharing of types across extension modules, and
|
||||
consume extra code space. To build <code>boost_python</code>, use <a
|
||||
href="../../../tools/build/v1/build_system.htm">Boost.Build</a> in the
|
||||
usual way from the <code>libs/python/build</code> subdirectory of your
|
||||
boost installation (if you have already built boost from the top level
|
||||
this may have no effect, since the work is already done).</p>
|
||||
|
||||
<h3><a name="configuration">Basic Configuration</a></h3>
|
||||
You may need to configure the following variables to point Boost.Build at
|
||||
your Python installation:
|
||||
|
||||
<table border="1" summary="build configuration variables">
|
||||
<tr>
|
||||
<th>Variable Name</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Default</th>
|
||||
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>PYTHON_ROOT</code></td>
|
||||
|
||||
<td>The root directory of your Python installation</td>
|
||||
|
||||
<td>Windows: <code>c:/tools/python</code>
|
||||
Unix: <code>/usr/local</code></td>
|
||||
|
||||
<td>On Unix, this is the <code>--with-prefix=</code> directory used
|
||||
to configure Python</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>PYTHON_VERSION</code></td>
|
||||
|
||||
<td>The The 2-part python Major.Minor version number</td>
|
||||
|
||||
<td><code>2.2</code></td>
|
||||
|
||||
<td>Be sure not to include a third number, e.g. <b>not</b>
|
||||
"<code>2.2.1</code>", even if that's the version you have.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>PYTHON_INCLUDES</code></td>
|
||||
|
||||
<td>path to Python <code>#include</code> directories</td>
|
||||
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code>. Try the default
|
||||
before attempting to set it yourself.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>PYTHON_LIB_PATH</code></td>
|
||||
|
||||
<td>path to Python library object.</td>
|
||||
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code>. Try the default
|
||||
before attempting to set it yourself.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="cygwin_configuration">Configuration for Cygwin GCC from a
|
||||
Windows prompt</a></h3>
|
||||
The following settings may be useful when building with <a href=
|
||||
"http://www.cygwin.com">Cygwin</a> GCC (not MinGW) from a Windows command
|
||||
shell using a Windows build of <code>bjam</code>. <b>If
|
||||
"<code>bjam -v</code>" does not report "<code>OS=NT</code>", these
|
||||
settings do not apply to you</b>; you should use the <a href=
|
||||
"#configuration">normal configuration</a> variables instead. They are
|
||||
only useful when building and testing with multiple toolsets on Windows
|
||||
using a single build command, since Cygwin GCC requires a different build
|
||||
of Python.
|
||||
|
||||
<table border="1" summary=
|
||||
"Cygwin GCC under NT build configuration variables">
|
||||
<tr>
|
||||
<th>Variable Name</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]VERSION</code></td>
|
||||
|
||||
<td>The version of python being used under Cygwin.</td>
|
||||
|
||||
<td>$(PYTHON_VERSION)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td>
|
||||
|
||||
<td>unix-style path containing the <code>include/</code> directory
|
||||
containing
|
||||
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td>
|
||||
|
||||
<td>$(PYTHON_ROOT)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]LIB_PATH</code></td>
|
||||
|
||||
<td>path containing the user's Cygwin Python import lib
|
||||
<code>libpython$(CYGWIN_PYTHON_[DEBUG_]VERSION).dll.a</code></td>
|
||||
|
||||
<td>Autoconfigured from <code>CYGWIN_PYTHON_ROOT</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]DLL_PATH</code></td>
|
||||
|
||||
<td>path containing the user's Cygwin Python dll
|
||||
(<code>libpython$(CYGWIN_PYTHON_[DEBUG_]VERSION).dll</code>)</td>
|
||||
|
||||
<td><code>/bin</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="cygwin">Notes for Cygwin GCC Users</a></h3>
|
||||
|
||||
<p>If you are using Cygwin GCC to build extension modules, you must use a
|
||||
Cygwin build of Python. The regular Win32 Python installation that you
|
||||
can download from <a href="http://www.python.org">python.org</a> will not
|
||||
work with your compiler because the dynamic linking conventions are
|
||||
different (you can use <a href="http://www.mingw.org/">MinGW</a> GCC if
|
||||
you want to build extension modules which are compatible with a stock
|
||||
Win32 Python). The Cygwin installer may be able to install an appropriate
|
||||
version of Python, or you can follow the traditional <a href=
|
||||
"http://www.python.org/download/download_source.html">Unix installation
|
||||
process</a> to build Python from source.</p>
|
||||
|
||||
<p>The special build configuration variables listed <a href=
|
||||
"#cygwin_configuration">above</a> make it possible to use a regular Win32
|
||||
build of bjam to build and test Boost.Python and Boost.Python extensions
|
||||
using Cygwin GCC and targeting a Cygwin build of Python.</p>
|
||||
|
||||
<h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC
|
||||
Users</a></h3>
|
||||
|
||||
<p>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 href=
|
||||
"http://www.python.org/doc/current/inst/index.html">Installing Python
|
||||
Modules</a> to create <code>libpythonXX.a</code>, where <code>XX</code>
|
||||
corresponds to the major and minor version numbers of your Python
|
||||
installation.</p>
|
||||
|
||||
<h3><a name="results">Results</a></h3>
|
||||
|
||||
<p>The build process will create a
|
||||
<code>libs/python/build/bin-stage</code> subdirectory of the boost root
|
||||
(or of <code>$(ALL_LOCATE_TARGET)</code>, if you have set that variable),
|
||||
containing the built libraries. The libraries are actually built to
|
||||
unique directories for each toolset and variant elsewhere in the
|
||||
filesystem, and copied to the <code>bin-stage</code> directory as a
|
||||
convenience, so if you build with multiple toolsets at once, the product
|
||||
of later toolsets will overwrite that of earlier toolsets in
|
||||
<code>bin-stage</code>.</p>
|
||||
|
||||
<h3><a name="testing">Testing</a></h3>
|
||||
|
||||
<p>To build and test Boost.Python, start from the
|
||||
<code>libs/python/test</code> directory and invoke</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
bjam -sTOOLS=<i><a href=
|
||||
"../../../more/getting_started.html#Tools">toolset</a></i> test
|
||||
</pre>
|
||||
</blockquote>
|
||||
This will update all of the Boost.Python v1 test and example targets. The
|
||||
tests are relatively verbose by default. To get less-verbose output, you
|
||||
might try
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
bjam -sTOOLS=<i><a href=
|
||||
"../../../more/getting_started.html#Tools">toolset</a></i> -sPYTHON_TEST_ARGS= test
|
||||
</pre>
|
||||
</blockquote>
|
||||
By default, <code>PYTHON_TEST_ARGS</code> is set to <code>-v</code>.
|
||||
|
||||
<h2><a name="building_ext">Building your Extension Module</a></h2>
|
||||
Though there are other approaches, the smoothest and most reliable way to
|
||||
build an extension module using Boost.Python is with Boost.Build. If you
|
||||
have to use another build system, you should use Boost.Build at least
|
||||
once with the "<code><b>-n</b></code>" option so you can see the
|
||||
command-lines it uses, and replicate them. You are likely to run into
|
||||
compilation or linking problems otherwise.
|
||||
|
||||
<p>The files required to build a Boost.Python extension module using bjam
|
||||
are the "local" files <tt>Jamfile</tt>, <tt>Jamrules</tt>, and
|
||||
<tt>boost_build.jam</tt>, and the <tt>boost/</tt>
|
||||
and <tt>tools/build/v1/</tt> subdirectories of your Boost
|
||||
tree. The latter directory contains the source code of the
|
||||
Boost.Build system, which is used to generate the correct build
|
||||
commands for your extension module. The '<tt>v1</tt>' refers to
|
||||
Boost.Build version 1. Version 2 is pre-release and currently not
|
||||
ready for general use.
|
||||
|
||||
<p>
|
||||
The <tt>libs/python/example/</tt> project we're going to build is
|
||||
set up to automatically rebuild the Boost.Python library in place
|
||||
whenever it's out-of-date rather than just reusing an existing
|
||||
library, so you'll also need the Boost.Python library sources in
|
||||
<tt>boost/python/src/</tt>.
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<b>Note:</b> Third-party package and distribution maintainers
|
||||
for various operating systems sometimes split up Boost's
|
||||
structure or omit parts of it, so if you didn't download an
|
||||
official <a href=
|
||||
"http://sourceforge.net/project/showfiles.php?group_id=7586">Boost
|
||||
release</a> you might want to <a href=
|
||||
"http://cvs.sourceforge.net/viewcvs.py/boost/boost/">browse our CVS
|
||||
structure</a> to make sure you have everything you need, and in the
|
||||
right places.
|
||||
</blockquote>
|
||||
|
||||
<p>The <code><a href="../example">libs/python/example</a></code>
|
||||
subdirectory of your boost installation contains a small example which
|
||||
builds and tests two extensions. To build your own extensions copy the
|
||||
example subproject and make the following two edits:</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<code><a href=
|
||||
"../example/boost-build.jam"><b>boost-build.jam</b></a></code> - edit
|
||||
the line which reads
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
so that the path refers to the <code>tools/build/v1</code>
|
||||
subdirectory of your Boost installation.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<code><a href="../example/Jamrules"><b>Jamrules</b></a></code> - edit
|
||||
the line which reads
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
so that the path refers to the root directory of your Boost
|
||||
installation.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>The instructions <a href="#testing">above</a> for testing Boost.Python
|
||||
apply equally to your new extension modules in this subproject.</p>
|
||||
|
||||
<h2><a name="variants">Build Variants</a></h2>
|
||||
Three <a href=
|
||||
"../../../tools/build/v1/build_system.htm#variants">variant</a>
|
||||
configurations of all python-related targets are supported, and can be
|
||||
selected by setting the <code><a href=
|
||||
"../../../tools/build/v1/build_system.htm#user_globals">BUILD</a></code>
|
||||
variable:
|
||||
|
||||
<ul>
|
||||
<li><code>release</code> (optimization, <tt>-DNDEBUG</tt>)</li>
|
||||
|
||||
<li><code>debug</code> (no optimization <tt>-D_DEBUG</tt>)</li>
|
||||
|
||||
<li><code>debug-python</code> (no optimization, <tt>-D_DEBUG
|
||||
-DBOOST_DEBUG_PYTHON</tt>)</li>
|
||||
</ul>
|
||||
|
||||
<p>The first two variants of the <code>boost_python</code> library are
|
||||
built by default, and are compatible with the default Python
|
||||
distribution. The <code>debug-python</code> variant corresponds to a
|
||||
specially-built debugging version of Python. On Unix platforms, this
|
||||
python is built by adding <code>--with-pydebug</code> when configuring
|
||||
the Python build. On Windows, the debugging version of Python is
|
||||
generated by the "Win32 Debug" target of the <code>PCBuild.dsw</code>
|
||||
Visual C++ 6.0 project in the <code>PCBuild</code> subdirectory of your
|
||||
Python distribution. Extension modules built with Python debugging
|
||||
enabled are <b>not link-compatible</b> with a non-debug build of Python.
|
||||
Since few people actually have a debug build of Python (it doesn't come
|
||||
with the standard distribution), the normal <code>debug</code> variant
|
||||
builds modules which are compatible with ordinary Python.</p>
|
||||
|
||||
<p>On many windows compilers, when extension modules are built with
|
||||
<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 - unless <code>BOOST_DEBUG_PYTHON</code> is
|
||||
defined.</p>
|
||||
|
||||
<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
|
||||
python debuggin, and link with the <code>debug-python</code> variant of
|
||||
<tt>boost_python</tt>.</p>
|
||||
|
||||
<p>If you do not <tt>#define BOOST_DEBUG_PYTHON</tt>, be sure that any
|
||||
source files in your extension module <tt>#include <<a href=
|
||||
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a>></tt>
|
||||
instead of the usual <tt>Python.h</tt>, or you will have link
|
||||
incompatibilities.<br>
|
||||
</p>
|
||||
|
||||
<h2><a name="VisualStudio">Building Using the Microsoft Visual Studio
|
||||
IDE</a></h2>
|
||||
|
||||
<p>For the those of you who feel more comfortable in the IDE world, a
|
||||
workspace and project file have been included in the <a href=
|
||||
"../build/VisualStudio">libs/python/build/VisualStudio</a> subdirectory.
|
||||
It builds release and debug versions of the Boost.Python libraries and
|
||||
places them and the same directory as Jamfile build does, though the
|
||||
intermediate object files are placed in a different directory. The files
|
||||
have been created using Microsoft Visual C++ version 6, but they should
|
||||
work for later versions as well. You will need to tell the IDE where to
|
||||
find the Python <code>Include/</code> and <code>Libs/</code> directories.
|
||||
Under <b>Tools>Options>Directories</b>, add an entry for the Python
|
||||
include dir (i.e. <code>c:/Python22/Include</code>), and one for the Lib
|
||||
(i.e. <code>c:/Python/Libs</code>. Make sure it is <code>Libs</code> with
|
||||
an "<code>s</code>" and not just <code>Lib</code>).</p>
|
||||
|
||||
<h3>Using the IDE for your own projects</h3>
|
||||
|
||||
<p>Building your own projects using the IDE is slightly more complicated.
|
||||
Firstly, you need to make sure that the project you create as the right
|
||||
kind. It should be a "Win32 Dynamic-Link Library". The default one that
|
||||
Visual Studio 6 creates needs some modifications: turn on RTTI, and
|
||||
change the debug and release builds to use the respective debug and
|
||||
release Multithreaded DLL versions. You should probably turn off
|
||||
incremental linking too -- I believe it a bit flaky. If you do this, then
|
||||
change the "Debug Info" to "Program Database" to get rid of the Edit and
|
||||
Continue warning.</p>
|
||||
|
||||
<p>You'll need to add the Boost root directory under
|
||||
<b>Tools>Options>Directories</b> to get your code compiling. To
|
||||
make it link, add the above <code>boost_python.dsp</code> file to your
|
||||
workspace, and make your project depend upon it (under
|
||||
<b>Project>Dependencies</b>). You should be able to build now.</p>
|
||||
|
||||
<p>Lastly, go to the <b>Project Settings>Debug</b> Page and add the
|
||||
<code>Python.exe</code> as the executable for the project. Set a startup
|
||||
directory, and make sure that your current project's output dll, the
|
||||
<code>boost_python.dll</code> and the <code>python22.dll</code> are on
|
||||
the current <code>PATH</code>. If you have a python script that tests
|
||||
your dll, then add it in the "Program Arguments". Now, if all went well,
|
||||
you should be able to hit the Run (F5) button, and debug your code.</p>
|
||||
|
||||
<blockquote>
|
||||
<em>The Visual Studio project files are graciously contributed and
|
||||
maintained by <a href="mailto:brett.calcott@gmail.com">Brett
|
||||
Calcott</a></em>.
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<p>© Copyright David Abrahams 2002-2004. 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>
|
||||
|
||||
<p>Updated: 13 April 2004 (David Abrahams)</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
179
doc/index.html
@@ -1,179 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
<td align="right">
|
||||
|
||||
<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>
|
||||
|
||||
<span id="search-text">
|
||||
<input type="text" name="q" id="q" size="31" maxlength="255" alt="Search Text" />
|
||||
</span>
|
||||
|
||||
<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>
|
||||
|
||||
<span id="go">
|
||||
<input type="image" name="search" src="../../../more/space.gif" alt="Search" id="search-button" />
|
||||
</span>
|
||||
|
||||
<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>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
|
||||
<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:
|
||||
|
||||
<ul>
|
||||
<li>References and Pointers</li>
|
||||
|
||||
<li>Globally Registered Type Coercions</li>
|
||||
|
||||
<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>
|
||||
|
||||
<dt><a href="../pyste/index.html">Pyste (Boost.Python code generator)</a></dt>
|
||||
|
||||
<dt><a href="internals.html">Internals Documentation</a></dt>
|
||||
|
||||
<dt><a href="news.html">News/Change Log</a></dt>
|
||||
|
||||
<dt><a href="../todo.html">TODO list</a></dt>
|
||||
|
||||
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
|
||||
|
||||
<dt><a href="v2/acknowledgments.html">Acknowledgments</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2>Articles</h2>
|
||||
|
||||
"<a href="PyConDC_2003/bpl.html">Building Hybrid
|
||||
Systems With Boost Python</a>", 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>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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_<boring>("boring")
|
||||
;
|
||||
</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 "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.</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">
|
||||
>>> 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<boring,</span> <span class="pre">non_copyable,</span>
|
||||
<span class="pre">...></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<boring</span> <span class="pre">...>(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<boring></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<></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 ->
|
||||
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<>(...)</span></tt>, <tt class="literal"><span class="pre">call_method<>(...)</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, "return value" conversion
|
||||
(for Python->C++ calls) and "argument" conversion (for
|
||||
C++->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 "default" 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 "return value"
|
||||
and "argument" 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>
|
||||
@@ -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.
|
||||
|
||||
218
doc/news.html
@@ -1,218 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - 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>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
|
||||
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> => 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>
|
||||
>>> import test
|
||||
>>> f(0, z = "bar")
|
||||
>>> 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ßauge</a> has contributed <a href=
|
||||
"v2/opaque_pointer_converter.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<X></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<></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>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
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?
|
||||
|
||||
|
||||
@@ -1,436 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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="utf-8">
|
||||
<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>
|
||||
“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>”</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>
|
||||
</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>
|
||||
|
||||
</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>
|
||||
|
||||
</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>
|
||||
</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 LBFGS conjugate
|
||||
gradient 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>
|
||||
</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://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 -->
|
||||
15 July, 2003</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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>
|
||||
</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>
|
||||
</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>
|
||||
</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>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
project boost/libs/python/doc/tutorial/doc ;
|
||||
|
||||
import boostbook : boostbook ;
|
||||
using quickbook ;
|
||||
|
||||
boostbook tutorial
|
||||
:
|
||||
tutorial.qbk
|
||||
:
|
||||
<xsl:param>boost.root=../../../../../..
|
||||
<xsl:param>boost.libraries=../../../../../../libs/libraries.htm
|
||||
;
|
||||
@@ -1,430 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2004 Joel de Guzman
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
/*=============================================================================
|
||||
Body defaults
|
||||
=============================================================================*/
|
||||
|
||||
body
|
||||
{
|
||||
margin: 1em;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Paragraphs
|
||||
=============================================================================*/
|
||||
|
||||
p
|
||||
{
|
||||
text-align: justify;
|
||||
font-size: 11pt;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Program listings
|
||||
=============================================================================*/
|
||||
|
||||
tt.computeroutput
|
||||
{
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
pre.synopsis
|
||||
{
|
||||
font-size: 10pt;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
font-size: 10pt;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Headings
|
||||
=============================================================================*/
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6
|
||||
{
|
||||
text-align: left;
|
||||
margin-top: 2pc;
|
||||
}
|
||||
|
||||
h1 { font: 170% }
|
||||
h2 { font: bold 140% }
|
||||
h3 { font: bold 120% }
|
||||
h4 { font: bold 100% }
|
||||
h5 { font: italic 100% }
|
||||
h6 { font: italic 100% }
|
||||
|
||||
/* Top page titles */
|
||||
title,
|
||||
h1.title,
|
||||
h2.title
|
||||
h3.title,
|
||||
h4.title,
|
||||
h5.title,
|
||||
h6.title,
|
||||
.refentrytitle
|
||||
{
|
||||
font-weight: bold;
|
||||
margin-bottom: 1pc;
|
||||
}
|
||||
|
||||
h1.title { font-size: 220% }
|
||||
h2.title { font-size: 220% }
|
||||
h3.title { font-size: 170% }
|
||||
h4.title { font-size: 140% }
|
||||
h5.title { font-size: 120% }
|
||||
h6.title { font-size: 120% }
|
||||
|
||||
/*=============================================================================
|
||||
Lists
|
||||
=============================================================================*/
|
||||
|
||||
li
|
||||
{
|
||||
font-size: 11pt;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Unordered lists */
|
||||
ul
|
||||
{
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/* Ordered lists */
|
||||
ol
|
||||
{
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Links
|
||||
=============================================================================*/
|
||||
|
||||
a
|
||||
{
|
||||
text-decoration: none; /* no underline */
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Spirit style navigation
|
||||
=============================================================================*/
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.spirit-nav a
|
||||
{
|
||||
color: white;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.spirit-nav img
|
||||
{
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Table of contents
|
||||
=============================================================================*/
|
||||
|
||||
.toc
|
||||
{
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc;
|
||||
font-size: 11pt;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.boost-toc
|
||||
{
|
||||
float: right;
|
||||
padding: 0.5pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Tables
|
||||
=============================================================================*/
|
||||
|
||||
.table-title,
|
||||
div.table p.title
|
||||
{
|
||||
margin-left: 4%;
|
||||
padding-right: 0.5em;
|
||||
padding-left: 0.5em;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
width: 92%;
|
||||
margin-left: 4%;
|
||||
margin-right: 4%;
|
||||
}
|
||||
|
||||
div.informaltable table,
|
||||
div.table table
|
||||
{
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
/* Table Cells */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
padding: 0.5em;
|
||||
text-align: justify;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||
border: 1pt solid white;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Blurbs
|
||||
=============================================================================*/
|
||||
|
||||
div.informaltable table tr td.blurb
|
||||
{
|
||||
font-size: 10pt; /* A little bit smaller than the main text */
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
td.blurb img
|
||||
{
|
||||
padding: 1pt;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Misc
|
||||
=============================================================================*/
|
||||
|
||||
/* Tone down the title of Parameter lists */
|
||||
div.variablelist p.title
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Tabularize parameter lists */
|
||||
div.variablelist dl dt
|
||||
{
|
||||
float: left;
|
||||
clear: left;
|
||||
display: block;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.variablelist dl dd
|
||||
{
|
||||
display: block;
|
||||
clear: right;
|
||||
padding-left: 8pc;
|
||||
}
|
||||
|
||||
/* Title of books and articles in bibliographies */
|
||||
span.title
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
span.underline
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
span.strikethrough
|
||||
{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
div div.legalnotice p
|
||||
{
|
||||
text-align: left
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Colors
|
||||
=============================================================================*/
|
||||
|
||||
@media screen
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: #005a9c;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: #9c5a9c;
|
||||
}
|
||||
|
||||
/* Syntax Highlighting */
|
||||
.keyword { color: #0000AA; }
|
||||
.identifier { color: #000000; }
|
||||
.special { color: #707070; }
|
||||
.preprocessor { color: #402080; }
|
||||
.char { color: teal; }
|
||||
.comment { color: #800000; }
|
||||
.string { color: teal; }
|
||||
.number { color: teal; }
|
||||
.white_bkd { background-color: #FFFFFF; }
|
||||
.dk_grey_bkd { background-color: #999999; }
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
.copyright
|
||||
{
|
||||
color: #666666;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div div.legalnotice p
|
||||
{
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
background-color: #F3F3F3;
|
||||
border: 1pt solid #C0C0C0;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
background-color: #F3F3F3;
|
||||
border: 1pt solid #C0C0C0;
|
||||
}
|
||||
|
||||
/* Blurbs */
|
||||
div.informaltable table tr td.blurb
|
||||
{
|
||||
background-color: #FFFFF0;
|
||||
border: 1pt solid #707070;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
background-color: #F3F3F3;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
background-color: #E4E4E4;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
color: #00A000;
|
||||
}
|
||||
}
|
||||
|
||||
@media print
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
border: 1px solid gray;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 358 B |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 658 B |
|
Before Width: | Height: | Size: 334 B |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 867 B |
|
Before Width: | Height: | Size: 640 B |
|
Before Width: | Height: | Size: 370 B |
@@ -1,134 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Chapter 1. python 1.0</title>
|
||||
<link rel="stylesheet" href="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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="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="id442427"></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="id372086"></a>Hello World</h2>
|
||||
<p>
|
||||
Following C/C++ tradition, let's start with the "hello, world". A C++
|
||||
Function:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
can be exposed to Python by writing a Boost.Python wrapper:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> <</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">></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">
|
||||
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></tt></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"><tt class="literal"><span class="special">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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></tt></pre>
|
||||
<p></p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><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></blockquote></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><small><p>Last revised: July 12, 2005 at 07:50:43 GMT</p></small></td>
|
||||
<td align="right"><small></small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="images/next.png" alt="Next"></a></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,346 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Embedding</title>
|
||||
<link rel="stylesheet" href="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="object.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../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"></span></p>
|
||||
<a name="embedding.building_embedded_programs"></a><h2>
|
||||
<a name="id456196"></a>Building embedded programs</h2>
|
||||
<p>
|
||||
To be able to use embedding in your programs, they have to be linked to
|
||||
both Boost.Python's and Python's static link library.</p>
|
||||
<p>
|
||||
Boost.Python's static link 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 static link 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"><tt class="literal">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
|
||||
<find-library>boost_python <library-path>c:\boost\libs\python
|
||||
$(PYTHON_PROPERTIES)
|
||||
<library-path>$(PYTHON_LIB_PATH)
|
||||
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
||||
</tt></pre>
|
||||
<a name="embedding.getting_started"></a><h2>
|
||||
<a name="id456277"></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"><boost/python.hpp></tt><br><br>
|
||||
</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.<br><br>
|
||||
</li>
|
||||
<li>
|
||||
Call other Python C API routines to use the interpreter.<br><br>
|
||||
</li>
|
||||
<li>
|
||||
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>() to stop the interpreter and release its resources.
|
||||
</li>
|
||||
</ol></div>
|
||||
<p>
|
||||
(Of course, there can be other C++ code between all of these steps.)</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><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></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/api/refcounts.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.reference_counting_handles_and_objects"></a><h2>
|
||||
<a name="id456409"></a>Reference-counting handles and objects</h2>
|
||||
<p>
|
||||
There are two ways in which a function in the Python/C API can return a
|
||||
<tt class="literal">PyObject*</tt>: as a <span class="emphasis"><em>borrowed reference</em></span> or as a <span class="emphasis"><em>new reference</em></span>. Which of
|
||||
these a function uses, is listed in that function's documentation. The two
|
||||
require slightely different approaches to reference-counting but both can
|
||||
be 'handled' by Boost.Python.</p>
|
||||
<p>
|
||||
For a function returning a <span class="emphasis"><em>borrowed reference</em></span> we'll have to tell the
|
||||
<tt class="literal">handle</tt> that the <tt class="literal">PyObject*</tt> is borrowed with the aptly named
|
||||
<a href="../../../../v2/handle.html#borrowed-spec" target="_top">borrowed</a> function. Two functions
|
||||
returning borrowed references are <a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a> and <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594" target="_top">PyModule_GetDict</a>.
|
||||
The former returns a reference to an already imported module, the latter
|
||||
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||
namespace of the <tt class="literal"><span class="underline">_main</span>_</tt> module:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> main_module</span><span class="special">((</span><span class="identifier">
|
||||
handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><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></tt></pre>
|
||||
<p>
|
||||
For a function returning a <span class="emphasis"><em>new reference</em></span> we can just create a <tt class="literal">handle</tt>
|
||||
out of the raw <tt class="literal">PyObject*</tt> without wrapping it in a call to borrowed. One
|
||||
such function that returns a new reference is <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a> which we'll
|
||||
discuss in the next section.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>, so why haven't we been using any template parameters?</b></span><br><br><tt class="literal">handle</tt> has a single template parameter specifying the type of the managed object. This type is <tt class="literal">PyObject</tt> 99% of the time, so the parameter was defaulted to <tt class="literal">PyObject</tt> for convenience. Therefore we can use the shorthand <tt class="literal">handle<></tt> instead of the longer, but equivalent, <tt class="literal">handle<PyObject></tt>.
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h2>
|
||||
<a name="id456714"></a>Running Python code</h2>
|
||||
<p>
|
||||
To run Python code from C++ there is a family of functions in the API
|
||||
starting with the PyRun prefix. You can find the full list of these
|
||||
functions <a href="http://www.python.org/doc/current/api/veryhigh.html" target="_top">here</a>. They
|
||||
all work similarly so we will look at only one of them, namely:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">PyObject</span><span class="special">*</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="keyword">char</span><span class="special"> *</span><span class="identifier">str</span><span class="special">,</span><span class="keyword"> int</span><span class="identifier"> start</span><span class="special">,</span><span class="identifier"> PyObject</span><span class="special"> *</span><span class="identifier">globals</span><span class="special">,</span><span class="identifier"> PyObject</span><span class="special"> *</span><span class="identifier">locals</span><span class="special">)</span></tt></pre>
|
||||
<p><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a> takes the code to execute as a null-terminated (C-style)
|
||||
string in its <tt class="literal">str</tt> parameter. The function returns a new reference to a
|
||||
Python object. Which object is returned depends on the <tt class="literal">start</tt> paramater.</p>
|
||||
<p>
|
||||
The <tt class="literal">start</tt> parameter is the start symbol from the Python grammar to use
|
||||
for interpreting the code. The possible values are:</p>
|
||||
<div class="informaltable">
|
||||
<h4>
|
||||
<a name="id456876"></a><span class="table-title">Start symbols</span>
|
||||
</h4>
|
||||
<table class="table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a></th>
|
||||
<th>for interpreting isolated expressions</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a></td>
|
||||
<td>for interpreting sequences of statements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a></td>
|
||||
<td>for interpreting a single statement</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>
|
||||
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>, the input string must contain a single expression
|
||||
and its result is returned. When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>, the string can
|
||||
contain an abitrary number of statements and None is returned.
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a> works in the same way as <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a> but only accepts a
|
||||
single statement.</p>
|
||||
<p>
|
||||
Lastly, 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>
|
||||
We have already seen how to get the <tt class="literal"><span class="underline">_main</span>_</tt> module's namespace so let's
|
||||
run some Python code in it:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> main_module</span><span class="special">((</span><span class="identifier">
|
||||
handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><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">
|
||||
|
||||
handle</span><span class="special"><></span><span class="identifier"> ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><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> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span><span class="special">
|
||||
));</span></tt></pre>
|
||||
<p>
|
||||
Because the Python/C API doesn't know anything about <tt class="literal">object</tt>s, we used
|
||||
the object's <tt class="literal">ptr</tt> member function to retrieve the <tt class="literal">PyObject*</tt>.</p>
|
||||
<p>
|
||||
This should create a file called 'hello.txt' in the current directory
|
||||
containing a phrase that is well-known in programming circles.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a> in a
|
||||
(nameless) <tt class="literal">handle</tt> even though we are not interested in it. If we didn't
|
||||
do this, the the returned object would be kept alive unnecessarily. Unless
|
||||
you want to be a Dr. Frankenstein, always wrap <tt class="literal">PyObject*</tt>s in <tt class="literal">handle</tt>s.
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<a name="using_the_interpreter.beyond_handles"></a><h2>
|
||||
<a name="id457324"></a>Beyond handles</h2>
|
||||
<p>
|
||||
It's nice that <tt class="literal">handle</tt> manages the reference counting details for us, but
|
||||
other than that it doesn't do much. Often we'd like to have a more useful
|
||||
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 it's 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"><tt class="literal"><span class="identifier">object</span><span class="identifier"> main_module</span><span class="special">((</span><span class="identifier">
|
||||
handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><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">
|
||||
|
||||
handle</span><span class="special"><></span><span class="identifier"> ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">
|
||||
|
||||
"result = 5 ** 2"</span><span class="special">
|
||||
|
||||
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span></tt></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 let
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a> return the result directly with <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> result</span><span class="special">((</span><span class="identifier">handle</span><span class="special"><>(</span>
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">"5 ** 2"</span><span class="special">
|
||||
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span></tt></pre>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s member function to return the wrapped
|
||||
<tt class="literal">PyObject*</tt> is called <tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes sense if you
|
||||
take into account the different functions that <tt class="literal">object</tt> and <tt class="literal">handle</tt>
|
||||
perform.
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h2>
|
||||
<a name="id457906"></a>Exception handling</h2>
|
||||
<p>
|
||||
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
function returns a null pointer. Constructing a <tt class="literal">handle</tt> out of this null
|
||||
pointer throws <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>,
|
||||
so basically, the Python exception is automatically translated into a
|
||||
C++ exception when using <tt class="literal">handle</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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">handle</span><span class="special"><>(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">
|
||||
"5/0"</span><span class="special">
|
||||
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</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"><</span><span class="keyword">int</span><span class="special">>(</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="special">)</span><span class="special">
|
||||
{</span><span class="comment">
|
||||
// handle the exception in some way
|
||||
</span><span class="special">}</span></tt></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"><tt class="literal"><span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</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></tt></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>
|
||||
<p>
|
||||
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception when it is constructed, you
|
||||
can use the <a href="../../../../v2/handle.html#allow_null-spec" target="_top">allow_null</a> function in the same
|
||||
way you'd use borrowed:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">handle</span><span class="special"><></span><span class="identifier"> result</span><span class="special">((</span><span class="identifier">allow_null</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">
|
||||
"5/0"</span><span class="special">
|
||||
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special">
|
||||
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))));</span><span class="keyword">
|
||||
|
||||
if</span><span class="special"> (!</span><span class="identifier">result</span><span class="special">)</span><span class="comment">
|
||||
// Python exception occurred
|
||||
</span><span class="keyword">else</span><span class="comment">
|
||||
// everything went okay, it's safe to use the result
|
||||
</span></tt></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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="object.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,54 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exception Translation</title>
|
||||
<link rel="stylesheet" href="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="iterators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../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"><tt class="literal"><span class="identifier">raise</span><span class="identifier"> RuntimeError</span><span class="special">,</span><span class="char"> 'unidentifiable C++ Exception'</span></tt></pre>
|
||||
<p>
|
||||
Users may provide custom translation. Here's an example:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> PodBayDoorException</span><span class="special">;</span><span class="keyword">
|
||||
void</span><span class="identifier"> translator</span><span class="special">(</span><span class="identifier">PodBayDoorException</span><span class="keyword"> const</span><span class="special">&</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"><</span><span class="identifier">
|
||||
PodBayDoorException</span><span class="special">>(</span><span class="identifier">translator</span><span class="special">);</span><span class="special">
|
||||
...</span></tt></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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="iterators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,476 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exposing Classes</title>
|
||||
<link rel="stylesheet" href="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="hello.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../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"><tt class="literal"><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">-></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></tt></pre>
|
||||
<p>
|
||||
We can expose this to Python by writing a corresponding Boost.Python
|
||||
C++ Wrapper:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> <</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">></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"><</span><span class="identifier">World</span><span class="special">>(</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"> &</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"> &</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></tt></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"><tt class="literal"><span class="special">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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">
|
||||
>>></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">
|
||||
>>></span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="string">
|
||||
'howdy'</span></tt></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"><tt class="literal"><span class="special">>>></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></tt></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"><tt class="literal"><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">-></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></tt></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_<World></tt> about the constructor we want to
|
||||
expose instead.</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> <</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">></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"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span><span class="identifier"> init</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="special">
|
||||
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span><span class="special"> &</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"> &</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></tt></pre>
|
||||
<p><tt class="literal">init<std::string>()</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<...></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"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span><span class="identifier"> init</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="special">
|
||||
.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span><span class="keyword"> double</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"> &</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"> &</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span><span class="special">
|
||||
;</span></tt></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"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Abstract</span><span class="special">>(</span><span class="string">"Abstract"</span><span class="special">,</span><span class="identifier"> no_init</span><span class="special">)</span></tt></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Our C++ <tt class="literal">Var</tt> class and its data members can be exposed to Python:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Var</span><span class="special">>(</span><span class="string">"Var"</span><span class="special">,</span><span class="identifier"> init</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="special">
|
||||
.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span><span class="special"> &</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"> &</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span></tt></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"><tt class="literal"><span class="special">>>></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">
|
||||
>>></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">
|
||||
>>></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></tt></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"><tt class="literal"><span class="special">>>></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"> "<stdin>"</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></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Num</span><span class="special">>(</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"> &</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"> &</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">Num</span><span class="special">::</span><span class="identifier">set</span><span class="special">);</span></tt></pre>
|
||||
<p>
|
||||
And at last, in Python:</p>
|
||||
<p></p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> Num</span><span class="special">()</span><span class="special">
|
||||
>>></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">
|
||||
>>></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">
|
||||
>>></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></tt></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"><tt class="literal"><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"> &</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
We've seen how we can wrap the base class <tt class="literal">Base</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span><span class="comment">
|
||||
/*...*/</span><span class="special">
|
||||
;</span></tt></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"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Derived</span><span class="special">,</span><span class="identifier"> bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span><span class="special"> >(</span><span class="string">"Derived"</span><span class="special">)</span><span class="comment">
|
||||
/*...*/</span><span class="special">
|
||||
;</span></tt></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 shall 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"><tt class="literal"><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></tt></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<manage_new_object></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 shall see more of
|
||||
Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call policies</a> later.</p>
|
||||
<pre class="programlisting"><tt class="literal"><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"><</span><span class="identifier">manage_new_object</span><span class="special">>());</span></tt></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 shall 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"><tt class="literal"><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></tt></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"><tt class="literal"><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"><</span><span class="identifier">Base</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="special">
|
||||
{</span><span class="keyword">
|
||||
return</span><span class="keyword"> this</span><span class="special">-></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></tt></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"><</span><span class="identifier">Base</span><span class="special">></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="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>MSVC6/7 Workaround</b></span><br><br>
|
||||
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt> as:<br><br><tt class="computeroutput"><span class="keyword">return</span><span class="identifier"> call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></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>.</td></tr></tbody>
|
||||
</table></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"><tt class="literal"><span class="identifier">class_</span><span class="special"><</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">>(</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">(&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span><span class="special">
|
||||
;</span></tt></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="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>member function and methods</b></span><br><br>
|
||||
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>
|
||||
</td></tr></tbody>
|
||||
</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"><tt class="literal"><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></tt></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
We wrap it this way:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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"><</span><span class="identifier">Base</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="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">-></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">-></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></tt></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="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>MSVC6/7 Workaround</b></span><br><br>
|
||||
|
||||
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:<br><br><tt class="computeroutput"><span class="keyword">return</span><span class="identifier"> call</span><span class="special"><</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Finally, exposing:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</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">>(</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"> &</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="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span><span class="special">
|
||||
;</span></tt></pre>
|
||||
<p>
|
||||
Take note that we expose both <tt class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</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"><tt class="literal"><span class="special">>>></span><span class="identifier"> base</span><span class="special"> =</span><span class="identifier"> Base</span><span class="special">()</span><span class="special">
|
||||
>>></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">
|
||||
>>></span><span class="identifier"> derived</span><span class="special"> =</span><span class="identifier"> Derived</span><span class="special">()</span></tt></pre>
|
||||
<p>
|
||||
Calling <tt class="literal">base.f()</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span><span class="number">
|
||||
0</span></tt></pre>
|
||||
<p>
|
||||
Calling <tt class="literal">derived.f()</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span><span class="number">
|
||||
42</span></tt></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="id447543"></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"><tt class="literal"><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">&</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">&</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="keyword">
|
||||
bool</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></tt></pre>
|
||||
<p>
|
||||
The class and the various operators can be mapped to Python rather easily
|
||||
and intuitively:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">FilePos</span><span class="special">>(</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"><</span><span class="keyword">int</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="identifier"> self</span><span class="special">);</span><span class="comment"> // __lt__
|
||||
</span></tt></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<T>()</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="id448230"></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"><tt class="literal"><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">&</span><span class="keyword"> operator</span><span class="special"><<(</span><span class="identifier">ostream</span><span class="special">&,</span><span class="identifier">Rational</span><span class="special">);</span><span class="identifier">
|
||||
|
||||
class_</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>(</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"><</span><span class="identifier">Rational</span><span class="special">>))</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></tt></pre>
|
||||
<p>
|
||||
Need we say more?</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span> What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</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"><<</span></tt> to do its work (i.e.
|
||||
<tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</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>.</td></tr></tbody>
|
||||
</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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="hello.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,480 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Functions</title>
|
||||
<link rel="stylesheet" href="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exposing.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../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 shall see some facilities to make exposing C++ functions to
|
||||
Python safe from potential pifalls such as dangling pointers and
|
||||
references. We shall 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><span class="emphasis"><em>Read on...</em></span></p></blockquote></div>
|
||||
<p>
|
||||
But before you do, you might want to fire up Python 2.2 or later and type
|
||||
<tt class="literal">>>> import this</tt>.</p>
|
||||
<pre class="programlisting"><tt class="literal">>>> 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!
|
||||
</tt></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"><tt class="literal"><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"> y</span><span class="special">,</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">);</span></tt></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"><tt class="literal"><span class="special">>>></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="identifier"> 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">
|
||||
>>></span><span class="identifier"> del</span><span class="identifier"> y</span><span class="special">
|
||||
>>></span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> #<span class="identifier"> CRASH</span><span class="special">!</span></tt></pre>
|
||||
<p>
|
||||
What's the problem?</p>
|
||||
<p>
|
||||
Well, what if f() was implemented as shown below:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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"> 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></tt></pre>
|
||||
<p>
|
||||
The problem is that the lifetime of result X& 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"><tt class="literal"><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="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">>>></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></tt></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"><tt class="literal"><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">-></span><span class="identifier">value</span><span class="special">();</span><span class="special"> }</span><span class="special">
|
||||
};</span></tt></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"><tt class="literal"><span class="special">>>></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="identifier"> y</span><span class="identifier"> refers</span><span class="identifier"> to</span><span class="identifier"> z</span><span class="special">
|
||||
>>></span><span class="identifier"> del</span><span class="identifier"> z</span> #<span class="identifier"> Kill</span><span class="identifier"> the</span><span class="identifier"> z</span><span class="identifier"> object</span><span class="special">
|
||||
>>></span><span class="identifier"> y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> #<span class="identifier"> CRASH</span><span class="special">!</span></tt></pre>
|
||||
<p>
|
||||
For reference, here's the implementation of <tt class="literal">f</tt> again:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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"> 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></tt></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->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="id449896"></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"><tt class="literal"><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"><</span><span class="number">1</span><span class="special">,</span><span class="identifier">
|
||||
with_custodian_and_ward</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="special"> >());</span></tt></pre>
|
||||
<p>
|
||||
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you ask?</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">return_internal_reference</span><span class="special"><</span><span class="number">1</span></tt></pre>
|
||||
<p>
|
||||
Informs Boost.Python that the first argument, in our case <tt class="literal">Y& y</tt>, is the
|
||||
owner of the returned reference: <tt class="literal">X&</tt>. The "<tt class="literal">1</tt>" simply specifies the
|
||||
first argument. In short: "return an internal reference <tt class="literal">X&</tt> owned by the
|
||||
1st argument <tt class="literal">Y& y</tt>".</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span><span class="number"> 2</span><span class="special">></span></tt></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& 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"><tt class="literal"><span class="identifier">policy1</span><span class="special"><</span><span class="identifier">args</span><span class="special">...,</span><span class="identifier">
|
||||
policy2</span><span class="special"><</span><span class="identifier">args</span><span class="special">...,</span><span class="identifier">
|
||||
policy3</span><span class="special"><</span><span class="identifier">args</span><span class="special">...></span><span class="special"> ></span><span class="special"> ></span></tt></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><br>
|
||||
Ties lifetimes of the arguments
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>with_custodian_and_ward_postcall</b></span><br>
|
||||
Ties lifetimes of the arguments and results
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>return_internal_reference</b></span><br>
|
||||
Ties lifetime of one argument to that of result
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>return_value_policy<T> with T one of:</b></span><br>
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>reference_existing_object</b></span><br>
|
||||
naive (dangerous) approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>copy_const_reference</b></span><br>
|
||||
Boost.Python v1 approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>copy_non_const_reference</b></span><br>
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>manage_new_object</b></span><br>
|
||||
Adopt a pointer and hold the instance
|
||||
</li>
|
||||
</ul></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/smiley.png"></span><span class="bold"><b>Remember the Zen, Luke:</b></span><br><br>
|
||||
|
||||
"Explicit is better than implicit"<br>
|
||||
|
||||
"In the face of ambiguity, refuse the temptation to guess"<br>
|
||||
</td></tr></tbody>
|
||||
</table></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Class X has 4 overloaded functions. We shall start by introducing some
|
||||
member function pointer variables:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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"> &</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"> &</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"> &</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"> &</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span></tt></pre>
|
||||
<p>
|
||||
With these in hand, we can proceed to define and wrap this for Python:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><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">
|
||||
|
||||
/*...*/
|
||||
|
||||
// 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></tt></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="id451716"></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
The macro invocation:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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"><tt class="literal"><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></tt></pre>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
|
||||
<a name="id451995"></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
The macro invocation:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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"><tt class="literal"><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"> &</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></tt></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="id452323"></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<...></tt>? For example,
|
||||
given a class X with a constructor:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
You can easily add this constructor to Boost.Python in one shot:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span><span class="identifier"> optional</span><span class="special"><</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">></span><span class="special"> >())</span></tt></pre>
|
||||
<p>
|
||||
Notice the use of <tt class="literal">init<...></tt> and <tt class="literal">optional<...></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Like in the previous section, we can generate thin wrappers for these
|
||||
overloaded functions in one-shot:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Then...</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">.</span><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></tt></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="id452969"></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Create a member function pointers as above for both X::f overloads:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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"> &</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"> &</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span></tt></pre>
|
||||
<p>
|
||||
Then...</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exposing.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,243 +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="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../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="id374047"></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 shall outline the steps
|
||||
necessary to achieve that. We shall use the build tool that comes bundled
|
||||
with every boost distribution: <span class="bold"><b>bjam</b></span>.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Building without bjam</b></span><br><br>
|
||||
|
||||
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>.<br><br>
|
||||
|
||||
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.
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
We shall 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 two DLLs:</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
boost_python.dll
|
||||
</li>
|
||||
<li>
|
||||
hello.pyd
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
if you are on Windows, and</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
libboost_python.so
|
||||
</li>
|
||||
<li>
|
||||
hello.so
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
if you are on Unix.</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>
|
||||
Jamfile
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The <tt class="literal">Jamfile</tt> is a
|
||||
minimalist <span class="emphasis"><em>bjam</em></span> script that builds the DLLs for us.</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="id372653"></a>Let's Jam!</h2>
|
||||
<p><span class="inlinemediaobject"><img src="../images/jam.png"></span></p>
|
||||
<p>
|
||||
Here is our minimalist Jamfile:</p>
|
||||
<pre class="programlisting"><tt class="literal"># This is the top of our own project tree
|
||||
project-root ;
|
||||
|
||||
import python ;
|
||||
|
||||
extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
</tt></pre>
|
||||
<p>
|
||||
First, we need to specify our location. You may place your project anywhere.
|
||||
<tt class="literal">project-root</tt> allows you to do that.</p>
|
||||
<pre class="programlisting"><tt class="literal">project-root ;
|
||||
</tt></pre>
|
||||
<p>
|
||||
By doing so, you'll need a Jamrules file. Simply copy the one in the
|
||||
<a href="../../../../../example/tutorial/Jamrules" target="_top">example/tutorial directory</a> and tweak
|
||||
the <tt class="literal">path-global BOOST_ROOT</tt> to where your boost root directory is. The file
|
||||
has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed instructions</a> you can follow.</p>
|
||||
<p>
|
||||
Then we will import the definitions needed by Python modules:</p>
|
||||
<pre class="programlisting"><tt class="literal">import python ;
|
||||
</tt></pre>
|
||||
<p>
|
||||
Finally we declare our <tt class="literal">hello</tt> extension:</p>
|
||||
<pre class="programlisting"><tt class="literal">extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
</tt></pre>
|
||||
<p>
|
||||
The last part tells BJam that we are depending on the Boost Python Library.</p>
|
||||
<a name="hello.running_bjam"></a><h2>
|
||||
<a name="id372775"></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>Start it up.</p></blockquote></div>
|
||||
<p>
|
||||
Make sure that the environment is set so that we can invoke the C++
|
||||
compiler. With MSVC, that would mean running the <tt class="literal">Vcvars32.bat</tt> batch
|
||||
file. For instance:</p>
|
||||
<pre class="programlisting"><tt class="literal">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
|
||||
</tt></pre>
|
||||
<p>
|
||||
Some environment variables will have to be setup for proper building of our
|
||||
Python modules. Example:</p>
|
||||
<pre class="programlisting"><tt class="literal">set PYTHON_ROOT=c:/dev/tools/python
|
||||
set PYTHON_VERSION=2.2
|
||||
</tt></pre>
|
||||
<p>
|
||||
The above assumes that the Python installation is in <tt class="literal">c:/dev/tools/python</tt>
|
||||
and that we are using Python version 2.2. You'll have to tweak these
|
||||
appropriately.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png"></span> Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span> "2.2.1",
|
||||
even if that's the version you have.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Take note that you may also do that through the Jamrules file we put in
|
||||
our project as detailed above. The file
|
||||
has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed instructions</a> you
|
||||
can follow.</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">"Jamfile"</tt> is situated.</p>
|
||||
<p>
|
||||
Finally:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">bjam</span><span class="special"> -</span><span class="identifier">sTOOLS</span><span class="special">=</span><span class="identifier">vc</span><span class="special">-</span><span class="number">7</span><span class="identifier">_1</span></tt></pre>
|
||||
<p>
|
||||
We are again assuming that we are using Microsoft Visual C++ version 7.1. If
|
||||
not, then you will have to specify the appropriate tool. See
|
||||
<a href="../../../../../../../tools/build/index.html" target="_top">Building Boost Libraries</a> for
|
||||
further details.</p>
|
||||
<p>
|
||||
It should be building now:</p>
|
||||
<pre class="programlisting"><tt class="literal">cd C:\dev\boost\libs\python\example\tutorial
|
||||
bjam -sTOOLS=msvc
|
||||
...patience...
|
||||
...found 1703 targets...
|
||||
...updating 40 targets...
|
||||
</tt></pre>
|
||||
<p>
|
||||
And so on... Finally:</p>
|
||||
<pre class="programlisting"><tt class="literal">Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th
|
||||
reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth
|
||||
on.dll\vc-7_1\debug\threading-multi\boost_python.exp
|
||||
vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj
|
||||
hello.cpp
|
||||
vc-Link bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.pyd bin\tutori
|
||||
al\hello.pyd\vc-7_1\debug\threading-multi\hello.lib
|
||||
Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li
|
||||
b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
...updated 31 targets...
|
||||
</tt></pre>
|
||||
<p>
|
||||
If all is well, you should now have:</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
boost_python.dll
|
||||
</li>
|
||||
<li>
|
||||
hello.pyd
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
if you are on Windows, and</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
libboost_python.so
|
||||
</li>
|
||||
<li>
|
||||
hello.so
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
if you are on Unix.</p>
|
||||
<p><tt class="literal">boost_python.dll</tt> and <tt class="literal">hello.pyd</tt> can be found somewhere in your project's
|
||||
<tt class="literal">bin</tt> directory. After a successful build, you can just link in these DLLs with
|
||||
the Python interpreter. In Windows for example, you can simply put these libraries
|
||||
inside the directory where the Python executable is.</p>
|
||||
<p>
|
||||
You may now fire up Python and run our hello module:</p>
|
||||
<p></p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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></tt></pre>
|
||||
<p></p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p><span class="bold"><b>There you go... Have fun!</b></span></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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,133 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Iterators</title>
|
||||
<link rel="stylesheet" href="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="embedding.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../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"><tt class="literal"><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></tt></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"><tt class="literal"><span class="identifier">object</span><span class="identifier"> get_iterator</span><span class="special"> =</span><span class="identifier"> iterator</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span><span class="special"> >();</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></tt></pre>
|
||||
<p>
|
||||
Or for use in class_<>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span><span class="special"> >())</span></tt></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<Policies,Target>(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<T, Policies>()
|
||||
</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 &T::begin, &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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Now, our C++ Wrapper:</p>
|
||||
<p></p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">F</span><span class="special">>(</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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span><span class="special"> &</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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span><span class="special"> &</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span></tt></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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="embedding.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,269 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Object Interface</title>
|
||||
<link rel="stylesheet" href="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="functions.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../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 shall 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"></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Can be rewritten in C++ using Boost.Python facilities this way:</p>
|
||||
<p></p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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"><tt class="literal"><span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special"> ==></span><span class="string"> "1"</span></tt></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"><tt class="literal"><span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
In finer detail:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Illustrates that we provide versions of the str type's methods as C++
|
||||
member functions.</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png"></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.
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Python:
|
||||
</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></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">>>></span><span class="identifier"> d</span><span class="special">[</span><span class="string">'whatever'</span><span class="special">]</span><span class="comment"> # modifies the copy
|
||||
</span></tt></pre>
|
||||
<p>
|
||||
C++:
|
||||
</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></pre>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
|
||||
<a name="id454735"></a>class_<T> as objects</h2>
|
||||
<p>
|
||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></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"><tt class="literal"><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"><</span><span class="identifier">Vec2</span><span class="special">>(</span><span class="string">"Vec2"</span><span class="special">,</span><span class="identifier"> init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span><span class="keyword"> double</span><span class="special">>())</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"> &</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"> &</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></tt></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<T></tt> function. Consider the following:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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"><tt class="literal"><span class="keyword">double</span><span class="identifier"> l</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special"><</span><span class="keyword">double</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="identifier">
|
||||
Vec2</span><span class="special">&</span><span class="identifier"> v</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">&>(</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></tt></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"><tt class="literal"><span class="identifier">extract</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">&></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">&</span><span class="identifier"> v</span><span class="special"> =</span><span class="identifier"> x</span><span class="special">();</span><span class="special"> ...</span></tt></pre>
|
||||
<p><span class="inlinemediaobject"><img src="../images/tip.png"></span> The astute reader might have noticed that the <tt class="literal">extract<T></tt>
|
||||
facility in fact solves the mutable copying problem:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">dict</span><span class="identifier"> d</span><span class="special"> =</span><span class="identifier"> extract</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">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="char">'whatever'</span><span class="special">]</span><span class="special"> =</span><span class="number"> 3</span><span class="special">;</span> #<span class="identifier"> modifies</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special"> !</span></tt></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
the construct:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">enum_</span><span class="special"><</span><span class="identifier">choice</span><span class="special">>(</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></tt></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="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>what is a scope?</b></span><br><br>
|
||||
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>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
You can access those values in Python as</p>
|
||||
<p></p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></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></tt></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"><tt class="literal"><span class="identifier">scope</span><span class="identifier"> in_X</span><span class="special"> =</span><span class="identifier"> class_</span><span class="special"><</span><span class="identifier">X</span><span class="special">>(</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"><</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">nested</span><span class="special">>(</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></tt></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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="functions.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,366 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> General Techniques</title>
|
||||
<link rel="stylesheet" href="../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%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exception.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../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"><tt class="literal"><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></tt></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"><tt class="literal"><span class="identifier">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="identifier"> echo</span><span class="identifier"> is</span><span class="identifier"> a</span><span class="identifier"> C</span><span class="special">++</span><span class="identifier"> function</span></tt></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"><tt class="literal"><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="comment">
|
||||
/* export everything in the sounds::core namespace */</span><span class="special">
|
||||
...</span><span class="special">
|
||||
}</span><span class="comment">
|
||||
|
||||
/* file io.cpp */</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="comment">
|
||||
/* export everything in the sounds::io namespace */</span><span class="special">
|
||||
...</span><span class="special">
|
||||
}</span><span class="comment">
|
||||
|
||||
/* file filters.cpp */</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="comment">
|
||||
/* export everything in the sounds::filters namespace */</span><span class="special">
|
||||
...</span><span class="special">
|
||||
}</span></tt></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="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span> 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.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Now, we create this directory structure for our Python package:</p>
|
||||
<pre class="programlisting"><tt class="literal">sounds/
|
||||
__init__.py
|
||||
core.pyd
|
||||
filters.pyd
|
||||
io.pyd
|
||||
</tt></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"><tt class="literal"><span class="special">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">
|
||||
>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
|
||||
>>></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">
|
||||
>>></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></tt></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"><tt class="literal"><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></tt></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"><tt class="literal">sounds/
|
||||
__init__.py
|
||||
core/
|
||||
__init__.py
|
||||
_core.pyd
|
||||
filters/
|
||||
__init__.py
|
||||
_filters.pyd
|
||||
io/
|
||||
__init__.py
|
||||
_io.pyd
|
||||
</tt></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"><tt class="literal"><span class="special">>>></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">
|
||||
>>></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></tt></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"><tt class="literal"><span class="keyword">from</span><span class="identifier"> _core</span><span class="keyword"> import</span><span class="special"> *</span></tt></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"><tt class="literal"><span class="special">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</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></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><span class="keyword">from</span><span class="identifier"> echo_noise</span><span class="keyword"> import</span><span class="identifier"> echo_noise</span></tt></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"><tt class="literal"><span class="special">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</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_noise</span><span class="special">(...)</span></tt></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"><tt class="literal"><span class="special">>>></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">
|
||||
>>></span><span class="special">
|
||||
>>></span><span class="comment"> # a regular function
|
||||
</span><span class="special">>>></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">
|
||||
>>></span><span class="special">
|
||||
>>></span><span class="comment"> # now we turn it in a member function
|
||||
</span><span class="special">>>></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">
|
||||
>>></span><span class="special">
|
||||
>>></span><span class="identifier"> c</span><span class="special"> =</span><span class="identifier"> C</span><span class="special">()</span><span class="special">
|
||||
>>></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">
|
||||
>>></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></tt></pre>
|
||||
<p>
|
||||
Yes, Python rox. <span class="inlinemediaobject"><img src="../images/smiley.png"></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"><tt class="literal"><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"><</span><span class="identifier">point</span><span class="special">>(</span><span class="string">"point"</span><span class="special">)...;</span><span class="special">
|
||||
}</span></tt></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"><tt class="literal"><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></tt></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"><tt class="literal"><span class="comment"># The one Boost.Python uses for all wrapped classes.
|
||||
# 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></tt></pre>
|
||||
<p>
|
||||
Now let's see how it got:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></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">
|
||||
>>></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></tt></pre>
|
||||
<p>
|
||||
Another useful idea is to replace constructors with factory functions:</p>
|
||||
<pre class="programlisting"><tt class="literal"><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></tt></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"><tt class="literal"><span class="comment">/* file point.cpp */</span><span class="preprocessor">
|
||||
#include</span><span class="special"> <</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="preprocessor">
|
||||
#include</span><span class="special"> <</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">></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"><</span><span class="identifier">point</span><span class="special">>(</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"> <</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="preprocessor">
|
||||
#include</span><span class="special"> <</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">></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"><</span><span class="identifier">triangle</span><span class="special">>(</span><span class="string">"triangle"</span><span class="special">)...;</span><span class="special">
|
||||
}</span></tt></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"><tt class="literal"><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></tt></pre>
|
||||
<p>
|
||||
Compiling and linking together all this files produces the same result as the
|
||||
usual approach:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> <</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">></span><span class="preprocessor">
|
||||
#include</span><span class="special"> <</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="preprocessor">
|
||||
#include</span><span class="special"> <</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</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"><</span><span class="identifier">point</span><span class="special">>(</span><span class="string">"point"</span><span class="special">)...;</span><span class="identifier">
|
||||
class_</span><span class="special"><</span><span class="identifier">triangle</span><span class="special">>(</span><span class="string">"triangle"</span><span class="special">)...;</span><span class="special">
|
||||
}</span></tt></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="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span> 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.</td></tr></tbody>
|
||||
</table></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span> 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>.</td></tr></tbody>
|
||||
</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"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exception.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<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>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,163 +0,0 @@
|
||||
<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 "manually" expand the metaprograms for
|
||||
arities from zero to fifteen arguments, and EDG-based compilers with
|
||||
<code>__EDG_VERSION__ <= 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 "callback", as in "calling
|
||||
back into Python", 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 "callback" 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 "first match" 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>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,152 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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>
|
||||
</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>() != 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>() != 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>
|
||||
</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>© Copyright <a href=
|
||||
"../../../../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>
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<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><T>::type*</code>
|
||||
<td><code>&*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>© Copyright <a href="../../../../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>
|
||||
@@ -1,93 +0,0 @@
|
||||
<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
|
||||
"traditional" 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>&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>© Copyright <a href="../../../../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>
|
||||
@@ -1,71 +0,0 @@
|
||||
<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<X>::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>© Copyright <a href="../../../../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>
|
||||
@@ -1,226 +0,0 @@
|
||||
<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<T></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
|
||||
"Writing Python in C++". 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<T></code></a></h2>
|
||||
|
||||
The most basic element needed was a replacement for the
|
||||
<code>reference<></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
|
||||
"<code>ref</code>" (for
|
||||
<code>reference<PyObject></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<></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<></code>; its major distinguishing features are
|
||||
that it gives direct access to the underlying object representation
|
||||
through <code>operator*</code> and <code>operator-></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("foo");
|
||||
<tr>
|
||||
<td><code>x.foo = 1</code> <td><code>x.attr("foo") = 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("f")(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._("foo");
|
||||
x._("foo") = 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,"foo" // error
|
||||
x,"foo" = 1; // error
|
||||
|
||||
y = (x,"foo"); // ok
|
||||
(x,"foo") = 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><></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 "interesting" 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>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,234 +0,0 @@
|
||||
<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&</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><X&>::call(f, obj);
|
||||
</pre>
|
||||
However, I think the following may be possible and I plan to investigate:
|
||||
<pre>
|
||||
return apply<X&>(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<></code> to specify the class
|
||||
actually held. This move began to put pressure on the
|
||||
<code>class_<></code> interface, since the need for the user to
|
||||
produce complicated instantations of
|
||||
<code>class_<></code> was increased:
|
||||
|
||||
<pre>
|
||||
class<Foo, bases<>, value_holder_generator<Foo_callback> >("Foo")
|
||||
.def("hello", &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 "holder") 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_<></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_<></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<></code> and <code>bases<></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>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,308 +0,0 @@
|
||||
<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 "creatively designed"
|
||||
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<...>/right_operand<...></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("__iter__", iterator<list_int>())
|
||||
</pre>
|
||||
<dd>
|
||||
|
||||
<dt>Creation of iterators from member functions...
|
||||
<pre>
|
||||
...
|
||||
.def("__iter__"
|
||||
, range(&my_class::x_begin, &my_class::x_end))
|
||||
)
|
||||
</pre>
|
||||
<dd>
|
||||
|
||||
<dt>...and member data:
|
||||
<pre>
|
||||
...
|
||||
.def("__iter__"
|
||||
, range(&std::pair<char*,char*>::first, &std::pair<char*,char*>::second))
|
||||
)
|
||||
</pre>
|
||||
<dd>
|
||||
|
||||
<dt>The ability to specify <a
|
||||
href="CallPolicies.html">CallPolicies</a>, e.g. to prevent copying of
|
||||
heavyweight values:
|
||||
|
||||
<pre>
|
||||
...
|
||||
.def("__iter__",
|
||||
, range<return_value_policy<copy_non_const_reference> >(
|
||||
&my_sequence<heavy>::begin
|
||||
, &my_sequence<heavy>::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>
|
||||
>>> f = field()
|
||||
>>> 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_<></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<T></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<T></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++ <==> 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>"foobar"</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>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,150 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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><R>(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><></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>
|
||||
>>> 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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
<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>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#ResultConverter-concept">ResultConverter Concept</a></dt>
|
||||
<dt><a href="#ResultConverterGenerator-concept">ResultConverterGenerator Concept</a></dt>
|
||||
</dl>
|
||||
</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>
|
||||
</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<R>::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>© Copyright <a href="../../../../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>
|
||||
@@ -1,132 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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="../../../../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="../../../../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="../../../../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="../../../../people/paul_mensonides.htm">Paul Mensonides</a>,
|
||||
building on the work <a href="../../../../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> ("Pie-Steh")
|
||||
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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
196
doc/v2/args.html
@@ -1,196 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/args.hpp></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 <boost/python/args.hpp></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 <class T>
|
||||
arg &perator = (T const &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 <class T> arg &operator = (T const &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 &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 <boost/python/def.hpp>
|
||||
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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<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 - <call.hpp></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 <call.hpp></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><boost/python/call.hpp></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 <class R, class A1, class A2, ... class A<i>n</i>></a>
|
||||
R call(PyObject* callable, A1 const&, A2 const&, ... A<i>n</i> const&)
|
||||
</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, a2, ...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<double>(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>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,158 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <call_method.hpp></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 <call_method.hpp></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><boost/python/call_method.hpp></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 <class R, class A1, class A2, ... class A<i>n</i>></a>
|
||||
R call_method(PyObject* self, char const* method, A1 const&, A2 const&, ... A<i>n</i> const&)
|
||||
</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, a2, ...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 <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <cstring>
|
||||
|
||||
// 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->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><char const*>(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_<Base,Base_callback, noncopyable>("Base")
|
||||
.def("class_name", &Base_callback::Base_name)
|
||||
;
|
||||
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Python Code</h3>
|
||||
<pre>
|
||||
>>> from my_module import *
|
||||
>>> class Derived(Base):
|
||||
... def __init__(self):
|
||||
... Base.__init__(self)
|
||||
... def class_name(self):
|
||||
... return self.__class__.__name__
|
||||
...
|
||||
>>> is_base(Base()) # calls the class_name() method from C++
|
||||
1
|
||||
>>> 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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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<ResultType>(callable_object, a1, a2... a<i>N</i>);
|
||||
</pre>
|
||||
Calling a method of a Python object is similarly easy:
|
||||
<pre>
|
||||
call_method<ResultType>(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& x)
|
||||
{
|
||||
// Invoke callable, passing a Python object which holds a reference to x
|
||||
boost::python::call<void>(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&</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 == 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><T></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><T></code></td>
|
||||
|
||||
<td>If <code>x.get() == 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<ResultType>()</code> and
|
||||
<code>call_method<ResultType>()</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<char
|
||||
const*>(...)</code> returns.</p>
|
||||
|
||||
<p>The old Boost.Python v1 deals with this issue by refusing to compile
|
||||
any uses of <code>call<char const*>()</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<U>(...)</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<U></code>, and
|
||||
they will be protected against dangles at runtime, at least long enough
|
||||
to get out of the <code>call<U>(...)</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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
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.
|
||||
@@ -1,804 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/class.hpp>,
|
||||
<boost/python/class_fwd.hpp></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 <boost/python/class.hpp>,
|
||||
<boost/python/class_fwd.hpp></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"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/class.hpp></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><boost/python/class_fwd.hpp></code> contains a forward
|
||||
declaration of the <code>class_</code> class template.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="class_-spec"></a>Class template
|
||||
<code>class_<T, <font color="#007F00">Bases, HeldType,
|
||||
NonCopyable</font>></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<</code>...<code>></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<></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><HeldType>::type</code>
|
||||
is <code>T</code> or a class derived from <code>T</code>.</td>
|
||||
|
||||
<td>Specifies the type which is actually embedded in a Python object
|
||||
wrapping a <code>T</code> instance. 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">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<></code> or <code><a href=
|
||||
"../../../smart_ptr/shared_ptr.htm">boost::shared_ptr<></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<HeldType></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<T></a>.</li>
|
||||
</ol>
|
||||
|
||||
<h4><a name="class_-spec-synopsis"></a>Class template <code>class_</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T
|
||||
<font color="#007F00"> , class Bases = bases<>
|
||||
, class HeldType = T
|
||||
, class NonCopyable = <i>unspecified</i>
|
||||
>
|
||||
</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 <class Init>
|
||||
class_(char const* name, Init);
|
||||
template <class Init>
|
||||
class_(char const* name, char const* docstring, Init);
|
||||
|
||||
// Exposing additional __init__ functions
|
||||
template <class Init>
|
||||
class_& def(Init);
|
||||
|
||||
// defining methods
|
||||
template <class F>
|
||||
class_& def(char const* name, F f);
|
||||
template <class Fn, class A1>
|
||||
class_& def(char const* name, Fn fn, A1 const&);
|
||||
template <class Fn, class A1, class A2>
|
||||
class_& def(char const* name, Fn fn, A1 const&, A2 const&);
|
||||
template <class Fn, class A1, class A2, class A3>
|
||||
class_& def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
|
||||
|
||||
// declaring method as static
|
||||
class_& staticmethod(char const* name);
|
||||
|
||||
// exposing operators
|
||||
template <<i>unspecified</i>>
|
||||
class_& def(<a href=
|
||||
"operators.html#operator_-spec">detail::operator_</a><unspecified>);
|
||||
|
||||
// Raw attribute modification
|
||||
template <class U>
|
||||
class_& setattr(char const* name, U const&);
|
||||
|
||||
// exposing data members
|
||||
template <class D>
|
||||
class_& def_readonly(char const* name, D T::*pm);
|
||||
|
||||
template <class D>
|
||||
class_& def_readwrite(char const* name, D T::*pm);
|
||||
|
||||
// exposing static data members
|
||||
template <class D>
|
||||
class_& def_readonly(char const* name, D const& d);
|
||||
template <class D>
|
||||
class_& def_readwrite(char const* name, D& d);
|
||||
|
||||
// property creation
|
||||
template <class Get>
|
||||
void add_property(char const* name, Get const& fget, char const* doc=0);
|
||||
template <class Get, class Set>
|
||||
void add_property(
|
||||
char const* name, Get const& fget, Set const& fset, char const* doc=0);
|
||||
|
||||
template <class Get>
|
||||
void add_static_property(char const* name, Get const& fget);
|
||||
template <class Get, class Set>
|
||||
void add_static_property(char const* name, Get const& fget, Set const& fset);
|
||||
|
||||
// pickle support
|
||||
template <typename PickleSuite>
|
||||
self& def_pickle(PickleSuite const&);
|
||||
self& enable_pickling();
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="class_-spec-ctors"></a>Class template <code>class_</code>
|
||||
constructors</h4>
|
||||
<pre>
|
||||
class_(char const* name);
|
||||
class_(char const* name, char const* docstring);
|
||||
template <class Init>
|
||||
class_(char const* name, Init init_spec);
|
||||
template <class Init>
|
||||
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->def(init_spec)</code>
|
||||
is called.</li>
|
||||
|
||||
<li>If <code>init_spec</code> is not supplied,
|
||||
<code>this->def(init<>())</code> is called.</li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt><b>Rationale:</b>Allowing the user to specify constructor arguments
|
||||
in the <code>class_<></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"></a>Class template
|
||||
<code>class_</code> modifier functions</h4>
|
||||
<pre>
|
||||
template <class Init>
|
||||
class_& 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 <class F>
|
||||
class_& def(char const* name, Fn fn);
|
||||
template <class Fn, class A1>
|
||||
class_& def(char const* name, Fn fn, A1 const& a1);
|
||||
template <class Fn, class A1, class A2>
|
||||
class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2);
|
||||
template <class Fn, class A1, class A2, class A3>
|
||||
class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& 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>&</code>,
|
||||
<code>U <em>cv</em>*</code>, or
|
||||
<code>U <em>cv</em>* const&</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_& 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 <<i>unspecified</i>>
|
||||
class_& def(<a href=
|
||||
"operators.html#operator_-spec">detail::operator_</a><unspecified>);
|
||||
</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 <class U>
|
||||
class_& setattr(char const* name, U const& 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->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 <class Get>
|
||||
void add_property(char const* name, Get const& fget, char const* doc=0);
|
||||
template <class Get, class Set>
|
||||
void add_property(
|
||||
char const* name, Get const& fget, Set const& 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 <class Get>
|
||||
void add_static_property(char const* name, Get const& fget);
|
||||
template <class Get, class Set>
|
||||
void add_static_property(char const* name, Get const& fget, Set const& 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 <class D>
|
||||
class_& def_readonly(char const* name, D T::*pm, char const* doc=0);
|
||||
template <class D>
|
||||
class_& def_readonly(char const* name, D const& 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->add_property(name, <a href=
|
||||
"data_members.html#make_getter-spec">make_getter</a>(pm), doc);
|
||||
</pre>
|
||||
and
|
||||
<pre>
|
||||
this->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 <class D>
|
||||
class_& def_readwrite(char const* name, D T::*pm, char const* doc=0);
|
||||
template <class D>
|
||||
class_& def_readwrite(char const* name, D& d);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b></dt>
|
||||
|
||||
<dd>
|
||||
<pre>
|
||||
this->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->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 <typename PickleSuite>
|
||||
class_& def_pickle(PickleSuite const&);
|
||||
</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_& 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><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"></a>Class template
|
||||
<code>bases<T1, T2,</code>...<code>TN></code></h3>
|
||||
|
||||
<p>An <a href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a>
|
||||
which can be used in <code>class_<</code>...<code>></code>
|
||||
instantiations indicate a list of base classes.</p>
|
||||
|
||||
<h4><a name="bases-spec-synopsis"></a>Class template <code>bases</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <T1 = <i>unspecified</i>,...T<i>n</i> = <i>unspecified</i>>
|
||||
struct bases
|
||||
{};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="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& 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_<Foo,bases<Bar,Baz> >("Foo",
|
||||
"This is Foo's docstring."
|
||||
"It describes our Foo extension class",
|
||||
|
||||
init<int,char const*>(args("x","y"), "__init__ docstring")
|
||||
)
|
||||
.def(init<double>())
|
||||
.def("get_name", &Foo::get_name, return_internal_reference<>())
|
||||
.def("set_name", &Foo::set_name)
|
||||
.def_readwrite("value", &Foo::value)
|
||||
;
|
||||
</pre>
|
||||
<hr>
|
||||
<a name="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_<B<font color="#007F00">, ...</font>></code> must have
|
||||
already been constructed.
|
||||
<pre>
|
||||
class_<Base>("Base");
|
||||
class_<Derived, bases<Base> >("Derived");
|
||||
</pre>
|
||||
Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
5 August, 2002 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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"><boost/config.hpp></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, 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><R>(</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><</code>...<code>></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 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 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>
|
||||
</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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 -
|
||||
<boost/python/copy_const_reference.hpp></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
|
||||
<boost/python/copy_const_reference.hpp></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 <class T> struct apply;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="copy_const_reference-spec-metafunctions"></a>Class
|
||||
<code>copy_const_reference</code> metafunctions</h4>
|
||||
<pre>
|
||||
template <class T> struct apply
|
||||
</pre>
|
||||
|
||||
<dl class="metafunction-semantics">
|
||||
<dt><b>Requires:</b> <code>T</code> is <code>U const&</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><T>
|
||||
type;</code></dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<h3>C++ Module Definition</h3>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/copy_const_reference.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
|
||||
// classes to wrap
|
||||
struct Bar { int x; }
|
||||
|
||||
struct Foo {
|
||||
Foo(int x) : { b.x = x; }
|
||||
Bar const& get_bar() const { return b; }
|
||||
private:
|
||||
Bar b;
|
||||
};
|
||||
|
||||
// Wrapper code
|
||||
using namespace boost::python;
|
||||
BOOST_PYTHON_MODULE(my_module)
|
||||
{
|
||||
class_<Bar>("Bar");
|
||||
|
||||
class_<Foo>("Foo", init<int>())
|
||||
.def("get_bar", &Foo::get_bar
|
||||
, return_value_policy<copy_const_reference>())
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Python Code</h3>
|
||||
<pre>
|
||||
>>> from my_module import *
|
||||
>>> f = Foo(3) # create a Foo object
|
||||
>>> 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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 -
|
||||
<boost/python/copy_non_const_reference.hpp></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
|
||||
<boost/python/copy_non_const_reference.hpp></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 <class T> struct apply;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="copy_non_const_reference-spec-metafunctions"></a>Class
|
||||
<code>copy_non_const_reference</code> metafunctions</h4>
|
||||
<pre>
|
||||
template <class T> struct apply
|
||||
</pre>
|
||||
|
||||
<dl class="metafunction-semantics">
|
||||
<dt><b>Requires:</b> <code>T</code> is <code>U&</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><T>
|
||||
type;</code></dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<p>C++ code:</p>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/copy_non_const_reference.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
|
||||
// classes to wrap
|
||||
struct Bar { int x; }
|
||||
|
||||
struct Foo {
|
||||
Foo(int x) : { b.x = x; }
|
||||
Bar& get_bar() { return b; }
|
||||
private:
|
||||
Bar b;
|
||||
};
|
||||
|
||||
// Wrapper code
|
||||
using namespace boost::python;
|
||||
BOOST_PYTHON_MODULE(my_module)
|
||||
{
|
||||
class_<Bar>("Bar");
|
||||
|
||||
class_<Foo>("Foo", init<int>())
|
||||
.def("get_bar", &Foo::get_bar
|
||||
, return_value_policy<copy_non_const_reference>())
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
Python Code:
|
||||
<pre>
|
||||
>>> from my_module import *
|
||||
>>> f = Foo(3) # create a Foo object
|
||||
>>> 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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/data_members.hpp></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
|
||||
<boost/python/data_members.hpp></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_<>::<a href=
|
||||
"class.html#class_-spec-modifiers">def_readonly</a></code> and
|
||||
<code>class_<>::<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 <class C, class D></a>
|
||||
<a href="object.html#object-spec">object</a> make_getter(D C::*pm);
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_getter(D C::*pm, Policies const& 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><></code></dt>
|
||||
|
||||
<dt>for <code>Policies</code>. Note that this test may inappropriately
|
||||
choose <code>return_internal_reference<></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 <class D>
|
||||
<a href="object.html#object-spec">object</a> make_getter(D const& d);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_getter(D const& d, Policies const& policies);
|
||||
|
||||
template <class D>
|
||||
<a href="object.html#object-spec">object</a> make_getter(D const* p);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_getter(D const* p, Policies const& 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 <class C, class D></a>
|
||||
<a href="object.html#object-spec">object</a> make_setter(D C::*pm);
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_setter(D C::*pm, Policies const& 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 const&</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 <class D>
|
||||
<a href="object.html#object-spec">object</a> make_setter(D& d);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_setter(D& d, Policies const& policies);
|
||||
|
||||
template <class D>
|
||||
<a href="object.html#object-spec">object</a> make_setter(D* p);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_setter(D* p, Policies const& 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&</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 <boost/python/data_members.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
|
||||
struct X
|
||||
{
|
||||
X(int x) : y(x) {}
|
||||
int y;
|
||||
};
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(data_members_example)
|
||||
{
|
||||
class_<X>("X", init<int>())
|
||||
.def("get", make_getter(&X::y))
|
||||
.def("set", make_setter(&X::y))
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
It can be used this way in Python:
|
||||
<pre>
|
||||
>>> from data_members_example import *
|
||||
>>> x = X(1)
|
||||
>>> x.get()
|
||||
1
|
||||
>>> x.set(2)
|
||||
>>> 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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
188
doc/v2/def.html
@@ -1,188 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/def.hpp></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 <boost/python/def.hpp></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 <class F>
|
||||
void def(char const* name, F f);
|
||||
|
||||
template <class Fn, class A1>
|
||||
void def(char const* name, Fn fn, A1 const&);
|
||||
|
||||
template <class Fn, class A1, class A2>
|
||||
void def(char const* name, Fn fn, A1 const&, A2 const&);
|
||||
|
||||
template <class Fn, class A1, class A2, class A3>
|
||||
void def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
|
||||
</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> - <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 <boost/python/def.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/args.hpp>
|
||||
|
||||
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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,135 +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 - <boost/python/def_visitor.hpp></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 <boost/python/def_visitor.hpp></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><boost/python/def_visitor.hpp></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<T> </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<DerivedVisitor></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, 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 <class DerivedVisitor>
|
||||
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> 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<my_def_visitor>
|
||||
{
|
||||
friend class def_visitor_access;
|
||||
|
||||
template <class classT>
|
||||
void visit(classT& c) const
|
||||
{
|
||||
c
|
||||
.def("foo", &my_def_visitor::foo)
|
||||
.def("bar", &my_def_visitor::bar)
|
||||
;
|
||||
}
|
||||
|
||||
static void foo(X& self);
|
||||
static void bar(X& self);
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(my_ext)
|
||||
{
|
||||
class_<X>("X")
|
||||
.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>© Copyright Joel de Guzman 2003. </i>
|
||||
@@ -1,170 +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 -
|
||||
<boost/python/default_call_policies.hpp></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
|
||||
<boost/python/default_call_policies.hpp></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;
|
||||
};
|
||||
}}
|
||||
</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 <class T> struct apply;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="default_result_converter-spec-metafunctions"></a>Class
|
||||
<code>default_result_converter</code> metafunctions</h4>
|
||||
<pre>
|
||||
template <class T> 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><T
|
||||
const&> 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 <class Handler, class Base = default_call_policies>
|
||||
struct return_value_policy : Base
|
||||
{
|
||||
typedef Handler result_converter;
|
||||
};
|
||||
</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><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 "One Definition
|
||||
Rule", 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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
149
doc/v2/dict.html
@@ -1,149 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/dict.hpp></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 <boost/python/dict.hpp></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< class T >
|
||||
dict(T const & data);
|
||||
|
||||
// modifiers
|
||||
void clear();
|
||||
dict copy();
|
||||
|
||||
template <class T1, class T2>
|
||||
tuple popitem();
|
||||
|
||||
template <class T>
|
||||
object setdefault(T const &k);
|
||||
|
||||
template <class T1, class T2>
|
||||
object setdefault(T1 const & k, T2 const & d);
|
||||
|
||||
void update(object_cref E);
|
||||
|
||||
template< class T >
|
||||
void update(T const & E);
|
||||
|
||||
// observers
|
||||
list values() const;
|
||||
|
||||
object get(object_cref k) const;
|
||||
|
||||
template<class T>
|
||||
object get(T const & k) const;
|
||||
|
||||
object get(object_cref k, object_cref d) const;
|
||||
object get(T1 const & k, T2 const & d) const;
|
||||
|
||||
bool has_key(object_cref k) const;
|
||||
|
||||
template< class T >
|
||||
bool has_key(T const & 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<dict>(target.attr("__dict__"));
|
||||
target.attr("__dict__") = d;
|
||||
return result;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised 30 September, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
231
doc/v2/enum.html
@@ -1,231 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/enum.hpp></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 <boost/python/enum.hpp></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="#enum_-spec">Class template
|
||||
<code>enum_</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#enum_-spec-synopsis">Class template <code>enum_</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#enum_-spec-ctors">Class template <code>enum_</code>
|
||||
constructors</a></dt>
|
||||
|
||||
<dt><a href="#enum_-spec-modifiers">Class template <code>enum_</code>
|
||||
modifier functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/enum.hpp></code> defines the
|
||||
interface through which users expose their C++ enumeration types
|
||||
to Python. It declares the
|
||||
<code>enum_</code> class template, which is parameterized on the
|
||||
enumeration type being exposed. </p>
|
||||
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="enum_-spec"></a>Class template
|
||||
<code>enum_<T></code></h3>
|
||||
|
||||
<p>Creates a Python class derived from Python's <code>int</code>
|
||||
type which is associated with the C++ type passed as its first
|
||||
parameter.
|
||||
|
||||
<h4><a name="enum_-spec-synopsis"></a>Class template <code>enum_</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T>
|
||||
class enum_ : public <a href="object.html#object-spec">object</a>
|
||||
{
|
||||
enum_(char const* name);
|
||||
enum_<T>& value(char const* name, T);
|
||||
enum_<T>& export_values();
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="enum_-spec-ctors"></a>Class template <code>enum_</code>
|
||||
constructors</h4>
|
||||
<pre>
|
||||
enum_(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>.
|
||||
|
||||
<dt><b>Effects:</b> Constructs an <code>enum_</code> object
|
||||
holding a Python extension type derived from <code>int</code>
|
||||
which is 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 type.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="enum_-spec-modifiers"></a>Class template
|
||||
<code>enum_</code> modifier functions</h4>
|
||||
<pre>
|
||||
inline enum_<T>& value(char const* name, T x);
|
||||
</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><b>Effects:</b> adds an instance of the wrapped enumeration
|
||||
type with value <code>x</code> to the type's dictionary as the
|
||||
<code>name</code>d attribute</dt>.
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
</dl>
|
||||
|
||||
<pre>
|
||||
inline enum_<T>& export_values();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
|
||||
<dt><b>Effects:</b> sets attributes in the current <a
|
||||
href="scope.html#scope-spec"><code>scope</code></a> with the
|
||||
same names and values as all enumeration values exposed so far
|
||||
by calling <code>value()</code></dt>.
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example(s)</h2>
|
||||
|
||||
<p>C++ module definition
|
||||
<pre>
|
||||
#include <boost/python/enum.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
enum color { red = 1, green = 2, blue = 4 };
|
||||
|
||||
color identity_(color x) { return x; }
|
||||
|
||||
BOOST_PYTHON_MODULE(enums)
|
||||
{
|
||||
enum_<color>("color")
|
||||
.value("red", red)
|
||||
.value("green", green)
|
||||
.export_values()
|
||||
.value("blue", blue)
|
||||
;
|
||||
|
||||
def("identity", identity_);
|
||||
}
|
||||
</pre>
|
||||
<p>Interactive Python:
|
||||
<pre>
|
||||
>>> from enums import *
|
||||
|
||||
>>> identity(red)
|
||||
enums.color.red
|
||||
|
||||
>>> identity(color.red)
|
||||
enums.color.red
|
||||
|
||||
>>> identity(green)
|
||||
enums.color.green
|
||||
|
||||
>>> identity(color.green)
|
||||
enums.color.green
|
||||
|
||||
>>> identity(blue)
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
NameError: name blue' is not defined
|
||||
|
||||
>>> identity(color.blue)
|
||||
enums.color.blue
|
||||
|
||||
>>> identity(color(1))
|
||||
enums.color.red
|
||||
|
||||
>>> identity(color(2))
|
||||
enums.color.green
|
||||
|
||||
>>> identity(color(3))
|
||||
enums.color(3)
|
||||
|
||||
>>> identity(color(4))
|
||||
enums.color.blue
|
||||
|
||||
>>> identity(1)
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
TypeError: bad argument type for built-in operation
|
||||
</pre>
|
||||
<hr>
|
||||
|
||||
Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 December, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/errors.hpp></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 <boost/python/errors.hpp></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="#error_already_set-spec">Class
|
||||
<code>error_already_set</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#error_already_set-spec-synopsis">Class
|
||||
<code>error_already_set</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#handle_exception-spec">handle_exception</a></dt>
|
||||
|
||||
<dt><a href="#expect_non_null-spec">expect_non_null</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"#throw_error_already_set-spec">throw_error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Examples</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/errors.hpp></code> provides types and
|
||||
functions for managing and translating between Python and C++ exceptions.
|
||||
This is relatively low-level functionality that is mostly used internally
|
||||
by Boost.Python. Users should seldom need it.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="error_already_set-spec"></a>Class
|
||||
<code>error_already_set</code></h3>
|
||||
|
||||
<p><code>error_already_set</code> is an exception type which can be
|
||||
thrown to indicate that a Python error has occurred. If thrown, the
|
||||
precondition is that <a href=
|
||||
"http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71">PyErr_Occurred()</a>
|
||||
returns a value convertible to <code>true</code>. Portable code shouldn't
|
||||
throw this exception type directly, but should instead use <code><a href=
|
||||
"#throw_error_already_set-spec">throw_error_already_set</a>()</code>,
|
||||
below.</p>
|
||||
|
||||
<h4><a name="error_already_set-spec-synopsis"></a>Class error_already_set
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
class error_already_set {};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<pre>
|
||||
<a name=
|
||||
"handle_exception-spec">template <class T> bool handle_exception</a>(T f) throw();
|
||||
|
||||
void handle_exception() throw();
|
||||
</pre>
|
||||
|
||||
<dl class="handle_exception-semantics">
|
||||
<dt><b>Requires:</b> The first form requires that the expression
|
||||
<code><a href=
|
||||
"../../../../doc/html/functionN.html">function0</a><void>(f)</code>
|
||||
is valid. The second form requires that a C++ exception is currently
|
||||
being handled (see section 15.1 in the C++ standard).</dt>
|
||||
|
||||
<dt><b>Effects:</b> The first form calls <code>f()</code> inside a
|
||||
<code>try</code> block which first attempts to use all registered <a
|
||||
href="exception_translator.html">exception translators</a>. If none of
|
||||
those translates the exception, the <code>catch</code> clauses then set
|
||||
an appropriate Python exception for the C++ exception caught, returning
|
||||
<code>true</code> if an exception was thrown, <code>false</code>
|
||||
otherwise. The second form passes a function which rethrows the
|
||||
exception currently being handled to the first form.</dt>
|
||||
|
||||
<dt><b>Postconditions:</b> No exception is being handled</dt>
|
||||
|
||||
<dt><b>Throws:</b> nothing</dt>
|
||||
|
||||
<dt><b>Rationale:</b> At inter-language boundaries it is important to
|
||||
ensure that no C++ exceptions escape, since the calling language
|
||||
usually doesn't have the equipment necessary to properly unwind the
|
||||
stack. Use <code>handle_exception</code> to manage exception
|
||||
translation whenever your C++ code is called directly from the Python
|
||||
API. This is done for you automatically by the usual function wrapping
|
||||
facilities: <code><a href=
|
||||
"make_function.html#make_function-spec">make_function</a>()</code>,
|
||||
<code><a href=
|
||||
"make_function.html#make_constructor-spec">make_constructor</a>()</code>,
|
||||
<code><a href="def.html#class_-spec-modifiers">def</a>()</code> and <code><a href=
|
||||
"class.html#def-spec">class_::def</a>()</code>. The second form can be
|
||||
more convenient to use (see the <a href="#examples">example</a> below),
|
||||
but various compilers have problems when exceptions are rethrown from
|
||||
within an enclosing <code>try</code> block.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
<a name=
|
||||
"expect_non_null-spec">template <class T> T* expect_non_null(T* x);</a>
|
||||
</pre>
|
||||
|
||||
<dl class="expect_non_null-semantics">
|
||||
<dt><b>Returns:</b> <code>x</code></dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"#error_already_set-spec">error_already_set</a>()</code> iff <code>x ==
|
||||
0</code>.</dt>
|
||||
|
||||
<dt><b>Rationale:</b> Simplifies error-handling when calling functions
|
||||
in the <a href="http://www.python.org/doc/2.2/api/api.html">Python/C
|
||||
API</a> which return 0 on error.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
<a name="throw_error_already_set-spec">void throw_error_already_set();</a>
|
||||
</pre>
|
||||
|
||||
<dl class="throw_error_already_set-semantics">
|
||||
<dt><b>Effects:</b> <code>throw <a href=
|
||||
"#error_already_set-spec">error_already_set</a>();</code></dt>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt><b>Rationale:</b> Many platforms and compilers are not able to
|
||||
consistently catch exceptions thrown across shared library boundaries.
|
||||
Using this function from the Boost.Python library ensures that the
|
||||
appropriate <code>catch</code> block in <code><a href=
|
||||
"#handle_exception-spec">handle_exception</a>()</code> can catch the
|
||||
exception.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Examples</h2>
|
||||
<pre>
|
||||
#include <string>
|
||||
#include <boost/python/errors.hpp>
|
||||
#include <boost/python/object.hpp>
|
||||
#include <boost/python/handle.hpp>
|
||||
|
||||
// Returns a std::string which has the same value as obj's "__name__"
|
||||
// attribute.
|
||||
std::string get_name(boost::python::object obj)
|
||||
{
|
||||
// throws if there's no __name__ attribute
|
||||
PyObject* p = boost::python::expect_non_null(
|
||||
PyObject_GetAttrString(obj.ptr(), "__name__"));
|
||||
|
||||
char const* s = PyString_AsString(p);
|
||||
if (s != 0)
|
||||
Py_DECREF(p);
|
||||
|
||||
// throws if it's not a Python string
|
||||
std::string result(
|
||||
boost::python::expect_non_null(
|
||||
PyString_AsString(p)));
|
||||
|
||||
Py_DECREF(p); // Done with p
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Demonstrate form 1 of handle_exception
|
||||
//
|
||||
|
||||
// Place into result a Python Int object whose value is 1 if a and b have
|
||||
// identical "__name__" attributes, 0 otherwise.
|
||||
void same_name_impl(PyObject*& result, boost::python::object a, boost::python::object b)
|
||||
{
|
||||
result = PyInt_FromLong(
|
||||
get_name(a) == get_name(a2));
|
||||
}
|
||||
|
||||
object borrowed_object(PyObject* p)
|
||||
{
|
||||
return boost::python::object(
|
||||
boost::python::handle<>(
|
||||
boost::python::borrowed(a1)));
|
||||
}
|
||||
|
||||
// This is an example Python 'C' API interface function
|
||||
extern "C" PyObject*
|
||||
same_name(PyObject* args, PyObject* keywords)
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* result = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
|
||||
return 0;
|
||||
|
||||
// Use boost::bind to make an object compatible with
|
||||
// boost::Function0<void>
|
||||
if (boost::python::handle_exception(
|
||||
boost::bind<void>(same_name_impl, boost::ref(result), borrowed_object(a1), borrowed_object(a2))))
|
||||
{
|
||||
// an exception was thrown; the Python error was set by
|
||||
// handle_exception()
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Demonstrate form 2 of handle_exception. Not well-supported by all
|
||||
// compilers.
|
||||
//
|
||||
extern "C" PyObject*
|
||||
same_name2(PyObject* args, PyObject* keywords)
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* result = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
|
||||
return 0;
|
||||
|
||||
try {
|
||||
return PyInt_FromLong(
|
||||
get_name(borrowed_object(a1)) == get_name(borrowed_object(a2)));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// If an exception was thrown, translate it to Python
|
||||
boost::python::handle_exception();
|
||||
return 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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 -
|
||||
<boost/python/exception_translator.hpp></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
|
||||
<boost/python/exception_translator.hpp></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=
|
||||
"#register_exception_translator-spec">register_exception_translator</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>As described <a href="errors.html#handle_exception-spec">here</a>, it
|
||||
is important to make sure that exceptions thrown by C++ code do not pass
|
||||
into the Python interpreter core. By default, Boost.Python translates all
|
||||
C++ exceptions thrown by wrapped functions and module init functions into
|
||||
Python, but the default translators are extremely limited: most C++
|
||||
exceptions will appear in Python as a <a href=
|
||||
"http://www.python.org/doc/current/lib/module-exceptions.html">RuntimeError</a>
|
||||
exception whose representation is
|
||||
<code>'Unidentifiable C++ Exception'</code>. To produce better
|
||||
error messages, users can register additional exception translators as
|
||||
described below.</p>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
|
||||
<h3><code><a name="register_exception_translator-spec">register_exception_translator</a></code></h3>
|
||||
|
||||
<pre>
|
||||
<a name="register_exception_translator-spec">template<class ExceptionType, class Translate></a>
|
||||
void register_exception_translator(Translate translate);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b></dt>
|
||||
|
||||
<dd>
|
||||
<code>Translate</code> is <a href=
|
||||
"../../../utility/CopyConstructible.html">Copyconstructible</a>, and
|
||||
the following code must be well-formed:
|
||||
<pre>
|
||||
void f(ExceptionType x) { translate(x); }
|
||||
</pre>
|
||||
The expression <code>translate(x)</code> must either throw a C++
|
||||
exception, or a subsequent call to <code><a href=
|
||||
"http://www.python.org/doc/current/api/exceptionHandling.html">PyErr_Occurred</a>()</code>
|
||||
must return 1.
|
||||
</dd>
|
||||
|
||||
<p>
|
||||
|
||||
<dt><b>Effects:</b> Adds a copy of <code>translate</code> to the sequence of
|
||||
exception translators tried when Boost.Python catches an exception that
|
||||
is about to pass into Python's core interpreter. The new translator
|
||||
will get "first shot" at translating all exceptions matching the catch
|
||||
clause shown above. Any subsequently-registered translators will be
|
||||
allowed to translate the exception earlier. A translator which cannot
|
||||
translate a given C++ exception can re-throw it, and it will be handled
|
||||
by a translator which was registered earlier (or by the default
|
||||
translator).</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/exception_translator.hpp>
|
||||
#include <exception>
|
||||
|
||||
struct my_exception : std::exception
|
||||
{
|
||||
char const* what() throw() { return "One of my exceptions"; }
|
||||
};
|
||||
|
||||
void translate(my_exception const& e)
|
||||
{
|
||||
// Use the Python 'C' API to set up an exception object
|
||||
PyErr_SetString(PyExc_RuntimeError, e.what());
|
||||
}
|
||||
|
||||
void something_which_throws()
|
||||
{
|
||||
...
|
||||
throw my_exception();
|
||||
...
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(exception_translator_ext)
|
||||
{
|
||||
using namespace boost::python;
|
||||
register_exception_translator<my_exception>(&translate);
|
||||
|
||||
def("something_which_throws", something_which_throws);
|
||||
}
|
||||
</pre>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised 03 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/exec.hpp></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 <boost/python/exec.hpp></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="#exec-spec"><code>exec</code></a></dt>
|
||||
<dt><a href="#exec_file-spec"><code>exec_file</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Exposes a mechanism for embedding the python interpreter into C++ code.</p>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
|
||||
<h3><a name="exec-spec"></a><code>exec</code></h3>
|
||||
<pre>
|
||||
object exec(str code,
|
||||
object globals = object(),
|
||||
object locals = object());
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
Execute Python source code from <code>code</code> in the context
|
||||
specified by the dictionaries <code>globals</code> and <code>locals</code>.
|
||||
</dt>
|
||||
<dt><b>Returns:</b>
|
||||
An instance of <a href="object.html#object-spec">object</a>
|
||||
which holds the result of executing the code.
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="exec_file-spec"></a><code>exec_file</code></h3>
|
||||
<pre>
|
||||
object exec_file(str filename,
|
||||
object globals = object(),
|
||||
object locals = object());
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
Execute Python source code from the file named by <code>filename</code>
|
||||
in the context specified by the dictionaries <code>globals</code> and
|
||||
<code>locals</code>.
|
||||
</dt>
|
||||
<dt><b>Returns:</b>
|
||||
An instance of <a href="object.html#object-spec">object</a>
|
||||
which holds the result of executing the code.
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/extract.hpp></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 <boost/python/extract.hpp></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="#extract-spec">Class <code>extract</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#extract-spec-synopsis">Class <code>extract</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#extract-spec-ctors">Class <code>extract</code>
|
||||
constructors and destructor</a></dt>
|
||||
|
||||
<dt><a href="#extract-spec-observers">Class
|
||||
<code>extract</code> observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Exposes a mechanism for extracting C++ object values from
|
||||
generalized Python objects. Note that
|
||||
<code>extract<</code>...<code>></code> can also be used to
|
||||
"downcast" an <a
|
||||
href="object.html#object-spec">object</a> to some specific <a
|
||||
href="ObjectWrapper.html#ObjectWrapper-concept">ObjectWrapper</a>. Because
|
||||
invoking a mutable python type with an argument of the same type
|
||||
(e.g. <code>list([1,2])</code> typically makes a <em>copy</em> of
|
||||
the argument object, this may be the only way to access the <a
|
||||
href="ObjectWrapper.html#ObjectWrapper-concept">ObjectWrapper</a>'s
|
||||
interface on the original object.
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="extract-spec"></a>Class template <code>extract</code></h3>
|
||||
|
||||
<p><code>extract<T></code> can be used to extract a value of
|
||||
an arbitrary C++ type from an instance of <code><a
|
||||
href="object.html#object-spec">object</a></code>. Two usages are supported:
|
||||
<ol>
|
||||
<li><b><code>extract<T>(o)</code></b> is a temporary object
|
||||
which is implicitly convertible to <code>T</code> (explicit conversion
|
||||
is also available through the object's function-call
|
||||
operator). However, if no conversion is available which can convert
|
||||
<code>o</code> to an object of type <code>T</code>, a Python
|
||||
<code>TypeError</code> exception will be <a
|
||||
href="definitions.html#raise">raised</a>.
|
||||
|
||||
<li><b><code>extract<T> x(o);</code></b> constructs an extractor
|
||||
whose <code>check()</code> member function can be used to ask whether
|
||||
a conversion is available without causing an exception to be thrown.
|
||||
</ol>
|
||||
|
||||
<h4><a name="extract-spec-synopsis"></a>Class template <code>extract</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T>
|
||||
struct extract
|
||||
{
|
||||
typedef <i>unspecified</i> result_type;
|
||||
|
||||
extract(PyObject*);
|
||||
extract(object const&);
|
||||
|
||||
result_type operator()() const;
|
||||
operator result_type() const;
|
||||
|
||||
bool check() const;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="extract-spec-ctors"></a>Class <code>extract</code>
|
||||
constructors and destructor</h4>
|
||||
<pre>
|
||||
extract(PyObject* p);
|
||||
extract(object const&);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> The first form requires that <code>p</code> is non-null.</dt>
|
||||
|
||||
<dt><b>Effects:</b>Stores a pointer to the Python object managed
|
||||
by its constructor argument. In particular, the reference
|
||||
count of the object is not incremented. The onus is on the user
|
||||
to be sure it is not destroyed before the extractor's conversion
|
||||
function is called.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="extract-spec-observers"></a>Class <code>extract</code>
|
||||
observer functions</h4>
|
||||
<pre>
|
||||
result_type operator()() const;
|
||||
operator result_type() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Converts the stored pointer to
|
||||
<code>result_type</code>, which is either <code>T</code> or
|
||||
<code>T const&</code>.
|
||||
</dt>
|
||||
|
||||
<dt><b>Returns:</b> An object of <code>result_type</code>
|
||||
corresponding to the one referenced by the stored pointer.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a
|
||||
href="errors.html#error_already_set-spec">error_already_set</a></code>
|
||||
and sets a <code>TypeError</code> if no such conversion is
|
||||
available. May also emit other unspecified exceptions thrown by
|
||||
the converter which is actually used.</dt>
|
||||
</dl>
|
||||
|
||||
<pre>
|
||||
bool check() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
|
||||
<dt><b>Postconditions:</b> None. In particular, note that a
|
||||
return value of <code>true</code> does not preclude an exception
|
||||
being thrown from <code>operator result_type()</code> or
|
||||
<code>operator()()</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> <code>false</code> <i>only</i> if no conversion from the
|
||||
stored pointer to <code>T</code> is available.</dt>
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
<h2><a name="examples"></a>Examples</h2>
|
||||
|
||||
<pre>
|
||||
#include <cstdio>
|
||||
using namespace boost::python;
|
||||
int Print(str s)
|
||||
{
|
||||
// extract a C string from the Python string object
|
||||
char const* c_str = extract<char const*>(s);
|
||||
|
||||
// Print it using printf
|
||||
std::printf("%s\n", c_str);
|
||||
|
||||
// Get the Python string's length and convert it to an int
|
||||
return extract<int>(s.attr("__len__")())
|
||||
}
|
||||
</pre>
|
||||
|
||||
The following example shows how extract can be used along with
|
||||
<code><a
|
||||
href="class.html#class_-spec">class_</a><</code>...<code>></code>
|
||||
to create and access an instance of a wrapped C++ class.
|
||||
|
||||
<pre>
|
||||
struct X
|
||||
{
|
||||
X(int x) : v(x) {}
|
||||
int value() { return v; }
|
||||
private:
|
||||
int v;
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(extract_ext)
|
||||
{
|
||||
object x_class(
|
||||
class_<X>("X", init<int>())
|
||||
.def("value", &X::value))
|
||||
;
|
||||
|
||||
// Instantiate an X object through the Python interface.
|
||||
// Its lifetime is now managed by x_obj.
|
||||
object x_obj = x_class(3);
|
||||
|
||||
// Get a reference to the C++ object out of the Python object
|
||||
X& x = extract<X&>(x_obj);
|
||||
assert(x.value() == 3);
|
||||
}
|
||||
</pre>
|
||||
<p>Revised 15 November, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
883
doc/v2/faq.html
@@ -1,883 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - FAQ</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">Frequently Asked Questions (FAQs)</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
|
||||
<dt><a href="#funcptr">How can I wrap a function which takes a
|
||||
function pointer as an argument?</a><dd>
|
||||
|
||||
<dt><a href="#dangling">I'm getting the "attempt to return dangling
|
||||
reference" error. What am I doing wrong?</a></dt>
|
||||
|
||||
<dt><a href="#question1">Is return_internal_reference
|
||||
efficient?</a></dt>
|
||||
|
||||
<dt><a href="#question2">How can I wrap functions which take C++
|
||||
containers as arguments?</a></dt>
|
||||
|
||||
<dt><a href="#c1204">fatal error C1204:Compiler limit:internal
|
||||
structure overflow</a></dt>
|
||||
|
||||
<dt><a href="#debugging">How do I debug my Python extensions?</a></dt>
|
||||
|
||||
<dt><a href="#imul">Why doesn't my <code>*=</code> operator
|
||||
work?</a></dt>
|
||||
|
||||
<dt><a href="#macosx">Does Boost.Python work with Mac OS X?</a></dt>
|
||||
|
||||
<dt><a href="#xref">How can I find the existing PyObject that holds a
|
||||
C++ object?</a></dt>
|
||||
|
||||
<dt><a href="#ownership">How can I wrap a function which needs to take
|
||||
ownership of a raw pointer?</a></dt>
|
||||
|
||||
<dt><a href="#slow_compilation">Compilation takes too much time and eats too much memory!
|
||||
What can I do to make it faster?</a></dt>
|
||||
|
||||
<dt><a href="#packages">How do I create sub-packages using Boost.Python?</a></dt>
|
||||
|
||||
<dt><a href="#msvcthrowbug"
|
||||
>error C2064: term does not evaluate to a function taking 2 arguments</a>
|
||||
</dt>
|
||||
|
||||
<dt><a href="#voidptr">How do I handle <tt>void *</tt> conversion?</a></dt>
|
||||
|
||||
<dt><a href="#custom_string"
|
||||
>How can I automatically convert my custom string type to
|
||||
and from a Python string?</a></dt>
|
||||
|
||||
<dt><a href="#topythonconversionfailed">Why is my automatic to-python conversion not being
|
||||
found?</a></dt>
|
||||
|
||||
<dt><a href="#threadsupport">Is Boost.Python thread-aware/compatible with multiple interpreters?</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="funcptr">How can I wrap a function which takes a
|
||||
function pointer as an argument?</a></h2>
|
||||
|
||||
If what you're trying to do is something like this:
|
||||
<pre>
|
||||
typedef boost::function<void (string s) > funcptr;
|
||||
|
||||
void foo(funcptr fp)
|
||||
{
|
||||
fp("hello,world!");
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(test)
|
||||
{
|
||||
def("foo",foo) ;
|
||||
}
|
||||
</pre>
|
||||
|
||||
And then:
|
||||
|
||||
<pre>
|
||||
>>> def hello(s):
|
||||
... print s
|
||||
...
|
||||
>>> foo(hello)
|
||||
hello, world!
|
||||
</pre>
|
||||
|
||||
The short answer is: "you can't". This is not a
|
||||
Boost.Python limitation so much as a limitation of C++. The
|
||||
problem is that a Python function is actually data, and the only
|
||||
way of associating data with a C++ function pointer is to store it
|
||||
in a static variable of the function. The problem with that is
|
||||
that you can only associate one piece of data with every C++
|
||||
function, and we have no way of compiling a new C++ function
|
||||
on-the-fly for every Python function you decide to pass
|
||||
to <code>foo</code>. In other words, this could work if the C++
|
||||
function is always going to invoke the <em>same</em> Python
|
||||
function, but you probably don't want that.
|
||||
|
||||
<p>If you have the luxury of changing the C++ code you're
|
||||
wrapping, pass it an <code>object</code> instead and call that;
|
||||
the overloaded function call operator will invoke the Python
|
||||
function you pass it behind the <code>object</code>.
|
||||
|
||||
<p>For more perspective on the issue, see <a
|
||||
href="http://aspn.activestate.com/ASPN/Mail/Message/1554837">this
|
||||
posting</a>.
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="dangling">I'm getting the "attempt to return dangling
|
||||
reference" error. What am I doing wrong?</a></h2>
|
||||
That exception is protecting you from causing a nasty crash. It usually
|
||||
happens in response to some code like this:
|
||||
<pre>
|
||||
period const& get_floating_frequency() const
|
||||
{
|
||||
return boost::python::call_method<period const&>(
|
||||
m_self,"get_floating_frequency");
|
||||
}
|
||||
</pre>
|
||||
And you get:
|
||||
<pre>
|
||||
ReferenceError: Attempt to return dangling reference to object of type:
|
||||
class period
|
||||
</pre>
|
||||
|
||||
<p>In this case, the Python method invoked by <code>call_method</code>
|
||||
constructs a new Python object. You're trying to return a reference to a
|
||||
C++ object (an instance of <code>class period</code>) contained within
|
||||
and owned by that Python object. Because the called method handed back a
|
||||
brand new object, the only reference to it is held for the duration of
|
||||
<code>get_floating_frequency()</code> above. When the function returns,
|
||||
the Python object will be destroyed, destroying the instance of
|
||||
<code>class period</code>, and leaving the returned reference dangling.
|
||||
That's already undefined behavior, and if you try to do anything with
|
||||
that reference you're likely to cause a crash. Boost.Python detects this
|
||||
situation at runtime and helpfully throws an exception instead of letting
|
||||
you do that.<br>
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<h2><a name="question1"></a>Is return_internal_reference efficient?</h2>
|
||||
|
||||
<blockquote>
|
||||
<b>Q:</b> <i>I have an object composed of 12 doubles. A const& to
|
||||
this object is returned by a member function of another class. From the
|
||||
viewpoint of using the returned object in Python I do not care if I get
|
||||
a copy or a reference to the returned object. In Boost.Python Version 2
|
||||
I have the choice of using copy_const_reference or
|
||||
return_internal_reference. Are there considerations that would lead me
|
||||
to prefer one over the other, such as size of generated code or memory
|
||||
overhead?</i>
|
||||
|
||||
<p><b>A:</b> copy_const_reference will make an instance with storage
|
||||
for one of your objects, size = base_size + 12 * sizeof(double).
|
||||
return_internal_reference will make an instance with storage for a
|
||||
pointer to one of your objects, size = base_size + sizeof(void*).
|
||||
However, it will also create a weak reference object which goes in the
|
||||
source object's weakreflist and a special callback object to manage the
|
||||
lifetime of the internally-referenced object. My guess?
|
||||
copy_const_reference is your friend here, resulting in less overall
|
||||
memory use and less fragmentation, also probably fewer total
|
||||
cycles.</p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2><a name="question2"></a>How can I wrap functions which take C++
|
||||
containers as arguments?</h2>
|
||||
|
||||
<p>Ralf W. Grosse-Kunstleve provides these notes:</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
Using the regular <code>class_<></code> wrapper:
|
||||
<pre>
|
||||
class_<std::vector<double> >("std_vector_double")
|
||||
.def(...)
|
||||
...
|
||||
;
|
||||
</pre>
|
||||
This can be moved to a template so that several types (double, int,
|
||||
long, etc.) can be wrapped with the same code. This technique is used
|
||||
in the file
|
||||
|
||||
<blockquote>
|
||||
scitbx/include/scitbx/array_family/boost_python/flex_wrapper.h
|
||||
</blockquote>
|
||||
in the "scitbx" package. The file could easily be modified for
|
||||
wrapping std::vector<> instantiations.
|
||||
|
||||
<p>This type of C++/Python binding is most suitable for containers
|
||||
that may contain a large number of elements (>10000).</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Using custom rvalue converters. Boost.Python "rvalue converters"
|
||||
match function signatures such as:
|
||||
<pre>
|
||||
void foo(std::vector<double> const& array); // pass by const-reference
|
||||
void foo(std::vector<double> array); // pass by value
|
||||
</pre>
|
||||
Some custom rvalue converters are implemented in the file
|
||||
|
||||
<blockquote>
|
||||
scitbx/include/scitbx/boost_python/container_conversions.h
|
||||
</blockquote>
|
||||
This code can be used to convert from C++ container types such as
|
||||
std::vector<> or std::list<> to Python tuples and vice
|
||||
versa. A few simple examples can be found in the file
|
||||
|
||||
<blockquote>
|
||||
scitbx/array_family/boost_python/regression_test_module.cpp
|
||||
</blockquote>
|
||||
Automatic C++ container <-> Python tuple conversions are most
|
||||
suitable for containers of moderate size. These converters generate
|
||||
significantly less object code compared to alternative 1 above.
|
||||
</li>
|
||||
</ol>
|
||||
A disadvantage of using alternative 2 is that operators such as
|
||||
arithmetic +,-,*,/,% are not available. It would be useful to have custom
|
||||
rvalue converters that convert to a "math_array" type instead of tuples.
|
||||
This is currently not implemented but is possible within the framework of
|
||||
Boost.Python V2 as it will be released in the next couple of weeks. [ed.:
|
||||
this was posted on 2002/03/10]
|
||||
|
||||
<p>It would also be useful to also have "custom lvalue converters" such
|
||||
as std::vector<> <-> Python list. These converters would
|
||||
support the modification of the Python list from C++. For example:</p>
|
||||
|
||||
<p>C++:</p>
|
||||
<pre>
|
||||
void foo(std::vector<double>& array)
|
||||
{
|
||||
for(std::size_t i=0;i<array.size();i++) {
|
||||
array[i] *= 2;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Python:
|
||||
<pre>
|
||||
>>> l = [1, 2, 3]
|
||||
>>> foo(l)
|
||||
>>> print l
|
||||
[2, 4, 6]
|
||||
</pre>
|
||||
Custom lvalue converters require changes to the Boost.Python core library
|
||||
and are currently not available.
|
||||
|
||||
<p>P.S.:</p>
|
||||
|
||||
<p>The "scitbx" files referenced above are available via anonymous
|
||||
CVS:</p>
|
||||
<pre>
|
||||
cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx login
|
||||
cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
|
||||
</pre>
|
||||
<hr>
|
||||
|
||||
<h2><a name="c1204"></a>fatal error C1204:Compiler limit:internal
|
||||
structure overflow</h2>
|
||||
|
||||
<blockquote>
|
||||
<b>Q:</b> <i>I get this error message when compiling a large source
|
||||
file. What can I do?</i>
|
||||
|
||||
<p><b>A:</b> You have two choices:</p>
|
||||
|
||||
<ol>
|
||||
<li>Upgrade your compiler (preferred)</li>
|
||||
|
||||
<li>
|
||||
Break your source file up into multiple translation units.
|
||||
|
||||
<p><code><b>my_module.cpp</b></code>:</p>
|
||||
<pre>
|
||||
...
|
||||
void more_of_my_module();
|
||||
BOOST_PYTHON_MODULE(my_module)
|
||||
{
|
||||
def("foo", foo);
|
||||
def("bar", bar);
|
||||
...
|
||||
more_of_my_module();
|
||||
}
|
||||
</pre>
|
||||
<code><b>more_of_my_module.cpp</b></code>:
|
||||
<pre>
|
||||
void more_of_my_module()
|
||||
{
|
||||
def("baz", baz);
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
If you find that a <code><a href=
|
||||
"class.html#class_-spec">class_</a><...></code> declaration
|
||||
can't fit in a single source file without triggering the error, you
|
||||
can always pass a reference to the <code>class_</code> object to a
|
||||
function in another source file, and call some of its member
|
||||
functions (e.g. <code>.def(...)</code>) in the auxilliary source
|
||||
file:
|
||||
|
||||
<p><code><b>more_of_my_class.cpp</b></code>:</p>
|
||||
<pre>
|
||||
void more_of_my_class(class<my_class>& x)
|
||||
{
|
||||
x
|
||||
.def("baz", baz)
|
||||
.add_property("xx", &my_class::get_xx, &my_class::set_xx)
|
||||
;
|
||||
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2><a name="debugging"></a>How do I debug my Python extensions?</h2>
|
||||
|
||||
<p>Greg Burley gives the following answer for Unix GCC users:</p>
|
||||
|
||||
<blockquote>
|
||||
Once you have created a boost python extension for your c++ library or
|
||||
class, you may need to debug the code. Afterall this is one of the
|
||||
reasons for wrapping the library in python. An expected side-effect or
|
||||
benefit of using BPL is that debugging should be isolated to the c++
|
||||
library that is under test, given that python code is minimal and
|
||||
boost::python either works or it doesn't. (ie. While errors can occur
|
||||
when the wrapping method is invalid, most errors are caught by the
|
||||
compiler ;-).
|
||||
|
||||
<p>The basic steps required to initiate a gdb session to debug a c++
|
||||
library via python are shown here. Note, however that you should start
|
||||
the gdb session in the directory that contains your BPL my_ext.so
|
||||
module.</p>
|
||||
<pre>
|
||||
(gdb) target exec python
|
||||
(gdb) run
|
||||
>>> from my_ext import *
|
||||
>>> [C-c]
|
||||
(gdb) break MyClass::MyBuggyFunction
|
||||
(gdb) cont
|
||||
>>> pyobj = MyClass()
|
||||
>>> pyobj.MyBuggyFunction()
|
||||
Breakpoint 1, MyClass::MyBuggyFunction ...
|
||||
Current language: auto; currently c++
|
||||
(gdb) do debugging stuff
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Greg's approach works even better using Emacs' "<code>gdb</code>"
|
||||
command, since it will show you each line of source as you step through
|
||||
it.</p>
|
||||
|
||||
<p>On <b>Windows</b>, my favorite debugging solution is the debugger that
|
||||
comes with Microsoft Visual C++ 7. This debugger seems to work with code
|
||||
generated by all versions of Microsoft and Metrowerks toolsets; it's rock
|
||||
solid and "just works" without requiring any special tricks from the
|
||||
user.</p>
|
||||
|
||||
<p>Raoul Gough has provided the following for gdb on Windows:</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>gdb support for Windows DLLs has improved lately, so it is
|
||||
now possible to debug Python extensions using a few
|
||||
tricks. Firstly, you will need an up-to-date gdb with support
|
||||
for minimal symbol extraction from a DLL. Any gdb from version 6
|
||||
onwards, or Cygwin gdb-20030214-1 and onwards should do. A
|
||||
suitable release will have a section in the gdb.info file under
|
||||
Configuration – Native – Cygwin Native –
|
||||
Non-debug DLL symbols. Refer to that info section for more
|
||||
details of the procedures outlined here.</p>
|
||||
|
||||
<p>Secondly, it seems necessary to set a breakpoint in the
|
||||
Python interpreter, rather than using ^C to break execution. A
|
||||
good place to set this breakpoint is PyOS_Readline, which will
|
||||
stop execution immediately before reading each interactive
|
||||
Python command. You have to let Python start once under the
|
||||
debugger, so that it loads its own DLL, before you can set the
|
||||
breakpoint:</p>
|
||||
|
||||
<p>
|
||||
<pre>
|
||||
$ gdb python
|
||||
GNU gdb 2003-09-02-cvs (cygwin-special)
|
||||
[...]
|
||||
|
||||
(gdb) run
|
||||
Starting program: /cygdrive/c/Python22/python.exe
|
||||
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> ^Z
|
||||
|
||||
|
||||
Program exited normally.
|
||||
(gdb) break *&PyOS_Readline
|
||||
Breakpoint 1 at 0x1e04eff0
|
||||
(gdb) run
|
||||
Starting program: /cygdrive/c/Python22/python.exe
|
||||
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
|
||||
Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
|
||||
from /cygdrive/c/WINNT/system32/python22.dll
|
||||
(gdb) cont
|
||||
Continuing.
|
||||
>>> from my_ext import *
|
||||
|
||||
Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
|
||||
from /cygdrive/c/WINNT/system32/python22.dll
|
||||
(gdb) # my_ext now loaded (with any debugging symbols it contains)
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Debugging extensions through Boost.Build</h3>
|
||||
If you are launching your extension module tests with <a href=
|
||||
"../../../../tools/build/v1/build_system.htm">Boost.Build</a> using the
|
||||
<code>boost-python-runtest</code> rule, you can ask it to launch your
|
||||
debugger for you by adding "--debugger=<i>debugger</i>" to your bjam
|
||||
command-line:
|
||||
<pre>
|
||||
bjam -sTOOLS=vc7.1 "--debugger=devenv /debugexe" test
|
||||
bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
|
||||
</pre>
|
||||
It can also be extremely useful to add the <code>-d+2</code> option when
|
||||
you run your test, because Boost.Build will then show you the exact
|
||||
commands it uses to invoke it. This will invariably involve setting up
|
||||
PYTHONPATH and other important environment variables such as
|
||||
LD_LIBRARY_PATH which may be needed by your debugger in order to get
|
||||
things to work right.
|
||||
<hr>
|
||||
|
||||
<h2><a name="imul"></a>Why doesn't my <code>*=</code> operator work?</h2>
|
||||
|
||||
<blockquote>
|
||||
<b>Q:</b> <i>I have exported my class to python, with many overloaded
|
||||
operators. it works fine for me except the</i> <code>*=</code>
|
||||
<i>operator. It always tells me "can't multiply sequence with non int
|
||||
type". If I use</i> <code>p1.__imul__(p2)</code> <i>instead of</i>
|
||||
<code>p1 *= p2</code><i>, it successfully executes my code. What's
|
||||
wrong with me?</i>
|
||||
|
||||
<p><b>A:</b> There's nothing wrong with you. This is a bug in Python
|
||||
2.2. You can see the same effect in Pure Python (you can learn a lot
|
||||
about what's happening in Boost.Python by playing with new-style
|
||||
classes in Pure Python).</p>
|
||||
<pre>
|
||||
>>> class X(object):
|
||||
... def __imul__(self, x):
|
||||
... print 'imul'
|
||||
...
|
||||
>>> x = X()
|
||||
>>> x *= 1
|
||||
</pre>
|
||||
To cure this problem, all you need to do is upgrade your Python to
|
||||
version 2.2.1 or later.
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2><a name="macosx"></a>Does Boost.Python work with Mac OS X?</h2>
|
||||
|
||||
It is known to work under 10.2.8 and 10.3 using
|
||||
Apple's gcc 3.3 compiler:
|
||||
<pre>gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1493)</pre>
|
||||
Under 10.2.8 get the August 2003 gcc update (free at
|
||||
<a href="http://connect.apple.com/">http://connect.apple.com/</a>).
|
||||
Under 10.3 get the Xcode Tools v1.0 (also free).
|
||||
<p>
|
||||
Python 2.3 is required. The Python that ships with 10.3 is
|
||||
fine. Under 10.2.8 use these commands to install Python
|
||||
as a framework:
|
||||
<pre>./configure --enable-framework
|
||||
make
|
||||
make frameworkinstall</pre>
|
||||
The last command requires root privileges because the target
|
||||
directory is
|
||||
<tt>/Library/Frameworks/Python.framework/Versions/2.3</tt>.
|
||||
However, the installation does not interfere with the Python
|
||||
version that ships with 10.2.8.
|
||||
<p>
|
||||
It is also crucial to increase the <tt>stacksize</tt> before
|
||||
starting compilations, e.g.:
|
||||
<pre>limit stacksize 8192k</pre>
|
||||
If the <tt>stacksize</tt> is too small the build might crash with
|
||||
internal compiler errors.
|
||||
<p>
|
||||
Sometimes Apple's compiler exhibits a bug by printing an error
|
||||
like the following while compiling a
|
||||
<tt>boost::python::class_<your_type></tt>
|
||||
template instantiation:
|
||||
<pre>.../inheritance.hpp:44: error: cannot
|
||||
dynamic_cast `p' (of type `struct cctbx::boost_python::<unnamed>::add_pair*
|
||||
') to type `void*' (source type is not polymorphic)</pre>
|
||||
|
||||
We do not know a general workaround, but if the definition of
|
||||
<tt>your_type</tt> can be modified the following was found
|
||||
to work in all cases encountered so far:<pre>struct your_type
|
||||
{
|
||||
// before defining any member data
|
||||
#if defined(__MACH__) && defined(__APPLE_CC__) && __APPLE_CC__ == 1493
|
||||
bool dummy_;
|
||||
#endif
|
||||
// now your member data, e.g.
|
||||
double x;
|
||||
int j;
|
||||
// etc.
|
||||
};</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="xref">How can I find the existing PyObject that holds a C++
|
||||
object?</a></h2>
|
||||
|
||||
<blockquote>
|
||||
"I am wrapping a function that always returns a pointer to an
|
||||
already-held C++ object."
|
||||
</blockquote>
|
||||
One way to do that is to hijack the mechanisms used for wrapping a class
|
||||
with virtual functions. If you make a wrapper class with an initial
|
||||
PyObject* constructor argument and store that PyObject* as "self", you
|
||||
can get back to it by casting down to that wrapper type in a thin wrapper
|
||||
function. For example:
|
||||
<pre>
|
||||
class X { X(int); virtual ~X(); ... };
|
||||
X* f(); // known to return Xs that are managed by Python objects
|
||||
|
||||
|
||||
// wrapping code
|
||||
|
||||
struct X_wrap : X
|
||||
{
|
||||
X_wrap(PyObject* self, int v) : self(self), X(v) {}
|
||||
PyObject* self;
|
||||
};
|
||||
|
||||
handle<> f_wrap()
|
||||
{
|
||||
X_wrap* xw = dynamic_cast<X_wrap*>(f());
|
||||
assert(xw != 0);
|
||||
return handle<>(borrowed(xw->self));
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
def("f", f_wrap());
|
||||
class_<X,X_wrap>("X", init<int>())
|
||||
...
|
||||
;
|
||||
</pre>
|
||||
Of course, if X has no virtual functions you'll have to use
|
||||
<code>static_cast</code> instead of <code>dynamic_cast</code> with no
|
||||
runtime check that it's valid. This approach also only works if the
|
||||
<code>X</code> object was constructed from Python, because
|
||||
<code>X</code>s constructed from C++ are of course never
|
||||
<code>X_wrap</code> objects.
|
||||
|
||||
<p>Another approach to this requires you to change your C++ code a bit;
|
||||
if that's an option for you it might be a better way to go. work we've
|
||||
been meaning to get to anyway. When a <code>shared_ptr<X></code> is
|
||||
converted from Python, the shared_ptr actually manages a reference to the
|
||||
containing Python object. When a shared_ptr<X> is converted back to
|
||||
Python, the library checks to see if it's one of those "Python object
|
||||
managers" and if so just returns the original Python object. So you could
|
||||
just write <code>object(p)</code> to get the Python object back. To
|
||||
exploit this you'd have to be able to change the C++ code you're wrapping
|
||||
so that it deals with shared_ptr instead of raw pointers.</p>
|
||||
|
||||
<p>There are other approaches too. The functions that receive the Python
|
||||
object that you eventually want to return could be wrapped with a thin
|
||||
wrapper that records the correspondence between the object address and
|
||||
its containing Python object, and you could have your f_wrap function
|
||||
look in that mapping to get the Python object out.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="ownership">How can I wrap a function which needs to take
|
||||
ownership of a raw pointer?</a></h2>
|
||||
|
||||
<blockquote>
|
||||
<i>Part of an API that I'm wrapping goes something like this:</i>
|
||||
<pre>
|
||||
struct A {}; struct B { void add( A* ); }
|
||||
where B::add() takes ownership of the pointer passed to it.
|
||||
</pre>
|
||||
|
||||
<p><i>However:</i></p>
|
||||
<pre>
|
||||
a = mod.A()
|
||||
b = mod.B()
|
||||
b.add( a )
|
||||
del a
|
||||
del b
|
||||
# python interpreter crashes
|
||||
# later due to memory corruption.
|
||||
</pre>
|
||||
|
||||
<p><i>Even binding the lifetime of a</i> to b via
|
||||
with_custodian_and_ward doesn't prevent the python object a from
|
||||
ultimately trying to delete the object it's pointing to. Is there a way
|
||||
to accomplish a 'transfer-of-ownership' of a wrapped C++ object?</p>
|
||||
|
||||
<p><i>--Bruce Lowery</i></p>
|
||||
</blockquote>
|
||||
Yes: Make sure the C++ object is held by auto_ptr:
|
||||
<pre>
|
||||
class_<A, std::auto_ptr<A> >("A")
|
||||
...
|
||||
;
|
||||
</pre>
|
||||
Then make a thin wrapper function which takes an auto_ptr parameter:
|
||||
<pre>
|
||||
void b_insert(B& b, std::auto_ptr<A> a)
|
||||
{
|
||||
b.insert(a.get());
|
||||
a.release();
|
||||
}
|
||||
</pre>
|
||||
Wrap that as B.add. Note that pointers returned via <code><a href=
|
||||
"manage_new_object.html#manage_new_object-spec">manage_new_object</a></code>
|
||||
will also be held by <code>auto_ptr</code>, so this transfer-of-ownership
|
||||
will also work correctly.
|
||||
|
||||
<hr>
|
||||
<h2><a name="slow_compilation">Compilation takes too much time and eats too
|
||||
much memory! What can I do to make it faster?</a></h2>
|
||||
<p>
|
||||
Please refer to the <a href="../tutorial/doc/html/python/techniques.html#python.reducing_compiling_time"
|
||||
>Reducing Compiling Time</a> section in the tutorial.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="packages">How do I create sub-packages using Boost.Python?</a></h2>
|
||||
<p>
|
||||
Please refer to the <a href="../tutorial/doc/html/python/techniques.html#python.creating_packages"
|
||||
>Creating Packages</a> section in the tutorial.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="msvcthrowbug"></a>error C2064: term does
|
||||
not evaluate to a function taking 2 arguments</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
If you see Microsoft Visual C++ 7.1 (MS Visual Studio .NET 2003) issue
|
||||
an error message like the following it is most likely due to a bug
|
||||
in the compiler:
|
||||
<pre>boost\boost\python\detail\invoke.hpp(76):
|
||||
error C2064: term does not evaluate to a function taking 2 arguments"</pre>
|
||||
This message is triggered by code like the following:
|
||||
<pre>#include <boost/python.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
class FXThread
|
||||
{
|
||||
public:
|
||||
bool setAutoDelete(bool doso) throw();
|
||||
};
|
||||
|
||||
void Export_FXThread()
|
||||
{
|
||||
class_< FXThread >("FXThread")
|
||||
.def("setAutoDelete", &FXThread::setAutoDelete)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
The bug is related to the <code>throw()</code> modifier.
|
||||
As a workaround cast off the modifier. E.g.:
|
||||
<pre>
|
||||
.def("setAutoDelete", (bool (FXThread::*)(bool)) &FXThread::setAutoDelete)</pre>
|
||||
<p>(The bug has been reported to Microsoft.)</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="voidptr"></a>How do I handle <tt>void *</tt> conversion?</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
For several reasons Boost.Python does not support <tt>void *</tt> as
|
||||
an argument or as a return value. However, it is possible to wrap
|
||||
functions with <tt>void *</tt> arguments or return values using
|
||||
thin wrappers and the <i>opaque pointer</i> facility. E.g.:
|
||||
<pre>// Declare the following in each translation unit
|
||||
struct void_ {};
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(void_);
|
||||
|
||||
void *foo(int par1, void *par2);
|
||||
|
||||
void_ *foo_wrapper(int par1, void_ *par2)
|
||||
{
|
||||
return (void_ *) foo(par1, par2);
|
||||
}
|
||||
...
|
||||
BOOST_PYTHON_MODULE(bar)
|
||||
{
|
||||
def("foo", &foo_wrapper);
|
||||
}</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="custom_string"></a>How can I automatically
|
||||
convert my custom string type to and from a Python string?</h2>
|
||||
<font size="-1"><i>Ralf W. Grosse-Kunstleve provides these
|
||||
notes:</i></font><p>
|
||||
Below is a small, self-contained demo extension module that shows
|
||||
how to do this. Here is the corresponding trivial test:
|
||||
<pre>import custom_string
|
||||
assert custom_string.hello() == "Hello world."
|
||||
assert custom_string.size("california") == 10</pre>
|
||||
|
||||
If you look at the code you will find:
|
||||
|
||||
<ul>
|
||||
<li>A custom <tt>to_python</tt> converter (easy):
|
||||
<tt>custom_string_to_python_str</tt>
|
||||
|
||||
<li>A custom lvalue converter (needs more code):
|
||||
<tt>custom_string_from_python_str</tt>
|
||||
</ul>
|
||||
|
||||
The custom converters are registered in the global Boost.Python
|
||||
registry near the top of the module initialization function. Once
|
||||
flow control has passed through the registration code the automatic
|
||||
conversions from and to Python strings will work in any module
|
||||
imported in the same process.
|
||||
|
||||
<pre>#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
|
||||
namespace sandbox { namespace {
|
||||
|
||||
class custom_string
|
||||
{
|
||||
public:
|
||||
custom_string() {}
|
||||
custom_string(std::string const& value) : value_(value) {}
|
||||
std::string const& value() const { return value_; }
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
struct custom_string_to_python_str
|
||||
{
|
||||
static PyObject* convert(custom_string const& s)
|
||||
{
|
||||
return boost::python::incref(boost::python::object(s.value()).ptr());
|
||||
}
|
||||
};
|
||||
|
||||
struct custom_string_from_python_str
|
||||
{
|
||||
custom_string_from_python_str()
|
||||
{
|
||||
boost::python::converter::registry::push_back(
|
||||
&convertible,
|
||||
&construct,
|
||||
boost::python::type_id<custom_string>());
|
||||
}
|
||||
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
if (!PyString_Check(obj_ptr)) return 0;
|
||||
return obj_ptr;
|
||||
}
|
||||
|
||||
static void construct(
|
||||
PyObject* obj_ptr,
|
||||
boost::python::converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
const char* value = PyString_AsString(obj_ptr);
|
||||
if (value == 0) boost::python::throw_error_already_set();
|
||||
void* storage = (
|
||||
(boost::python::converter::rvalue_from_python_storage<custom_string>*)
|
||||
data)->storage.bytes;
|
||||
new (storage) custom_string(value);
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
custom_string hello() { return custom_string("Hello world."); }
|
||||
|
||||
std::size_t size(custom_string const& s) { return s.value().size(); }
|
||||
|
||||
void init_module()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
boost::python::to_python_converter<
|
||||
custom_string,
|
||||
custom_string_to_python_str>();
|
||||
|
||||
custom_string_from_python_str();
|
||||
|
||||
def("hello", hello);
|
||||
def("size", size);
|
||||
}
|
||||
|
||||
}} // namespace sandbox::<anonymous>
|
||||
|
||||
BOOST_PYTHON_MODULE(custom_string)
|
||||
{
|
||||
sandbox::init_module();
|
||||
}</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="topythonconversionfailed"></a
|
||||
>Why is my automatic to-python conversion not being found?</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
If you define custom converters similar to the ones
|
||||
shown above the <tt>def_readonly()</tt> and <tt>def_readwrite()</tt>
|
||||
member functions provided by <tt>boost::python::class_</tt> for
|
||||
direct access to your member data will not work as expected.
|
||||
This is because <tt>def_readonly("bar", &foo::bar)</tt> is
|
||||
equivalent to:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_internal_reference()))</pre>
|
||||
|
||||
Similarly, <tt>def_readwrite("bar", &foo::bar)</tt> is
|
||||
equivalent to:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_internal_reference()),
|
||||
make_setter(&foo::bar, return_internal_reference())</pre>
|
||||
|
||||
In order to define return value policies compatible with the
|
||||
custom conversions replace <tt>def_readonly()</tt> and
|
||||
<tt>def_readwrite()</tt> by <tt>add_property()</tt>. E.g.:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_value_policy<return_by_value>()),
|
||||
make_setter(&foo::bar, return_value_policy<return_by_value>()))</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="threadsupport"></a
|
||||
>Is Boost.Python thread-aware/compatible with multiple interpreters?</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
The quick answer to this is: no.</p>
|
||||
<p>
|
||||
The longer answer is that it can be patched to be so, but it's
|
||||
complex. You will need to add custom lock/unlock wrapping of every
|
||||
time your code enters Boost.Python (particularly every virtual
|
||||
function override) plus heavily modify
|
||||
<tt>boost/python/detail/invoke.hpp</tt> with custom unlock/lock
|
||||
wrapping of every time Boost.Python enters your code. You must
|
||||
furthermore take care to <i>not</i> unlock/lock when Boost.Python
|
||||
is invoking iterator changes via <tt>invoke.hpp</tt>.</p>
|
||||
<p>
|
||||
There is a patched <tt>invoke.hpp</tt> posted on the C++-SIG
|
||||
mailing list archives and you can find a real implementation of all
|
||||
the machinery necessary to fully implement this in the TnFOX
|
||||
project at <a href="http://sourceforge.net/projects/tnfox/"> this
|
||||
SourceForge project location</a>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
28 January, 2004
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,366 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<meta http-equiv="Content-Type" content=
|
||||
"text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - February 2002 Progress Report</title>
|
||||
<style type="text/css">
|
||||
:link { color: #0000ff }
|
||||
:visited { color: #800080 }
|
||||
p.c3 {font-style: italic}
|
||||
h2.c2 {text-align: center}
|
||||
h1.c1 {text-align: center}
|
||||
</style>
|
||||
|
||||
<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 class="c1"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 class="c2">February 2002 Progress Report</h2>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="index">
|
||||
<dt><a href="#Python10">Python10 Conference Report</a>
|
||||
|
||||
<dt><a href="#progress">Boost.Python v2 Progress</a>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="#documentation">Documentation</a>
|
||||
|
||||
<dt><a href="#conversion">Overhaul of
|
||||
<code>to_python</code>/<code>from_python</code>
|
||||
conversion mechanism</a>
|
||||
|
||||
<dt><a href="#miscellaneous">Miscellaneous</a>
|
||||
</dl>
|
||||
</dl>
|
||||
|
||||
<h2><a name="Python10">Python10 Conference Report</a></h2>
|
||||
I spent the first week of February at the Python10 conference
|
||||
in Alexandria, VA. I'm including this experience report
|
||||
for two reasons: firstly, it documents where my time was
|
||||
used. Secondly, a public presence for Boost.Python and
|
||||
interaction between the Python and C++ communities is
|
||||
important to the future of Boost.Python, which in turn is
|
||||
important to the Kull Project.
|
||||
|
||||
<p>Andy Koenig, of all people, was the keynote speaker of
|
||||
this year's opening plenary session. He presented his
|
||||
"impressions of a polyglot outsider", which
|
||||
studiously avoided any mention of C++ until the end of his
|
||||
talk, when he was asked about standardization. I was
|
||||
surprised to learn that the C++ community at large wanted a
|
||||
few more years before beginning but when ANSI accepted
|
||||
HP's request for a standard, the process was forced to
|
||||
start: it was a matter of participating or having
|
||||
standardization proceed without one's input. Andy managed
|
||||
to highlight very effectively the balance of strengths in
|
||||
Python, one of the most important being its support for
|
||||
extension via libraries. In many ways that makes Python a
|
||||
good analogue for C++ in the interpreted world
|
||||
|
||||
<p>There were several kind mentions of the Boost.Python
|
||||
library from people who found it indispensable. I was
|
||||
particularly happy that Karl MacMillan, Michael Droettboom,
|
||||
and Ichiro Fujinaga from Johns Hopkins is using it to do OCR
|
||||
on a vast library of music notation, since in a previous life
|
||||
I was an author of music notation software. These guys are
|
||||
also drawing on Ullrich Koethe's VIGRA library for image
|
||||
manipulation (Ullrich has been a major contributor to
|
||||
Boost.Python). They also have a system for writing the
|
||||
Boost.Python wrapper code in C++ comments, which allows them
|
||||
to keep all of the code in one place. I've asked them to
|
||||
send me some information on that.
|
||||
|
||||
<p>The development of Swig has been gaining momentum again
|
||||
(the basic description at
|
||||
www.boost.org/libs/python/doc/comparisons.html still
|
||||
applies). The talk given about it by David Beazly was very
|
||||
well-attended, and they appear to have quite a few users.
|
||||
Swig's strengths (coverage of many langauages) and
|
||||
weaknesses (incomplete C++ language support) haven't
|
||||
changed, although the C++ support seems to have improved
|
||||
considerably - they now claim to have a complete model of the
|
||||
C++ type system. It seems to be mostly geared at wrapping
|
||||
what Walter Landry calls "C-Tran": C++ code which
|
||||
traffics in built-in types with little use of abstraction.
|
||||
I'm not knocking that, either: I'm sure a lot of that
|
||||
code exists, so it's a valuable service. One feature Swig
|
||||
has which I'd like to steal is the ability to unwrap a
|
||||
single Python argument into multiple C++ arguments, for
|
||||
example, by converting a Python string into a pointer and
|
||||
length. When his talk was over, David approached me about a
|
||||
possible joint workshop on language binding, which sounds
|
||||
like a fun idea to me.
|
||||
|
||||
<p>I spent some considerable time talking with Steven Knight,
|
||||
the leader of the Scons build tool effort. We had a lot to
|
||||
share with one another, and I gained a much better
|
||||
appreciation for many of the Scons design decisions. Scons
|
||||
seems to be concentrating on being the ultimate build system
|
||||
substrate, and Steve seemed to think that we were on the
|
||||
right track with our high-level design. We both hope that the
|
||||
Boost.Build V2 high-level architecture can eventually be
|
||||
ported to run on top of Scons.
|
||||
|
||||
<p>They also have a highly-refined and successful development
|
||||
procedure which I'd like to emulate for Boost.Build V2.
|
||||
Among many other things they do, their source-control system
|
||||
automatically ensures that when you check in a new test, it
|
||||
is automatically run on the currently checked-in state of the
|
||||
code, and is expected to fail -- a relatively obvious good
|
||||
idea which I've never heard before.
|
||||
|
||||
<p>Guido Van Rossum's "State of the Python
|
||||
Union" address was full of questions for the community
|
||||
about what should be done next, but the one idea Guido seemed
|
||||
to stress was that core language stability and continuing
|
||||
library development would be a good idea (sound familiar?) I
|
||||
mentioned the Boost model as a counterpoint to the idea of
|
||||
something like CPAN (the massive Perl library archives), and
|
||||
it seemed to generate some significant interest. I've
|
||||
offered to work with anyone from the Python community who
|
||||
wants to set up something like Boost.
|
||||
|
||||
<p>There was some discussion of "string
|
||||
interpolation" (variable substitution in strings), and
|
||||
Guido mentioned that he had some thoughts about the
|
||||
strengths/weaknesses of Python's formatting interface. It
|
||||
might be useful for those working on formatting for boost to
|
||||
contact him and find out what he has to say.
|
||||
|
||||
<p>Ka-Ping Yee demoed a Mailman discussion thread weaver.
|
||||
This tool weaves the various messages in a discussion thread
|
||||
into a single document so you can follow the entire
|
||||
conversation. Since we're looking very seriously at
|
||||
moving Boost to Mailman, this could be a really useful thing
|
||||
for us to have. If we do this, we'll move the yahoogroups
|
||||
discussions into the mailman archive so old discussions can
|
||||
be easily accessed in the same fashion.
|
||||
|
||||
<p>And, just because it's cool, though perhaps not
|
||||
relevant: http://homepages.ulb.ac.be/~arigo/psyco/ is a
|
||||
promising effort to accelerate the execution of Python code
|
||||
to speeds approaching those of compiled languages. It
|
||||
reminded me a lot of Todd Veldhuizen's research into
|
||||
moving parts of C++ template compilation to runtime, only
|
||||
coming from the opposite end of things.
|
||||
|
||||
<h2><a name="progress">Boost.Python v2 Progress</a></h2>
|
||||
Here's what actually got accomplished.
|
||||
|
||||
<h3><a name="documentation">Documentation</a></h3>
|
||||
|
||||
<p>My first priority upon returning from Python10 was to get
|
||||
some documentation in place. After wasting an unfortunate
|
||||
amount of time looking at automatic documentation tools which
|
||||
don't quite work, I settled down to use Bill Kempf's
|
||||
HTML templates designed to be a boost standard. While they
|
||||
are working well, it is highly labor-intensive.
|
||||
|
||||
<p>I decided to begin with the high-level reference material,
|
||||
as opposed to tutorial, narrative, or nitty-gritty details of
|
||||
the framework. It seemed more important to have a precise
|
||||
description of the way the commonly-used components work than
|
||||
to have examples in HTML (since we already have some test
|
||||
modules), and since the low-level details are much
|
||||
less-frequently needed by users it made sense for me to
|
||||
simply respond to support requests for the time being.
|
||||
|
||||
<p>After completing approximately 60% of the high-level docs
|
||||
(currently checked in to libs/python/doc/v2), I found myself
|
||||
ready to start documenting the mechanisms for creating
|
||||
to-/from-python converters. This caused a dilemma: I had
|
||||
realized during the previous week that a much simpler,
|
||||
more-efficient, and easier-to-use implementation was
|
||||
possible, but I hadn't planned on implementing it right
|
||||
away, since what was already in place worked adequately. I
|
||||
had also received my first query on the C++-sig about how to
|
||||
write such a converter
|
||||
|
||||
<p>Given the labor-intensive nature of documentation writing,
|
||||
I decided it would be a bad idea to document the conversion
|
||||
mechanism if I was just going to rewrite it. Often the best
|
||||
impetus for simplifying a design is the realization that
|
||||
understandably documenting its current state would be too
|
||||
difficult, and this was no exception.
|
||||
|
||||
<h3><a name="conversion">Overhaul of
|
||||
<code>to_python</code>/<code>from_python</code> conversion
|
||||
mechanism</a></h3>
|
||||
|
||||
<p>There were two basic realizations involved here:
|
||||
|
||||
<ol>
|
||||
<li><code>to_python</code> conversion could be a one-step
|
||||
process, once an appropriate conversion function is found.
|
||||
This allows elimination of the separate indirect
|
||||
convertibility check
|
||||
|
||||
<li>There are basically two categories of from_python
|
||||
conversions: those which lvalues stored within or held by
|
||||
the Python object (essentially extractions), like what
|
||||
happens when an instance of a C++ class exposed with class_
|
||||
is used as the target of a wrapped member function), and
|
||||
those in which a new rvalue gets created, as when a Python
|
||||
Float is converted to a C++
|
||||
<code>complex<double></code> or a Python tuple is
|
||||
converted to a C++ <code>std::vector<></code>. From
|
||||
the client side, there are two corresponding categories of
|
||||
conversion: those which demand an lvalue conversion and
|
||||
those which can accept an lvalue or an rvalue conversion.
|
||||
</ol>
|
||||
The latter realization allowed the following collapse, which
|
||||
considerably simplified things:
|
||||
|
||||
<blockquote>
|
||||
<table border="1" summary="Conversion protocol">
|
||||
<tr>
|
||||
<th>Target Type
|
||||
|
||||
<th>Eligible Converters
|
||||
|
||||
<tr>
|
||||
<td><code>T</code>
|
||||
|
||||
<td rowspan="5"><code>T</code> rvalue or lvalue
|
||||
|
||||
<tr>
|
||||
<td><code>T const</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T volatile</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T const volatile</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T const&</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T const*</code>
|
||||
|
||||
<td rowspan="9"><code>T</code> lvalue
|
||||
|
||||
<tr>
|
||||
<td><code>T volatile*</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T const volatile*</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T&</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T volatile&</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T const volatile&</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T* const&</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T const* const&</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T volatile*const&</code>
|
||||
|
||||
<tr>
|
||||
<td><code>T const volatile*const&</code>
|
||||
</table>
|
||||
</blockquote>
|
||||
This job included the following additional enhancements:
|
||||
|
||||
<ul>
|
||||
<li>Elimination of virtual functions, which cause object
|
||||
code bloat
|
||||
|
||||
<li>Registration of a single converter function for all
|
||||
lvalue conversions, two for all rvalue conversions
|
||||
|
||||
<li>Killed lots of unneeded code
|
||||
|
||||
<li>Increased opacity of registry interface
|
||||
|
||||
<li>Eliminated all need for decorated runtime type
|
||||
identifiers
|
||||
|
||||
<li>Updated test modules to reflect new interface
|
||||
|
||||
<li>Eliminated the need for users to worry about converter
|
||||
lifetime issues Additional Builtin Conversion Enhancements
|
||||
|
||||
<li>Support for complex<float>,
|
||||
complex<double>, and complex<long double>
|
||||
conversions
|
||||
|
||||
<li>Support for bool conversions
|
||||
|
||||
<li>NULL pointers representable by None in Python
|
||||
|
||||
<li>Support for conversion of Python classic classes to
|
||||
numeric types
|
||||
</ul>
|
||||
|
||||
<h3><a name="miscellaneous">Miscellaneous</a></h3>
|
||||
These don't fit easily under a large heading:
|
||||
|
||||
<ul>
|
||||
<li>Support CallPolicies for class member functions
|
||||
|
||||
<li>from_python_data.hpp: revamped type alignment
|
||||
metaprogram so that it's fast enough for KCC
|
||||
|
||||
<li>classfwd.hpp header forward-declares class_<T>
|
||||
|
||||
<li>indirect_traits.hpp:
|
||||
|
||||
<li>added is_pointer_to_reference
|
||||
|
||||
<li>fixed bugs
|
||||
|
||||
<li>Reduced recompilation dependencies
|
||||
|
||||
<li>msvc_typeinfo works around broken MS/Intel typeid()
|
||||
implementation
|
||||
|
||||
<li>Many fixes and improvements to the type_traits library
|
||||
in order to work around compiler bugs and suppress warnings
|
||||
|
||||
<li>Eliminated the need for explicit acquisition of
|
||||
converter registrations
|
||||
|
||||
<li>Expanded constructor support to 6 arguments
|
||||
|
||||
<li>Implemented generalized pointer lifetime support
|
||||
|
||||
<li>Updated code generation for returning.hpp
|
||||
|
||||
<li>Tracked down and fixed cycle GC bugs
|
||||
|
||||
<li>Added comprehensive unit tests for destroy_reference,
|
||||
pointer_type_id, select_from_python, complex<T>,
|
||||
bool, and classic class instance conversions
|
||||
</ul>
|
||||
|
||||
<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 class="c3">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002.
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/handle.hpp></title>
|
||||
|
||||
<style type="text/css">
|
||||
p.c4 {font-style: italic}
|
||||
span.c3 {color: #ff0000}
|
||||
h2.c2 {text-align: center}
|
||||
h1.c1 {text-align: center}
|
||||
</style>
|
||||
</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 class="c1"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 class="c2">Header <boost/python/handle.hpp></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="#handle-spec">Class template
|
||||
<code>handle</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#handle-spec-synopsis">Class <code>handle</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#handle-spec-ctors">Class <code>handle</code>
|
||||
constructors and destructor</a></dt>
|
||||
|
||||
<dt><a href="#handle-spec-modifiers">Class <code>handle</code>
|
||||
modifier functions</a></dt>
|
||||
|
||||
<dt><a href="#handle-spec-observers">Class <code>handle</code>
|
||||
observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#borrowed-spec"><code>borrowed</code></a></dt>
|
||||
|
||||
<dt><a href="#allow_null-spec"><code>allow_null</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/handle.hpp></code> provides
|
||||
<code>class template handle</code>, a smart pointer for
|
||||
managing reference-counted Python objects.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="handle-spec"></a>Class template <code>handle</code></h3>
|
||||
|
||||
<p><code>handle</code> is a smart pointer to a Python object type; it
|
||||
holds a pointer of type <code>T*</code>, where T is its template
|
||||
parameter. <code>T</code> must be either a type derived from
|
||||
<code>PyObject</code> or a <a href="definitions.html#POD">POD</a> type
|
||||
whose initial <code>sizeof(PyObject)</code> bytes are layout-compatible
|
||||
with <code>PyObject</code>. Use <code>handle<></code> at the
|
||||
boundary between the Python/'C' API and high-level code; prefer <code><a
|
||||
href="object.html#object-spec">object</a></code> for a generalized
|
||||
interface to Python objects.</p>
|
||||
|
||||
<p><a name="upcast"></a>In this document, the term "upcast" refers to an
|
||||
operation which converts a pointer <code>Y*</code> to a base class
|
||||
pointer <code>T*</code> via <code>static_cast<T*></code> if
|
||||
<code>Y</code> is derived from <code>T</code>, or via C-style cast
|
||||
<code>(T*)</code> if it is not. However, in the latter case the "upcast"
|
||||
is ill-formed if the initial <code>sizeof(PyObject)</code> bytes of
|
||||
<code>Y</code> are not layout-compatible with <code>PyObject</code>.</p>
|
||||
|
||||
<h4><a name="handle-spec-synopsis"></a>Class template handle
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T>
|
||||
class handle
|
||||
{
|
||||
typedef <i>unspecified-member-function-pointer</i> bool_type;
|
||||
|
||||
public: // types
|
||||
typedef T element_type;
|
||||
|
||||
public: // member functions
|
||||
~handle();
|
||||
|
||||
template <class Y>
|
||||
explicit handle(detail::borrowed<null_ok<Y> >* p);
|
||||
|
||||
template <class Y>
|
||||
explicit handle(null_ok<detail::borrowed<Y> >* p);
|
||||
|
||||
template <class Y>
|
||||
explicit handle(detail::borrowed<Y>* p);
|
||||
|
||||
template <class Y>
|
||||
explicit handle(null_ok<Y>* p);
|
||||
|
||||
template <class Y>
|
||||
explicit handle(Y* p);
|
||||
|
||||
handle();
|
||||
|
||||
handle& operator=(handle const& r);
|
||||
|
||||
template<typename Y>
|
||||
handle& operator=(handle<Y> const & r); // never throws
|
||||
|
||||
|
||||
template <typename Y>
|
||||
handle(handle<Y> const& r);
|
||||
|
||||
handle(handle const& r);
|
||||
|
||||
T* operator-> () const;
|
||||
T& operator* () const;
|
||||
T* get() const;
|
||||
void reset();
|
||||
T* release();
|
||||
|
||||
operator bool_type() const; // never throws
|
||||
private:
|
||||
T* m_p;
|
||||
};
|
||||
|
||||
template <class T> struct null_ok;
|
||||
namespace detail { template <class T> struct borrowed; }
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="handle-spec-ctors">Class <code>handle</code> constructors
|
||||
and destructor</a></h4>
|
||||
<pre>
|
||||
virtual ~handle();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>Py_XDECREF(</code><i>upcast</i><code><PyObject*>(m_p))</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class Y>
|
||||
explicit handle(detail::borrowed<null_ok<Y> >* p);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>Py_XINCREF(</code><i>upcast</i><code><PyObject*>(p));
|
||||
m_p = </code><i>upcast</i><code><T*>(p);</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class Y>
|
||||
explicit handle(null_ok<detail::borrowed<Y> >* p);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>Py_XINCREF(</code><i>upcast</i><code><PyObject*>(p));
|
||||
m_p = </code><i>upcast</i><code><T*>(p);</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class Y>
|
||||
explicit handle(detail::borrowed<Y>* p);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>Py_XINCREF(</code><i>upcast</i><code><PyObject*>(p));
|
||||
m_p = </code><i>upcast</i><code><T*>(<a href=
|
||||
"errors.html#expect_non_null-spec">expect_non_null</a>(p));</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class Y>
|
||||
explicit handle(null_ok<Y>* p);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>m_p = </code><i>upcast</i><code><T*>(p);</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class Y>
|
||||
explicit handle(Y* p);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>m_p = </code><i>upcast</i><code><T*>(<a href=
|
||||
"errors.html#expect_non_null-spec">expect_non_null</a>(p));</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
handle();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> <code>m_p = 0;</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <typename Y>
|
||||
handle(handle<Y> const& r);
|
||||
handle(handle const& r);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>m_p = r.m_p; Py_XINCREF(</code><i>upcast</i><code><PyObject*>(m_p));</code></dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="handle-spec-modifiers">Class <code>handle</code>
|
||||
modifiers</a></h4>
|
||||
<pre>
|
||||
handle& operator=(handle const& r);
|
||||
template<typename Y>
|
||||
handle& operator=(handle<Y> const & r); // never throws
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>Py_XINCREF(</code><i>upcast</i><code><PyObject*>(r.m_p)); Py_XDECREF(</code><i>
|
||||
upcast</i><code><PyObject*>(m_p)); m_p = r.m_p;</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
T* release();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> <code>T* x = m_p; m_p = 0;return
|
||||
x;</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
void reset();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>*this = handle<T>();</code></dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="handle-spec-observers">Class <code>handle</code>
|
||||
observers</a></h4>
|
||||
<pre>
|
||||
T* operator-> () const;
|
||||
T* get() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>m_p;</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
T& operator* () const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>*m_p;</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
operator bool_type() const; // never throws
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> 0 if <code>m_p == 0</code>, a pointer
|
||||
convertible to <code>true</code> otherwise.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
|
||||
<h3><a name="borrowed-spec"></a><code>borrowed</code></h3>
|
||||
<pre>
|
||||
template <class T>
|
||||
detail::borrowed<T>* borrowed(T* p)
|
||||
{
|
||||
return (detail::borrowed<T>*)p;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3><a name="allow_null-spec"></a><code>allow_null</code></h3>
|
||||
<pre>
|
||||
template <class T>
|
||||
null_ok<T>* allow_null(T* p)
|
||||
{
|
||||
return (null_ok<T>*)p;
|
||||
}
|
||||
</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 class="c4">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||
.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/has_back_reference.hpp></title>
|
||||
|
||||
<style type="text/css">
|
||||
p.c3 {font-style: italic}
|
||||
h2.c2 {text-align: center}
|
||||
h1.c1 {text-align: center}
|
||||
</style>
|
||||
</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 class="c1"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 class="c2">Header
|
||||
<boost/python/has_back_reference.hpp></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="#has_back_reference-spec">Class template
|
||||
<code>has_back_reference</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#has_back_reference-spec-synopsis">Class template
|
||||
<code>has_back_reference</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/has_back_reference.hpp></code> defines the
|
||||
predicate metafunction <code>has_back_reference<></code>, which can
|
||||
be specialized by the user to indicate that a wrapped class instance
|
||||
holds a <code>PyObject*</code> corresponding to a Python object.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="has_back_reference-spec"></a>Class template
|
||||
<code>has_back_reference</code></h3>
|
||||
|
||||
<p>A unary metafunction whose <code>value</code> is true iff its argument
|
||||
is a <code>pointer_wrapper<></code>.</p>
|
||||
|
||||
<h4><a name="has_back_reference-spec-synopsis"></a>Class template
|
||||
<code>has_back_reference</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template<class WrappedClass> class has_back_reference
|
||||
{
|
||||
typedef mpl::false_ type;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
<p>A "<a href="../../../mpl/doc/refmanual/metafunction.html">
|
||||
metafunction</a>" that is inspected by Boost.Python to determine how
|
||||
wrapped classes can be constructed.</p>
|
||||
|
||||
<dl class="traits-semantics">
|
||||
<dt><code>type::value</code> is an integral constant convertible to bool
|
||||
of unspecified type.</dt>
|
||||
|
||||
<dt>Specializations may substitute a <code>true</code>-valued integral constant wrapper for
|
||||
<code>type</code> iff for each invocation of
|
||||
<code>class_<WrappedClass>::def(init<</code>
|
||||
<i>type-sequence...</i><code>>())</code> and the implicitly wrapped
|
||||
copy constructor (unless it is <a href="class.html#class_-spec">
|
||||
noncopyable</a>), there exists a corresponding constructor
|
||||
<code>WrappedClass::WrappedClass(PyObject*, </code>
|
||||
<i>type-sequence...</i><code>)</code>. If such a specialization exists,
|
||||
the <code>WrappedClass</code> constructors will be called with a "back
|
||||
reference" pointer to the corresponding Python object whenever they are
|
||||
invoked from Python. The easiest way to provide this nested <code>
|
||||
type
|
||||
</code>
|
||||
is to
|
||||
derive the specialization from <code>mpl::true_</code>.
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<h3>C++ module definition</h3>
|
||||
<pre>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/has_back_reference.hpp>
|
||||
#include <boost/python/handle.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
using boost::shared_ptr;
|
||||
|
||||
struct X
|
||||
{
|
||||
X(PyObject* self) : m_self(self), m_x(0) {}
|
||||
X(PyObject* self, int x) : m_self(self), m_x(x) {}
|
||||
X(PyObject* self, X const& other) : m_self(self), m_x(other.m_x) {}
|
||||
|
||||
handle<> self() { return handle<>(borrowed(m_self)); }
|
||||
int get() { return m_x; }
|
||||
void set(int x) { m_x = x; }
|
||||
|
||||
PyObject* m_self;
|
||||
int m_x;
|
||||
};
|
||||
|
||||
// specialize has_back_reference for X
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <>
|
||||
struct has_back_reference<X>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}
|
||||
|
||||
struct Y
|
||||
{
|
||||
Y() : m_x(0) {}
|
||||
Y(int x) : m_x(x) {}
|
||||
int get() { return m_x; }
|
||||
void set(int x) { m_x = x; }
|
||||
|
||||
int m_x;
|
||||
};
|
||||
|
||||
shared_ptr<Y>
|
||||
Y_self(shared_ptr<Y> self) { return self; }
|
||||
|
||||
BOOST_PYTHON_MODULE(back_references)
|
||||
{
|
||||
class_<X>("X")
|
||||
.def(init<int>())
|
||||
.def("self", &X::self)
|
||||
.def("get", &X::get)
|
||||
.def("set", &X::set)
|
||||
;
|
||||
|
||||
class_<Y, shared_ptr<Y> >("Y")
|
||||
.def(init<int>())
|
||||
.def("get", &Y::get)
|
||||
.def("set", &Y::set)
|
||||
.def("self", Y_self)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
The following Python session illustrates that <code>x.self()</code>
|
||||
returns the same Python object on which it is invoked, while
|
||||
<code>y.self()</code> must create a new Python object which refers to the
|
||||
same Y instance.
|
||||
|
||||
<h3>Python code</h3>
|
||||
<pre>
|
||||
>>> from back_references import *
|
||||
>>> x = X(1)
|
||||
>>> x2 = x.self()
|
||||
>>> x2 is x
|
||||
<b>1</b>
|
||||
>>> (x.get(), x2.get())
|
||||
(1, 1)
|
||||
>>> x.set(10)
|
||||
>>> (x.get(), x2.get())
|
||||
(10, 10)
|
||||
>>>
|
||||
>>>
|
||||
>>> y = Y(2)
|
||||
>>> y2 = y.self()
|
||||
>>> y2 is y
|
||||
<b>0</b>
|
||||
>>> (y.get(), y2.get())
|
||||
(2, 2)
|
||||
>>> y.set(20)
|
||||
>>> (y.get(), y2.get())
|
||||
(20, 20)
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
18 July, 2004
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p class="c3">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||
.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/implicit.hpp></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 <boost/python/implicit.hpp></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="#implicitly_convertible-spec">Function Template
|
||||
<code>implicitly_convertible</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
<code>implicitly_convertible</code> allows Boost.Python to implicitly
|
||||
take advantage of a C++ implicit or explicit conversion when matching
|
||||
Python objects to C++ argument types.
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
|
||||
<h3><a name="implicitly_convertible-spec"></a>Function template
|
||||
<code>implicitly_convertible</code></h3>
|
||||
<pre>
|
||||
template <class Source, class Target>
|
||||
void implicitly_convertible();
|
||||
</pre>
|
||||
|
||||
<table border="1" summary="implicitly_convertible template parameters">
|
||||
<caption>
|
||||
<b><code>implicitly_convertible</code> template parameters</b><br>
|
||||
</caption>
|
||||
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>Source</code></td>
|
||||
|
||||
<td>The source type of the implicit conversion</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>Target</code></td>
|
||||
|
||||
<td>The target type of the implicit conversion</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> The declaration <code>Target t(s);</code>, where
|
||||
<code>s</code> is of type <code>Source</code>, is valid.</dt>
|
||||
|
||||
<dt><b>Effects:</b> registers an rvalue <code>from_python</code>
|
||||
converter to <code>Target</code> which can succeed for any
|
||||
<code>PyObject* p</code> iff there exists any registered converter
|
||||
which can produce <code>Source</code> rvalues</dt>
|
||||
|
||||
<dt><b>Rationale:</b> C++ users expect to be able to take advantage of
|
||||
the same sort of interoperability in Python as they do in C++.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<h3>C++ module definition</h3>
|
||||
<pre>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct X
|
||||
{
|
||||
X(int x) : v(x) {}
|
||||
operator int() const { return v; }
|
||||
int v;
|
||||
};
|
||||
|
||||
int x_value(X const& x)
|
||||
{
|
||||
return x.v;
|
||||
}
|
||||
|
||||
X make_x(int n) { return X(n); }
|
||||
|
||||
BOOST_PYTHON_MODULE(implicit_ext)
|
||||
{
|
||||
def("x_value", x_value);
|
||||
def("make_x", make_x);
|
||||
|
||||
class_<X>("X",
|
||||
init<int>())
|
||||
;
|
||||
|
||||
implicitly_convertible<X,int>();
|
||||
implicitly_convertible<int,X>();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Python code</h3>
|
||||
<pre>
|
||||
>>> from implicit_ext import *
|
||||
>>> x_value(X(42))
|
||||
42
|
||||
>>> x_value(42)
|
||||
42
|
||||
>>> x = make_x(X(42))
|
||||
>>> x_value(x)
|
||||
42
|
||||
</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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/import.hpp></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 <boost/python/import.hpp></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="#import-spec"><code>import</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Exposes a mechanism for importing python modules.</p>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
|
||||
<h3><a name="import-spec"></a><code>import</code></h3>
|
||||
<pre>
|
||||
object import(str name);
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Imports the module named by <code>name</code>.</dt>
|
||||
<dt><b>Returns:</b> An instance of <a href="object.html#object-spec">object</a>
|
||||
which holds a reference to the imported module.</dt>
|
||||
</dl>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<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=../index.html">
|
||||
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
Loading index page; if nothing happens, please go to <a href=
|
||||
"../index.html">../index.html</a>.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,636 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st February 2003), 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>
|
||||
Indexing Support
|
||||
</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> Headers <boost/python/indexing/indexing_suite.hpp><br>
|
||||
<boost/python/indexing/vector_indexing_suite.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<h2>
|
||||
Contents
|
||||
</h2>
|
||||
<dl class="page-index">
|
||||
<dt>
|
||||
<a href="#introduction">Introduction</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="#interface">Interface</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt>
|
||||
<a href="#indexing_suite">indexing_suite</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="#indexing_suite_subclasses">indexing_suite
|
||||
sub-classes</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt>
|
||||
<a href="#vector_indexing_suite">vector_indexing_suite</a>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<a href="#indexing_suite_class">indexing_suite class</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="#vector_indexing_suite_class">vector_indexing_suite
|
||||
class</a>
|
||||
</dt>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>
|
||||
<a name="introduction" id="introduction"></a>Introduction
|
||||
</h2>
|
||||
<p>
|
||||
Indexing is a Boost Python facility for easy exportation of indexable
|
||||
C++ containers to Python. Indexable containers are containers that
|
||||
allow random access through the operator[] (e.g. std::vector).
|
||||
</p>
|
||||
<p>
|
||||
While Boost Python has all the facilities needed to expose indexable
|
||||
C++ containers such as the ubiquitous std::vector to Python, the
|
||||
procedure is not as straightforward as we'd like it to be. Python
|
||||
containers do not map easily to C++ containers. Emulating Python
|
||||
containers in C++ (see Python Reference Manual, <a href=
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html">Emulating
|
||||
container types</a>) using Boost Python is non trivial. There are a lot
|
||||
of issues to consider before we can map a C++ container to Python.
|
||||
These involve implementing wrapper functions for the methods
|
||||
<strong>__len__</strong>, <strong>__getitem__</strong>,
|
||||
<strong>__setitem__</strong>, <strong>__delitem__,</strong>
|
||||
<strong>__iter__</strong> and <strong>__contains</strong>.
|
||||
</p>
|
||||
<p>
|
||||
The goals:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<div>
|
||||
Make indexable C++ containers behave exactly as one would expect a
|
||||
Python container to behave.
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Provide default reference semantics for container element indexing
|
||||
(<tt>__getitem__</tt>) such that <tt>c[i]</tt> can be mutable.
|
||||
Require:
|
||||
<div>
|
||||
<pre>
|
||||
val = c[i]
|
||||
c[i].m()
|
||||
val == c[i]
|
||||
</pre>
|
||||
</div>where <tt>m</tt> is a non-const (mutating) member function
|
||||
(method).
|
||||
</li>
|
||||
<li>
|
||||
Return safe references from <tt>__getitem__</tt> such that subsequent
|
||||
adds and deletes to and from the container will not result in
|
||||
dangling references (will not crash Python).
|
||||
</li>
|
||||
<li>
|
||||
Support slice indexes.
|
||||
</li>
|
||||
<li>
|
||||
Accept Python container arguments (e.g. lists, tuples) wherever
|
||||
appropriate.
|
||||
</li>
|
||||
<li>
|
||||
Allow for extensibility through re-definable policy classes.
|
||||
</li>
|
||||
<li>
|
||||
Provide predefined support for the most common STL and STL like
|
||||
indexable containers.
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<h2> <a name="interface"></a>The Boost.Python Indexing Interface</h2>
|
||||
<h3> <a name="indexing_suite"></a>indexing_suite [ Header <boost/python/indexing/indexing_suite.hpp>
|
||||
]</h3>
|
||||
<p>
|
||||
The <tt>indexing_suite</tt> class is the base protocol class for the
|
||||
management of C++ containers intended to be integrated to Python. The
|
||||
objective is make a C++ container look and feel and behave exactly as
|
||||
we'd expect a Python container. The class automatically wraps these
|
||||
special Python methods (taken from the Python reference: <a href=
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html">Emulating
|
||||
container types</a>):
|
||||
</p>
|
||||
<dl>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-126"><tt class=
|
||||
"method">__len__</tt></a></b>(<var>self</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement the built-in function <tt class=
|
||||
"function">len()</tt><a name="l2h-134"> </a> Should return
|
||||
the length of the object, an integer <code>>=</code> 0. Also,
|
||||
an object that doesn't define a <tt class=
|
||||
"method">__nonzero__()</tt> method and whose <tt class=
|
||||
"method">__len__()</tt> method returns zero is considered to be
|
||||
false in a Boolean context. <a name="l2h-128"> </a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-129"><tt class=
|
||||
"method">__getitem__</tt></a></b>(<var>self, key</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement evaluation of
|
||||
<code><var>self</var>[<var>key</var>]</code>. For sequence types,
|
||||
the accepted keys should be integers and slice
|
||||
objects.<a name="l2h-135"> </a> Note that the special
|
||||
interpretation of negative indexes (if the class wishes to
|
||||
emulate a sequence type) is up to the <tt class=
|
||||
"method">__getitem__()</tt> method. If <var>key</var> is of
|
||||
an inappropriate type, <tt class="exception">TypeError</tt>
|
||||
may be raised; if of a value outside the set of indexes for
|
||||
the sequence (after any special interpretation of negative
|
||||
values), <tt class="exception">IndexError</tt> should be
|
||||
raised. <span class="note"><b class="label">Note:</b>
|
||||
<tt class="keyword">for</tt> loops expect that an <tt class=
|
||||
"exception">IndexError</tt> will be raised for illegal
|
||||
indexes to allow proper detection of the end of the
|
||||
sequence.</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-130"><tt class=
|
||||
"method">__setitem__</tt></a></b>(<var>self, key, value</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement assignment to
|
||||
<code><var>self</var>[<var>key</var>]</code>. Same note as for
|
||||
<tt class="method">__getitem__()</tt>. This should only be
|
||||
implemented for mappings if the objects support changes to the
|
||||
values for keys, or if new keys can be added, or for sequences if
|
||||
elements can be replaced. The same exceptions should be raised
|
||||
for improper <var>key</var> values as for the <tt class=
|
||||
"method">__getitem__()</tt> method.
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-131"><tt class=
|
||||
"method">__delitem__</tt></a></b>(<var>self, key</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement deletion of
|
||||
<code><var>self</var>[<var>key</var>]</code>. Same note as for
|
||||
<tt class="method">__getitem__()</tt>. This should only be
|
||||
implemented for mappings if the objects support removal of keys,
|
||||
or for sequences if elements can be removed from the sequence.
|
||||
The same exceptions should be raised for improper <var>key</var>
|
||||
values as for the <tt class="method">__getitem__()</tt> method.
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-132"><tt class=
|
||||
"method">__iter__</tt></a></b>(<var>self</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
This method is called when an iterator is required for a
|
||||
container. This method should return a new iterator object that
|
||||
can iterate over all the objects in the container. For mappings,
|
||||
it should iterate over the keys of the container, and should also
|
||||
be made available as the method <tt class=
|
||||
"method">iterkeys()</tt>.
|
||||
<p>
|
||||
Iterator objects also need to implement this method; they are
|
||||
required to return themselves. For more information on iterator
|
||||
objects, see ``<a class="ulink" href=
|
||||
"http://www.python.org/doc/current/lib/typeiter.html">Iterator
|
||||
Types</a>'' in the <em class="citetitle"><a href=
|
||||
"http://www.python.org/doc/current/lib/lib.html" title=
|
||||
"Python Library Reference">Python Library Reference</a></em>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-133"><tt class=
|
||||
"method">__contains__</tt></a></b>(<var>self, item</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement membership test operators. Should return true
|
||||
if <var>item</var> is in <var>self</var>, false otherwise. For
|
||||
mapping objects, this should consider the keys of the mapping
|
||||
rather than the values or the key-item pairs.
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3> <a name="indexing_suite_subclasses"></a>indexing_suite sub-classes</h3>
|
||||
<p>
|
||||
The <tt>indexing_suite</tt> is not meant to be used as is. A couple of
|
||||
policy functions must be supplied by subclasses of
|
||||
<tt>indexing_suite</tt>. However, a set of <tt>indexing_suite</tt>
|
||||
subclasses for the standard indexable STL containers will be provided,
|
||||
In most cases, we can simply use the available predefined suites. In
|
||||
some cases, we can refine the predefined suites to suit our needs.
|
||||
</p>
|
||||
|
||||
<h3> <a name="vector_indexing_suite"></a>vector_indexing_suite [ Header <boost/python/indexing/vector_indexing_suite.hpp>
|
||||
] </h3>
|
||||
<p>
|
||||
The <tt>vector_indexing_suite</tt> class is a predefined
|
||||
<tt>indexing_suite</tt> derived class designed to wrap
|
||||
<tt>std::vector</tt> (and <tt>std::vector</tt> like [i.e. a class with
|
||||
std::vector interface]) classes (currently, this is the only predefined
|
||||
suite available). It provides all the policies required by the
|
||||
<tt>indexing_suite</tt>.
|
||||
</p>
|
||||
<p>
|
||||
Example usage:
|
||||
</p>
|
||||
<pre>
|
||||
class X {...};
|
||||
...
|
||||
|
||||
class_<std::vector<X> >("XVec")
|
||||
.def(vector_indexing_suite<std::vector<X> >())
|
||||
;
|
||||
</pre>
|
||||
<p>
|
||||
<tt>XVec</tt> is now a full-fledged Python container (see the
|
||||
<a href="../../test/vector_indexing_suite.cpp">example in full</a>,
|
||||
along with its <a href="../../test/vector_indexing_suite.py">python
|
||||
test</a>).
|
||||
</p>
|
||||
<hr>
|
||||
<h2>
|
||||
<a name="indexing_suite_class"></a>indexing_suite class
|
||||
</h2>
|
||||
<h3>
|
||||
<br>
|
||||
<tt>indexing_suite<<br>
|
||||
class Container<br>
|
||||
, class DerivedPolicies<font color="#007F00"><br>
|
||||
</font></tt> <tt>,
|
||||
bool NoProxy<br>
|
||||
, class Element<br>
|
||||
, class Key<br>
|
||||
, class Index</tt>
|
||||
</h3>
|
||||
<table width="100%" border="1">
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Template Parameter</strong><br>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Requirements</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Semantics</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Default</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Container</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A class type
|
||||
</td>
|
||||
<td>
|
||||
The container type to be wrapped to Python.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>DerivedPolicies</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A subclass of indexing_suite
|
||||
</td>
|
||||
<td>
|
||||
Derived classes provide the policy hooks. See <a href=
|
||||
"#DerivedPolicies">DerivedPolicies</a> below.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>NoProxy</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A boolean
|
||||
</td>
|
||||
<td>
|
||||
By default indexed elements have Python reference semantics and are
|
||||
returned by proxy. This can be disabled by supplying
|
||||
<strong>true</strong> in the <tt>NoProxy</tt> template parameter.
|
||||
</td>
|
||||
<td>
|
||||
false
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Element</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
The container's element type.
|
||||
</td>
|
||||
<td>
|
||||
<tt>Container::value_type</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Key</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
The container's key type.
|
||||
</td>
|
||||
<td>
|
||||
<tt>Container::value_type</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Index</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
The container's index type.
|
||||
</td>
|
||||
<td>
|
||||
<tt>Container::size_type</tt>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre>
|
||||
template <<br> class Container
|
||||
, class DerivedPolicies
|
||||
, bool NoProxy = false
|
||||
, class Element = typename Container::value_type
|
||||
, class Key = typename Container::value_type
|
||||
, class Index = typename Container::size_type
|
||||
><br> class indexing_suite
|
||||
: unspecified
|
||||
{
|
||||
public:
|
||||
|
||||
indexing_suite(); // default constructor
|
||||
}
|
||||
</pre>
|
||||
<h2>
|
||||
<tt><a name="DerivedPolicies"></a>DerivedPolicies</tt>
|
||||
</h2>
|
||||
<dl>
|
||||
<dd>
|
||||
Derived classes provide the hooks needed by
|
||||
the<tt>indexing_suite:</tt>
|
||||
</dd>
|
||||
</dl>
|
||||
<pre>
|
||||
static element_type&
|
||||
get_item(Container& container, index_type i);
|
||||
|
||||
static object
|
||||
get_slice(Container& container, index_type from, index_type to);
|
||||
|
||||
static void
|
||||
set_item(Container& container, index_type i, element_type const& v);
|
||||
|
||||
static void
|
||||
set_slice(
|
||||
Container& container, index_type from,
|
||||
index_type to, element_type const& v
|
||||
);
|
||||
|
||||
template <class Iter>
|
||||
static void<br> set_slice(Container& container, index_type from,
|
||||
index_type to, Iter first, Iter last
|
||||
);
|
||||
|
||||
static void
|
||||
delete_item(Container& container, index_type i);
|
||||
|
||||
static void
|
||||
delete_slice(Container& container, index_type from, index_type to);
|
||||
|
||||
static size_t
|
||||
size(Container& container);
|
||||
|
||||
template <class T>
|
||||
static bool
|
||||
contains(Container& container, T const& val);
|
||||
|
||||
static index_type
|
||||
convert_index(Container& container, PyObject* i);
|
||||
|
||||
static index_type
|
||||
adjust_index(index_type current, index_type from,
|
||||
index_type to, size_type len
|
||||
);
|
||||
</pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
Most of these policies are self explanatory. <tt>However,
|
||||
<strong>convert_index</strong></tt> and
|
||||
<tt><strong>adjust_index</strong></tt> deserve some explanation.
|
||||
</p>
|
||||
<p>
|
||||
<strong><tt>convert_index</tt></strong> converts a Python index into
|
||||
a C++ index that the container can handle. For instance, negative
|
||||
indexes in Python, by convention, start counting from the right(e.g.
|
||||
<tt>C[-1]</tt> indexes the rightmost element in <tt>C</tt>).
|
||||
<strong><tt>convert_index</tt></strong> should handle the necessary
|
||||
conversion for the C++ container (e.g. convert <tt>-1</tt> to
|
||||
<tt>C.size()-1</tt>). <tt><strong>convert_index</strong></tt> should
|
||||
also be able to convert the type of the index (A dynamic Python type)
|
||||
to the actual type that the C++ container expects.
|
||||
</p>
|
||||
<p>
|
||||
When a container expands or contracts, held indexes to its elements
|
||||
must be adjusted to follow the movement of data. For instance, if we
|
||||
erase 3 elements, starting from index 0 from a 5 element vector, what
|
||||
used to be at index 4 will now be at index 1:
|
||||
</p>
|
||||
<pre>
|
||||
[a][b][c][d][e] ---> [d][e]
|
||||
^ ^
|
||||
4 1
|
||||
</pre>
|
||||
<p>
|
||||
<strong><tt>adjust_index</tt></strong> takes care of the adjustment.
|
||||
Given a current index, the function should return the adjusted index
|
||||
when data in the container at index <tt>from</tt>..<tt>to</tt> is
|
||||
replaced by <tt>len</tt> elements.
|
||||
</p>
|
||||
</blockquote>
|
||||
<div>
|
||||
<hr>
|
||||
<h2>
|
||||
<a name="vector_indexing_suite_class"></a>vector_indexing_suite class
|
||||
</h2>
|
||||
<h3>
|
||||
Class template <tt><br>
|
||||
vector_indexing_suite<<br>
|
||||
class <font color="#007F00">Container</font><br>
|
||||
, bool <font color="#007F00">NoProxy</font><br>
|
||||
, class <font color="#007F00">DerivedPolicies</font>></tt>
|
||||
</h3>
|
||||
<table width="100%" border="1">
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Template Parameter</strong><br>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Requirements</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Semantics</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Default</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Container</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A class type
|
||||
</td>
|
||||
<td>
|
||||
The container type to be wrapped to Python.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>NoProxy</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A boolean
|
||||
</td>
|
||||
<td>
|
||||
By default indexed elements have Python reference semantics and
|
||||
are returned by proxy. This can be disabled by supplying
|
||||
<strong>true</strong> in the <tt>NoProxy</tt> template parameter.
|
||||
</td>
|
||||
<td>
|
||||
false
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>DerivedPolicies</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A subclass of indexing_suite
|
||||
</td>
|
||||
<td>
|
||||
The <tt>vector_indexing_suite</tt> may still be derived to
|
||||
further tweak any of the predefined policies. Static polymorphism
|
||||
through CRTP (James Coplien. "Curiously Recurring Template
|
||||
Pattern". C++ Report, Feb. 1995) enables the base
|
||||
<tt>indexing_suite</tt> class to call policy function of the most
|
||||
derived class
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre>
|
||||
template <<br> class Container,<br> bool NoProxy = false,<br> class DerivedPolicies = unspecified_default<br> class vector_indexing_suite<br> : public indexing_suite<Container, DerivedPolicies, NoProxy><br> {<br> public:<br><br> typedef typename Container::value_type element_type;<br> typedef typename Container::value_type key_type;<br> typedef typename Container::size_type index_type;<br> typedef typename Container::size_type size_type;<br> typedef typename Container::difference_type difference_type;<br> <br> static element_type&<br> get_item(Container& container, index_type i);
|
||||
|
||||
static object
|
||||
get_slice(Container& container, index_type from, index_type to);
|
||||
|
||||
static void<br> set_item(Container& container, index_type i, element_type const& v);
|
||||
|
||||
static void
|
||||
set_slice(Container& container, index_type from,
|
||||
index_type to, element_type const& v);
|
||||
|
||||
template <class Iter><br> static void<br> set_slice(Container& container, index_type from,<br> index_type to, Iter first, Iter last);
|
||||
|
||||
static void
|
||||
delete_item(Container& container, index_type i);
|
||||
|
||||
static void
|
||||
delete_slice(Container& container, index_type from, index_type to);<br>
|
||||
static size_t
|
||||
size(Container& container);
|
||||
|
||||
static bool
|
||||
contains(Container& container, key_type const& key);
|
||||
|
||||
static index_type
|
||||
convert_index(Container& container, PyObject* i);
|
||||
|
||||
static index_type
|
||||
adjust_index(index_type current, index_type from,
|
||||
index_type to, size_type len);
|
||||
};
|
||||
</pre>
|
||||
<hr>
|
||||
© Copyright Joel de Guzman 2003. 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.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
248
doc/v2/init.html
@@ -1,248 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/init.hpp></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 <boost/python/init.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"#init-expressions"><em>init-expressions</em></a></dt>
|
||||
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#init-spec">Class template <code>init</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#init-spec-synopsis">Class template
|
||||
<code>init</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#init-spec-ctors">Class <code>init</code>
|
||||
constructors</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#optional-spec">Class template
|
||||
<code>optional</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#optional-spec-synopsis">Class template
|
||||
<code>optional</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><code><boost/python/init.hpp></code> defines the interface for
|
||||
exposing C++ constructors to Python as extension class
|
||||
<code>__init__</code> functions.</p>
|
||||
|
||||
<h2><a name="init-expressions"><em>init-expressions</em></a></h2>
|
||||
An <em>init-expression</em> is used to describe a family of
|
||||
<code>__init__</code> methods to be generated for an extension class, and
|
||||
the result has the following properties:
|
||||
|
||||
<blockquote>
|
||||
<dl class="properties">
|
||||
<dt><b>docstring:</b> An <a href="definitions.html#ntbs">ntbs</a>
|
||||
whose value will bound to the method's <code>__doc__</code>
|
||||
attribute</dt>
|
||||
|
||||
<dt><b>keywords:</b> A <a href=
|
||||
"args.html#keyword-expression">keyword-expression</a> which will be
|
||||
used to name (a trailing subsequence of) the arguments to the
|
||||
generated <code>__init__</code> function(s).</dt>
|
||||
|
||||
<dt><b>call policies:</b> An instance of a model of <a href=
|
||||
"CallPolicies.html">CallPolicies</a>.</dt>
|
||||
|
||||
<dt><b>argument types:</b> An MPL sequence of C++ argument types
|
||||
which will be used to construct the wrapped C++ object. An init
|
||||
expression has one or more
|
||||
<b>valid prefixes</b> which are given by a sequence of
|
||||
prefixes of its argument types.</dt>
|
||||
</dl>
|
||||
</blockquote>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="init-spec"></a>Class template <code>init<T1 =</code>
|
||||
<i>unspecified</i><code>, T2 =</code>
|
||||
<i>unspecified</i><code>,</code>...<code>Tn</code> =
|
||||
<i>unspecified</i><code>></code></h3>
|
||||
|
||||
<p>A <a href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a> which
|
||||
can be used to specify a family of one or more <code>__init__</code>
|
||||
functions. Only the last <code>T</code><i><small>i</small></i> supplied
|
||||
may be an instantiation of <a href=
|
||||
"#optional-spec"><code>optional</code></a><code><</code>...<code>></code>.</p>
|
||||
|
||||
<h4><a name="init-spec-synopsis"></a>Class template <code>init</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <T1 = <i>unspecified</i>,...T<i>n</i> = <i>unspecified</i>>
|
||||
struct init
|
||||
{
|
||||
init(char const* doc = 0);
|
||||
template <class Keywords> init(Keywords const& kw, char const* doc = 0);
|
||||
template <class Keywords> init(char const* doc, Keywords const& kw);
|
||||
|
||||
template <class CallPolicies>
|
||||
<em>unspecified</em> operator[](CallPolicies const& policies) const
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="init-spec-ctors"></a>Class template <code>init</code>
|
||||
constructors</h4>
|
||||
<pre>
|
||||
init(char const* doc = 0);
|
||||
template <class Keywords> init(Keywords const& kw, char const* doc = 0);
|
||||
template <class Keywords> init(char const* doc, Keywords const& kw);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> If supplied, <code>doc</code> is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>. If supplied, <code>kw</code> is the
|
||||
result of a <a href="args.html#keyword-expression"></a></dt>
|
||||
|
||||
<dt><b>Effects:</b> The result is an <em>init-expression</em> whose
|
||||
<em>docstring</em> is <code>doc</code> and whose <em>keywords</em> are
|
||||
a reference to <code>kw</code>. If the first form is used, the
|
||||
resulting expression's <em>keywords</em> are empty. The expression's
|
||||
<em>call policies</em> are an instance of <a href=
|
||||
"default_call_policies.html#default_call_policies-spec">default_call_policies</a>.
|
||||
If <code>T</code><i><small>n</small></i> is <a href=
|
||||
"#optional-spec"><code>optional</code></a><code><U1, U2,</code>...
|
||||
<code>U</code><small><i>m</i></small><code>></code>, the
|
||||
expression's <em>valid prefixes</em> are given by:</dt>
|
||||
|
||||
<dd>
|
||||
<blockquote>
|
||||
(<code>T1, T2,</code>...<code>T</code><i><small>n-1</small></i>),
|
||||
(<code>T1, T2,</code>...<code>T</code><i><small>n-1</small></i>
|
||||
<code>, U1</code>),
|
||||
(<code>T1, T2,</code>...<code>T</code><i><small>n-1</small></i>
|
||||
<code>, U1, U2</code>),
|
||||
...(<code>T1, T2,</code>...<code>T</code><i><small>n-1</small></i>
|
||||
<code>, U1, U2,</code>...<code>U</code><i><small>m</small></i>).
|
||||
</blockquote>
|
||||
Otherwise, the expression has one <em>valid prefix</em> given by the
|
||||
the template arguments the user specified.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h4><a name="init-spec-observers"></a>Class template <code>init</code>
|
||||
observer functions</h4>
|
||||
<pre>
|
||||
template <class Policies>
|
||||
<em>unspecified</em> operator[](Policies const& policies) const
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> Policies is a model of <a href=
|
||||
"CallPolicies.html">CallPolicies</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Returns a new <a href=
|
||||
"#init-expressions"><em>init-expression</em></a> with all the same
|
||||
properties as the <code>init</code> object except that its <em>call
|
||||
policies</em> are replaced by a reference to
|
||||
<code>policies</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="optional-spec"></a>Class template <code>optional<T1
|
||||
=</code> <i>unspecified</i><code>, T2 =</code>
|
||||
<i>unspecified</i><code>,</code>...<code>Tn</code> =
|
||||
<i>unspecified</i><code>></code></h3>
|
||||
|
||||
<p>A <a href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a> which
|
||||
can be used to specify the optional arguments to an <code>__init__</code>
|
||||
function.</p>
|
||||
|
||||
<h4><a name="optional-spec-synopsis"></a>Class template
|
||||
<code>optional</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <T1 = <i>unspecified</i>,...T<i>n</i> = <i>unspecified</i>>
|
||||
struct optional {};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="examples"></a>Example(s)</h2>
|
||||
|
||||
<p>Given the C++ declarations:</p>
|
||||
<pre>
|
||||
class Y;
|
||||
class X
|
||||
{
|
||||
public:
|
||||
X(int x, Y* y) : m_y(y) {}
|
||||
X(double);
|
||||
private:
|
||||
Y* m_y;
|
||||
};
|
||||
</pre>
|
||||
A corresponding Boost.Python extension class can be created with:
|
||||
<pre>
|
||||
using namespace boost::python;
|
||||
|
||||
class_<X>("X", "This is X's docstring.",
|
||||
init<int,char const*>(args("x","y"), "X.__init__'s docstring")[
|
||||
with_custodian_and_ward<1,3>()]
|
||||
)
|
||||
.def(init<double>())
|
||||
;
|
||||
</pre>
|
||||
<hr>
|
||||
Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<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 - <boost/python/instance_holder.hpp></title>
|
||||
</head>
|
||||
|
||||
<style type="text/css">
|
||||
p.c4 {font-style: italic}
|
||||
span.c3 {color: #ff0000}
|
||||
h2.c2 {text-align: center}
|
||||
h1.c1 {text-align: center}
|
||||
</style>
|
||||
|
||||
<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 valign="top">
|
||||
<h1 class="c1"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 class="c2">Header <boost/python/instance_holder.hpp></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="#instance_holder-spec">Class
|
||||
<code>instance_holder</code></a>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#instance_holder-spec-synopsis">Class
|
||||
<code>instance_holder</code> synopsis</a>
|
||||
|
||||
<dt><a href="#instance_holder-spec-ctors">Class
|
||||
<code>instance_holder</code> destructor</a>
|
||||
|
||||
<dt><a href="#instance_holder-spec-modifiers">Class
|
||||
<code>instance_holder</code> modifier functions</a>
|
||||
|
||||
<dt><a href="#instance_holder-spec-observers">Class
|
||||
<code>instance_holder</code> observer functions</a>
|
||||
</dl>
|
||||
</dl>
|
||||
|
||||
<dt><a href="#examples">Example</a>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/instance_holder.hpp></code> provides
|
||||
<code>class instance_holder</code>, the base class for types
|
||||
which hold C++ instances of wrapped classes.
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="instance_holder-spec"></a>Class <code>instance_holder</code></h3>
|
||||
|
||||
<p><code>instance_holder</code> is an abstract base class whose
|
||||
concrete derived classes hold C++ class instances within their
|
||||
Python object wrappers. To allow multiple inheritance in Python
|
||||
from C++ class wrappers, each such Python object contains a chain
|
||||
of <code>instance_holder</code>s. When an <code>__init__</code>
|
||||
function for a wrapped C++ class is invoked, a new
|
||||
<code>instance_holder</code> instance is created and installed in
|
||||
the Python object using its <code><a
|
||||
href="#instance_holder-spec-modifiers">install</a></code>()
|
||||
function. Each concrete class derived from
|
||||
<code>instance_holder</code> must provide a <code><a
|
||||
href="#instance_holder-spec-observers">holds</a>()</code>
|
||||
implementation which allows Boost.Python to query it for the
|
||||
type(s) it is holding. In order to support the held type's wrapped
|
||||
constructor(s), the class must also provide constructors that can
|
||||
accept an initial <code>PyObject*</code> argument referring to the
|
||||
owning Python object, and which forward the rest of their
|
||||
arguments to the constructor of the held type. The initial
|
||||
argument is needed to enable virtual function overriding in
|
||||
Python, and may be ignored, depending on the specific
|
||||
<code>instance_holder</code> subclass.
|
||||
|
||||
<h4><a name="instance_holder-spec-synopsis"></a>Class instance_holder
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
class instance_holder : <a href="../../../utility/utility.htm#Class_noncopyable">noncopyable</a>
|
||||
{
|
||||
public:
|
||||
// destructor
|
||||
virtual ~instance_holder();
|
||||
|
||||
// instance_holder modifiers
|
||||
void install(PyObject* inst) throw();
|
||||
|
||||
// instance_holder observers
|
||||
virtual void* holds(type_info) = 0;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="instance_holder-spec-ctors">Class <code>instance_holder</code>
|
||||
destructor</a></h4>
|
||||
<pre>
|
||||
virtual ~instance_holder();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> destroys the object
|
||||
</dl>
|
||||
|
||||
<h4><a name="instance_holder-spec-modifiers">Class
|
||||
<code>instance_holder</code> modifiers</a></h4>
|
||||
<pre>
|
||||
void install(PyObject* inst) throw();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>inst</code> is a Python instance of a
|
||||
wrapped C++ class type, or is a type derived from a wrapped C++
|
||||
class type.
|
||||
<dt><b>Effects:</b> installs the new instance at the head of the
|
||||
Python object's chain of held instances.
|
||||
<dt><b>Throws:</b> nothing
|
||||
</dl>
|
||||
|
||||
<h4><a name="instance_holder-spec-observers">Class <code>instance_holder</code>
|
||||
observers</a></h4>
|
||||
<pre>
|
||||
virtual void* holds(type_info x) = 0;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> A pointer to an object of the type described
|
||||
by <code>x</code> if <code>*this</code> contains such an object,
|
||||
0 otherwise.
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
The following is a simplified version of the instance holder template
|
||||
used by Boost.Python to wrap classes held by smart pointers:
|
||||
<pre>
|
||||
template <class SmartPtr, class Value>
|
||||
struct pointer_holder : instance_holder
|
||||
{
|
||||
// construct from the SmartPtr type
|
||||
pointer_holder(SmartPtr p)
|
||||
:m_p(p)
|
||||
|
||||
// Forwarding constructors for the held type
|
||||
pointer_holder(PyObject*)
|
||||
:m_p(new Value())
|
||||
{
|
||||
}
|
||||
|
||||
template<class A0>
|
||||
pointer_holder(PyObject*,A0 a0)
|
||||
:m_p(new Value(a0))
|
||||
{
|
||||
}
|
||||
|
||||
template<class A0,class A1>
|
||||
pointer_holder(PyObject*,A0 a0,A1 a1)
|
||||
:m_p(new Value(a0,a1))
|
||||
{
|
||||
}
|
||||
...
|
||||
|
||||
private: // required holder implementation
|
||||
void* holds(type_info dst_t)
|
||||
{
|
||||
// holds an instance of the SmartPtr type...
|
||||
if (dst_t == python::type_id<SmartPtr>())
|
||||
return &this->m_p;
|
||||
|
||||
// ...and an instance of the SmartPtr's element_type, if the
|
||||
// pointer is non-null
|
||||
return python::type_id<Value>() == dst_t ? &*this->m_p : 0;
|
||||
}
|
||||
|
||||
private: // data members
|
||||
SmartPtr m_p;
|
||||
};
|
||||
</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 class="c4">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,395 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/iterator.hpp></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 <boost/python/iterator.hpp></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="#iterator-spec">Class template
|
||||
<code>iterator</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#iterator-spec-synopsis">Class
|
||||
<code>iterator</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#iterator-spec-constructors">Class template
|
||||
<code>iterator</code> constructor</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#iterators-spec">Class template
|
||||
<code>iterators</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#iterators-spec-synopsis">Class
|
||||
<code>iterators</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#iterators-spec-types">Class template
|
||||
<code>iterators</code> nested types</a></dt>
|
||||
|
||||
<dt><a href="#iterators-spec-statics">Class template
|
||||
<code>iterators</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#range-spec">range</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Examples</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/iterator.hpp></code> provides types and
|
||||
functions for creating <a href=
|
||||
"http://www.python.org/doc/current/lib/typeiter.html">Python
|
||||
iterators</a> from <a href=
|
||||
"http://www.sgi.com/tech/stl/Container.html">C++ Containers</a> and <a
|
||||
href="http://www.sgi.com/tech/stl/Iterators.html">Iterators</a>. Note
|
||||
that if your <code>class_</code> supports random-access iterators,
|
||||
implementing <code><a href=
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html#l2h-128">__getitem__</a></code>
|
||||
(also known as the Sequence Protocol) may serve you better than using
|
||||
this facility: Python will automatically create an iterator type for you
|
||||
(see <a href=
|
||||
"http://www.python.org/doc/current/lib/built-in-funcs.html#l2h-35">iter()</a>),
|
||||
and each access can be range-checked, leaving no possiblity of accessing
|
||||
through an invalidated C++ iterator.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="iterator-spec"></a>Class Template <code>iterator</code></h3>
|
||||
|
||||
<p>Instances of <code>iterator<C,P></code> hold a reference to a
|
||||
callable Python object which, when invoked from Python, expects a single
|
||||
argument <code>c</code> convertible to <code>C</code> and creates a
|
||||
Python iterator that traverses [<code>c.begin()</code>,
|
||||
<code>c.end()</code>). The optional <a href=
|
||||
"CallPolicies.html">CallPolicies</a> <code>P</code> can be used to
|
||||
control how elements are returned during iteration.</p>
|
||||
|
||||
<p>In the table below, <code><b>c</b></code> is an instance of
|
||||
<code>Container</code>.</p>
|
||||
|
||||
<table border="1" summary="iterator template parameters">
|
||||
<tr>
|
||||
<th>Template Parameter</th>
|
||||
|
||||
<th>Requirements</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>Container</code></td>
|
||||
|
||||
<td>[c.begin(),c.end()) is a valid <a href=
|
||||
"http://www.sgi.com/tech/stl/Iterators.html">Iterator range</a>.</td>
|
||||
|
||||
<td>The result will convert its argument to <code>c</code> and call
|
||||
<code>c.begin()</code> and <code>c.end()</code> to acquire iterators.
|
||||
To invoke <code>Container</code>'s <code>const</code>
|
||||
<code>begin()</code> and <code>end()</code> functions, make it
|
||||
<code>const</code>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>NextPolicies</code></td>
|
||||
|
||||
<td>A default-constructible model of <a href=
|
||||
"CallPolicies.html#CallPolicies-concept">CallPolicies</a>.</td>
|
||||
|
||||
<td>Applied to the resulting iterators' <code>next()</code>
|
||||
method.</td>
|
||||
|
||||
<td>An unspecified model of <a href=
|
||||
"CallPolicies.html#CallPolicies-concept">CallPolicies</a> which
|
||||
always makes a copy of the result of deferencing the underlying C++
|
||||
iterator</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="iterator-spec-synopsis"></a>Class Template iterator
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class Container
|
||||
, class NextPolicies = <i>unspecified</i>>
|
||||
struct iterator : <a href="object.html#object-spec">object</a>
|
||||
{
|
||||
iterator();
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="iterator-spec-constructors"></a>Class Template iterator
|
||||
constructor</h4>
|
||||
<pre>
|
||||
iterator()
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b></dt>
|
||||
|
||||
<dd>
|
||||
Initializes its base class with the result of:
|
||||
<pre>
|
||||
range<NextPolicies>(&iterators<Container>::begin, &iterators<Container>::end)
|
||||
</pre>
|
||||
</dd>
|
||||
|
||||
<dt><b>Postconditions:</b> <code>this->get()</code> points to a
|
||||
Python callable object which creates a Python iterator as described
|
||||
above.</dt>
|
||||
|
||||
<dt><b>Rationale:</b> Provides an easy way to create iterators for the
|
||||
common case where a C++ class being wrapped provides
|
||||
<code>begin()</code> and <code>end()</code>.</dt>
|
||||
</dl>
|
||||
<!-- -->
|
||||
|
||||
<h3><a name="iterators-spec"></a>Class Template
|
||||
<code>iterators</code></h3>
|
||||
|
||||
<p>A utility class template which provides a way to reliably call its
|
||||
argument's <code>begin()</code> and <code>end()</code> member functions.
|
||||
Note that there is no portable way to take the address of a member
|
||||
function of a C++ standard library container, so
|
||||
<code>iterators<></code> can be particularly helpful when wrapping
|
||||
them.</p>
|
||||
|
||||
<p>In the table below, <code><b>x</b></code> is an instance of
|
||||
<code>C</code>.</p>
|
||||
|
||||
<table border="1" summary="iterator template parameters">
|
||||
<tr>
|
||||
<th>Required Valid Expression</th>
|
||||
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>x.begin()</code></td>
|
||||
|
||||
<td>Convertible to <code>C::const_iterator</code> if <code>C</code>
|
||||
is a <code>const</code> type; convertible to <code>C::iterator</code>
|
||||
otherwise.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>x.end()</code></td>
|
||||
|
||||
<td>Convertible to <code>C::const_iterator</code> if <code>C</code>
|
||||
is a <code>const</code> type; convertible to <code>C::iterator</code>
|
||||
otherwise.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="iterators-spec-synopsis"></a>Class Template iterators
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class C>
|
||||
struct iterators
|
||||
{
|
||||
typedef typename C::[const_]iterator iterator;
|
||||
static iterator begin(C& x);
|
||||
static iterator end(C& x);
|
||||
};
|
||||
}}
|
||||
|
||||
</pre>
|
||||
|
||||
<h4><a name="iterators-spec-types"></a>Class Template iterators nested
|
||||
types</h4>
|
||||
If C is a <code>const</code> type,
|
||||
<pre>
|
||||
typedef typename C::const_iterator iterator;
|
||||
</pre>
|
||||
Otherwise:
|
||||
<pre>
|
||||
typedef typename C::iterator iterator;
|
||||
</pre>
|
||||
|
||||
<h4><a name="iterators-spec-statics"></a>Class Template iterators static
|
||||
functions</h4>
|
||||
<pre>
|
||||
static iterator begin(C&);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>x.begin()</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
static iterator end(C&);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>x.end()</code></dt>
|
||||
</dl>
|
||||
<!-- -->
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<pre>
|
||||
<a name=
|
||||
"range-spec">template</a> <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> range(Accessor1 start, Accessor2 finish);
|
||||
|
||||
template <class NextPolicies, class Accessor1, class Accessor2>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> range(Accessor1 start, Accessor2 finish);
|
||||
|
||||
template <class Accessor1, class Accessor2>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> range(Accessor1 start, Accessor2 finish);
|
||||
</pre>
|
||||
|
||||
<dl class="range-semantics">
|
||||
<dt><b>Requires:</b> <code>NextPolicies</code> is a
|
||||
default-constructible model of <a href=
|
||||
"CallPolicies.html#CallPolicies-concept">CallPolicies</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b></dt>
|
||||
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>The first form creates a Python callable object which, when
|
||||
invoked, converts its argument to a <code>Target</code> object
|
||||
<code>x</code>, and creates a Python iterator which traverses
|
||||
[<code><a href=
|
||||
"../../../bind/bind.html">bind</a>(start,_1)(x)</code>, <code><a
|
||||
href="../../../bind/bind.html">bind</a>(finish,_1)(x)</code>),
|
||||
applying <code>NextPolicies</code> to the iterator's
|
||||
<code>next()</code> function.</dt>
|
||||
|
||||
<dt>The second form is identical to the first, except that
|
||||
<code>Target</code> is deduced from <code>Accessor1</code> as
|
||||
follows:</dt>
|
||||
|
||||
<dd>
|
||||
<ol>
|
||||
<li>If <code>Accessor1</code> is a function type,
|
||||
<code>Target</code> is the type of its first argument.</li>
|
||||
|
||||
<li>If <code>Accessor1</code> is a data member pointer of the
|
||||
form <code>R (T::*)</code>, <code>Target</code> is
|
||||
identical to <code>T</code>.</li>
|
||||
|
||||
<li>If <code>Accessor1</code> is a member function pointer of
|
||||
the form
|
||||
<code>R (T::*)(</code><i>arguments...</i><code>)</code>
|
||||
<i>cv-opt</i>, where <i>cv-opt</i> is an optional
|
||||
<code>cv-qualifier</code>, <code>Target</code> is identical to
|
||||
<code>T</code>.</li>
|
||||
</ol>
|
||||
</dd>
|
||||
|
||||
<dt>The third form is identical to the second, except that
|
||||
<code>NextPolicies</code> is an unspecified model of <a href=
|
||||
"CallPolicies.html#CallPolicies-concept">CallPolicies</a> which
|
||||
always makes a copy of the result of deferencing the underlying C++
|
||||
iterator</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><b>Rationale:</b> The use of <code><a href=
|
||||
"../../../bind/bind.html">boost::bind</a>()</code> allows C++ iterators
|
||||
to be accessed through functions, member functions or data member
|
||||
pointers. Customization of <code>NextPolicies</code> (e.g. using
|
||||
<code><a href=
|
||||
"return_internal_reference.html#return_internal_reference-spec">return_internal_reference</a></code>)
|
||||
is useful when it is expensive to copy sequence elements of a wrapped
|
||||
class type. Customization of <code>Target</code> is useful when
|
||||
<code>Accessor1</code> is a function object, or when a base class of
|
||||
the intended target type would otherwise be deduced.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Examples</h2>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::python;
|
||||
BOOST_PYTHON_MODULE(demo)
|
||||
{
|
||||
class_<std::vector<double> >("dvec")
|
||||
.def("__iter__", iterator<std::vector<double> >())
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
A more comprehensive example can be found in:
|
||||
|
||||
<dl>
|
||||
<dt><code><a href=
|
||||
"../../test/iterator.cpp">libs/python/test/iterator.cpp</a></code></dt>
|
||||
|
||||
<dt><code><a href=
|
||||
"../../test/input_iterator.cpp">libs/python/test/input_iterator.cpp</a></code></dt>
|
||||
|
||||
<dt><code><a href=
|
||||
"../../test/iterator.py">libs/python/test/input_iterator.py</a></code></dt>
|
||||
|
||||
</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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
139
doc/v2/list.html
@@ -1,139 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/list.hpp></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 <boost/python/list.hpp></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="#list-spec">Class <code>list</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#list-spec-synopsis">Class <code>list</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/doc/current/lib/typesseq-mutable.html">list</a>
|
||||
type.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="list-spec"></a>Class <code>list</code></h3>
|
||||
|
||||
<p>Exposes the <a href=
|
||||
"http://www.python.org/doc/current/lib/typesseq-mutable.html">mapping
|
||||
protocol</a> of Python's built-in <code>list</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>list</code> is publicly derived from <code><a
|
||||
href="object.html#object-spec">object</a></code>, the public object
|
||||
interface applies to <code>list</code> instances as well.</p>
|
||||
|
||||
<h4><a name="list-spec-synopsis"></a>Class <code>list</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
class list : public object
|
||||
{
|
||||
public:
|
||||
list(); // new list
|
||||
|
||||
template <class T>
|
||||
explicit list(T const& sequence);
|
||||
|
||||
template <class T>
|
||||
void append(T const& x);
|
||||
|
||||
template <class T>
|
||||
long count(T const& value) const;
|
||||
|
||||
template <class T>
|
||||
void extend(T const& x);
|
||||
|
||||
template <class T>
|
||||
long index(T const& x) const;
|
||||
|
||||
template <class T>
|
||||
void insert(object const& index, T const& x); // insert object before index
|
||||
|
||||
object pop(); // remove and return item at index (default last)
|
||||
object pop(long index);
|
||||
object pop(object const& index);
|
||||
|
||||
template <class T>
|
||||
void remove(T const& value);
|
||||
|
||||
void reverse(); // reverse *IN PLACE*
|
||||
|
||||
void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
|
||||
|
||||
template <class T>
|
||||
void sort(T const& value);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
<pre>
|
||||
using namespace boost::python;
|
||||
|
||||
// Return the number of zeroes in the list
|
||||
long zeroes(list l)
|
||||
{
|
||||
return l.count(0);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised 1 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
116
doc/v2/long.html
@@ -1,116 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/long.hpp></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 <boost/python/long.hpp></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="#long_-spec">Class <code>long_</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#long_-spec-synopsis">Class <code>long_</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/doc/current/lib/typesnumeric.html">long</a>
|
||||
integer type.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="long_-spec"></a>Class <code>long_</code></h3>
|
||||
|
||||
<p>Exposes the <a href=
|
||||
"http://www.python.org/doc/current/lib/typesnumeric.html">numeric type
|
||||
protocol</a> of Python's built-in <code>long</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>long_</code> is publicly derived from <code><a
|
||||
href="object.html#object-spec">object</a></code>, the public object
|
||||
interface applies to <code>long_</code> instances as well.</p>
|
||||
|
||||
<h4><a name="long_-spec-synopsis"></a>Class <code>long_</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
class long_ : public object
|
||||
{
|
||||
public:
|
||||
long_(); // new long_
|
||||
|
||||
template <class T>
|
||||
explicit long_(T const& rhs);
|
||||
|
||||
template <class T, class U>
|
||||
long_(T const& rhs, U const& base);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
<pre>
|
||||
namespace python = boost::python;
|
||||
|
||||
// compute a factorial without overflowing
|
||||
python::long_ fact(long n)
|
||||
{
|
||||
if (n == 0)
|
||||
return python::long_(1);
|
||||
else
|
||||
return n * fact(n - 1);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised 1 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,298 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/lvalue_from_python.hpp></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
|
||||
<boost/python/lvalue_from_pytype.hpp></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="#lvalue_from_pytype-spec">Class Template
|
||||
<code>lvalue_from_pytype</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#lvalue_from_pytype-spec-synopsis">Class Template
|
||||
<code>lvalue_from_pytype</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#lvalue_from_pytype-spec-ctors">Class Template
|
||||
<code>lvalue_from_pytype</code> constructor</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#extract_identity-spec">Class Template
|
||||
<code>extract_identity</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#extract_identity-spec-synopsis">Class Template
|
||||
<code>extract_identity</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#extract_identity-spec-statics">Class Template
|
||||
<code>extract_identity</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#extract_member-spec">Class Template
|
||||
<code>extract_member</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#extract_member-spec-synopsis">Class Template
|
||||
<code>extract_member</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#extract_member-spec-statics">Class Template
|
||||
<code>extract_member</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
<code><boost/python/lvalue_from_pytype.hpp></code> supplies a
|
||||
facility for extracting C++ objects from within Python instances of a
|
||||
given type. This is typically useful for dealing with "traditional"
|
||||
Python extension types.
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="lvalue_from_pytype-spec"></a>Class template
|
||||
<code>lvalue_from_pytype</code></h3>
|
||||
|
||||
<p>Class template <code>lvalue_from_pytype</code> will register
|
||||
from_python converters which, given an object of the given Python type,
|
||||
can extract references and pointers to a particular C++ type. Its
|
||||
template arguments are:</p>
|
||||
|
||||
<table border="1" summary="lvalue_from_pytype template parameters">
|
||||
<caption>
|
||||
<b><code>lvalue_from_pytype</code> Requirements</b><br>
|
||||
In the table below, <b><code>x</code></b> denotes an object of type
|
||||
<code>PythonObject&</code>
|
||||
</caption>
|
||||
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
|
||||
<th>Requirements</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>Extractor</code></td>
|
||||
|
||||
<td>a model of <a href=
|
||||
"Extractor.html#Extractor-concept">Extractor</a> whose execute
|
||||
function returns a reference type.</td>
|
||||
|
||||
<td>Extracts the lvalue from the Python object once its type has been
|
||||
confirmed</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>python_type</code></td>
|
||||
|
||||
<td>A compile-time constant <code><a href=
|
||||
"http://www.python.org/doc/2.2/ext/dnt-type-methods.html">PyTypeObject</a>*</code></td>
|
||||
|
||||
<td>The Python type of instances convertible by this converter.
|
||||
Python subtypes are also convertible.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="lvalue_from_pytype-spec-synopsis"></a>Class template
|
||||
<code>lvalue_from_pytype</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class Extractor, PyTypeObject const* python_type>
|
||||
struct lvalue_from_pytype
|
||||
{
|
||||
lvalue_from_pytype();
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="lvalue_from_pytype-spec-ctors"></a>Class template
|
||||
<code>lvalue_from_pytype</code> constructor</h4>
|
||||
<pre>
|
||||
lvalue_from_pytype();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Registers converters which can convert Python
|
||||
objects of the given type to lvalues of the type returned by
|
||||
<code>Extractor::execute</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="extract_identity-spec"></a>Class template
|
||||
<code>extract_identity</code></h3>
|
||||
|
||||
<p><code>extract_identity</code> is a model of <a href=
|
||||
"Extractor.html#Extractor-concept">Extractor</a> which can be used in the
|
||||
common case where the C++ type to be extracted is the same as the Python
|
||||
object type.</p>
|
||||
|
||||
<h4><a name="extract_identity-spec-synopsis"></a>Class template
|
||||
<code>extract_identity</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class InstanceType>
|
||||
struct extract_identity
|
||||
{
|
||||
static InstanceType& execute(InstanceType& c);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="extract_identity-spec-statics"></a>Class template
|
||||
<code>extract_identity</code> static functions</h4>
|
||||
<pre>
|
||||
InstanceType& execute(InstanceType& c);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>c</code></dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="extract_member-spec"></a>Class template
|
||||
<code>extract_member</code></h3>
|
||||
|
||||
<p><code>extract_member</code> is a model of <a href=
|
||||
"Extractor.html#Extractor-concept">Extractor</a> which can be used in the
|
||||
common case in the common case where the C++ type to be extracted is a
|
||||
member of the Python object.</p>
|
||||
|
||||
<h4><a name="extract_member-spec-synopsis"></a>Class template
|
||||
<code>extract_member</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
|
||||
struct extract_member
|
||||
{
|
||||
static MemberType& execute(InstanceType& c);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="extract_member-spec-statics"></a>Class template
|
||||
<code>extract_member</code> static functions</h4>
|
||||
<pre>
|
||||
static MemberType& execute(InstanceType& c);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>c.*member</code></dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
This example presumes that someone has implemented the standard <a href=
|
||||
"http://www.python.org/doc/2.2/ext/dnt-basics.html">noddy example
|
||||
module</a> from the Python documentation, and we want to build a module
|
||||
which manipulates <code>Noddy</code>s. Since
|
||||
<code>noddy_NoddyObject</code> is so simple that it carries no
|
||||
interesting information, the example is a bit contrived: it assumes you
|
||||
want to keep track of one particular object for some reason. This module
|
||||
would have to be dynamically linked to the module which defines
|
||||
<code>noddy_NoddyType</code>.
|
||||
|
||||
<h3>C++ module definition</h3>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/handle.hpp>
|
||||
#include <boost/python/borrowed.hpp>
|
||||
#include <boost/python/lvalue_from_pytype.hpp>
|
||||
|
||||
// definition lifted from the Python docs
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
} noddy_NoddyObject;
|
||||
|
||||
using namespace boost::python;
|
||||
static handle<noddy_NoddyObject> cache;
|
||||
|
||||
bool is_cached(noddy_NoddyObject* x)
|
||||
{
|
||||
return x == cache.get();
|
||||
}
|
||||
|
||||
void set_cache(noddy_NoddyObject* x)
|
||||
{
|
||||
cache = handle<noddy_NoddyObject>(borrowed(x));
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(noddy_cache)
|
||||
{
|
||||
def("is_cached", is_cached);
|
||||
def("set_cache", set_cache);
|
||||
|
||||
// register Noddy lvalue converter
|
||||
lvalue_from_pytype<extract_identity<noddy_NoddyObject>,&noddy_NoddyType>();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Python code</h3>
|
||||
<pre>
|
||||
>>> import noddy
|
||||
>>> n = noddy.new_noddy()
|
||||
>>> import noddy_cache
|
||||
>>> noddy_cache.is_cached(n)
|
||||
0
|
||||
>>> noddy_cache.set_cache(n)
|
||||
>>> noddy_cache.is_cached(n)
|
||||
1
|
||||
>>> noddy_cache.is_cached(noddy.new_noddy())
|
||||
0
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
20 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/make_function.hpp></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
|
||||
<boost/python/make_function.hpp></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_function-spec">make_function</a></dt>
|
||||
|
||||
<dt><a href="#make_constructor-spec">make_constructor</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_function-spec">make_function</a>()</code> and
|
||||
<code><a href="#make_constructor-spec">make_constructor</a>()</code> are
|
||||
the functions used internally by <code><a href=
|
||||
"def.html#def-spec">def</a>()</code> and <code>class_<>::<a href=
|
||||
"class.html#class_-spec-modifiers">def</a>()</code> to produce Python
|
||||
callable objects which wrap C++ functions and member functions.</p>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<pre>
|
||||
<a name="make_function-spec">template <class F></a>
|
||||
<a href="object.html#object-spec">object</a> make_function(F f)
|
||||
|
||||
template <class F, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies)
|
||||
|
||||
template <class F, class Policies, class KeywordsOrSignature>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, KeywordsOrSignature const& ks)
|
||||
|
||||
template <class F, class Policies, class Keywords, class Signature>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>F</code> is a function pointer or member
|
||||
function pointer type. If <code>policies</code> are supplied, it must
|
||||
be a model of <a href="CallPolicies.html">CallPolicies</a>. If
|
||||
<code>kewords</code> are supplied, it must be 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>f</code>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Creates a Python callable object which, when called
|
||||
from Python, converts its arguments to C++ and calls <code>f</code>. If
|
||||
<code>F</code> is a pointer-to-member-function type, the target
|
||||
object of the function call (<code>*this</code>) will be taken
|
||||
from the first Python argument, and subsequent Python arguments
|
||||
will be used as the arguments
|
||||
to <code>f</code>. <ul>
|
||||
<li> If <code>policies</code> are supplied, it
|
||||
will be applied to the function as described <a href=
|
||||
"CallPolicies.html">here</a>.
|
||||
<li>If <code>keywords</code> are
|
||||
supplied, the keywords will be applied in order to the final
|
||||
arguments of the resulting function.
|
||||
<li>If <code>Signature</code>
|
||||
is supplied, it should be an instance of an <a
|
||||
href="../../../mpl/doc/refmanual/front-extensible-sequence.html">MPL front-extensible
|
||||
sequence</a> representing the function's return type followed by
|
||||
its argument types. Pass a <code>Signature</code> when wrapping
|
||||
function object types whose signatures can't be deduced, or when
|
||||
you wish to override the types which will be passed to the
|
||||
wrapped function.
|
||||
</ul></dt>
|
||||
|
||||
<dt><b>Returns:</b> An instance of <a href=
|
||||
"object.html#object-spec">object</a> which holds the new Python
|
||||
callable object.</dt>
|
||||
|
||||
<dt><b>Caveats:</b> An argument of pointer type may
|
||||
be <code>0</code> if <code>None</code> is passed from Python.
|
||||
An argument type which is a constant reference may refer to a
|
||||
temporary which was created from the Python object for just the
|
||||
duration of the call to the wrapped function, for example
|
||||
a <code>std::vector</code> conjured up by the conversion process
|
||||
from a Python list. Use a non-<code>const</code> reference
|
||||
argument when a persistent lvalue is required.
|
||||
</dl>
|
||||
|
||||
<pre>
|
||||
<a name=
|
||||
"make_constructor-spec"></a>template <class T, class ArgList, class Generator>
|
||||
<a href="object.html#object-spec">object</a> make_constructor();
|
||||
|
||||
template <class ArgList, class Generator, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_constructor(Policies const& policies)
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>T</code> is a class type.
|
||||
<code>Policies</code> is a model of <a href=
|
||||
"CallPolicies.html">CallPolicies</a>. <code>ArgList</code> is an <a
|
||||
href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a> of C++ argument
|
||||
types (<i>A1, A2,... AN</i>) such that if
|
||||
<code>a1, a2</code>... <code>aN</code> are objects of type
|
||||
<i>A1, A2,... AN</i> respectively, the expression <code>new
|
||||
Generator::apply<T>::type(a1, a2</code>... <code>aN</code>)
|
||||
is valid. Generator is a model of <a href=
|
||||
"HolderGenerator.html">HolderGenerator</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Creates a Python callable object which, when called
|
||||
from Python, expects its first argument to be a Boost.Python extension
|
||||
class object. It converts its remaining its arguments to C++ and passes
|
||||
them to the constructor of a dynamically-allocated
|
||||
<code>Generator::apply<T>::type</code> object, which is then
|
||||
installed in the extension class object. In the second form, the
|
||||
<code>policies</code> are applied to the arguments and result (<a href=
|
||||
"http://www.python.org/doc/current/lib/bltin-null-object.html">None</a>)
|
||||
of the Python callable object</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>C++ function exposed below returns a callable object wrapping one of
|
||||
two functions.</p>
|
||||
<pre>
|
||||
#include <boost/python/make_function.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
|
||||
char const* foo() { return "foo"; }
|
||||
char const* bar() { return "bar"; }
|
||||
|
||||
using namespace boost::python;
|
||||
object choose_function(bool selector)
|
||||
{
|
||||
if (selector)
|
||||
return boost::python::make_function(foo);
|
||||
else
|
||||
return boost::python::make_function(bar);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(make_function_test)
|
||||
{
|
||||
def("choose_function", choose_function);
|
||||
}
|
||||
</pre>
|
||||
It can be used this way in Python:
|
||||
<pre>
|
||||
>>> from make_function_test import *
|
||||
>>> f = choose_function(1)
|
||||
>>> g = choose_function(0)
|
||||
>>> f()
|
||||
'foo'
|
||||
>>> g()
|
||||
'bar'
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<!--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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/manage_new_object.hpp></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
|
||||
<boost/python/manage_new_object.hpp></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="#manage_new_object-spec">Class
|
||||
<code>manage_new_object</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#manage_new_object-spec-synopsis">Class
|
||||
<code>manage_new_object</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#manage_new_object-spec-metafunctions">Class
|
||||
<code>manage_new_object</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="manage_new_object-spec"></a>Class
|
||||
<code>manage_new_object</code></h3>
|
||||
|
||||
<p><code>manage_new_object</code> is a model of <a href=
|
||||
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>
|
||||
which can be used to wrap C++ functions which return a pointer to an
|
||||
object allocated with a <i>new-expression</i>, and expect the caller to
|
||||
take responsibility for deleting that object.</p>
|
||||
|
||||
<h4><a name="manage_new_object-spec-synopsis"></a>Class
|
||||
<code>manage_new_object</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
struct manage_new_object
|
||||
{
|
||||
template <class T> struct apply;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="manage_new_object-spec-metafunctions"></a>Class
|
||||
<code>manage_new_object</code> metafunctions</h4>
|
||||
<pre>
|
||||
template <class T> struct apply
|
||||
</pre>
|
||||
|
||||
<dl class="metafunction-semantics">
|
||||
<dt><b>Requires:</b> <code>T</code> is <code>U*</code> for some
|
||||
<code>U</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> <code>typedef <a href=
|
||||
"to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a><T>
|
||||
type;</code></dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<p>In C++:</p>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/manage_new_object.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
|
||||
|
||||
struct Foo {
|
||||
Foo(int x) : x(x){}
|
||||
int get_x() { return x; }
|
||||
int x;
|
||||
};
|
||||
|
||||
Foo* make_foo(int x) { return new Foo(x); }
|
||||
|
||||
// Wrapper code
|
||||
using namespace boost::python;
|
||||
BOOST_PYTHON_MODULE(my_module)
|
||||
{
|
||||
def("make_foo", make_foo, return_value_policy<manage_new_object>())
|
||||
class_<Foo>("Foo")
|
||||
.def("get_x", &Foo::get_x)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
In Python:
|
||||
<pre>
|
||||
>>> from my_module import *
|
||||
>>> f = make_foo(3) # create a Foo object
|
||||
>>> f.get_x()
|
||||
3
|
||||
</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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,108 +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 - <boost/python/module.hpp></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 <boost/python/module.hpp></h2>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a>
|
||||
|
||||
<dt><a href="#macros">Macros</a>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href=
|
||||
"#BOOST_PYTHON_MODULE-spec">BOOST_PYTHON_MODULE</a>
|
||||
</dl>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>This header provides the basic facilities needed to create a
|
||||
Boost.Python extension module.
|
||||
|
||||
<h2><a name="macros"></a>Macros</h2>
|
||||
|
||||
<p><a name=
|
||||
"BOOST_PYTHON_MODULE-spec"><code>BOOST_PYTHON_MODULE(name)</code></a>
|
||||
is used to declare Python <a href=
|
||||
"http://www.python.org/doc/2.2/ext/methodTable.html#SECTION003400000000000000000">
|
||||
module initialization functions</a>. The <code>name</code> argument must
|
||||
exactly match the name of the module to be initialized, and must conform to
|
||||
Python's <a href=
|
||||
"http://www.python.org/doc/2.2/ref/identifiers.html">identifier naming
|
||||
rules</a>. Where you would normally write
|
||||
<pre>
|
||||
extern "C" void init<i>name</i>()
|
||||
{
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
Boost.Python modules should be initialized with
|
||||
<pre>
|
||||
BOOST_PYTHON_MODULE(<i>name</i>)
|
||||
{
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
This macro generates two functions in the scope where it is used:
|
||||
<code>extern "C" void init<i>name</i>()</code>,
|
||||
and <code>void init_module_<i>name</i>()</code>, whose body must
|
||||
follow the macro invocation. <code>init_<i>name</i></code> passes
|
||||
<code>init_module_<i>name</i></code> to <code><a
|
||||
href="errors.html#handle_exception-spec">handle_exception</a>()</code> so
|
||||
that any C++ exceptions generated are safely processeed. During the
|
||||
body of <code>init_<i>name</i></code>, the current <code><a
|
||||
href="scope.html#scope-spec">scope</a></code> refers to the module
|
||||
being initialized.
|
||||
|
||||
<h2><a name="examples"></a>Example(s)</h2>
|
||||
|
||||
<p>C++ module definition:
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
|
||||
BOOST_PYTHON_MODULE(xxx)
|
||||
{
|
||||
throw "something bad happened"
|
||||
}
|
||||
</pre>
|
||||
|
||||
Interactive Python:
|
||||
<pre>
|
||||
>>> import xxx
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
RuntimeError: Unidentifiable C++ Exception
|
||||
</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><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
@@ -1,267 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/numeric.hpp></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 <boost/python/numeric.hpp></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="#array-spec">Class <code>array</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#array-spec-synopsis">Class <code>array</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#array-spec-observers">Class <code>array</code>
|
||||
observer functions</a></dt>
|
||||
|
||||
<dt><a href="#array-spec-statics">Class <code>array</code>
|
||||
static functions</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">array</a>
|
||||
type.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="array-spec"></a>Class <code>array</code></h3>
|
||||
|
||||
<p>Provides access to the array types of <a href=
|
||||
"http://www.pfdubois.com/numpy/">Numerical Python</a>'s <a href=
|
||||
"http://www.pfdubois.com/numpy/#Numeric">Numeric</a> and <a href=
|
||||
"http://stsdas.stsci.edu/numarray/index.html">NumArray</a> modules. With
|
||||
the exception of the functions documented <a href=
|
||||
"#array-spec-observers">below</a>, 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>array</code> is publicly derived from <code><a
|
||||
href="object.html#object-spec">object</a></code>, the public object
|
||||
interface applies to <code>array</code> instances as well.</p>
|
||||
|
||||
<p><a name="default_search"></a>The default behavior is to use
|
||||
<code>numarray.NDArray</code> as the associated Python type if the
|
||||
<code>numarray</code> module is installed in the default location.
|
||||
Otherwise it falls back to use <code>Numeric.ArrayType</code>. If neither
|
||||
extension module is installed, conversions to arguments of type
|
||||
<code>numeric::array</code> will cause overload resolution to reject the
|
||||
overload, and other attempted uses of <code>numeric::array</code> will <a
|
||||
href="definitions.html#raise">raise</a> an appropriate Python exception.
|
||||
The associated Python type can be set manually using the <code><a href=
|
||||
"#array-spec-statics">set_module_and_type</a>(...)</code> static
|
||||
function.</p>
|
||||
|
||||
<h4><a name="array-spec-synopsis"></a>Class <code>array</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace numeric
|
||||
{
|
||||
class array : public object
|
||||
{
|
||||
public:
|
||||
object astype();
|
||||
template <class Type>
|
||||
object astype(Type const& type_);
|
||||
|
||||
template <class Type>
|
||||
object new_(Type const& type_) const;
|
||||
|
||||
template <class Sequence>
|
||||
void resize(Sequence const& x);
|
||||
void resize(long x1);
|
||||
void resize(long x1, long x2);
|
||||
...
|
||||
void resize(long x1, long x2,...long x<i>n</i>);
|
||||
|
||||
template <class Sequence>
|
||||
void setshape(Sequence const& x);
|
||||
void setshape(long x1);
|
||||
void setshape(long x1, long x2);
|
||||
...
|
||||
void setshape(long x1, long x2,...long x<i>n</i>);
|
||||
|
||||
template <class Indices, class Values>
|
||||
void put(Indices const& indices, Values const& values);
|
||||
|
||||
template <class Sequence>
|
||||
object take(Sequence const& sequence, long axis = 0);
|
||||
|
||||
template <class File>
|
||||
void tofile(File const& f) const;
|
||||
|
||||
object factory();
|
||||
template <class Buffer>
|
||||
object factory(Buffer const&);
|
||||
template <class Buffer, class Type>
|
||||
object factory(Buffer const&, Type const&);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy, bool savespace, char typecode);
|
||||
|
||||
template <class T1>
|
||||
explicit array(T1 const& x1);
|
||||
template <class T1, class T2>
|
||||
explicit array(T1 const& x1, T2 const& x2);
|
||||
...
|
||||
template <class T1, class T2,...class T<i>n</i>>
|
||||
explicit array(T1 const& x1, T2 const& x2,...T<i>n</i> const& xn);
|
||||
|
||||
static void set_module_and_type();
|
||||
static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
|
||||
|
||||
object argmax(long axis=-1);
|
||||
|
||||
object argmin(long axis=-1);
|
||||
|
||||
object argsort(long axis=-1);
|
||||
|
||||
void byteswap();
|
||||
|
||||
object copy() const;
|
||||
|
||||
object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const;
|
||||
|
||||
void info() const;
|
||||
|
||||
bool is_c_array() const;
|
||||
bool isbyteswapped() const;
|
||||
void sort();
|
||||
object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
|
||||
object type() const;
|
||||
char typecode() const;
|
||||
|
||||
object getflat() const;
|
||||
long getrank() const;
|
||||
object getshape() const;
|
||||
bool isaligned() const;
|
||||
bool iscontiguous() const;
|
||||
long itemsize() const;
|
||||
long nelements() const;
|
||||
object nonzero() const;
|
||||
|
||||
void ravel();
|
||||
|
||||
object repeat(object const& repeats, long axis=0);
|
||||
|
||||
void setflat(object const& flat);
|
||||
|
||||
void swapaxes(long axis1, long axis2);
|
||||
|
||||
str tostring() const;
|
||||
|
||||
void transpose(object const& axes = object());
|
||||
|
||||
object view() const;
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="array-spec-observers"></a>Class <code>array</code> observer
|
||||
functions</h4>
|
||||
<pre>
|
||||
object factory();
|
||||
template <class Buffer>
|
||||
object factory(Buffer const&);
|
||||
template <class Buffer, class Type>
|
||||
object factory(Buffer const&, Type const&);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy, bool savespace, char typecode);
|
||||
</pre>
|
||||
These functions map to the underlying array type's <code>array()</code>
|
||||
function family. They are not called "<code>array</code>" because of the
|
||||
C++ limitation that you can't define a member function with the same name
|
||||
as its enclosing class.
|
||||
<pre>
|
||||
template <class Type>
|
||||
object new_(Type const&) const;
|
||||
</pre>
|
||||
This function maps to the underlying array type's <code>new()</code>
|
||||
function. It is not called "<code>new</code>" because that is a keyword
|
||||
in C++.
|
||||
|
||||
<h4><a name="array-spec-statics"></a>Class <code>array</code> static
|
||||
functions</h4>
|
||||
<pre>
|
||||
static void set_module_and_type(char const* package_path, char const* type_name);
|
||||
static void set_module_and_type();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>package_path</code> and
|
||||
<code>type_name</code>, if supplied, is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> The first form sets the package path of the module
|
||||
which supplies the type named by <code>type_name</code> to
|
||||
<code>package_path</code>. The second form restores the <a href=
|
||||
"#default_search">default search behavior</a>. The associated Python
|
||||
type will be searched for only the first time it is needed, and
|
||||
thereafter the first time it is needed after an invocation of
|
||||
<code>set_module_and_type</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
<pre>
|
||||
#include <boost/python/numeric.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
|
||||
// sets the first element in a 2d numeric array
|
||||
void set_first_element(numeric::array& y, double value)
|
||||
{
|
||||
y[make_tuple(0,0)] = value;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised 03 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,933 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/object.hpp></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 <boost/python/object.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#types">Types</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#slice_nil-spec">slice_nil</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#const_attribute_policies-spec">Class
|
||||
<code>const_attribute_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#const_attribute_policies-spec-synopsis">Class
|
||||
<code>const_attribute_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#const_attribute_policies-spec-statics">Class
|
||||
<code>const_attribute_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#attribute_policies-spec">Class
|
||||
<code>attribute_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#attribute_policies-spec-synopsis">Class
|
||||
<code>attribute_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#attribute_policies-spec-statics">Class
|
||||
<code>attribute_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#const_item_policies-spec">Class
|
||||
<code>const_item_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#const_item_policies-spec-synopsis">Class
|
||||
<code>const_item_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#const_item_policies-spec-statics">Class
|
||||
<code>const_item_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#item_policies-spec">Class
|
||||
<code>item_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#item_policies-spec-synopsis">Class
|
||||
<code>item_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#item_policies-spec-statics">Class
|
||||
<code>item_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#const_slice_policies-spec">Class
|
||||
<code>const_slice_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#const_slice_policies-spec-synopsis">Class
|
||||
<code>const_slice_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#const_slice_policies-spec-statics">Class
|
||||
<code>const_slice_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#slice_policies-spec">Class
|
||||
<code>slice_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#slice_policies-spec-synopsis">Class
|
||||
<code>slice_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#slice_policies-spec-statics">Class
|
||||
<code>slice_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#object_operators-spec">Class
|
||||
<code>object_operators</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#object_operators-spec-synopsis">Class
|
||||
<code>object_operators</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#object_operators-spec-observers">Class
|
||||
<code>object_operators</code> observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#object-spec">Class <code>object</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#object-spec-synopsis">Class <code>object</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#object-spec-ctors">Class <code>object</code>
|
||||
constructors and destructor</a></dt>
|
||||
|
||||
<dt><a href="#object-spec-modifiers">Class template
|
||||
<code>object</code> modifier functions</a></dt>
|
||||
|
||||
<dt><a href="#object-spec-observers">Class template
|
||||
<code>object</code> observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#proxy-spec">Class template
|
||||
<code>proxy</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#proxy-spec-synopsis">Class template
|
||||
<code>proxy</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#proxy-spec-modifiers">Class template
|
||||
<code>proxy</code> modifier functions</a></dt>
|
||||
|
||||
<dt><a href="#proxy-spec-observers">Class template
|
||||
<code>proxy</code> observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#del-spec">del</a></dt>
|
||||
|
||||
<dt><a href="#comparisons-spec">comparisons</a></dt>
|
||||
|
||||
<dt><a href="#binary-spec">binary operations</a></dt>
|
||||
|
||||
<dt><a href="#assignment-spec">assignment operations</a></dt>
|
||||
</dl>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#object_operators-spec">operators</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Exposes the generic Python object wrapper class <code>object</code>,
|
||||
and related classes. In order to avoid some potenential problems with
|
||||
argument-dependent lookup and the generalized operators defined on
|
||||
<code>object</code>, all these facilities are defined in
|
||||
<code>namespace boost::python::api</code>, and <code>object</code>
|
||||
is imported into <code>namespace boost::python</code> with a
|
||||
<i>using-declaration</i>.</p>
|
||||
|
||||
<h2><a name="types"></a>Types</h2>
|
||||
|
||||
<p><a name="slice_nil-spec"></a></p>
|
||||
<pre>
|
||||
class slice_nil;
|
||||
static const _ = slice_nil();
|
||||
</pre>
|
||||
A type that can be used to get the effect of leaving out an index in a
|
||||
Python slice expression:
|
||||
<pre>
|
||||
>>> x[:-1]
|
||||
>>> x[::-1]
|
||||
</pre>
|
||||
C++ equivalent:
|
||||
<pre>
|
||||
x.slice(_,-1)
|
||||
x[slice(_,_,-1)]
|
||||
</pre>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
<!-- begin -->
|
||||
|
||||
<h3><a name="const_attribute_policies-spec"></a>Class
|
||||
<code>const_attribute_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an attribute
|
||||
access to a <code>const object</code>.</p>
|
||||
|
||||
<h4><a name="const_attribute_policies-spec-synopsis"></a>Class
|
||||
<code>const_attribute_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct const_attribute_policies
|
||||
{
|
||||
typedef char const* key_type;
|
||||
static object get(object const& target, char const* key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="const_attribute_policies-spec-statics"></a>Class
|
||||
<code>const_attribute_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object get(object const& target, char const* key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>key</code> is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> accesses the attribute of <code>target</code> named
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> An <code>object</code> managing the result of the
|
||||
attribute access.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="attribute_policies-spec"></a>Class
|
||||
<code>attribute_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an attribute
|
||||
access to a mutable <code>object</code>.</p>
|
||||
|
||||
<h4><a name="attribute_policies-spec-synopsis"></a>Class
|
||||
<code>attribute_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct attribute_policies : const_attribute_policies
|
||||
{
|
||||
static object const& set(object const& target, char const* key, object const& value);
|
||||
static void del(object const&target, char const* key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="attribute_policies-spec-statics"></a>Class
|
||||
<code>attribute_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object const& set(object const& target, char const* key, object const& value);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>key</code> is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> sets the attribute of <code>target</code> named by
|
||||
<code>key</code> to <code>value</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
static void del(object const&target, char const* key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>key</code> is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> deletes the attribute of <code>target</code> named
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<!-- end -->
|
||||
<!-- begin -->
|
||||
|
||||
<h3><a name="const_item_policies-spec"></a>Class
|
||||
<code>const_item_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an item access
|
||||
(via the Python bracket operators <code>[]</code>) to a
|
||||
<code>const object</code>.</p>
|
||||
|
||||
<h4><a name="const_item_policies-spec-synopsis"></a>Class
|
||||
<code>const_item_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct const_item_policies
|
||||
{
|
||||
typedef object key_type;
|
||||
static object get(object const& target, object const& key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="const_item_policies-spec-statics"></a>Class
|
||||
<code>const_item_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object get(object const& target, object const& key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> accesses the item of <code>target</code> specified
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> An <code>object</code> managing the result of the
|
||||
item access.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="item_policies-spec"></a>Class
|
||||
<code>item_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an item access
|
||||
(via the Python bracket operators <code>[]</code>) to a mutable
|
||||
<code>object</code>.</p>
|
||||
|
||||
<h4><a name="item_policies-spec-synopsis"></a>Class
|
||||
<code>item_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct item_policies : const_item_policies
|
||||
{
|
||||
static object const& set(object const& target, object const& key, object const& value);
|
||||
static void del(object const& target, object const& key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="item_policies-spec-statics"></a>Class
|
||||
<code>item_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object const& set(object const& target, object const& key, object const& value);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> sets the item of <code>target</code> specified by
|
||||
<code>key</code> to <code>value</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
static void del(object const& target, object const& key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> deletes the item of <code>target</code> specified
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<!-- end -->
|
||||
<!-- begin -->
|
||||
|
||||
<h3><a name="const_slice_policies-spec"></a>Class
|
||||
<code>const_slice_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an slice access
|
||||
(via the Python slice notation
|
||||
<code>[</code><i>x</i><code>:</code><i>y</i><code>]</code>) to a
|
||||
<code>const object</code>.</p>
|
||||
|
||||
<h4><a name="const_slice_policies-spec-synopsis"></a>Class
|
||||
<code>const_slice_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct const_slice_policies
|
||||
{
|
||||
typedef std::pair<handle<>, handle<> > key_type;
|
||||
static object get(object const& target, key_type const& key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="const_slice_policies-spec-statics"></a>Class
|
||||
<code>const_slice_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object get(object const& target, key_type const& key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> accesses the slice of <code>target</code> specified
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> An <code>object</code> managing the result of the
|
||||
slice access.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="slice_policies-spec"></a>Class
|
||||
<code>slice_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an slice access
|
||||
to a mutable <code>object</code>.</p>
|
||||
|
||||
<h4><a name="slice_policies-spec-synopsis"></a>Class
|
||||
<code>slice_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct slice_policies : const_slice_policies
|
||||
{
|
||||
static object const& set(object const& target, key_type const& key, object const& value);
|
||||
static void del(object const& target, key_type const& key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="slice_policies-spec-statics"></a>Class
|
||||
<code>slice_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object const& set(object const& target, key_type const& key, object const& value);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> sets the slice of <code>target</code> specified by
|
||||
<code>key</code> to <code>value</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
static void del(object const& target, key_type const& key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> deletes the slice of <code>target</code> specified
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<!-- end -->
|
||||
|
||||
<h3><a name="object_operators-spec"></a>Class template
|
||||
<code>object_operators<U></code></h3>
|
||||
|
||||
<p>This is the base class of <code>object</code> and its
|
||||
<code>proxy</code> template used to supply common interface: member
|
||||
functions, and operators which must be defined within the class body. Its
|
||||
template parameter <code>U</code> is expected to be a class derived from
|
||||
<code>object_operators<U></code>. In practice users should never
|
||||
use this class directly, but it is documented here because it supplies
|
||||
important interface to <code>object</code> and its proxies.</p>
|
||||
|
||||
<h4><a name="object_operators-spec-synopsis"></a>Class template
|
||||
<code>object_operators</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
template <class U>
|
||||
class object_operators
|
||||
{
|
||||
public:
|
||||
// function call
|
||||
//
|
||||
object operator()() const;
|
||||
|
||||
template <class A0>
|
||||
object operator()(A0 const&) const;
|
||||
template <class A0, class A1>
|
||||
object operator()(A0 const&, A1 const&) const;
|
||||
...
|
||||
template <class A0, class A1,...class An>
|
||||
object operator()(A0 const&, A1 const&,...An const&) const;
|
||||
|
||||
// truth value testing
|
||||
//
|
||||
typedef unspecified bool_type;
|
||||
operator bool_type() const;
|
||||
|
||||
// Attribute access
|
||||
//
|
||||
proxy<const_object_attribute> attr(char const*) const;
|
||||
proxy<object_attribute> attr(char const*);
|
||||
|
||||
// item access
|
||||
//
|
||||
template <class T>
|
||||
proxy<const_object_item> operator[](T const& key) const;
|
||||
|
||||
template <class T>
|
||||
proxy<object_item> operator[](T const& key);
|
||||
|
||||
// slicing
|
||||
//
|
||||
template <class T, class V>
|
||||
proxy<const_object_slice> slice(T const& start, V const& end) const
|
||||
|
||||
template <class T, class V>
|
||||
proxy<object_slice> slice(T const& start, V const& end);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="object_operators-spec-observers"></a>Class template
|
||||
<code>object_operators</code> observer functions</h4>
|
||||
<pre>
|
||||
object operator()() const;
|
||||
template <class A0>
|
||||
object operator()(A0 const&) const;
|
||||
template <class A0, class A1>
|
||||
object operator()(A0 const&, A1 const&) const;
|
||||
...
|
||||
template <class A0, class A1,...class An>
|
||||
object operator()(A0 const& a1, A1 const& a2,...An const& aN) const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
call<object>(object(*static_cast<U*>(this)).ptr(), a1,
|
||||
a2,...aN)</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
operator bool_type() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Tests truth value of <code>*this</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b>
|
||||
call<object>(object(*static_cast<U*>(this)).ptr(), a1,
|
||||
a2,...aN)</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
proxy<const_object_attribute> attr(char const* name) const;
|
||||
proxy<object_attribute> attr(char const* name);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> name is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> accesses the named attribute of
|
||||
<code>*this</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> a proxy object which binds
|
||||
<code>object(*static_cast<U*>(this))</code> as its target, and
|
||||
<code>name</code> as its key.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class T>
|
||||
proxy<const_object_item> operator[](T const& key) const;
|
||||
template <class T>
|
||||
proxy<object_item> operator[](T const& key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> accesses the item of <code>*this</code> indicated
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> a proxy object which binds
|
||||
<code>object(*static_cast<U*>(this))</code> as its target, and
|
||||
<code>object(key)</code> as its key.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class T, class V>
|
||||
proxy<const_object_slice> slice(T const& start; start, V const& finish) const
|
||||
template <class T, class V>
|
||||
proxy<object_slice> slice(T const& start; start, V const& finish);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> accesses the slice of <code>*this</code> indicated
|
||||
by <code>std::make_pair(object(start), object(finish))</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> a proxy object which binds
|
||||
<code>object(*static_cast<U*>(this))</code> as its target, and
|
||||
<code>std::make_pair(object(start), object(finish))</code> as its
|
||||
key.</dt>
|
||||
</dl>
|
||||
<!-- -->
|
||||
|
||||
<h3><a name="object-spec"></a>Class <code>object</code></h3>
|
||||
|
||||
<p>The intention is that <code>object</code> acts as much like a
|
||||
Python variable as possible. Thus expressions you'd expect to work
|
||||
in Python should generally work in the same way from C++. Most of
|
||||
<code>object</code>'s interface is provided by its base class
|
||||
<code><a
|
||||
href="#object_operators-spec">object_operators</a><object></code>,
|
||||
and the <a href="#functions">free functions</a> defined in this
|
||||
header.
|
||||
</p>
|
||||
|
||||
<h4><a name="object-spec-synopsis"></a>Class <code>object</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
class object : public object_operators<object>
|
||||
{
|
||||
public:
|
||||
object();
|
||||
|
||||
object(object const&);
|
||||
|
||||
template <class T>
|
||||
explicit object(T const& x);
|
||||
|
||||
~object();
|
||||
|
||||
object& operator=(object const&);
|
||||
|
||||
PyObject* ptr() const;
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="object-spec-ctors"></a>Class <code>object</code>
|
||||
constructors and destructor</h4>
|
||||
<pre>
|
||||
object();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Constructs an object managing a reference to the
|
||||
Python <code>None</code> object.</dt>
|
||||
|
||||
<dt><b>Throws:</b> nothing.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class T>
|
||||
explicit object(T const& x);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> converts <code>x</code> to python and manages a
|
||||
reference to it.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code>error_already_set</code> and sets a Python
|
||||
<code>TypeError</code> exception if no such conversion is
|
||||
possible.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
~object();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> decrements the reference count of the
|
||||
internally-held object.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="object-spec-modifiers"></a>Class <code>object</code>
|
||||
modifiers</h4>
|
||||
<pre>
|
||||
object& operator=(object const& rhs);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> increments the reference count of the object held
|
||||
by <code>rhs</code> and decrements the reference count of the object
|
||||
held by <code>*this</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="object-spec-observers"></a>Class <code>object</code>
|
||||
observers</h4>
|
||||
<pre>
|
||||
PyObject* ptr() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> a pointer to the internally-held Python
|
||||
object.</dt>
|
||||
</dl>
|
||||
<!-- -->
|
||||
|
||||
<h3><a name="proxy-spec"></a>Class template <code>proxy</code></h3>
|
||||
|
||||
<p>This template is instantiated with various Policies described in this
|
||||
document in order to implement attribute, item, and slice access for
|
||||
<code>object</code>. It stores an object of type
|
||||
<code>Policies::key_type</code>.</p>
|
||||
|
||||
<h4><a name="proxy-spec-synopsis"></a>Class template <code>proxy</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
template <class Policies>
|
||||
class proxy : public object_operators<proxy<Policies> >
|
||||
{
|
||||
public:
|
||||
operator object() const;
|
||||
|
||||
proxy const& operator=(proxy const&) const;
|
||||
template <class T>
|
||||
inline proxy const& operator=(T const& rhs) const;
|
||||
|
||||
void del() const;
|
||||
|
||||
template <class R>
|
||||
proxy operator+=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator-=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator*=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator/=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator%=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator<<=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator>>=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator&=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator|=(R const& rhs);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="proxy-spec-observers"></a>Class template <code>proxy</code>
|
||||
observer functions</h4>
|
||||
<pre>
|
||||
operator object() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> applies
|
||||
<code>Policies::get(</code><i>target</i><code>,</code> <i>key</i>
|
||||
<code>)</code> with the proxy's target and key objects.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="proxy-spec-modifiers"></a>Class template <code>proxy</code>
|
||||
modifier functions</h4>
|
||||
<pre>
|
||||
proxy const& operator=(proxy const& rhs) const;
|
||||
template <class T>
|
||||
inline proxy const& operator=(T const& rhs) const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>Policies::set(</code><i>target</i><code>,</code> <i>key</i>
|
||||
<code>, object(rhs))</code> with the proxy's target and key
|
||||
objects.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class R>
|
||||
proxy operator+=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator-=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator*=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator/=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator%=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator<<=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator>>=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator&=(R const& rhs);
|
||||
template <class R>
|
||||
proxy operator|=(R const& rhs);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> for a given operator@=,
|
||||
<code>object(*this) @= rhs;</code></dt>
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
void del() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<code>Policies::del(</code><i>target</i><code>,</code> <i>key</i>
|
||||
<code>)</code> with the proxy's target and key objects.</dt>
|
||||
</dl>
|
||||
<!-- -->
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<pre>
|
||||
<a name="del-spec"></a>template <class T>
|
||||
void del(proxy<T> const& x);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> x.del()</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
<a name="comparisons-spec"></a>
|
||||
template<class L,class R> bool operator>(L const&l,R const&r);
|
||||
template<class L,class R> bool operator>=(L const&l,R const&r);
|
||||
template<class L,class R> bool operator<(L const&l,R const&r);
|
||||
template<class L,class R> bool operator<=(L const&l,R const&r);
|
||||
template<class L,class R> bool operator==(L const&l,R const&r);
|
||||
template<class L,class R> bool operator!=(L const&l,R const&r);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> returns the result of applying the operator to
|
||||
<code>object(l)</code> and <code>object(r)</code>, respectively, in
|
||||
Python.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
<a name="binary-spec"></a>
|
||||
template<class L,class R> object operator+(L const&l,R const&r);
|
||||
template<class L,class R> object operator-(L const&l,R const&r);
|
||||
template<class L,class R> object operator*(L const&l,R const&r);
|
||||
template<class L,class R> object operator/(L const&l,R const&r);
|
||||
template<class L,class R> object operator%(L const&l,R const&r);
|
||||
template<class L,class R> object operator<<(L const&l,R const&r);
|
||||
template<class L,class R> object operator>>(L const&l,R const&r);
|
||||
template<class L,class R> object operator&(L const&l,R const&r);
|
||||
template<class L,class R> object operator^(L const&l,R const&r);
|
||||
template<class L,class R> object operator|(L const&l,R const&r);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> returns the result of applying the operator to
|
||||
<code>object(l)</code> and <code>object(r)</code>, respectively, in
|
||||
Python.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
<a name="assignment-spec"></a>
|
||||
template<class R> object& operator+=(object&l,R const&r);
|
||||
template<class R> object& operator-=(object&l,R const&r);
|
||||
template<class R> object& operator*=(object&l,R const&r);
|
||||
template<class R> object& operator/=(object&l,R const&r);
|
||||
template<class R> object& operator%=(object&l,R const&r);
|
||||
template<class R> object& operator<<=(object&l,R const&r)
|
||||
template<class R> object& operator>>=(object&l,R const&r);
|
||||
template<class R> object& operator&=(object&l,R const&r);
|
||||
template<class R> object& operator^=(object&l,R const&r);
|
||||
template<class R> object& operator|=(object&l,R const&r);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> assigns to l the result of applying the
|
||||
corresponding Python inplace operator to <code>l</code> and
|
||||
<code>object(r)</code>, respectively.</dt>
|
||||
|
||||
<dt><b>Returns:</b> <code>l</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
Python code:
|
||||
<pre>
|
||||
def sum_items(seq):
|
||||
result = 0
|
||||
for x in seq:
|
||||
result += x
|
||||
return result
|
||||
</pre>
|
||||
C++ version:
|
||||
<pre>
|
||||
object sum_items(object seq)
|
||||
{
|
||||
object result = object(0);
|
||||
for (int i = 0; i < seq.attr("__len__")(); ++i)
|
||||
result += seq[i];
|
||||
return result;
|
||||
}
|
||||
</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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/opaque_pointer_converter.hpp></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
|
||||
<boost/python/opaque_pointer_converter.hpp></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="#opaque_pointer_converter-spec">Class template
|
||||
<code>opaque_pointer_converter<P></code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque_pointer_converter-spec-synopsis">Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">Macro
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
|
||||
<dt><a href="#see-also">See Also</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="opaque_pointer_converter-spec"></a>Class template
|
||||
<code>opaque_pointer_converter<P></code></h3>
|
||||
|
||||
<p><code>opaque_pointer_converter<></code> is derived from
|
||||
<a href="to_python_converter.html#to_python_converter-spec">
|
||||
<code>to_python_converter</code></a>
|
||||
and registers itself as an
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into pointers to undefined types.
|
||||
Thus it may be used as a converter from opaque pointers into
|
||||
Python objects and vice versa.</p>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-synopsis"></a>Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template<class Pointer>
|
||||
struct opaque_pointer_converter
|
||||
: to_python_converter<
|
||||
Pointer, opaque_pointer_converter<Pointer> >
|
||||
{
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-constructor"></a>Class template
|
||||
<code>opaque_pointer_converter</code> constructor</h4>
|
||||
<pre>
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<p>Registers the instance as a
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into opaque pointers.</p>
|
||||
<p>The name is used for the type of the Python Objects created;
|
||||
it should be printable but needn't be an
|
||||
<a href="definitions.html#ntbs">ntbs</a> because the object type is
|
||||
not supposed to be user constructible within python scripts.</p>
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="macros"></a>Macros</h2>
|
||||
|
||||
<h3><a name="BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec"></a>
|
||||
Macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)</h3>
|
||||
<p>This macro must be used to define specializations of the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
which can't be instantiated for incomplete types.</p>
|
||||
<h4>Note</h4>
|
||||
<p>In order for this to work in a cross-module environment the macro must
|
||||
be invoked in every translation unit which uses the
|
||||
opaque_pointer_converter.</p>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
please see example for <a href="return_opaque_pointer.html#examples">
|
||||
return_opaque_pointer</a>.
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="return_opaque_pointer.html">return_opaque_pointer</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
10 March, 2003
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright 2003 Haufe Mediengruppe. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,906 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/operators.hpp></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 <boost/python/operators.hpp></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="#self_t-spec">Class
|
||||
<code>self_ns::self_t</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#self_t-spec-synopsis">Class <code>self_t</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#self_t-spec-inplace">Class <code>self_t</code>
|
||||
inplace operators</a></dt>
|
||||
|
||||
<dt><a href="#self_t-spec-comparisons">Class
|
||||
<code>self_t</code> comparison functions</a></dt>
|
||||
|
||||
<dt><a href="#self_t-spec-ops">Class <code>self_t</code>
|
||||
non-member operations</a></dt>
|
||||
|
||||
<dt><a href="#self_t-spec-value-unary-ops">Class
|
||||
<code>self_t</code> unary operations</a></dt>
|
||||
|
||||
<dt><a href="#self_t-spec-value-ops">Class
|
||||
<code>self_t</code> value operations</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#other-spec">Class template
|
||||
<code>other</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#other-spec-synopsis">Class <code>other</code>
|
||||
synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#operator_-spec">Class template
|
||||
<code>operator_</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#operator_-spec-synopsis">Class
|
||||
<code>operator_</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#objects">Objects</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#self-spec">self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Examples</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><boost/python/operators.hpp></code> provides types and
|
||||
functions for automatically generating Python <a href=
|
||||
"http://www.python.org/doc/ref/specialnames.html">special methods</a>
|
||||
from the corresponding C++ constructs. Most of these constructs are
|
||||
operator expressions, hence the name. To use the facility, substitute the
|
||||
<code><a href="#self-spec">self</a></code> object for an object of the
|
||||
class type being wrapped in the expression to be exposed, and pass the
|
||||
result to <a href=
|
||||
"class.html#class_-spec-modifiers">class_<>::def()</a>. Much of
|
||||
what is exposed in this header should be considered part of the
|
||||
implementation, so is not documented in detail here.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="self_t-spec"></a>Class <code>self_ns::self_t</code></h3>
|
||||
|
||||
<p><code>self_ns::self_t</code> is the actual type of the <a href=
|
||||
"#self-spec"><code>self</code></a> object. The library isolates
|
||||
<code>self_t</code> in its own namespace, <code>self_ns</code>, in order
|
||||
to prevent the generalized operator templates which operate on it from
|
||||
being found by argument-dependent lookup in other contexts. This should
|
||||
be considered an implementation detail, since users should never have to
|
||||
mention <code>self_t</code> directly.</p>
|
||||
|
||||
<h4><a name="self_t-spec-synopsis"></a>Class <code>self_ns::self_t</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace self_ns {
|
||||
{
|
||||
<i>unspecified-type-declaration</i> self_t;
|
||||
|
||||
// inplace operators
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator+=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator-=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator*=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator/=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator%=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator>>=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator<<=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator&=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator^=(self_t, T);
|
||||
template <class T> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator|=(self_t, T);
|
||||
|
||||
// comparisons
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator==(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator!=(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator<(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator>(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator<=(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator>=(L const&, R const&);
|
||||
|
||||
// non-member operations
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator+(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator-(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator*(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator/(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator%(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator>>(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator<<(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator&(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator^(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator|(L const&, R const&);
|
||||
template <class L, class R> <a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> pow(L const&, R const&);
|
||||
|
||||
// unary operations
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator-(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator+(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator~(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator!(self_t);
|
||||
|
||||
// value operations
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> int_(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> long_(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> float_(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> complex_(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> str(self_t);
|
||||
|
||||
}}};
|
||||
</pre>
|
||||
The tables below describe the methods generated when the results of the
|
||||
expressions described are passed as arguments to <a href=
|
||||
"class.html#class_-spec-modifiers">class_<>::def()</a>.
|
||||
<code><b>x</b></code> is an object of the class type being wrapped.
|
||||
|
||||
<h4><a name="self_t-spec-inplace"></a>Class <code>self_t</code> inplace
|
||||
operators</h4>
|
||||
In the table below, If <code><b>r</b></code> is an object of type
|
||||
<code><a href="#other-spec">other</a><T></code>,
|
||||
<code><b>y</b></code> is an object of type <code>T</code>; otherwise,
|
||||
<code><b>y</b></code> is an object of the same type as
|
||||
<code><b>r</b></code>.
|
||||
|
||||
<table border="1" summary="self_t inplace operators">
|
||||
<tr>
|
||||
<th>C++ Expression</th>
|
||||
|
||||
<th>Python Method Name</th>
|
||||
|
||||
<th>C++ Implementation</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self += r</code></td>
|
||||
|
||||
<td><code>__iadd__</code></td>
|
||||
|
||||
<td><code>x += y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self -= r</code></td>
|
||||
|
||||
<td><code>__isub__</code></td>
|
||||
|
||||
<td><code>x -= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self *= r</code></td>
|
||||
|
||||
<td><code>__imul__</code></td>
|
||||
|
||||
<td><code>x *= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self /= r</code></td>
|
||||
|
||||
<td><code>__idiv__</code></td>
|
||||
|
||||
<td><code>x /= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self %= r</code></td>
|
||||
|
||||
<td><code>__imod__</code></td>
|
||||
|
||||
<td><code>x %= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self >>= r</code></td>
|
||||
|
||||
<td><code>__irshift__</code></td>
|
||||
|
||||
<td><code>x >>= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self <<= r</code></td>
|
||||
|
||||
<td><code>__ilshift__</code></td>
|
||||
|
||||
<td><code>x <<= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self &= r</code></td>
|
||||
|
||||
<td><code>__iand__</code></td>
|
||||
|
||||
<td><code>x &= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self ^= r</code></td>
|
||||
|
||||
<td><code>__ixor__</code></td>
|
||||
|
||||
<td><code>x ^= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self |= r</code></td>
|
||||
|
||||
<td><code>__ior__</code></td>
|
||||
|
||||
<td><code>x |= y</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="self_t-spec-comparisons"></a>Class <code>self_t</code>
|
||||
comparison functions</h4>
|
||||
In the tables below, if <code><b>r</b></code> is of type <code><a href=
|
||||
"#self_t-spec">self_t</a></code>, <code><b>y</b></code> is an object of
|
||||
the same type as <code>x</code>; <br>
|
||||
if <code><b>l</b></code> or <code><b>r</b></code> is an object of type
|
||||
<code><a href="#other-spec">other</a><T></code>,
|
||||
<code><b>y</b></code> is an object of type <code>T</code>; <br>
|
||||
otherwise, <code><b>y</b></code> is an object of the same type as
|
||||
<code><b>l</b></code> or <code><b>r</b></code>.<br>
|
||||
<code><b>l</b></code> is never of type <code><a href=
|
||||
"#self_t-spec">self_t</a></code>.
|
||||
|
||||
<p>The column of <b>Python Expressions</b> illustrates the expressions
|
||||
that will be supported in Python for objects convertible to the types of
|
||||
<code>x</code> and <code>y</code>. The secondary operation arises due to
|
||||
Python's <a href=
|
||||
"http://www.python.org/doc/ref/customization.html#l2h-89">reflection
|
||||
rules</a> for rich comparison operators, and are only used when the
|
||||
corresponding operation is not defined as a method of the <code>y</code>
|
||||
object.</p>
|
||||
|
||||
<table border="1" summary="self_t comparison functions">
|
||||
<tr>
|
||||
<th>C++ Expression</th>
|
||||
|
||||
<th>Python Method Name</th>
|
||||
|
||||
<th>C++ Implementation</th>
|
||||
|
||||
<th>Python Expressions<br>
|
||||
(primary, secondary)</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self == r</code></td>
|
||||
|
||||
<td><code>__eq__</code></td>
|
||||
|
||||
<td><code>x == y</code></td>
|
||||
|
||||
<td><code>x == y, y == x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l == self</code></td>
|
||||
|
||||
<td><code>__eq__</code></td>
|
||||
|
||||
<td><code>y == x</code></td>
|
||||
|
||||
<td><code>y == x, x == y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self != r</code></td>
|
||||
|
||||
<td><code>__ne__</code></td>
|
||||
|
||||
<td><code>x != y</code></td>
|
||||
|
||||
<td><code>x != y, y != x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l != self</code></td>
|
||||
|
||||
<td><code>__ne__</code></td>
|
||||
|
||||
<td><code>y != x</code></td>
|
||||
|
||||
<td><code>y != x, x != y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self < r</code></td>
|
||||
|
||||
<td><code>__lt__</code></td>
|
||||
|
||||
<td><code>x < y</code></td>
|
||||
|
||||
<td><code>x < y, y > x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l < self</code></td>
|
||||
|
||||
<td><code>__gt__</code></td>
|
||||
|
||||
<td><code>y < x</code></td>
|
||||
|
||||
<td><code>y > x, x < y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self > r</code></td>
|
||||
|
||||
<td><code>__gt__</code></td>
|
||||
|
||||
<td><code>x > y</code></td>
|
||||
|
||||
<td><code>x > y, y < x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l > self</code></td>
|
||||
|
||||
<td><code>__lt__</code></td>
|
||||
|
||||
<td><code>y > x</code></td>
|
||||
|
||||
<td><code>y < x, x > y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self <= r</code></td>
|
||||
|
||||
<td><code>__le__</code></td>
|
||||
|
||||
<td><code>x <= y</code></td>
|
||||
|
||||
<td><code>x <= y, y >= x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l <= self</code></td>
|
||||
|
||||
<td><code>__ge__</code></td>
|
||||
|
||||
<td><code>y <= x</code></td>
|
||||
|
||||
<td><code>y >= x, x <= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self >= r</code></td>
|
||||
|
||||
<td><code>__ge__</code></td>
|
||||
|
||||
<td><code>x >= y</code></td>
|
||||
|
||||
<td><code>x >= y, y <= x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l >= self</code></td>
|
||||
|
||||
<td><code>__le__</code></td>
|
||||
|
||||
<td><code>y >= x</code></td>
|
||||
|
||||
<td><code>y <= x, x >= y</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="self_t-spec-ops"></a>Class <code>self_t</code> non-member
|
||||
operations</h4>
|
||||
The operations whose names begin with "<code>__r</code>" below will only
|
||||
be called if the left-hand operand does not already support the given
|
||||
operation, as described <a href=
|
||||
"http://www.python.org/doc/current/ref/numeric-types.html#l2h-152">here</a>.
|
||||
|
||||
|
||||
<table border="1" summary="self_t non-member operations">
|
||||
<tr>
|
||||
<th>C++ Expression</th>
|
||||
|
||||
<th>Python Method Name</th>
|
||||
|
||||
<th>C++ Implementation</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self + r</code></td>
|
||||
|
||||
<td><code>__add__</code></td>
|
||||
|
||||
<td><code>x + y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l + self</code></td>
|
||||
|
||||
<td><code>__radd__</code></td>
|
||||
|
||||
<td><code>y + x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self - r</code></td>
|
||||
|
||||
<td><code>__sub__</code></td>
|
||||
|
||||
<td><code>x - y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l - self</code></td>
|
||||
|
||||
<td><code>__rsub__</code></td>
|
||||
|
||||
<td><code>y - x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self * r</code></td>
|
||||
|
||||
<td><code>__mul__</code></td>
|
||||
|
||||
<td><code>x * y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l * self</code></td>
|
||||
|
||||
<td><code>__rmul__</code></td>
|
||||
|
||||
<td><code>y * x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self / r</code></td>
|
||||
|
||||
<td><code>__div__</code></td>
|
||||
|
||||
<td><code>x / y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l / self</code></td>
|
||||
|
||||
<td><code>__rdiv__</code></td>
|
||||
|
||||
<td><code>y / x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self % r</code></td>
|
||||
|
||||
<td><code>__mod__</code></td>
|
||||
|
||||
<td><code>x % y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l % self</code></td>
|
||||
|
||||
<td><code>__rmod__</code></td>
|
||||
|
||||
<td><code>y % x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self >> r</code></td>
|
||||
|
||||
<td><code>__rshift__</code></td>
|
||||
|
||||
<td><code>x >> y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l >> self</code></td>
|
||||
|
||||
<td><code>__rrshift__</code></td>
|
||||
|
||||
<td><code>y >> x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self << r</code></td>
|
||||
|
||||
<td><code>__lshift__</code></td>
|
||||
|
||||
<td><code>x << y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l << self</code></td>
|
||||
|
||||
<td><code>__rlshift__</code></td>
|
||||
|
||||
<td><code>y << x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self & r</code></td>
|
||||
|
||||
<td><code>__and__</code></td>
|
||||
|
||||
<td><code>x & y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l & self</code></td>
|
||||
|
||||
<td><code>__rand__</code></td>
|
||||
|
||||
<td><code>y & x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self ^ r</code></td>
|
||||
|
||||
<td><code>__xor__</code></td>
|
||||
|
||||
<td><code>x ^ y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l ^ self</code></td>
|
||||
|
||||
<td><code>__rxor__</code></td>
|
||||
|
||||
<td><code>y ^ x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>self | r</code></td>
|
||||
|
||||
<td><code>__or__</code></td>
|
||||
|
||||
<td><code>x | y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>l | self</code></td>
|
||||
|
||||
<td><code>__ror__</code></td>
|
||||
|
||||
<td><code>y | x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>pow(self, r)</code></td>
|
||||
|
||||
<td><code>__pow__</code></td>
|
||||
|
||||
<td><code>pow(x, y)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>pow(l, self)</code></td>
|
||||
|
||||
<td><code>__rpow__</code></td>
|
||||
|
||||
<td><code>pow(y, x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="self_t-spec-value-unary-ops"></a>Class <code>self_t</code> unary
|
||||
operations</h4>
|
||||
|
||||
<table border="1" summary="self_t unary operations">
|
||||
<tr>
|
||||
<th>C++ Expression</th>
|
||||
|
||||
<th>Python Method Name</th>
|
||||
|
||||
<th>C++ Implementation</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>-self</code></td>
|
||||
|
||||
<td><code>__neg__</code></td>
|
||||
|
||||
<td><code>-x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>+self</code></td>
|
||||
|
||||
<td><code>__pos__</code></td>
|
||||
|
||||
<td><code>+x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>~self</code></td>
|
||||
|
||||
<td><code>__invert__</code></td>
|
||||
|
||||
<td><code>~x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>not self</code><br><i>or</i><br><code>!self</code></td>
|
||||
|
||||
<td><code>__nonzero__</code></td>
|
||||
|
||||
<td><code>!!x</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="self_t-spec-value-ops"></a>Class <code>self_t</code> value
|
||||
operations</h4>
|
||||
|
||||
<table border="1" summary="self_t value operations">
|
||||
<tr>
|
||||
<th>C++ Expression</th>
|
||||
|
||||
<th>Python Method Name</th>
|
||||
|
||||
<th>C++ Implementation</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>int_(self)</code></td>
|
||||
|
||||
<td><code>__int__</code></td>
|
||||
|
||||
<td><code>long(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>long_</code></td>
|
||||
|
||||
<td><code>__long__</code></td>
|
||||
|
||||
<td><code>PyLong_FromLong(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>float_</code></td>
|
||||
|
||||
<td><code>__float__</code></td>
|
||||
|
||||
<td><code>double(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>complex_</code></td>
|
||||
|
||||
<td><code>__complex__</code></td>
|
||||
|
||||
<td><code>std::complex<double>(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>str</code></td>
|
||||
|
||||
<td><code>__str__</code></td>
|
||||
|
||||
<td><code><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="other-spec"></a>Class Template <code>other</code></h3>
|
||||
|
||||
<p>Instances of <code>other<T></code> can be used in operator
|
||||
expressions with <a href="#self-spec">self</a>; the result is equivalent
|
||||
to the same expression with a <code>T</code> object in place of
|
||||
<code>other<T></code>. Use <code>other<T></code> to prevent
|
||||
construction of a <code>T</code> object in case it is heavyweight, when
|
||||
no constructor is available, or simply for clarity.</p>
|
||||
|
||||
<h4><a name="other-spec-synopsis"></a>Class Template other synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T>
|
||||
struct other
|
||||
{
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
<!-- -->
|
||||
|
||||
<h3><a name="operator_-spec"></a>Class Template
|
||||
<code>detail::operator_</code></h3>
|
||||
|
||||
<p>Instantiations of <code>detail::operator_<></code> are used as
|
||||
the return type of operator expressions involving <code><a href=
|
||||
"#self-spec">self</a></code>. This should be considered an implementation
|
||||
detail and is only documented here as a way of showing how the result of
|
||||
<code>self</code>-expressions match calls to <a href=
|
||||
"class.html#class_-spec-modifiers">class_<>::def()</a>.</p>
|
||||
|
||||
<h4><a name="operator_-spec-synopsis"></a>Class Template
|
||||
<code>detail::operator_</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace detail
|
||||
{
|
||||
template <<i>unspecified</i>>
|
||||
struct operator_
|
||||
{
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="objects"></a>Objects</h2>
|
||||
|
||||
<p><a name="self-spec"><code>self</code></a></p>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
using self_ns::self;
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/operators.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
struct number
|
||||
: boost::<a href=
|
||||
"../../../utility/operators.htm#grpd_oprs">integer_arithmetic</a><number>
|
||||
{
|
||||
explicit number(long x_) : x(x_) {}
|
||||
operator long() const { return x; }
|
||||
|
||||
template <class T>
|
||||
number& operator+=(T const& rhs)
|
||||
{ x += rhs; return *this; }
|
||||
|
||||
template <class T>
|
||||
number& operator-=(T const& rhs)
|
||||
{ x -= rhs; return *this; }
|
||||
|
||||
template <class T>
|
||||
number& operator*=(T const& rhs)
|
||||
{ x *= rhs; return *this; }
|
||||
|
||||
template <class T>
|
||||
number& operator/=(T const& rhs)
|
||||
{ x /= rhs; return *this; }
|
||||
|
||||
template <class T>
|
||||
number& operator%=(T const& rhs)
|
||||
{ x %= rhs; return *this; }
|
||||
|
||||
long x;
|
||||
};
|
||||
|
||||
using namespace boost::python;
|
||||
BOOST_PYTHON_MODULE(demo)
|
||||
{
|
||||
class_<number>("number", init<long>())
|
||||
// interoperate with self
|
||||
.def(self += self)
|
||||
.def(self + self)
|
||||
.def(self -= self)
|
||||
.def(self - self)
|
||||
.def(self *= self)
|
||||
.def(self * self)
|
||||
.def(self /= self)
|
||||
.def(self / self)
|
||||
.def(self %= self)
|
||||
.def(self % self)
|
||||
|
||||
// Convert to Python int
|
||||
.def(int_(self))
|
||||
|
||||
// interoperate with long
|
||||
.def(self += long())
|
||||
.def(self + long())
|
||||
.def(long() + self)
|
||||
.def(self -= long())
|
||||
.def(self - long())
|
||||
.def(long() - self)
|
||||
.def(self *= long())
|
||||
.def(self * long())
|
||||
.def(long() * self)
|
||||
.def(self /= long())
|
||||
.def(self / long())
|
||||
.def(long() / self)
|
||||
.def(self %= long())
|
||||
.def(self % long())
|
||||
.def(long() % self)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
5 October, 2004
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - <boost/python/overloads.hpp></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 <boost/python/overloads.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"#overload-dispatch-expression"><i>overload-dispatch-expressions</i></a></dt>
|
||||
|
||||
<dt><a href= "#OverloadDispatcher-concept">OverloadDispatcher</a> concept</dt>
|
||||
|
||||
<dt><a href="#macros">Macros</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href=
|
||||
"#BOOST_PYTHON_FUNCTION_OVERLOADS-spec">BOOST_PYTHON_FUNCTION_OVERLOADS</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"#BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS-spec">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Defines facilities for generating families of overloaded Python
|
||||
functions and extension class methods from C++ functions and
|
||||
member functions with default arguments, or from similar families
|
||||
of C++ overloads</p>
|
||||
|
||||
<h2><a name=
|
||||
"overload-dispatch-expression"></a><i>overload-dispatch-expressions</i></h2>
|
||||
|
||||
<p>
|
||||
An <em>overload-dispatch-expression</em> is used to describe a
|
||||
family of overloaded methods to be generated for an extension
|
||||
class. It has the following properties:
|
||||
|
||||
<blockquote>
|
||||
<dl class="properties">
|
||||
<dt><b>docstring:</b> An <a href="definitions.html#ntbs">ntbs</a>
|
||||
whose value will bound to the methods' <code>__doc__</code>
|
||||
attribute</dt>
|
||||
|
||||
<dt><b>keywords:</b> A <a href=
|
||||
"args.html#keyword-expression">keyword-expression</a> which
|
||||
will be used to name (a trailing subsequence of) the arguments
|
||||
to the generated methods.</dt>
|
||||
|
||||
<dt><b>call policies:</b> An instance of some type which models <a href=
|
||||
"CallPolicies.html">CallPolicies</a>.</dt>
|
||||
|
||||
<dt><b>minimum <a href="definitions.html#arity">arity</a></b>
|
||||
The minimum number of arguments to be accepted by a generated
|
||||
method overload.</dt>
|
||||
|
||||
<dt><b>maximum <a href="definitions.html#arity">arity</a></b>
|
||||
The maximum number of arguments to be accepted by a generated
|
||||
method overload.</dt>
|
||||
</dl>
|
||||
</blockquote>
|
||||
|
||||
<h2><a name="OverloadDispatcher-concept"></a>OverloadDispatcher Concept</h2>
|
||||
|
||||
An OverloadDispatcher <code>X</code> is a class which has a
|
||||
<em>minimum arity</em> and a <em>maximum arity</em>, and for which
|
||||
the following following are valid <a
|
||||
href="#overload-dispatch-expression"><em>overload-dispatch-expression</em></a>s,
|
||||
with the same minimum and maximum arity as the OverloadDispatcher.
|
||||
|
||||
<pre>
|
||||
X()
|
||||
X(docstring)
|
||||
X(docstring, keywords)
|
||||
X(keywords, docstring)
|
||||
X()[policies]
|
||||
X(docstring)[policies]
|
||||
X(docstring, keywords)[policies]
|
||||
X(keywords, docstring)[policies]
|
||||
</pre>
|
||||
|
||||
<ul>
|
||||
<li>If <code>policies</code> are supplied, it must be an instance of a
|
||||
type which models <a
|
||||
href="CallPolicies.html#CallPolicies-concept">CallPolicies</a>, and
|
||||
will be used as the result's call policies. Otherwise the result's
|
||||
call policies will be an instance of <a
|
||||
href="default_call_policies.html#default_call_policies-spec">default_call_policies</a>.
|
||||
|
||||
<li>If <code>docstring</code> is supplied it must be an <a
|
||||
href="definitions.html#ntbs">ntbs</a>, and will be used as the result's docstring. Otherwise the result has an empty docstring.
|
||||
|
||||
<li>If <code>keywords</code> is supplied it must be the result of a <a
|
||||
href= "args.html#keyword-expression">keyword-expression</a>
|
||||
whose length is no greater than <code>X</code>'s maximum
|
||||
arity, and will be used as the result's keywords. Otherwise
|
||||
the result's keywords will be empty.
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2><a name="macros"></a>Macros</h2>
|
||||
|
||||
<h3><a name=
|
||||
"BOOST_PYTHON_FUNCTION_OVERLOADS-spec">BOOST_PYTHON_FUNCTION_OVERLOADS(name, func_id, min_args, max_args)</a></h3>
|
||||
Expands to the definition of an OverloadDispatcher called
|
||||
<code>name</code> in the current scope which can be used to
|
||||
generate the following function invocation:
|
||||
<pre>
|
||||
func_id(a<small><i>1</i></small>, a<small><i>2</i></small>,...a<small><i>i</i></small>);
|
||||
</pre>
|
||||
|
||||
for all <code>min_args</code> <= <i>i</i> <= <code>max_args</code>.
|
||||
|
||||
<h3><a name=
|
||||
"BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS-spec">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(name, member_name, min_args, max_args)</a></h3>
|
||||
|
||||
Expands to the definition of an OverloadDispatcher called
|
||||
<code>name</code> in the current scope which can be used to
|
||||
generate the following function invocation:
|
||||
<pre>
|
||||
x.member_name(a<small><i>1</i></small>, a<small><i>2</i></small>,...a<small><i>i</i></small>);
|
||||
</pre>
|
||||
|
||||
for all <code>min_args</code> <= <i>i</i> <=
|
||||
<code>max_args</code>, where <code>x</code> is a reference to an
|
||||
object of class type.
|
||||
|
||||
<h2><a name="examples"></a>Example(s)</h2>
|
||||
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/args.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/overloads.hpp>
|
||||
#include <boost/python/return_internal_reference.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
|
||||
{
|
||||
return make_tuple(x, y, z);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
|
||||
|
||||
struct Y {};
|
||||
struct X
|
||||
{
|
||||
Y& f(int x, double y = 4.25, char const* z = "wow")
|
||||
{
|
||||
return inner;
|
||||
}
|
||||
Y inner;
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(f_member_overloads, f, 1, 3)
|
||||
|
||||
BOOST_PYTHON_MODULE(args_ext)
|
||||
{
|
||||
def("f", f,
|
||||
f_overloads(
|
||||
args("x", "y", "z"), "This is f's docstring"
|
||||
));
|
||||
|
||||
|
||||
class_<Y>("Y")
|
||||
;
|
||||
|
||||
class_<X>("X", "This is X's docstring")
|
||||
.def("f1", &X::f,
|
||||
f_member_overloads(
|
||||
args("x", "y", "z"), "f's docstring"
|
||||
)[return_internal_reference<>()]
|
||||
)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
15 April, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
<!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="../../../../boost.png"
|
||||
alt="boost.png (6897 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
|
||||
through the interface as described in detail in the
|
||||
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
|
||||
>Python Library Reference for pickle.</a> This interface
|
||||
involves the special methods <tt>__getinitargs__</tt>,
|
||||
<tt>__getstate__</tt> and <tt>__setstate__</tt> as described
|
||||
in the following. Note that Boost.Python is also fully compatible
|
||||
with Python's cPickle module.
|
||||
|
||||
<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, <tt>pickle.load</tt>
|
||||
will call the constructor (<tt>__init__</tt>) without arguments;
|
||||
i.e., the object must be default-constructible.
|
||||
|
||||
<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>
|
||||
<dt>
|
||||
<strong><tt>__setstate__</tt></strong>
|
||||
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is restored by the
|
||||
unpickler (<tt>pickle.load</tt>), 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.
|
||||
|
||||
</dl>
|
||||
|
||||
The three special methods described above may be <tt>.def()</tt>'ed
|
||||
individually by the user. However, Boost.Python provides an easy to use
|
||||
high-level interface via the
|
||||
<strong><tt>boost::python::pickle_suite</tt></strong> class that also
|
||||
enforces consistency: <tt>__getstate__</tt> and <tt>__setstate__</tt>
|
||||
must be defined as pairs. Use of this interface is demonstrated by the
|
||||
following examples.
|
||||
|
||||
<hr>
|
||||
<h2>Examples</h2>
|
||||
|
||||
There are three files in <a href="../../test/"
|
||||
><tt>boost/libs/python/test</tt></a> that show how to
|
||||
provide pickle support.
|
||||
|
||||
<hr>
|
||||
<h3><a href="../../test/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>.
|
||||
This is done in the following way:
|
||||
|
||||
<ul>
|
||||
<li>1. Definition of the C++ pickle function:
|
||||
<pre>
|
||||
struct world_pickle_suite : boost::python::pickle_suite
|
||||
{
|
||||
static
|
||||
boost::python::tuple
|
||||
getinitargs(world const& w)
|
||||
{
|
||||
return boost::python::make_tuple(w.get_country());
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<li>2. Establishing the Python binding:
|
||||
<pre>
|
||||
class_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.def_pickle(world_pickle_suite())
|
||||
// ...
|
||||
</pre>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<h3><a href="../../test/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:
|
||||
|
||||
<ul>
|
||||
<li>1. Definition of the C++ pickle functions:
|
||||
<pre>
|
||||
struct world_pickle_suite : boost::python::pickle_suite
|
||||
{
|
||||
static
|
||||
boost::python::tuple
|
||||
getinitargs(const world& w)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
static
|
||||
boost::python::tuple
|
||||
getstate(const world& w)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
setstate(world& w, boost::python::tuple state)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<li>2. Establishing the Python bindings for the entire suite:
|
||||
<pre>
|
||||
class_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.def_pickle(world_pickle_suite())
|
||||
// ...
|
||||
</pre>
|
||||
</ul>
|
||||
|
||||
<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 guard
|
||||
described below will catch the cases where this assumption is violated.
|
||||
|
||||
<hr>
|
||||
<h3><a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>
|
||||
|
||||
This example is similar to <a
|
||||
href="../../test/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 a little more code but is
|
||||
unavoidable if the object's <tt>__dict__</tt> is not always empty.
|
||||
|
||||
<hr>
|
||||
<h2>Pitfall and Safety Guard</h2>
|
||||
|
||||
The pickle protocol described above has an important pitfall that the
|
||||
end user of a Boost.Python extension module might not be aware of:
|
||||
<p>
|
||||
<strong>
|
||||
<tt>__getstate__</tt> is defined and the instance's <tt>__dict__</tt>
|
||||
is not empty.
|
||||
</strong>
|
||||
<p>
|
||||
|
||||
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
|
||||
either at the C++ or the Python level. Finally, the safety guard
|
||||
should intentionally be overridden. E.g. in C++ (from
|
||||
<a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a>):
|
||||
|
||||
<pre>
|
||||
struct world_pickle_suite : boost::python::pickle_suite
|
||||
{
|
||||
// ...
|
||||
|
||||
static bool getstate_manages_dict() { return true; }
|
||||
};
|
||||
</pre>
|
||||
|
||||
Alternatively 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>
|
||||
|
||||
<hr>
|
||||
<h2>Practical Advice</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
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.
|
||||
|
||||
<p>
|
||||
<li>
|
||||
Avoid using <tt>__getstate__</tt> if the instance can also be
|
||||
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
|
||||
avoids the pitfall described above.
|
||||
|
||||
<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>Light-weight alternative: pickle support implemented in Python</h2>
|
||||
|
||||
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>
|
||||
|
||||
The <tt>pickle4.cpp</tt> example demonstrates an alternative technique
|
||||
for implementing pickle support. First we direct Boost.Python via
|
||||
the <tt>class_::enable_pickling()</tt> member function to define only
|
||||
the basic attributes required for pickling:
|
||||
|
||||
<pre>
|
||||
class_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.enable_pickling()
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
This enables the standard Python pickle interface as described
|
||||
in the Python documentation. By "injecting" a
|
||||
<tt>__getinitargs__</tt> method into the definition of the wrapped
|
||||
class we make all instances pickleable:
|
||||
|
||||
<pre>
|
||||
# import the wrapped world class
|
||||
from pickle4_ext import world
|
||||
|
||||
# definition of __getinitargs__
|
||||
def world_getinitargs(self):
|
||||
return (self.get_country(),)
|
||||
|
||||
# now inject __getinitargs__ (Python is a dynamic language!)
|
||||
world.__getinitargs__ = world_getinitargs
|
||||
</pre>
|
||||
|
||||
See also the
|
||||
<a href="../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python"
|
||||
>tutorial section</a> on injecting additional methods from Python.
|
||||
|
||||
<hr>
|
||||
|
||||
© Copyright Ralf W. Grosse-Kunstleve 2001-2004. 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: Feb 2004.
|
||||
</div>
|
||||
@@ -1,132 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<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 - Known Working Platforms and Compilers</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">Known Working Platforms and Compilers</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
Please see
|
||||
our <a
|
||||
href="http://boost.sourceforge.net/regression-logs">regression
|
||||
logs</a> for up-to-date information. Note that logs not marked
|
||||
otherwise reflect the CVS state, not the condition of the release.
|
||||
|
||||
<p>
|
||||
Earlier versions of <b>Boost.Python</b> have been successfully
|
||||
tested on the following platforms and compilers.
|
||||
|
||||
<dl class="page-index">
|
||||
<dt>Unix Platforms:</dt>
|
||||
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>with Python <a href="http://www.python.org/2.2">2.2</a> and <a
|
||||
href="http://www.python.org/2.2.2">2.2.2b1</a>:</dt>
|
||||
|
||||
<dd>
|
||||
<dl>
|
||||
<dt><a href="http://gcc.gnu.org">GCC</a> 2.95.3, 2.96, 3.0.4,
|
||||
3.1, and 3.2 on <a href="http://www.redhat.com">RedHat Linux 7.3</a>
|
||||
for Intel x86</dt>
|
||||
|
||||
<dt>Tru64 CXX 6.5.1 on OSF v. 5.1 for Dec/Compaq
|
||||
Alpha</dt>
|
||||
|
||||
<dt>
|
||||
MIPSPro 7.3.1.2m on <a href=
|
||||
"http://www.sgi.com/software/irix6.5/">IRIX 6.5</a> for SGI
|
||||
mips</dt>
|
||||
|
||||
<dt><a href="http://gcc.gnu.org">GCC 3.1</a> on SunOS 5.8</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt>with Python <a href=
|
||||
"http://www.python.org/2.2.1">2.2.1</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>KCC 3.4d on OSF v. 5.1 for Dec/Compaq Alpha</dt>
|
||||
|
||||
<dt>KCC 3.4d</a> on AIX</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<br>
|
||||
</dd>
|
||||
|
||||
<dt>Microsoft Windows XP Professional with Python <a href=
|
||||
"http://www.python.org/2.2">2.2</a>, <a href=
|
||||
"http://www.python.org/2.2.1">2.2.1</a>, and <a href=
|
||||
"http://www.python.org/2.2.2">2.2.2b1</a>:</dt>
|
||||
|
||||
<dd>
|
||||
<dl>
|
||||
<dt><a href=
|
||||
"http://msdn.microsoft.com/visualc/default.asp">Microsoft Visual
|
||||
C++</a> 6, 7, and 7.1 beta</dt>
|
||||
|
||||
<dt><a href=
|
||||
"http://msdn.microsoft.com/visualc/default.asp">Microsoft Visual
|
||||
C++ 6</a> with <a href="http://www.stlport.org">STLPort
|
||||
4.5.3</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"http://www.metrowerks.com/MW/Develop/Desktop/Windows/Professional/Default.htm">
|
||||
Metrowerks CodeWarrior</a> 7.2, 8.0, 8.2 and 8.3 beta</dt>
|
||||
|
||||
<dt><a href=
|
||||
"http://www.intel.com/software/products/compilers/c60/">Intel
|
||||
C++</a> 5.0, 6.0, and 7.0 beta</dt>
|
||||
|
||||
<dt><a href=
|
||||
"http://www.intel.com/software/products/compilers/c60/">Intel C++
|
||||
5.0</a> with <a href="http://www.stlport.org">STLPort
|
||||
4.5.3</a></dt>
|
||||
|
||||
<dt><a href="http://www.cygwin.com">Cygwin</a> <a href=
|
||||
"http://gcc.gnu.org">GCC</a> 3.0.4 and 3.2</dt>
|
||||
|
||||
<dt><a href="http://www.mingw.org">MinGW-1.1</a> (<a href=
|
||||
"http://gcc.gnu.org">GCC 2.95.3-5</a>)</dt>
|
||||
|
||||
<dt><a href="http://www.mingw.org">MinGW-2.0</a> (<a href=
|
||||
"http://gcc.gnu.org">GCC 3.2</a>)</dt>
|
||||
</dl>
|
||||
</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>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||