mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 16:52:15 +00:00
Compare commits
24 Commits
python
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d248e6af3c | ||
|
|
efd89ae564 | ||
|
|
9230705eea | ||
|
|
a5c2402565 | ||
|
|
55b0fb875d | ||
|
|
229ea1b679 | ||
|
|
06ed9cb5b3 | ||
|
|
70e7f111e8 | ||
|
|
fcfd4dae07 | ||
|
|
937a47f2c2 | ||
|
|
f6a85e2e04 | ||
|
|
3c9230c0e4 | ||
|
|
1e30b68a1a | ||
|
|
5f8ddc1833 | ||
|
|
fd1d332d3f | ||
|
|
c7eae3512f | ||
|
|
163bb06a43 | ||
|
|
e5d4e14a2d | ||
|
|
17f0899211 | ||
|
|
40e6b73721 | ||
|
|
37270cb809 | ||
|
|
200fc2ed29 | ||
|
|
f57e4fc652 | ||
|
|
fd16f736f3 |
24
Jamfile
24
Jamfile
@@ -1,24 +0,0 @@
|
|||||||
subproject libs/python ;
|
|
||||||
|
|
||||||
# bring in the rules for python
|
|
||||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
|
||||||
include <module@>python.jam ;
|
|
||||||
|
|
||||||
dll bpl
|
|
||||||
:
|
|
||||||
src/converter/from_python.cpp
|
|
||||||
src/converter/registry.cpp
|
|
||||||
src/converter/type_id.cpp
|
|
||||||
src/object/class.cpp
|
|
||||||
src/object/function.cpp
|
|
||||||
src/object/inheritance.cpp
|
|
||||||
src/object/life_support.cpp
|
|
||||||
src/errors.cpp
|
|
||||||
src/module.cpp
|
|
||||||
src/objects.cpp
|
|
||||||
src/converter/builtin_converters.cpp
|
|
||||||
src/converter/callback.cpp
|
|
||||||
:
|
|
||||||
$(BOOST_PYTHON_V2_PROPERTIES)
|
|
||||||
<define>BOOST_PYTHON_SOURCE
|
|
||||||
;
|
|
||||||
164
build/Jamfile
164
build/Jamfile
@@ -1,164 +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 build and test Jamfile
|
|
||||||
#
|
|
||||||
# To run all tests quietly: jam test
|
|
||||||
# To run all tests with verbose output: jam -sPYTHON_TEST_ARGS=-v test
|
|
||||||
#
|
|
||||||
# Declares the following targets:
|
|
||||||
# 1. libboost_python.dll/.so, a dynamic library to be linked with all
|
|
||||||
# Boost.Python modules
|
|
||||||
#
|
|
||||||
# 2. pairs of test targets of the form <name>.test and <name>.run
|
|
||||||
# <name>.test runs the test when it is out-of-date, and the "test"
|
|
||||||
# pseudotarget depends on it. <name>.run runs
|
|
||||||
# a test unconditionally, and can be used to force a test to run.. Each
|
|
||||||
# test target builds one or more Boost.Python modules and runs a Python
|
|
||||||
# script to test them. The test names are:
|
|
||||||
#
|
|
||||||
# from ../test
|
|
||||||
#
|
|
||||||
# comprehensive - a comprehensive test of Boost.Python features
|
|
||||||
#
|
|
||||||
# from ../example:
|
|
||||||
# abstract -
|
|
||||||
# getting_started1 -
|
|
||||||
# getting_started2 -
|
|
||||||
# simple_vector -
|
|
||||||
# do_it_yourself_convts -
|
|
||||||
# pickle1 -
|
|
||||||
# pickle2 -
|
|
||||||
# pickle3 -
|
|
||||||
#
|
|
||||||
# dvect1 -
|
|
||||||
# dvect2 -
|
|
||||||
# ivect1 -
|
|
||||||
# ivect2 -
|
|
||||||
# noncopyable -
|
|
||||||
#
|
|
||||||
# subproject-specific environment/command-line variables:
|
|
||||||
#
|
|
||||||
# PYTHON - How to invoke the Python interpreter. Defaults to "python"
|
|
||||||
#
|
|
||||||
# PYTHON_ROOT - Windows only: where Python is installed. Defaults to "c:/tools/python"
|
|
||||||
#
|
|
||||||
# PYTHON_VERSION - Version of Python. Defaults to "2.1" on Windows, "1.5" on Unix
|
|
||||||
#
|
|
||||||
# PYTHON_TEST_ARGS - specifies arguments to be passed to test scripts on
|
|
||||||
# the command line. "-v" can be useful if you want to
|
|
||||||
# see the output of successful tests.
|
|
||||||
#
|
|
||||||
# PYTHON_VECT_ITERATIONS - specifies the number of test iterations to use for
|
|
||||||
# the dvect and ivect tests above.
|
|
||||||
|
|
||||||
# declare the location of this subproject relative to the root
|
|
||||||
subproject libs/python/build ;
|
|
||||||
|
|
||||||
# bring in the rules for python
|
|
||||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
|
||||||
include <module@>python.jam ;
|
|
||||||
|
|
||||||
# This nasty hack works with versions of Python 1.5.2 -> 2.2 to avoid
|
|
||||||
# building any Python stuff if there's no installation.
|
|
||||||
SEARCH on <find-python-install>__init__.py = $(PYTHON_STDLIB_PATH)/test $(SUBDIR) ;
|
|
||||||
include <find-python-install>__init__.py ;
|
|
||||||
if ! $(gNO_PYTHON_INSTALL)
|
|
||||||
{
|
|
||||||
|
|
||||||
local PYTHON_PROPERTIES = $(PYTHON_PROPERTIES) <define>BOOST_PYTHON_DYNAMIC_LIB ;
|
|
||||||
|
|
||||||
#######################
|
|
||||||
rule bpl-test ( test-name : sources + )
|
|
||||||
{
|
|
||||||
boost-python-test $(test-name) : $(sources) <dll>boost_python ;
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################
|
|
||||||
|
|
||||||
#
|
|
||||||
# Declare the boost python static link library
|
|
||||||
#
|
|
||||||
|
|
||||||
# Base names of the source files for libboost_python
|
|
||||||
local CPP_SOURCES =
|
|
||||||
types classes conversions extension_class functions
|
|
||||||
init_function module_builder objects cross_module errors
|
|
||||||
;
|
|
||||||
|
|
||||||
lib boost_python_static : ../src/$(CPP_SOURCES).cpp
|
|
||||||
# requirements
|
|
||||||
: $(BOOST_PYTHON_INCLUDES)
|
|
||||||
<shared-linkable>true
|
|
||||||
<define>BOOST_PYTHON_STATIC_LIB=1
|
|
||||||
$(PYTHON_PROPERTIES) ;
|
|
||||||
|
|
||||||
dll boost_python
|
|
||||||
# $(SUFDLL[1])
|
|
||||||
: ../src/$(CPP_SOURCES).cpp
|
|
||||||
# requirements
|
|
||||||
: $(BOOST_PYTHON_INCLUDES)
|
|
||||||
<shared-linkable>true
|
|
||||||
<runtime-link>dynamic
|
|
||||||
<define>BOOST_PYTHON_HAS_DLL_RUNTIME=1
|
|
||||||
$(PYTHON_PROPERTIES)
|
|
||||||
;
|
|
||||||
|
|
||||||
############# comprehensive module and test ###########
|
|
||||||
bpl-test boost_python_test
|
|
||||||
: ../test/comprehensive.cpp ;
|
|
||||||
|
|
||||||
boost-python-runtest comprehensive
|
|
||||||
: ../test/comprehensive.py <pyd>boost_python_test <dll>boost_python ;
|
|
||||||
|
|
||||||
############# simple tests from ../example ############
|
|
||||||
|
|
||||||
rule boost-python-example-runtest ( name )
|
|
||||||
{
|
|
||||||
bpl-test $(name)
|
|
||||||
: ../example/$(name).cpp ;
|
|
||||||
|
|
||||||
boost-python-runtest $(name)
|
|
||||||
: ../example/test_$(name).py <pyd>$(name) <dll>boost_python ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
boost-python-example-runtest abstract ;
|
|
||||||
boost-python-example-runtest getting_started1 ;
|
|
||||||
boost-python-example-runtest getting_started2 ;
|
|
||||||
boost-python-example-runtest simple_vector ;
|
|
||||||
boost-python-example-runtest do_it_yourself_convts ;
|
|
||||||
boost-python-example-runtest pickle1 ;
|
|
||||||
boost-python-example-runtest pickle2 ;
|
|
||||||
boost-python-example-runtest pickle3 ;
|
|
||||||
|
|
||||||
|
|
||||||
bpl-test ivect : ../example/ivect.cpp ;
|
|
||||||
bpl-test dvect : ../example/dvect.cpp ;
|
|
||||||
bpl-test noncopyable_export : ../example/noncopyable_export.cpp ;
|
|
||||||
bpl-test noncopyable_import : ../example/noncopyable_import.cpp ;
|
|
||||||
|
|
||||||
############## cross-module tests from ../example ##########
|
|
||||||
|
|
||||||
# A simple rule to build a test which depends on multiple modules in the PYTHONPATH
|
|
||||||
rule boost-python-multi-example-runtest ( test-name : modules + )
|
|
||||||
{
|
|
||||||
boost-python-runtest $(test-name)
|
|
||||||
: ../example/tst_$(test-name).py <pyd>$(modules) <dll>boost_python
|
|
||||||
: : : $(PYTHON_VECT_ITERATIONS) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
PYTHON_VECT_ITERATIONS ?= 10 ;
|
|
||||||
|
|
||||||
boost-python-multi-example-runtest dvect1 : ivect dvect ;
|
|
||||||
boost-python-multi-example-runtest dvect2 : ivect dvect ;
|
|
||||||
|
|
||||||
boost-python-multi-example-runtest ivect1 : ivect dvect ;
|
|
||||||
boost-python-multi-example-runtest ivect2 : ivect dvect ;
|
|
||||||
|
|
||||||
boost-python-multi-example-runtest
|
|
||||||
noncopyable : noncopyable_import noncopyable_export ;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# Dummy file actually to be included by Jam when the python headers
|
|
||||||
# can't be found
|
|
||||||
|
|
||||||
if ! $(gNO_PYTHON_INSTALL)
|
|
||||||
{
|
|
||||||
ECHO "Couldn't find Python $(PYTHON_VERSION) installation in $(PYTHON_ROOT)" ;
|
|
||||||
ECHO skipping Boost.Python library build ;
|
|
||||||
ECHO You can configure the location of your python installation, by setting: ;
|
|
||||||
ECHO PYTHON_ROOT - currently \"$(PYTHON_ROOT)\" ;
|
|
||||||
ECHO PYTHON_VERSION - currently \"$(PYTHON_VERSION)\" ;
|
|
||||||
ECHO ;
|
|
||||||
ECHO "The following are automatically configured from PYTHON_ROOT if not otherwise set" ;
|
|
||||||
ECHO " PYTHON_INCLUDES - path to Python #include directories; currently" \"$(PYTHON_INCLUDES)\" ;
|
|
||||||
ECHO " PYTHON_LIB_PATH - path to Python library; currently" \"$(PYTHON_LIB_PATH)\" ;
|
|
||||||
ECHO " PYTHON_STDLIB_PATH - path to Python standard library modules; currently" \"$(PYTHON_STDLIB_PATH)\" ;
|
|
||||||
}
|
|
||||||
gNO_PYTHON_INSTALL ?= true ;
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="bpl_static" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
|
||||||
|
|
||||||
CFG=bpl_static - Win32 DebugPython
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "bpl_static.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "bpl_static.mak" CFG="bpl_static - Win32 DebugPython"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "bpl_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
|
||||||
!MESSAGE "bpl_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
|
||||||
!MESSAGE "bpl_static - Win32 DebugPython" (based on "Win32 (x86) Static Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=cl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "bpl_static - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MD /W4 /WX /GR /GX /O2 /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /c
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LIB32=link.exe -lib
|
|
||||||
# ADD BASE LIB32 /nologo
|
|
||||||
# ADD LIB32 /nologo
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "bpl_static - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LIB32=link.exe -lib
|
|
||||||
# ADD BASE LIB32 /nologo
|
|
||||||
# ADD LIB32 /nologo
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "bpl_static - Win32 DebugPython"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "bpl_static___Win32_DebugPython"
|
|
||||||
# PROP BASE Intermediate_Dir "bpl_static___Win32_DebugPython"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "DebugPython"
|
|
||||||
# PROP Intermediate_Dir "DebugPython"
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /EHs /c
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LIB32=link.exe -lib
|
|
||||||
# ADD BASE LIB32 /nologo
|
|
||||||
# ADD LIB32 /nologo
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "bpl_static - Win32 Release"
|
|
||||||
# Name "bpl_static - Win32 Debug"
|
|
||||||
# Name "bpl_static - Win32 DebugPython"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\classes.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\conversions.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\extension_class.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\functions.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\init_function.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\module_builder.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\objects.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\src\types.cpp
|
|
||||||
# ADD CPP /W3
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\base_object.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\callback.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\caller.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\cast.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\class_builder.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\classes.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\config.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\conversions.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\errors.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\extension_class.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\functions.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\init_function.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\module_builder.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\none.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\objects.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\operators.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\reference.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\signatures.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\singleton.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\types.hpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\..\boost\python\detail\wrap_python.hpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
108
build/build.dsw
108
build/build.dsw
@@ -1,108 +0,0 @@
|
|||||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
|
||||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "bpl_static"=.\bpl_static.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "example1"=.\example1\example1.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
Begin Project Dependency
|
|
||||||
Project_Dep_Name bpl_static
|
|
||||||
End Project Dependency
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "getting_started1"=.\getting_started1\getting_started1.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
Begin Project Dependency
|
|
||||||
Project_Dep_Name bpl_static
|
|
||||||
End Project Dependency
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "getting_started2"=.\getting_started2\getting_started2.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
begin source code control
|
|
||||||
getting_started2
|
|
||||||
.\getting_started2
|
|
||||||
end source code control
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
Begin Project Dependency
|
|
||||||
Project_Dep_Name bpl_static
|
|
||||||
End Project Dependency
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "rwgk1"=.\rwgk1\rwgk1.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
Begin Project Dependency
|
|
||||||
Project_Dep_Name bpl_static
|
|
||||||
End Project Dependency
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "test"=.\test\test.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
Begin Project Dependency
|
|
||||||
Project_Dep_Name bpl_static
|
|
||||||
End Project Dependency
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Global:
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<3>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
BIN
build/build.opt
BIN
build/build.opt
Binary file not shown.
@@ -1,59 +0,0 @@
|
|||||||
# Revision History:
|
|
||||||
# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve) UNTESTED!
|
|
||||||
# 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams)
|
|
||||||
# 04 Mar 01 Changed library name to libboost_python.a (David Abrahams)
|
|
||||||
|
|
||||||
LIBSRC = \
|
|
||||||
classes.cpp \
|
|
||||||
conversions.cpp \
|
|
||||||
cross_module.cpp \
|
|
||||||
errors.cpp \
|
|
||||||
extension_class.cpp \
|
|
||||||
functions.cpp \
|
|
||||||
init_function.cpp \
|
|
||||||
module_builder.cpp \
|
|
||||||
objects.cpp \
|
|
||||||
types.cpp
|
|
||||||
|
|
||||||
LIBOBJ = $(LIBSRC:.cpp=.o)
|
|
||||||
OBJ = $(LIBOBJ)
|
|
||||||
|
|
||||||
|
|
||||||
ifeq "$(OS)" "Windows_NT"
|
|
||||||
PYTHON_LIB=c:/tools/python/libs/python15.lib
|
|
||||||
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -Ic:/tools/python/include
|
|
||||||
MODULE_EXTENSION=dll
|
|
||||||
else
|
|
||||||
INC = -I/usr/local/include/python1.5
|
|
||||||
MODULE_EXTENSION=so
|
|
||||||
endif
|
|
||||||
|
|
||||||
%.o: ../src/%.cpp
|
|
||||||
como --pic $(INC) -o $*.o -c $<
|
|
||||||
|
|
||||||
%.d: ../src/%.cpp
|
|
||||||
@echo creating $@
|
|
||||||
@set -e; como -M $(INC) -c $< \
|
|
||||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
|
||||||
[ -s $@ ] || rm -f $@
|
|
||||||
|
|
||||||
getting_started1: getting_started1.o libboost_python.a
|
|
||||||
como-dyn-link -o ../example/getting_started1.$(MODULE_EXTENSION) $(PYTHON_LIB) getting_started1.o -L. -lboost_python
|
|
||||||
ln -s ../test/doctest.py ../example
|
|
||||||
python ../example/test_getting_started1.py
|
|
||||||
|
|
||||||
getting_started1.o: ../example/getting_started1.cpp
|
|
||||||
como --pic $(INC) -o $*.o -c $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
|
||||||
|
|
||||||
libboost_python.a: $(LIBOBJ)
|
|
||||||
rm -f libboost_python.a
|
|
||||||
ar cq libboost_python.a $(LIBOBJ)
|
|
||||||
|
|
||||||
DEP = $(OBJ:.o=.d)
|
|
||||||
|
|
||||||
ifneq "$(MAKECMDGOALS)" "clean"
|
|
||||||
include $(DEP)
|
|
||||||
endif
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="example1" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
|
||||||
|
|
||||||
CFG=example1 - Win32 DebugPython
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "example1.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "example1.mak" CFG="example1 - Win32 DebugPython"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "example1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "example1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "example1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=cl.exe
|
|
||||||
MTL=midl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "example1 - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /c
|
|
||||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/hello.dll" /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "example1 - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "example1 - Win32 DebugPython"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "example1___Win32_DebugPython"
|
|
||||||
# PROP BASE Intermediate_Dir "example1___Win32_DebugPython"
|
|
||||||
# PROP BASE Ignore_Export_Lib 0
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "DebugPython"
|
|
||||||
# PROP Intermediate_Dir "DebugPython"
|
|
||||||
# PROP Ignore_Export_Lib 1
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /EHs /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/hello_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "example1 - Win32 Release"
|
|
||||||
# Name "example1 - Win32 Debug"
|
|
||||||
# Name "example1 - Win32 DebugPython"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\example\example1.cpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Resource Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
146
build/filemgr.py
146
build/filemgr.py
@@ -1,146 +0,0 @@
|
|||||||
# Revision history:
|
|
||||||
# 12 Apr 01 use os.path, shutil
|
|
||||||
# Initial version: R.W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
bpl_src = "/libs/python/src"
|
|
||||||
bpl_tst = "/libs/python/test"
|
|
||||||
bpl_exa = "/libs/python/example"
|
|
||||||
files = (
|
|
||||||
bpl_src + "/classes.cpp",
|
|
||||||
bpl_src + "/conversions.cpp",
|
|
||||||
bpl_src + "/errors.cpp",
|
|
||||||
bpl_src + "/extension_class.cpp",
|
|
||||||
bpl_src + "/functions.cpp",
|
|
||||||
bpl_src + "/init_function.cpp",
|
|
||||||
bpl_src + "/module_builder.cpp",
|
|
||||||
bpl_src + "/objects.cpp",
|
|
||||||
bpl_src + "/types.cpp",
|
|
||||||
bpl_src + "/cross_module.cpp",
|
|
||||||
bpl_tst + "/comprehensive.cpp",
|
|
||||||
bpl_tst + "/comprehensive.hpp",
|
|
||||||
bpl_tst + "/comprehensive.py",
|
|
||||||
bpl_tst + "/doctest.py",
|
|
||||||
bpl_exa + "/abstract.cpp",
|
|
||||||
bpl_exa + "/getting_started1.cpp",
|
|
||||||
bpl_exa + "/getting_started2.cpp",
|
|
||||||
bpl_exa + "/simple_vector.cpp",
|
|
||||||
bpl_exa + "/do_it_yourself_convts.cpp",
|
|
||||||
bpl_exa + "/nested.cpp",
|
|
||||||
bpl_exa + "/pickle1.cpp",
|
|
||||||
bpl_exa + "/pickle2.cpp",
|
|
||||||
bpl_exa + "/pickle3.cpp",
|
|
||||||
bpl_exa + "/test_abstract.py",
|
|
||||||
bpl_exa + "/test_getting_started1.py",
|
|
||||||
bpl_exa + "/test_getting_started2.py",
|
|
||||||
bpl_exa + "/test_simple_vector.py",
|
|
||||||
bpl_exa + "/test_do_it_yourself_convts.py",
|
|
||||||
bpl_exa + "/test_nested.py",
|
|
||||||
bpl_exa + "/test_pickle1.py",
|
|
||||||
bpl_exa + "/test_pickle2.py",
|
|
||||||
bpl_exa + "/test_pickle3.py",
|
|
||||||
bpl_exa + "/noncopyable.h",
|
|
||||||
bpl_exa + "/noncopyable_export.cpp",
|
|
||||||
bpl_exa + "/noncopyable_import.cpp",
|
|
||||||
bpl_exa + "/dvect.h",
|
|
||||||
bpl_exa + "/dvect.cpp",
|
|
||||||
bpl_exa + "/dvect_conversions.cpp",
|
|
||||||
bpl_exa + "/dvect_defs.cpp",
|
|
||||||
bpl_exa + "/ivect.h",
|
|
||||||
bpl_exa + "/ivect.cpp",
|
|
||||||
bpl_exa + "/ivect_conversions.cpp",
|
|
||||||
bpl_exa + "/ivect_defs.cpp",
|
|
||||||
bpl_exa + "/tst_noncopyable.py",
|
|
||||||
bpl_exa + "/tst_dvect1.py",
|
|
||||||
bpl_exa + "/tst_dvect2.py",
|
|
||||||
bpl_exa + "/tst_ivect1.py",
|
|
||||||
bpl_exa + "/tst_ivect2.py",
|
|
||||||
bpl_exa + "/test_cross_module.py",
|
|
||||||
bpl_exa + "/vector_wrapper.h",
|
|
||||||
bpl_exa + "/richcmp1.cpp",
|
|
||||||
bpl_exa + "/richcmp2.cpp",
|
|
||||||
bpl_exa + "/richcmp3.cpp",
|
|
||||||
bpl_exa + "/test_richcmp1.py",
|
|
||||||
bpl_exa + "/test_richcmp2.py",
|
|
||||||
bpl_exa + "/test_richcmp3.py",
|
|
||||||
)
|
|
||||||
|
|
||||||
defs = (
|
|
||||||
"boost_python_test",
|
|
||||||
"abstract",
|
|
||||||
"getting_started1",
|
|
||||||
"getting_started2",
|
|
||||||
"simple_vector",
|
|
||||||
"do_it_yourself_convts",
|
|
||||||
"nested",
|
|
||||||
"pickle1",
|
|
||||||
"pickle2",
|
|
||||||
"pickle3",
|
|
||||||
"noncopyable_export",
|
|
||||||
"noncopyable_import",
|
|
||||||
"ivect",
|
|
||||||
"dvect",
|
|
||||||
"richcmp1",
|
|
||||||
"richcmp2",
|
|
||||||
"richcmp3",
|
|
||||||
)
|
|
||||||
|
|
||||||
if (__name__ == "__main__"):
|
|
||||||
|
|
||||||
import sys, os, shutil
|
|
||||||
|
|
||||||
path = sys.argv[1]
|
|
||||||
mode = sys.argv[2]
|
|
||||||
if (not mode in ("softlinks", "unlink", "cp", "rm", "copy", "del")):
|
|
||||||
raise RuntimeError, \
|
|
||||||
"usage: python filemgr.py path <softlinks|unlink|cp|rm|copy|del>"
|
|
||||||
|
|
||||||
if (mode in ("cp", "copy")):
|
|
||||||
for fn in files:
|
|
||||||
f = os.path.basename(fn)
|
|
||||||
print "Copying: " + f
|
|
||||||
shutil.copy(path + fn, ".")
|
|
||||||
|
|
||||||
elif (mode == "softlinks"):
|
|
||||||
for fn in files:
|
|
||||||
f = os.path.basename(fn)
|
|
||||||
if (os.path.exists(f)):
|
|
||||||
print "File exists: " + f
|
|
||||||
else:
|
|
||||||
print "Linking: " + f
|
|
||||||
os.symlink(path + fn, f)
|
|
||||||
|
|
||||||
elif (mode in ("rm", "del")):
|
|
||||||
for fn in files:
|
|
||||||
f = os.path.basename(fn)
|
|
||||||
if (os.path.exists(f)):
|
|
||||||
print "Removing: " + f
|
|
||||||
try: os.unlink(f)
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
elif (mode == "unlink"):
|
|
||||||
for fn in files:
|
|
||||||
f = os.path.basename(fn)
|
|
||||||
if (os.path.exists(f)):
|
|
||||||
if (os.path.islink(f)):
|
|
||||||
print "Unlinking: " + f
|
|
||||||
try: os.unlink(f)
|
|
||||||
except: pass
|
|
||||||
else:
|
|
||||||
print "Not a softlink: " + f
|
|
||||||
|
|
||||||
if (mode in ("softlinks", "cp", "copy")):
|
|
||||||
for d in defs:
|
|
||||||
fn = d + ".def"
|
|
||||||
print "Creating: " + fn
|
|
||||||
f = open(fn, "w")
|
|
||||||
f.write("EXPORTS\n")
|
|
||||||
f.write("\tinit" + d + "\n")
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if (mode in ("unlink", "rm", "del")):
|
|
||||||
for d in defs:
|
|
||||||
fn = d + ".def"
|
|
||||||
if (os.path.exists(fn)):
|
|
||||||
print "Removing: " + fn
|
|
||||||
try: os.unlink(fn)
|
|
||||||
except: pass
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
# Revision History
|
|
||||||
|
|
||||||
# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve)
|
|
||||||
# 17 Apr 01 build shared library (patch provided by Dan Nuffer)
|
|
||||||
# 04 Mar 01 Changed library name to libboost_python.a, various cleanups,
|
|
||||||
# attempted Cygwin compatibility. Still needs testing on Linux
|
|
||||||
# (David Abrahams)
|
|
||||||
|
|
||||||
|
|
||||||
LIBSRC = \
|
|
||||||
classes.cpp \
|
|
||||||
conversions.cpp \
|
|
||||||
cross_module.cpp \
|
|
||||||
errors.cpp \
|
|
||||||
extension_class.cpp \
|
|
||||||
functions.cpp \
|
|
||||||
init_function.cpp \
|
|
||||||
module_builder.cpp \
|
|
||||||
objects.cpp \
|
|
||||||
types.cpp
|
|
||||||
|
|
||||||
LIBOBJ = $(LIBSRC:.cpp=.o)
|
|
||||||
OBJ = $(LIBOBJ)
|
|
||||||
|
|
||||||
LIBNAME = libboost_python
|
|
||||||
# libpython2.0.dll
|
|
||||||
|
|
||||||
ifeq "$(OS)" "Windows_NT"
|
|
||||||
ROOT=c:/cygnus
|
|
||||||
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -I$(PYTHON_INC)
|
|
||||||
MODULE_EXTENSION=dll
|
|
||||||
PYTHON_LIB=c:/cygnus/usr/local/lib/python2.0/config/libpython2.0.dll.a
|
|
||||||
SHARED_LIB = $(LIBNAME).dll
|
|
||||||
else
|
|
||||||
PYTHON_INC=$(ROOT)/usr/local/Python-2.0/include/python2.0
|
|
||||||
BOOST_INC=../../..
|
|
||||||
INC = -I$(BOOST_INC) -I$(PYTHON_INC)
|
|
||||||
MODULE_EXTENSION=so
|
|
||||||
VERSION=1
|
|
||||||
SHARED_LIB = $(LIBNAME).so.$(VERSION)
|
|
||||||
endif
|
|
||||||
|
|
||||||
%.o: ../src/%.cpp
|
|
||||||
g++ -fPIC -Wall -W $(INC) $(CXXFLAGS) -o $*.o -c $<
|
|
||||||
|
|
||||||
%.d: ../src/%.cpp
|
|
||||||
@echo creating $@
|
|
||||||
@set -e; g++ -M $(INC) -c $< \
|
|
||||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
|
||||||
[ -s $@ ] || rm -f $@
|
|
||||||
|
|
||||||
|
|
||||||
PYTHON = python
|
|
||||||
|
|
||||||
all: test $(SHARED_LIB) getting_started1
|
|
||||||
|
|
||||||
test: comprehensive.o $(LIBNAME).a $(SHARED_LIB)
|
|
||||||
g++ $(CXXFLAGS) -shared -o ../test/boost_python_test.$(MODULE_EXTENSION) comprehensive.o -L. -lboost_python $(PYTHON_LIB)
|
|
||||||
$(PYTHON) ../test/comprehensive.py
|
|
||||||
|
|
||||||
comprehensive.o: ../test/comprehensive.cpp
|
|
||||||
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
|
||||||
|
|
||||||
|
|
||||||
getting_started1: getting_started1.o $(LIBNAME).a
|
|
||||||
g++ $(CXXFLAGS) -shared -o ../example/getting_started1.$(MODULE_EXTENSION) getting_started1.o -L. -lboost_python $(PYTHON_LIB)
|
|
||||||
ln -s ../test/doctest.py ../example
|
|
||||||
$(PYTHON) ../example/test_getting_started1.py
|
|
||||||
|
|
||||||
getting_started1.o: ../example/getting_started1.cpp
|
|
||||||
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
|
||||||
|
|
||||||
$(LIBNAME).a: $(LIBOBJ)
|
|
||||||
rm -f $@
|
|
||||||
ar cqs $@ $(LIBOBJ)
|
|
||||||
|
|
||||||
$(SHARED_LIB): $(LIBOBJ)
|
|
||||||
g++ $(CXXFLAGS) -shared -o $@ -Wl,--soname=$(LIBNAME).$(MODULE_EXTENSION)
|
|
||||||
|
|
||||||
DEP = $(OBJ:.o=.d)
|
|
||||||
|
|
||||||
ifneq "$(MAKECMDGOALS)" "clean"
|
|
||||||
include $(DEP)
|
|
||||||
endif
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="getting_started1" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
|
||||||
|
|
||||||
CFG=getting_started1 - Win32 DebugPython
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "getting_started1.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "getting_started1.mak" CFG="getting_started1 - Win32 DebugPython"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "getting_started1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "getting_started1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "getting_started1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=xicl6.exe
|
|
||||||
MTL=midl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "getting_started1 - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
|
||||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=xilink6.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "getting_started1 - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=xilink6.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "getting_started1 - Win32 DebugPython"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "DebugPython"
|
|
||||||
# PROP BASE Intermediate_Dir "DebugPython"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "DebugPython"
|
|
||||||
# PROP Intermediate_Dir "DebugPython"
|
|
||||||
# PROP Ignore_Export_Lib 1
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=xilink6.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"DebugPython/boost_python_test_d.pdb" /debug /machine:I386 /out:"DebugPython/getting_started1_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
|
||||||
# SUBTRACT LINK32 /pdb:none
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "getting_started1 - Win32 Release"
|
|
||||||
# Name "getting_started1 - Win32 Debug"
|
|
||||||
# Name "getting_started1 - Win32 DebugPython"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\example\getting_started1.cpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Resource Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="getting_started2" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
|
||||||
|
|
||||||
CFG=getting_started2 - Win32 DebugPython
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "getting_started2.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "getting_started2.mak" CFG="getting_started2 - Win32 DebugPython"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "getting_started2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "getting_started2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "getting_started2 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName "getting_started2"
|
|
||||||
# PROP Scc_LocalPath "."
|
|
||||||
CPP=xicl6.exe
|
|
||||||
MTL=midl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "getting_started2 - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
|
||||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=xilink6.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "getting_started2 - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=xilink6.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "getting_started2 - Win32 DebugPython"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "getting_started2___Win32_DebugPython"
|
|
||||||
# PROP BASE Intermediate_Dir "getting_started2___Win32_DebugPython"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "getting_started2___Win32_DebugPython"
|
|
||||||
# PROP Intermediate_Dir "getting_started2___Win32_DebugPython"
|
|
||||||
# PROP Ignore_Export_Lib 1
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=xilink6.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"DebugPython/getting_started2_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\pcbuild"
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "getting_started2 - Win32 Release"
|
|
||||||
# Name "getting_started2 - Win32 Debug"
|
|
||||||
# Name "getting_started2 - Win32 DebugPython"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\example\getting_started2.cpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Resource Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
# Usage:
|
|
||||||
#
|
|
||||||
# Create a new empty directory anywhere (preferably not in the boost tree).
|
|
||||||
# Copy this Makefile to that new directory and rename it to "Makefile"
|
|
||||||
# Adjust the pathnames below.
|
|
||||||
#
|
|
||||||
# make softlinks Create softlinks to source code and tests
|
|
||||||
# make Compile all sources
|
|
||||||
# make test Run doctest tests
|
|
||||||
# make clean Remove all object files
|
|
||||||
# make unlink Remove softlinks
|
|
||||||
#
|
|
||||||
# Revision history:
|
|
||||||
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
|
||||||
# Initial version: R.W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
ROOT=$(HOME)
|
|
||||||
BOOST=$(ROOT)/boost
|
|
||||||
|
|
||||||
#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python
|
|
||||||
#PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
|
||||||
PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python
|
|
||||||
PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1
|
|
||||||
STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers
|
|
||||||
|
|
||||||
STDOPTS=
|
|
||||||
WARNOPTS=-woff 1001,1234,1682
|
|
||||||
OPTOPTS=-g
|
|
||||||
|
|
||||||
CPP=CC -LANG:std -n32 -mips4
|
|
||||||
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
|
||||||
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
|
||||||
MAKEDEP=-M
|
|
||||||
|
|
||||||
LD=CC -LANG:std -n32 -mips4
|
|
||||||
LDOPTS=-shared
|
|
||||||
|
|
||||||
OBJ=classes.o conversions.o errors.o extension_class.o functions.o \
|
|
||||||
init_function.o module_builder.o \
|
|
||||||
objects.o types.o cross_module.o
|
|
||||||
DEPOBJ=$(OBJ) \
|
|
||||||
comprehensive.o \
|
|
||||||
abstract.o \
|
|
||||||
getting_started1.o getting_started2.o \
|
|
||||||
simple_vector.o \
|
|
||||||
do_it_yourself_convts.o \
|
|
||||||
nested.o \
|
|
||||||
pickle1.o pickle2.o pickle3.o \
|
|
||||||
noncopyable_export.o noncopyable_import.o \
|
|
||||||
ivect.o dvect.o \
|
|
||||||
richcmp1.o richcmp2.o richcmp3.o
|
|
||||||
|
|
||||||
.SUFFIXES: .o .cpp
|
|
||||||
|
|
||||||
all: libboost_python.a \
|
|
||||||
boost_python_test.so \
|
|
||||||
abstract.so \
|
|
||||||
getting_started1.so getting_started2.so \
|
|
||||||
simple_vector.so \
|
|
||||||
do_it_yourself_convts.so \
|
|
||||||
nested.so \
|
|
||||||
pickle1.so pickle2.so pickle3.so \
|
|
||||||
noncopyable_export.so noncopyable_import.so \
|
|
||||||
ivect.so dvect.so \
|
|
||||||
richcmp1.so richcmp2.so richcmp3.so
|
|
||||||
|
|
||||||
libboost_python.a: $(OBJ)
|
|
||||||
rm -f libboost_python.a
|
|
||||||
$(CPP) -ar -o libboost_python.a $(OBJ)
|
|
||||||
|
|
||||||
boost_python_test.so: $(OBJ) comprehensive.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
|
||||||
|
|
||||||
abstract.so: $(OBJ) abstract.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
|
||||||
|
|
||||||
getting_started1.so: $(OBJ) getting_started1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
|
||||||
|
|
||||||
getting_started2.so: $(OBJ) getting_started2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
|
||||||
|
|
||||||
simple_vector.so: $(OBJ) simple_vector.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so
|
|
||||||
|
|
||||||
do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so
|
|
||||||
|
|
||||||
nested.so: $(OBJ) nested.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so
|
|
||||||
|
|
||||||
pickle1.so: $(OBJ) pickle1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so
|
|
||||||
|
|
||||||
pickle2.so: $(OBJ) pickle2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so
|
|
||||||
|
|
||||||
pickle3.so: $(OBJ) pickle3.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so
|
|
||||||
|
|
||||||
noncopyable_export.so: $(OBJ) noncopyable_export.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
|
||||||
noncopyable_export.o -o noncopyable_export.so
|
|
||||||
|
|
||||||
noncopyable_import.so: $(OBJ) noncopyable_import.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
|
||||||
noncopyable_import.o -o noncopyable_import.so
|
|
||||||
|
|
||||||
ivect.so: $(OBJ) ivect.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
|
|
||||||
|
|
||||||
dvect.so: $(OBJ) dvect.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
|
|
||||||
|
|
||||||
richcmp1.so: $(OBJ) richcmp1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
|
|
||||||
|
|
||||||
richcmp2.so: $(OBJ) richcmp2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
|
|
||||||
|
|
||||||
richcmp3.so: $(OBJ) richcmp3.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
|
|
||||||
|
|
||||||
.cpp.o:
|
|
||||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(PYEXE) comprehensive.py
|
|
||||||
$(PYEXE) test_abstract.py
|
|
||||||
$(PYEXE) test_getting_started1.py
|
|
||||||
$(PYEXE) test_getting_started2.py
|
|
||||||
$(PYEXE) test_simple_vector.py
|
|
||||||
$(PYEXE) test_do_it_yourself_convts.py
|
|
||||||
$(PYEXE) test_nested.py
|
|
||||||
$(PYEXE) test_pickle1.py
|
|
||||||
$(PYEXE) test_pickle2.py
|
|
||||||
$(PYEXE) test_pickle3.py
|
|
||||||
$(PYEXE) test_cross_module.py
|
|
||||||
$(PYEXE) test_richcmp1.py
|
|
||||||
$(PYEXE) test_richcmp2.py
|
|
||||||
$(PYEXE) test_richcmp3.py
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
|
||||||
rm -f comprehensive.o boost_python_test.so
|
|
||||||
rm -f abstract.o abstract.so
|
|
||||||
rm -f getting_started1.o getting_started1.so
|
|
||||||
rm -f getting_started2.o getting_started2.so
|
|
||||||
rm -f simple_vector.o simple_vector.so
|
|
||||||
rm -f do_it_yourself_convts.o do_it_yourself_convts.so
|
|
||||||
rm -f nested.o nested.so
|
|
||||||
rm -f pickle1.o pickle1.so
|
|
||||||
rm -f pickle2.o pickle2.so
|
|
||||||
rm -f pickle3.o pickle3.so
|
|
||||||
rm -f noncopyable_export.o noncopyable_export.so
|
|
||||||
rm -f noncopyable_import.o noncopyable_import.so
|
|
||||||
rm -f ivect.o ivect.so
|
|
||||||
rm -f dvect.o dvect.so
|
|
||||||
rm -f richcmp1.o richcmp1.so
|
|
||||||
rm -f richcmp2.o richcmp2.so
|
|
||||||
rm -f richcmp3.o richcmp3.so
|
|
||||||
rm -f so_locations *.pyc
|
|
||||||
rm -rf ii_files
|
|
||||||
|
|
||||||
softlinks:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks
|
|
||||||
|
|
||||||
unlink:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink
|
|
||||||
|
|
||||||
cp:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp
|
|
||||||
|
|
||||||
rm:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm
|
|
||||||
|
|
||||||
depend:
|
|
||||||
@ cat Makefile.nodepend; \
|
|
||||||
for obj in $(DEPOBJ); \
|
|
||||||
do \
|
|
||||||
bn=`echo "$$obj" | cut -d. -f1`; \
|
|
||||||
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
# Usage:
|
|
||||||
#
|
|
||||||
# Create a new empty directory anywhere (preferably not in the boost tree).
|
|
||||||
# Copy this Makefile to that new directory and rename it to "Makefile"
|
|
||||||
# Adjust the pathnames below.
|
|
||||||
#
|
|
||||||
# make softlinks Create softlinks to source code and tests
|
|
||||||
# make Compile all sources
|
|
||||||
# make test Run doctest tests
|
|
||||||
# make clean Remove all object files
|
|
||||||
# make unlink Remove softlinks
|
|
||||||
#
|
|
||||||
# Revision history:
|
|
||||||
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
|
||||||
# Initial version: R.W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
ROOT=$(HOME)
|
|
||||||
BOOST=$(ROOT)/boost
|
|
||||||
|
|
||||||
#PYEXE=PYTHONPATH=. /usr/bin/python
|
|
||||||
#PYINC=-I/usr/include/python1.5
|
|
||||||
#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python
|
|
||||||
#PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
|
||||||
PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python
|
|
||||||
PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1
|
|
||||||
|
|
||||||
STDOPTS=-fPIC -ftemplate-depth-21
|
|
||||||
WARNOPTS=
|
|
||||||
OPTOPTS=-g
|
|
||||||
|
|
||||||
CPP=g++
|
|
||||||
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
|
||||||
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
|
||||||
MAKEDEP=-M
|
|
||||||
|
|
||||||
LD=$(CPP)
|
|
||||||
LDOPTS=-shared
|
|
||||||
|
|
||||||
OBJ=classes.o conversions.o errors.o extension_class.o functions.o \
|
|
||||||
init_function.o module_builder.o \
|
|
||||||
objects.o types.o cross_module.o
|
|
||||||
DEPOBJ=$(OBJ) \
|
|
||||||
comprehensive.o \
|
|
||||||
abstract.o \
|
|
||||||
getting_started1.o getting_started2.o \
|
|
||||||
simple_vector.o \
|
|
||||||
do_it_yourself_convts.o \
|
|
||||||
nested.o \
|
|
||||||
pickle1.o pickle2.o pickle3.o \
|
|
||||||
noncopyable_export.o noncopyable_import.o \
|
|
||||||
ivect.o dvect.o \
|
|
||||||
richcmp1.o richcmp2.o richcmp3.o
|
|
||||||
|
|
||||||
.SUFFIXES: .o .cpp
|
|
||||||
|
|
||||||
all: libboost_python.a \
|
|
||||||
boost_python_test.so \
|
|
||||||
abstract.so \
|
|
||||||
getting_started1.so getting_started2.so \
|
|
||||||
simple_vector.so \
|
|
||||||
do_it_yourself_convts.so \
|
|
||||||
nested.so \
|
|
||||||
pickle1.so pickle2.so pickle3.so \
|
|
||||||
noncopyable_export.so noncopyable_import.so \
|
|
||||||
ivect.so dvect.so \
|
|
||||||
richcmp1.so richcmp2.so richcmp3.so
|
|
||||||
|
|
||||||
libboost_python.a: $(OBJ)
|
|
||||||
rm -f libboost_python.a
|
|
||||||
ar r libboost_python.a $(OBJ)
|
|
||||||
|
|
||||||
boost_python_test.so: $(OBJ) comprehensive.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
|
||||||
|
|
||||||
abstract.so: $(OBJ) abstract.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
|
||||||
|
|
||||||
getting_started1.so: $(OBJ) getting_started1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
|
||||||
|
|
||||||
getting_started2.so: $(OBJ) getting_started2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
|
||||||
|
|
||||||
simple_vector.so: $(OBJ) simple_vector.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so
|
|
||||||
|
|
||||||
do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so
|
|
||||||
|
|
||||||
nested.so: $(OBJ) nested.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so
|
|
||||||
|
|
||||||
pickle1.so: $(OBJ) pickle1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so
|
|
||||||
|
|
||||||
pickle2.so: $(OBJ) pickle2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so
|
|
||||||
|
|
||||||
pickle3.so: $(OBJ) pickle3.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so
|
|
||||||
|
|
||||||
noncopyable_export.so: $(OBJ) noncopyable_export.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
|
||||||
noncopyable_export.o -o noncopyable_export.so
|
|
||||||
|
|
||||||
noncopyable_import.so: $(OBJ) noncopyable_import.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
|
||||||
noncopyable_import.o -o noncopyable_import.so
|
|
||||||
|
|
||||||
ivect.so: $(OBJ) ivect.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
|
|
||||||
|
|
||||||
dvect.so: $(OBJ) dvect.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
|
|
||||||
|
|
||||||
richcmp1.so: $(OBJ) richcmp1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
|
|
||||||
|
|
||||||
richcmp2.so: $(OBJ) richcmp2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
|
|
||||||
|
|
||||||
richcmp3.so: $(OBJ) richcmp3.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
|
|
||||||
|
|
||||||
.cpp.o:
|
|
||||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(PYEXE) comprehensive.py
|
|
||||||
$(PYEXE) test_abstract.py
|
|
||||||
$(PYEXE) test_getting_started1.py
|
|
||||||
$(PYEXE) test_getting_started2.py
|
|
||||||
$(PYEXE) test_simple_vector.py
|
|
||||||
$(PYEXE) test_do_it_yourself_convts.py
|
|
||||||
$(PYEXE) test_nested.py
|
|
||||||
$(PYEXE) test_pickle1.py
|
|
||||||
$(PYEXE) test_pickle2.py
|
|
||||||
$(PYEXE) test_pickle3.py
|
|
||||||
$(PYEXE) test_cross_module.py
|
|
||||||
$(PYEXE) test_richcmp1.py
|
|
||||||
$(PYEXE) test_richcmp2.py
|
|
||||||
$(PYEXE) test_richcmp3.py
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
|
||||||
rm -f comprehensive.o boost_python_test.so
|
|
||||||
rm -f abstract.o abstract.so
|
|
||||||
rm -f getting_started1.o getting_started1.so
|
|
||||||
rm -f getting_started2.o getting_started2.so
|
|
||||||
rm -f simple_vector.o simple_vector.so
|
|
||||||
rm -f do_it_yourself_convts.o do_it_yourself_convts.so
|
|
||||||
rm -f nested.o nested.so
|
|
||||||
rm -f pickle1.o pickle1.so
|
|
||||||
rm -f pickle2.o pickle2.so
|
|
||||||
rm -f pickle3.o pickle3.so
|
|
||||||
rm -f noncopyable_export.o noncopyable_export.so
|
|
||||||
rm -f noncopyable_import.o noncopyable_import.so
|
|
||||||
rm -f ivect.o ivect.so
|
|
||||||
rm -f dvect.o dvect.so
|
|
||||||
rm -f richcmp1.o richcmp1.so
|
|
||||||
rm -f richcmp2.o richcmp2.so
|
|
||||||
rm -f richcmp3.o richcmp3.so
|
|
||||||
rm -f so_locations *.pyc
|
|
||||||
|
|
||||||
softlinks:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks
|
|
||||||
|
|
||||||
unlink:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink
|
|
||||||
|
|
||||||
cp:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp
|
|
||||||
|
|
||||||
rm:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm
|
|
||||||
|
|
||||||
depend:
|
|
||||||
@ cat Makefile.nodepend; \
|
|
||||||
for obj in $(DEPOBJ); \
|
|
||||||
do \
|
|
||||||
bn=`echo "$$obj" | cut -d. -f1`; \
|
|
||||||
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
# Usage:
|
|
||||||
#
|
|
||||||
# make copy Copy the sources and tests
|
|
||||||
# make Compile all sources
|
|
||||||
# make test Run doctest tests
|
|
||||||
# make clean Remove all object files
|
|
||||||
# make del Remove the sources and tests
|
|
||||||
#
|
|
||||||
# Revision history:
|
|
||||||
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
|
||||||
# Initial version: R.W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
# To install mingw32, follow instructions at:
|
|
||||||
# http://starship.python.net/crew/kernr/mingw32/Notes.html
|
|
||||||
# In particular, install:
|
|
||||||
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/gcc-2.95.2-msvcrt.exe
|
|
||||||
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/fixes/quote-fix-msvcrt.exe
|
|
||||||
# http://starship.python.net/crew/kernr/mingw32/Python-1.5.2-mingw32.zip
|
|
||||||
# Unpack the first two archives in the default locations and update your PATH.
|
|
||||||
# Unpack the third archive in \usr.
|
|
||||||
|
|
||||||
# Note: comprehensive.cpp generates compiler errors and later crashes.
|
|
||||||
# L:\boost\boost\python\detail\extension_class.hpp:643: warning:
|
|
||||||
# alignment of `vtable for class
|
|
||||||
# boost::python::detail::held_instance<bpl_test::Derived1>'
|
|
||||||
# is greater than maximum object file alignment. Using 16.
|
|
||||||
# Could this be fixed with compiler options?
|
|
||||||
# -fhuge-objects looks interesting, but requires recompiling the C++ library.
|
|
||||||
# (what exactly does that mean?)
|
|
||||||
# -fvtable-thunks eliminates the compiler warning, but
|
|
||||||
# "import boost_python_test" still causes a crash.
|
|
||||||
|
|
||||||
ROOT=R:
|
|
||||||
BOOST_WIN="$(ROOT)\boost"
|
|
||||||
BOOST_UNIX=$(HOME)/boost
|
|
||||||
|
|
||||||
PYEXE="C:\Program files\Python\python.exe"
|
|
||||||
PYINC=-I"C:\usr\include\python1.5"
|
|
||||||
PYLIB="C:\usr\lib\libpython15.a"
|
|
||||||
#PYEXE="C:\Python21\python.exe"
|
|
||||||
#PYINC=-I"C:\usr\include\python2.1"
|
|
||||||
#PYLIB="C:\usr\lib\libpython21.a"
|
|
||||||
|
|
||||||
STDOPTS=-ftemplate-depth-21
|
|
||||||
WARNOPTS=
|
|
||||||
OPTOPTS=-g
|
|
||||||
|
|
||||||
CPP=g++
|
|
||||||
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \
|
|
||||||
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
|
||||||
|
|
||||||
LD=g++
|
|
||||||
LDOPTS=-shared
|
|
||||||
|
|
||||||
OBJ=classes.o conversions.o errors.o extension_class.o functions.o \
|
|
||||||
init_function.o module_builder.o \
|
|
||||||
objects.o types.o cross_module.o
|
|
||||||
|
|
||||||
.SUFFIXES: .o .cpp
|
|
||||||
|
|
||||||
all: libboost_python.a \
|
|
||||||
abstract.pyd \
|
|
||||||
getting_started1.pyd getting_started2.pyd \
|
|
||||||
simple_vector.pyd \
|
|
||||||
do_it_yourself_convts.pyd \
|
|
||||||
nested.pyd \
|
|
||||||
pickle1.pyd pickle2.pyd pickle3.pyd \
|
|
||||||
noncopyable_export.pyd noncopyable_import.pyd \
|
|
||||||
ivect.pyd dvect.pyd \
|
|
||||||
richcmp1.pyd richcmp2.pyd richcmp3.pyd
|
|
||||||
|
|
||||||
libboost_python.a: $(OBJ)
|
|
||||||
-del libboost_python.a
|
|
||||||
ar r libboost_python.a $(OBJ)
|
|
||||||
|
|
||||||
DLLWRAPOPTS=-s --driver-name g++ -s \
|
|
||||||
--entry _DllMainCRTStartup@12 --target=i386-mingw32
|
|
||||||
|
|
||||||
boost_python_test.pyd: $(OBJ) comprehensive.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname boost_python_test.pyd \
|
|
||||||
--def boost_python_test.def \
|
|
||||||
$(OBJ) comprehensive.o $(PYLIB)
|
|
||||||
|
|
||||||
abstract.pyd: $(OBJ) abstract.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname abstract.pyd \
|
|
||||||
--def abstract.def \
|
|
||||||
$(OBJ) abstract.o $(PYLIB)
|
|
||||||
|
|
||||||
getting_started1.pyd: $(OBJ) getting_started1.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname getting_started1.pyd \
|
|
||||||
--def getting_started1.def \
|
|
||||||
$(OBJ) getting_started1.o $(PYLIB)
|
|
||||||
|
|
||||||
getting_started2.pyd: $(OBJ) getting_started2.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname getting_started2.pyd \
|
|
||||||
--def getting_started2.def \
|
|
||||||
$(OBJ) getting_started2.o $(PYLIB)
|
|
||||||
|
|
||||||
simple_vector.pyd: $(OBJ) simple_vector.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname simple_vector.pyd \
|
|
||||||
--def simple_vector.def \
|
|
||||||
$(OBJ) simple_vector.o $(PYLIB)
|
|
||||||
|
|
||||||
do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname do_it_yourself_convts.pyd \
|
|
||||||
--def do_it_yourself_convts.def \
|
|
||||||
$(OBJ) do_it_yourself_convts.o $(PYLIB)
|
|
||||||
|
|
||||||
nested.pyd: $(OBJ) nested.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname nested.pyd \
|
|
||||||
--def nested.def \
|
|
||||||
$(OBJ) nested.o $(PYLIB)
|
|
||||||
|
|
||||||
pickle1.pyd: $(OBJ) pickle1.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname pickle1.pyd \
|
|
||||||
--def pickle1.def \
|
|
||||||
$(OBJ) pickle1.o $(PYLIB)
|
|
||||||
|
|
||||||
pickle2.pyd: $(OBJ) pickle2.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname pickle2.pyd \
|
|
||||||
--def pickle2.def \
|
|
||||||
$(OBJ) pickle2.o $(PYLIB)
|
|
||||||
|
|
||||||
pickle3.pyd: $(OBJ) pickle3.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname pickle3.pyd \
|
|
||||||
--def pickle3.def \
|
|
||||||
$(OBJ) pickle3.o $(PYLIB)
|
|
||||||
|
|
||||||
noncopyable_export.pyd: $(OBJ) noncopyable_export.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname noncopyable_export.pyd \
|
|
||||||
--def noncopyable_export.def \
|
|
||||||
$(OBJ) noncopyable_export.o $(PYLIB)
|
|
||||||
|
|
||||||
noncopyable_import.pyd: $(OBJ) noncopyable_import.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname noncopyable_import.pyd \
|
|
||||||
--def noncopyable_import.def \
|
|
||||||
$(OBJ) noncopyable_import.o $(PYLIB)
|
|
||||||
|
|
||||||
ivect.pyd: $(OBJ) ivect.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname ivect.pyd \
|
|
||||||
--def ivect.def \
|
|
||||||
$(OBJ) ivect.o $(PYLIB)
|
|
||||||
|
|
||||||
dvect.pyd: $(OBJ) dvect.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname dvect.pyd \
|
|
||||||
--def dvect.def \
|
|
||||||
$(OBJ) dvect.o $(PYLIB)
|
|
||||||
|
|
||||||
richcmp1.pyd: $(OBJ) richcmp1.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname richcmp1.pyd \
|
|
||||||
--def richcmp1.def \
|
|
||||||
$(OBJ) richcmp1.o $(PYLIB)
|
|
||||||
|
|
||||||
richcmp2.pyd: $(OBJ) richcmp2.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname richcmp2.pyd \
|
|
||||||
--def richcmp2.def \
|
|
||||||
$(OBJ) richcmp2.o $(PYLIB)
|
|
||||||
|
|
||||||
richcmp3.pyd: $(OBJ) richcmp3.o
|
|
||||||
dllwrap $(DLLWRAPOPTS) \
|
|
||||||
--dllname richcmp3.pyd \
|
|
||||||
--def richcmp3.def \
|
|
||||||
$(OBJ) richcmp3.o $(PYLIB)
|
|
||||||
|
|
||||||
.cpp.o:
|
|
||||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
|
||||||
|
|
||||||
test:
|
|
||||||
# $(PYEXE) comprehensive.py
|
|
||||||
$(PYEXE) test_abstract.py
|
|
||||||
$(PYEXE) test_getting_started1.py
|
|
||||||
$(PYEXE) test_getting_started2.py
|
|
||||||
$(PYEXE) test_simple_vector.py
|
|
||||||
$(PYEXE) test_do_it_yourself_convts.py
|
|
||||||
$(PYEXE) test_nested.py
|
|
||||||
$(PYEXE) test_pickle1.py
|
|
||||||
$(PYEXE) test_pickle2.py
|
|
||||||
$(PYEXE) test_pickle3.py
|
|
||||||
$(PYEXE) test_cross_module.py
|
|
||||||
$(PYEXE) test_richcmp1.py
|
|
||||||
$(PYEXE) test_richcmp2.py
|
|
||||||
$(PYEXE) test_richcmp3.py
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-del *.o
|
|
||||||
-del *.a
|
|
||||||
-del *.pyd
|
|
||||||
-del *.pyc
|
|
||||||
|
|
||||||
softlinks:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks
|
|
||||||
|
|
||||||
unlink:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink
|
|
||||||
|
|
||||||
cp:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp
|
|
||||||
|
|
||||||
rm:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm
|
|
||||||
|
|
||||||
copy:
|
|
||||||
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy
|
|
||||||
|
|
||||||
del:
|
|
||||||
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="rwgk1" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
|
||||||
|
|
||||||
CFG=rwgk1 - Win32 DebugPython
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "rwgk1.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "rwgk1.mak" CFG="rwgk1 - Win32 DebugPython"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "rwgk1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "rwgk1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "rwgk1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=cl.exe
|
|
||||||
MTL=midl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "rwgk1 - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /c
|
|
||||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "rwgk1 - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "rwgk1 - Win32 DebugPython"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "rwgk1___Win32_DebugPython"
|
|
||||||
# PROP BASE Intermediate_Dir "rwgk1___Win32_DebugPython"
|
|
||||||
# PROP BASE Ignore_Export_Lib 0
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "DebugPython"
|
|
||||||
# PROP Intermediate_Dir "DebugPython"
|
|
||||||
# PROP Ignore_Export_Lib 1
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/rwgk1_d.dll" /pdbtype:sept /libpath:"C:\tools\python\src\PCbuild"
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "rwgk1 - Win32 Release"
|
|
||||||
# Name "rwgk1 - Win32 Debug"
|
|
||||||
# Name "rwgk1 - Win32 DebugPython"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\example\rwgk1.cpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Resource Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
|
||||||
|
|
||||||
CFG=test - Win32 DebugPython
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "test.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 DebugPython"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "test - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=cl.exe
|
|
||||||
MTL=midl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "test - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /Zm200 /c
|
|
||||||
# SUBTRACT CPP /Fr
|
|
||||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/boost_python_test.dll" /libpath:"c:\tools\python\libs"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "test - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
|
||||||
# SUBTRACT CPP /Fr
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/boost_python_test.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
# SUBTRACT LINK32 /pdb:none
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "test - Win32 DebugPython"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "test___Win32_DebugPython"
|
|
||||||
# PROP BASE Intermediate_Dir "test___Win32_DebugPython"
|
|
||||||
# PROP BASE Ignore_Export_Lib 0
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "DebugPython"
|
|
||||||
# PROP Intermediate_Dir "DebugPython"
|
|
||||||
# PROP Ignore_Export_Lib 1
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /Zm200 /EHs /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
|
||||||
# SUBTRACT BASE LINK32 /pdb:none
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/boost_python_test_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
|
||||||
# SUBTRACT LINK32 /pdb:none
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "test - Win32 Release"
|
|
||||||
# Name "test - Win32 Debug"
|
|
||||||
# Name "test - Win32 DebugPython"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\test\comprehensive.cpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\test\comprehensive.hpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Resource Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
# Usage:
|
|
||||||
#
|
|
||||||
# Create a new empty directory anywhere (preferably not in the boost tree).
|
|
||||||
# Copy this Makefile to that new directory and rename it to "Makefile"
|
|
||||||
# Adjust the pathnames below.
|
|
||||||
#
|
|
||||||
# make softlinks Create softlinks to source code and tests
|
|
||||||
# make Compile all sources
|
|
||||||
# make test Run doctest tests
|
|
||||||
# make clean Remove all object files
|
|
||||||
# make unlink Remove softlinks
|
|
||||||
#
|
|
||||||
# Revision history:
|
|
||||||
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
|
||||||
# Initial version: R.W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
ROOT=$(HOME)
|
|
||||||
BOOST=$(ROOT)/boost
|
|
||||||
|
|
||||||
#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python
|
|
||||||
#PYINC=-I/usr/local/Python-1.5.2/include/python1.5
|
|
||||||
PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python
|
|
||||||
PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1
|
|
||||||
#STLPORTINC=-I/usr/local/STLport-4.1b3/stlport
|
|
||||||
#STLPORTINC=-I/usr/local/STLport-4.1b4/stlport
|
|
||||||
#STLPORTOPTS= \
|
|
||||||
# -D__USE_STD_IOSTREAM \
|
|
||||||
# -D__STL_NO_SGI_IOSTREAMS \
|
|
||||||
# -D__STL_USE_NATIVE_STRING \
|
|
||||||
# -D__STL_NO_NEW_C_HEADERS \
|
|
||||||
# -D_RWSTD_COMPILE_INSTANTIATE=1
|
|
||||||
STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers
|
|
||||||
|
|
||||||
STDOPTS=-std strict_ansi
|
|
||||||
# use -msg_display_number to obtain integer tags for -msg_disable
|
|
||||||
WARNOPTS=-msg_disable 186,450,1115
|
|
||||||
OPTOPTS=-g
|
|
||||||
|
|
||||||
CPP=cxx
|
|
||||||
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
|
||||||
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
|
||||||
MAKEDEP=-Em
|
|
||||||
|
|
||||||
LD=cxx
|
|
||||||
LDOPTS=-shared -expect_unresolved 'Py*' -expect_unresolved '_Py*'
|
|
||||||
|
|
||||||
#HIDDEN=-hidden
|
|
||||||
|
|
||||||
OBJ=classes.o conversions.o errors.o extension_class.o functions.o \
|
|
||||||
init_function.o module_builder.o \
|
|
||||||
objects.o types.o cross_module.o
|
|
||||||
DEPOBJ=$(OBJ) \
|
|
||||||
comprehensive.o \
|
|
||||||
abstract.o \
|
|
||||||
getting_started1.o getting_started2.o \
|
|
||||||
simple_vector.o \
|
|
||||||
do_it_yourself_convts.o \
|
|
||||||
nested.o \
|
|
||||||
pickle1.o pickle2.o pickle3.o \
|
|
||||||
noncopyable_export.o noncopyable_import.o \
|
|
||||||
ivect.o dvect.o \
|
|
||||||
richcmp1.o richcmp2.o richcmp3.o
|
|
||||||
|
|
||||||
.SUFFIXES: .o .cpp
|
|
||||||
|
|
||||||
all: libboost_python.a \
|
|
||||||
boost_python_test.so \
|
|
||||||
abstract.so \
|
|
||||||
getting_started1.so getting_started2.so \
|
|
||||||
simple_vector.so \
|
|
||||||
do_it_yourself_convts.so \
|
|
||||||
nested.so \
|
|
||||||
pickle1.so pickle2.so pickle3.so \
|
|
||||||
noncopyable_export.so noncopyable_import.so \
|
|
||||||
ivect.so dvect.so \
|
|
||||||
richcmp1.so richcmp2.so richcmp3.so
|
|
||||||
|
|
||||||
libboost_python.a: $(OBJ)
|
|
||||||
rm -f libboost_python.a
|
|
||||||
cd cxx_repository; \
|
|
||||||
ls -1 > ../libboost_python.a.input; \
|
|
||||||
ar r ../libboost_python.a -input ../libboost_python.a.input
|
|
||||||
rm -f libboost_python.a.input
|
|
||||||
ar r libboost_python.a $(OBJ)
|
|
||||||
|
|
||||||
boost_python_test.so: $(OBJ) comprehensive.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
|
||||||
|
|
||||||
abstract.so: $(OBJ) abstract.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
|
||||||
|
|
||||||
getting_started1.so: $(OBJ) getting_started1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
|
||||||
|
|
||||||
getting_started2.so: $(OBJ) getting_started2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
|
||||||
|
|
||||||
simple_vector.so: $(OBJ) simple_vector.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so
|
|
||||||
|
|
||||||
do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so
|
|
||||||
|
|
||||||
nested.so: $(OBJ) nested.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so
|
|
||||||
|
|
||||||
pickle1.so: $(OBJ) pickle1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so
|
|
||||||
|
|
||||||
pickle2.so: $(OBJ) pickle2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so
|
|
||||||
|
|
||||||
pickle3.so: $(OBJ) pickle3.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so
|
|
||||||
|
|
||||||
noncopyable_export.so: $(OBJ) noncopyable_export.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
|
||||||
noncopyable_export.o -o noncopyable_export.so
|
|
||||||
|
|
||||||
noncopyable_import.so: $(OBJ) noncopyable_import.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \
|
|
||||||
noncopyable_import.o -o noncopyable_import.so
|
|
||||||
|
|
||||||
ivect.so: $(OBJ) ivect.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so
|
|
||||||
|
|
||||||
dvect.so: $(OBJ) dvect.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
|
|
||||||
|
|
||||||
richcmp1.so: $(OBJ) richcmp1.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
|
|
||||||
|
|
||||||
richcmp2.so: $(OBJ) richcmp2.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
|
|
||||||
|
|
||||||
richcmp3.so: $(OBJ) richcmp3.o
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
|
|
||||||
|
|
||||||
.cpp.o:
|
|
||||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(PYEXE) comprehensive.py
|
|
||||||
$(PYEXE) test_abstract.py
|
|
||||||
$(PYEXE) test_getting_started1.py
|
|
||||||
$(PYEXE) test_getting_started2.py
|
|
||||||
$(PYEXE) test_simple_vector.py
|
|
||||||
$(PYEXE) test_do_it_yourself_convts.py
|
|
||||||
$(PYEXE) test_nested.py
|
|
||||||
$(PYEXE) test_pickle1.py
|
|
||||||
$(PYEXE) test_pickle2.py
|
|
||||||
$(PYEXE) test_pickle3.py
|
|
||||||
$(PYEXE) test_cross_module.py
|
|
||||||
$(PYEXE) test_richcmp1.py
|
|
||||||
$(PYEXE) test_richcmp2.py
|
|
||||||
$(PYEXE) test_richcmp3.py
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
|
||||||
rm -f comprehensive.o boost_python_test.so
|
|
||||||
rm -f abstract.o abstract.so
|
|
||||||
rm -f getting_started1.o getting_started1.so
|
|
||||||
rm -f getting_started2.o getting_started2.so
|
|
||||||
rm -f simple_vector.o simple_vector.so
|
|
||||||
rm -f do_it_yourself_convts.o do_it_yourself_convts.so
|
|
||||||
rm -f nested.o nested.so
|
|
||||||
rm -f pickle1.o pickle1.so
|
|
||||||
rm -f pickle2.o pickle2.so
|
|
||||||
rm -f pickle3.o pickle3.so
|
|
||||||
rm -f noncopyable_export.o noncopyable_export.so
|
|
||||||
rm -f noncopyable_import.o noncopyable_import.so
|
|
||||||
rm -f ivect.o ivect.so
|
|
||||||
rm -f dvect.o dvect.so
|
|
||||||
rm -f richcmp1.o richcmp1.so
|
|
||||||
rm -f richcmp2.o richcmp2.so
|
|
||||||
rm -f richcmp3.o richcmp3.so
|
|
||||||
rm -f so_locations *.pyc
|
|
||||||
rm -rf cxx_repository
|
|
||||||
|
|
||||||
softlinks:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks
|
|
||||||
|
|
||||||
unlink:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink
|
|
||||||
|
|
||||||
cp:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp
|
|
||||||
|
|
||||||
rm:
|
|
||||||
$(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm
|
|
||||||
|
|
||||||
depend:
|
|
||||||
@ cat Makefile.nodepend; \
|
|
||||||
for obj in $(DEPOBJ); \
|
|
||||||
do \
|
|
||||||
bn=`echo "$$obj" | cut -d. -f1`; \
|
|
||||||
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
|
||||||
done
|
|
||||||
|
|
||||||
154
build/vc60.mak
154
build/vc60.mak
@@ -1,154 +0,0 @@
|
|||||||
# Usage:
|
|
||||||
#
|
|
||||||
# Create a new empty directory anywhere (preferably not in the boost tree).
|
|
||||||
# Copy this Makefile to that new directory and rename it to "Makefile"
|
|
||||||
# Adjust the pathnames below.
|
|
||||||
#
|
|
||||||
# make copy Copy the sources and tests
|
|
||||||
# make Compile all sources
|
|
||||||
# make test Run doctest tests
|
|
||||||
# make clean Remove all object files
|
|
||||||
# make del Remove the sources and tests
|
|
||||||
#
|
|
||||||
# Revision history:
|
|
||||||
# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve)
|
|
||||||
# Initial version: R.W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
ROOT=R:
|
|
||||||
BOOST_WIN="$(ROOT)\boost"
|
|
||||||
BOOST_UNIX=$(HOME)/boost
|
|
||||||
|
|
||||||
#PYEXE="C:\Program files\Python\python.exe"
|
|
||||||
#PYINC=/I"C:\Program files\Python\include"
|
|
||||||
#PYLIB="C:\Program files\Python\libs\python15.lib"
|
|
||||||
PYEXE="C:\Python21\python.exe"
|
|
||||||
PYINC=/I"C:\Python21\include"
|
|
||||||
PYLIB="C:\Python21\libs\python21.lib"
|
|
||||||
|
|
||||||
STDOPTS=/nologo /MD /GR /GX /Zm300 /DBOOST_PYTHON_STATIC_LIB
|
|
||||||
WARNOPTS=
|
|
||||||
OPTOPTS=
|
|
||||||
|
|
||||||
CPP=cl.exe
|
|
||||||
CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) /I$(BOOST_WIN) $(PYINC) \
|
|
||||||
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
|
|
||||||
|
|
||||||
LD=link.exe
|
|
||||||
LDOPTS=/nologo /dll /incremental:no
|
|
||||||
|
|
||||||
OBJ=classes.obj conversions.obj errors.obj extension_class.obj functions.obj \
|
|
||||||
init_function.obj module_builder.obj \
|
|
||||||
objects.obj types.obj cross_module.obj
|
|
||||||
|
|
||||||
.SUFFIXES: .obj .cpp
|
|
||||||
|
|
||||||
all: boost_python.lib \
|
|
||||||
boost_python_test.pyd \
|
|
||||||
abstract.pyd \
|
|
||||||
getting_started1.pyd getting_started2.pyd \
|
|
||||||
simple_vector.pyd \
|
|
||||||
do_it_yourself_convts.pyd \
|
|
||||||
nested.pyd \
|
|
||||||
pickle1.pyd pickle2.pyd pickle3.pyd \
|
|
||||||
noncopyable_export.pyd noncopyable_import.pyd \
|
|
||||||
ivect.pyd dvect.pyd \
|
|
||||||
richcmp1.pyd richcmp2.pyd richcmp3.pyd
|
|
||||||
|
|
||||||
boost_python.lib: $(OBJ)
|
|
||||||
$(LD) -lib /nologo /out:boost_python.lib $(OBJ)
|
|
||||||
|
|
||||||
boost_python_test.pyd: $(OBJ) comprehensive.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) /export:initboost_python_test /out:"boost_python_test.pyd"
|
|
||||||
|
|
||||||
abstract.pyd: $(OBJ) abstract.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) /export:initabstract /out:"abstract.pyd"
|
|
||||||
|
|
||||||
getting_started1.pyd: $(OBJ) getting_started1.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) /export:initgetting_started1 /out:"getting_started1.pyd"
|
|
||||||
|
|
||||||
getting_started2.pyd: $(OBJ) getting_started2.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) /export:initgetting_started2 /out:"getting_started2.pyd"
|
|
||||||
|
|
||||||
simple_vector.pyd: $(OBJ) simple_vector.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) /export:initsimple_vector /out:"simple_vector.pyd"
|
|
||||||
|
|
||||||
do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.obj $(PYLIB) /export:initdo_it_yourself_convts /out:"do_it_yourself_convts.pyd"
|
|
||||||
|
|
||||||
nested.pyd: $(OBJ) nested.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) nested.obj $(PYLIB) /export:initnested /out:"nested.pyd"
|
|
||||||
|
|
||||||
pickle1.pyd: $(OBJ) pickle1.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd"
|
|
||||||
|
|
||||||
pickle2.pyd: $(OBJ) pickle2.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) /export:initpickle2 /out:"pickle2.pyd"
|
|
||||||
|
|
||||||
pickle3.pyd: $(OBJ) pickle3.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) /export:initpickle3 /out:"pickle3.pyd"
|
|
||||||
|
|
||||||
noncopyable_export.pyd: $(OBJ) noncopyable_export.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) /export:initnoncopyable_export /out:"noncopyable_export.pyd"
|
|
||||||
|
|
||||||
noncopyable_import.pyd: $(OBJ) noncopyable_import.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) /export:initnoncopyable_import /out:"noncopyable_import.pyd"
|
|
||||||
|
|
||||||
ivect.pyd: $(OBJ) ivect.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) /export:initivect /out:"ivect.pyd"
|
|
||||||
|
|
||||||
dvect.pyd: $(OBJ) dvect.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd"
|
|
||||||
|
|
||||||
richcmp1.pyd: $(OBJ) richcmp1.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp1.obj $(PYLIB) /export:initrichcmp1 /out:"richcmp1.pyd"
|
|
||||||
|
|
||||||
richcmp2.pyd: $(OBJ) richcmp2.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp2.obj $(PYLIB) /export:initrichcmp2 /out:"richcmp2.pyd"
|
|
||||||
|
|
||||||
richcmp3.pyd: $(OBJ) richcmp3.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp3.obj $(PYLIB) /export:initrichcmp3 /out:"richcmp3.pyd"
|
|
||||||
|
|
||||||
.cpp.obj:
|
|
||||||
$(CPP) $(CPPOPTS) /c $*.cpp
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(PYEXE) comprehensive.py --broken-auto-ptr
|
|
||||||
$(PYEXE) test_abstract.py
|
|
||||||
$(PYEXE) test_getting_started1.py
|
|
||||||
$(PYEXE) test_getting_started2.py
|
|
||||||
$(PYEXE) test_simple_vector.py
|
|
||||||
$(PYEXE) test_do_it_yourself_convts.py
|
|
||||||
$(PYEXE) test_nested.py
|
|
||||||
$(PYEXE) test_pickle1.py
|
|
||||||
$(PYEXE) test_pickle2.py
|
|
||||||
$(PYEXE) test_pickle3.py
|
|
||||||
$(PYEXE) test_cross_module.py --broken-auto-ptr
|
|
||||||
$(PYEXE) test_richcmp1.py
|
|
||||||
$(PYEXE) test_richcmp2.py
|
|
||||||
$(PYEXE) test_richcmp3.py
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-del *.obj
|
|
||||||
-del *.lib
|
|
||||||
-del *.exp
|
|
||||||
-del *.idb
|
|
||||||
-del *.pyd
|
|
||||||
-del *.pyc
|
|
||||||
|
|
||||||
softlinks:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks
|
|
||||||
|
|
||||||
unlink:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink
|
|
||||||
|
|
||||||
cp:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp
|
|
||||||
|
|
||||||
rm:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm
|
|
||||||
|
|
||||||
copy:
|
|
||||||
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy
|
|
||||||
|
|
||||||
del:
|
|
||||||
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
# Usage:
|
|
||||||
#
|
|
||||||
# make copy Copy the sources and tests
|
|
||||||
# make Compile all sources
|
|
||||||
# make test Run doctest tests
|
|
||||||
# make clean Remove all object files
|
|
||||||
# make del Remove the sources and tests
|
|
||||||
#
|
|
||||||
# Revision history:
|
|
||||||
# 14 Dec 01 derived from vc60.mak (R.W. Grosse-Kunstleve)
|
|
||||||
|
|
||||||
ROOT=R:
|
|
||||||
BOOST_WIN="$(ROOT)\boost"
|
|
||||||
BOOST_UNIX=$(HOME)/boost
|
|
||||||
|
|
||||||
#PYEXE="C:\Program files\Python\python.exe"
|
|
||||||
#PYINC=-I"C:\Program files\Python\include"
|
|
||||||
#PYLIB="C:\Program files\Python\libs\python15.lib"
|
|
||||||
PYEXE="C:\Python21\python.exe"
|
|
||||||
PYINC=-I"C:\Python21\include"
|
|
||||||
PYLIB="C:\Python21\libs\python21.lib"
|
|
||||||
|
|
||||||
STDOPTS=-gccinc -prefix UseDLLPrefix.h -DBOOST_PYTHON_STATIC_LIB
|
|
||||||
WARNOPTS=-warn on,nounusedexpr,nounused
|
|
||||||
OPTOPTS=-O
|
|
||||||
|
|
||||||
CPP=mwcc
|
|
||||||
CPPOPTS=$(STDOPTS) $(WARNOPTS) $(OPTOPTS) \
|
|
||||||
$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC)
|
|
||||||
|
|
||||||
LD=mwld
|
|
||||||
LDOPTS=-export dllexport -shared
|
|
||||||
|
|
||||||
OBJ=classes.obj conversions.obj errors.obj extension_class.obj functions.obj \
|
|
||||||
init_function.obj module_builder.obj \
|
|
||||||
objects.obj types.obj cross_module.obj
|
|
||||||
|
|
||||||
.SUFFIXES: .obj .cpp
|
|
||||||
|
|
||||||
all: libboost_python.lib \
|
|
||||||
boost_python_test.pyd \
|
|
||||||
abstract.pyd \
|
|
||||||
getting_started1.pyd getting_started2.pyd \
|
|
||||||
simple_vector.pyd \
|
|
||||||
do_it_yourself_convts.pyd \
|
|
||||||
nested.pyd \
|
|
||||||
pickle1.pyd pickle2.pyd pickle3.pyd \
|
|
||||||
noncopyable_export.pyd noncopyable_import.pyd \
|
|
||||||
ivect.pyd dvect.pyd \
|
|
||||||
richcmp1.pyd richcmp2.pyd richcmp3.pyd
|
|
||||||
|
|
||||||
libboost_python.lib: $(OBJ)
|
|
||||||
$(LD) -library -o libboost_python.lib $(OBJ)
|
|
||||||
|
|
||||||
boost_python_test.pyd: $(OBJ) comprehensive.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) -o boost_python_test.pyd
|
|
||||||
|
|
||||||
abstract.pyd: $(OBJ) abstract.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) -o abstract.pyd
|
|
||||||
|
|
||||||
getting_started1.pyd: $(OBJ) getting_started1.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) -o getting_started1.pyd
|
|
||||||
|
|
||||||
getting_started2.pyd: $(OBJ) getting_started2.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) -o getting_started2.pyd
|
|
||||||
|
|
||||||
simple_vector.pyd: $(OBJ) simple_vector.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) -o simple_vector.pyd
|
|
||||||
|
|
||||||
do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.obj $(PYLIB) -o do_it_yourself_convts.pyd
|
|
||||||
|
|
||||||
nested.pyd: $(OBJ) nested.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) nested.obj $(PYLIB) -o nested.pyd
|
|
||||||
|
|
||||||
pickle1.pyd: $(OBJ) pickle1.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) -o pickle1.pyd
|
|
||||||
|
|
||||||
pickle2.pyd: $(OBJ) pickle2.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) -o pickle2.pyd
|
|
||||||
|
|
||||||
pickle3.pyd: $(OBJ) pickle3.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) -o pickle3.pyd
|
|
||||||
|
|
||||||
noncopyable_export.pyd: $(OBJ) noncopyable_export.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) -o noncopyable_export.pyd
|
|
||||||
|
|
||||||
noncopyable_import.pyd: $(OBJ) noncopyable_import.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) -o noncopyable_import.pyd
|
|
||||||
|
|
||||||
ivect.pyd: $(OBJ) ivect.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) -o ivect.pyd
|
|
||||||
|
|
||||||
dvect.pyd: $(OBJ) dvect.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) -o dvect.pyd
|
|
||||||
|
|
||||||
richcmp1.pyd: $(OBJ) richcmp1.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp1.obj $(PYLIB) -o richcmp1.pyd
|
|
||||||
|
|
||||||
richcmp2.pyd: $(OBJ) richcmp2.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp2.obj $(PYLIB) -o richcmp2.pyd
|
|
||||||
|
|
||||||
richcmp3.pyd: $(OBJ) richcmp3.obj
|
|
||||||
$(LD) $(LDOPTS) $(OBJ) richcmp3.obj $(PYLIB) -o richcmp3.pyd
|
|
||||||
|
|
||||||
.cpp.obj:
|
|
||||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(PYEXE) comprehensive.py
|
|
||||||
$(PYEXE) test_abstract.py
|
|
||||||
$(PYEXE) test_getting_started1.py
|
|
||||||
$(PYEXE) test_getting_started2.py
|
|
||||||
$(PYEXE) test_simple_vector.py
|
|
||||||
$(PYEXE) test_do_it_yourself_convts.py
|
|
||||||
$(PYEXE) test_nested.py
|
|
||||||
$(PYEXE) test_pickle1.py
|
|
||||||
$(PYEXE) test_pickle2.py
|
|
||||||
$(PYEXE) test_pickle3.py
|
|
||||||
$(PYEXE) test_cross_module.py
|
|
||||||
$(PYEXE) test_richcmp1.py
|
|
||||||
$(PYEXE) test_richcmp2.py
|
|
||||||
$(PYEXE) test_richcmp3.py
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-del *.obj
|
|
||||||
-del *.lib
|
|
||||||
-del *.exp
|
|
||||||
-del *.idb
|
|
||||||
-del *.pyd
|
|
||||||
-del *.pyc
|
|
||||||
|
|
||||||
softlinks:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks
|
|
||||||
|
|
||||||
unlink:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink
|
|
||||||
|
|
||||||
cp:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp
|
|
||||||
|
|
||||||
rm:
|
|
||||||
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm
|
|
||||||
|
|
||||||
copy:
|
|
||||||
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy
|
|
||||||
|
|
||||||
del:
|
|
||||||
$(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
call "c:\program files\metrowerks\codewarrior\other metrowerks tools\command line tools\cwenv.bat"
|
|
||||||
set MWWinx86LibraryFiles=MSL_All-DLL_x86.lib;gdi32.lib;user32.lib;kernel32.lib
|
|
||||||
@@ -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,180 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
|
|
||||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
|
||||||
|
|
||||||
<title>Building an Extension Module</title>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h1><img width="277" height="86" align="center" src=
|
|
||||||
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Building an
|
|
||||||
Extension Module</h1>
|
|
||||||
|
|
||||||
<p>The build process for Boost is currently undergoing some evolution,
|
|
||||||
and, it is to be hoped, improvement. The following facts may help:
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
Makefiles for various platforms and a Visual Studio project
|
|
||||||
reside in the Boost subdirectory <tt>libs/python/build</tt>.
|
|
||||||
Build targets include:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>The <tt>boost_python</tt> library for static linking with your
|
|
||||||
extension module. On the various Unices, this library will be
|
|
||||||
called <tt>libboost_python.a</tt>. When using Visual C++, the
|
|
||||||
library will be called <tt>boost_python.lib</tt>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<li>A comprehensive test of Boost.Python features. This test builds
|
|
||||||
a Boost.Python extension module, then runs Python to import the
|
|
||||||
module, and runs a series of tests on it using <tt><a href=
|
|
||||||
"../test/doctest.py">doctest</a></tt>. Source code for the module
|
|
||||||
and tests is available in the Boost subdirectory
|
|
||||||
<tt>libs/python/test</tt>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<li>Various examples from the Boost subdirectory
|
|
||||||
<tt>libs/python/example</tt>.
|
|
||||||
All these examples include a doctest modeled
|
|
||||||
on the comprehensive test above.
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
There is a group of makefiles with support for simultaneous
|
|
||||||
compilation on multiple platforms and a consistent set of
|
|
||||||
features that build the <tt>boost_python</tt> library for static
|
|
||||||
linking, the comprehensive test, and all examples in
|
|
||||||
<tt>libs/python/example</tt>:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../build/vc60.mak">vc60.mak</a>:
|
|
||||||
Visual C++ 6.0 Service Pack 4
|
|
||||||
|
|
||||||
<li><a href="../build/mingw32.mak">mingw32.mak</a>:
|
|
||||||
mingw32 (Win32-targeted) gcc 2.95.2
|
|
||||||
|
|
||||||
<li><a href="../build/linux_gcc.mak">linux_gcc.mak</a>:
|
|
||||||
gcc 2.95.2 on Linux/Unix
|
|
||||||
|
|
||||||
<li><a href="../build/tru64_cxx.mak">tru64_cxx.mak</a>:
|
|
||||||
Compaq Alpha using the Compaq cxx compiler
|
|
||||||
|
|
||||||
<li><a href="../build/irix_CC.mak">irix_CC.mak</a>:
|
|
||||||
Silicon Graphics IRIX 6.5 CC compiler
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<a href="http://cctbx.sourceforge.net/page_installation_adv.html#installation_boost_python"
|
|
||||||
>Usage of these makefiles is described here.</a>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
There is another group of makefiles for GNU make.
|
|
||||||
These makefiles are less redundant than the makefiles
|
|
||||||
in the group above,
|
|
||||||
but the list of compilation targets is not as complete
|
|
||||||
and there is no support for simultaneous compilation
|
|
||||||
on multiple platforms.
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../build/como.mak">como.mak</a>:
|
|
||||||
Comeau C++ on Linux
|
|
||||||
|
|
||||||
<li><a href="../build/gcc.mak">gcc.mak</a>:
|
|
||||||
GCC on Linux/Unix.
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
A project workspace for Microsoft Visual Studio is provided at <tt><a
|
|
||||||
href="../build/build.dsw">libs/python/build/build.dsw</a></tt>. The
|
|
||||||
include paths for this project may need to be changed for your
|
|
||||||
installation. They currently assume that python has been installed at
|
|
||||||
<tt>c:\tools\python</tt>. Three configurations of all targets are
|
|
||||||
supported:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Release (optimization, <tt>-DNDEBUG</tt>)
|
|
||||||
|
|
||||||
<li>Debug (no optimization <tt>-D_DEBUG</tt>)
|
|
||||||
|
|
||||||
<li>DebugPython (no optimization, <tt>-D_DEBUG
|
|
||||||
-DBOOST_DEBUG_PYTHON</tt>)
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>When extension modules are built with Visual C++ using
|
|
||||||
<tt>-D_DEBUG</tt>, Python defaults to <i>force</i> linking with a
|
|
||||||
special debugging version of the Python DLL. Since this debug DLL
|
|
||||||
isn't supplied with the default Python installation for Windows,
|
|
||||||
Boost.Python uses <tt><a href=
|
|
||||||
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a></tt>
|
|
||||||
to temporarily undefine <tt>_DEBUG</tt> when <tt>Python.h</tt> is
|
|
||||||
<tt>#include</tt>d.
|
|
||||||
|
|
||||||
<p>If you want the extra runtime checks available with the debugging
|
|
||||||
version of the library, <tt>#define BOOST_DEBUG_PYTHON</tt> to
|
|
||||||
re-enable library forcing, and link with the DebugPython version of
|
|
||||||
<tt>boost_python.lib</tt>. You'll need to get the debugging version
|
|
||||||
of the Python executable (<tt>python_d.exe</tt>) and DLL
|
|
||||||
(<tt>python20_d.dll</tt> or <tt>python15_d.dll</tt>). The Python
|
|
||||||
sources include project files for building these. If you <a href=
|
|
||||||
"http://www.python.org">download</a> them, change the name of the
|
|
||||||
top-level directory to <tt>src</tt>, and install it under
|
|
||||||
<tt>c:\tools\python</tt>, the workspace supplied by Boost.Python will
|
|
||||||
be able to use it without modification. Just open
|
|
||||||
<tt>c:\tools\python\src\pcbuild\pcbuild.dsw</tt> and invoke "build
|
|
||||||
all" to generate all the debugging targets.
|
|
||||||
|
|
||||||
<p>If you do not <tt>#define BOOST_DEBUG_PYTHON</tt>, be sure that
|
|
||||||
any source files <tt>#include <<a href=
|
|
||||||
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a>></tt>
|
|
||||||
instead of the usual <tt>Python.h</tt>, or you will have link
|
|
||||||
incompatibilities.<br>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
If your platform isn't directly supported, you can build a static
|
|
||||||
library from the following source files (in the Boost subdirectory
|
|
||||||
<tt>libs/python/src</tt>), or compile them directly and link the
|
|
||||||
resulting objects into your extension module:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/classes.cpp">classes.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/conversions.cpp">conversions.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/cross_module.cpp">cross_module.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/extension_class.cpp">extension_class.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/functions.cpp">functions.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/init_function.cpp">init_function.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/module_builder.cpp">module_builder.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/objects.cpp">objects.cpp</a>
|
|
||||||
|
|
||||||
<li><a href=
|
|
||||||
"../../../libs/python/src/types.cpp">types.cpp</a>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
Next: <a href="enums.html">Wrapping Enums</a> Previous: <a href=
|
|
||||||
"under-the-hood.html">A Peek Under the Hood</a> Up: <a href=
|
|
||||||
"index.html">Top</a>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<p>© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided ``as is'' without
|
|
||||||
express or implied warranty, and with no claim as to its suitability for
|
|
||||||
any purpose.
|
|
||||||
|
|
||||||
<p>Updated: Apr 17, 2001 (R.W. Grosse-Kunstleve)
|
|
||||||
</div>
|
|
||||||
@@ -1,231 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
Comparisons with Other Systems
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
|
||||||
Comparisons with
|
|
||||||
Other Systems
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h2>CXX</h2>
|
|
||||||
<p>
|
|
||||||
Like Boost.Python, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
|
||||||
provide a C++-oriented interface to Python. In most cases, as with the
|
|
||||||
boost library, it relieves the user from worrying about
|
|
||||||
reference-counts. Both libraries automatically convert thrown C++
|
|
||||||
exceptions into Python exceptions. As far as I can tell, CXX has no
|
|
||||||
support for subclassing C++ extension types in Python. An even
|
|
||||||
more significant difference is that a user's C++ code is still basically
|
|
||||||
``dealing with Python objects'', though they are wrapped in
|
|
||||||
C++ classes. This means such jobs as argument parsing and conversion are
|
|
||||||
still left to be done explicitly by the user.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
CXX claims to interoperate well with the C++ Standard Library
|
|
||||||
(a.k.a. STL) by providing iterators into Python Lists and Dictionaries,
|
|
||||||
but the claim is unfortunately unsupportable. The problem is that in
|
|
||||||
general, access to Python sequence and mapping elements through
|
|
||||||
iterators requires the use of proxy objects as the return value of
|
|
||||||
iterator dereference operations. This usage conflicts with the basic
|
|
||||||
ForwardIterator requirements in <a
|
|
||||||
href="http://anubis.dkuug.dk/jtc1/sc22/open/n2356/lib-iterators.html#lib.forward.iterators">
|
|
||||||
section 24.1.3 of the standard</a> (dereferencing must produce a
|
|
||||||
reference). Although you may be able to use these iterators with some
|
|
||||||
operations in some standard library implementations, it is neither
|
|
||||||
guaranteed to work nor portable.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
As far as I can tell, CXX enables one to write what is essentially
|
|
||||||
idiomatic Python code in C++, manipulating Python objects through the
|
|
||||||
same fully-generic interfaces we use in Python. While you're hardly
|
|
||||||
programming directly to the ``bare metal'' with CXX, it basically
|
|
||||||
presents a ``C++-ized'' version of the Python 'C' API. Some fraction of
|
|
||||||
that capability is available in Boost.Python through <tt><a
|
|
||||||
href="../../../boost/python/objects.hpp">boost/python/objects.hpp</a></tt>,
|
|
||||||
which provides C++ objects corresponding to Python lists, tuples,
|
|
||||||
strings, and dictionaries, and through <tt><a
|
|
||||||
href="../../../boost/python/callback.hpp">boost/python/callback.hpp</a></tt>,
|
|
||||||
which allows you to call back into python with C++ arguments.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
|
|
||||||
author of CXX, has told me that what I've described is only half of the
|
|
||||||
picture with CXX, but I never understood his explanation well-enough to
|
|
||||||
fill in the other half. Here is his response to the commentary above:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
``My intention with CXX was not to do what you are doing. It was to enable a
|
|
||||||
person to write an extension directly in C++ rather than C. I figured others had
|
|
||||||
the wrapping business covered. I thought maybe CXX would provide an easier
|
|
||||||
target language for those making wrappers, but I never explored
|
|
||||||
that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h2>SWIG</h2>
|
|
||||||
<p>
|
|
||||||
<a href= "http://www.swig.org/">SWIG</a> is an impressively mature tool
|
|
||||||
for exporting an existing ANSI 'C' interface into various scripting
|
|
||||||
languages. Swig relies on a parser to read your source code and produce
|
|
||||||
additional source code files which can be compiled into a Python (or
|
|
||||||
Perl or Tcl) extension module. It has been successfully used to create
|
|
||||||
many Python extension modules. Like Boost.Python, SWIG is trying to allow an
|
|
||||||
existing interface to be wrapped with little or no change to the
|
|
||||||
existing code. The documentation says ``SWIG parses a form of ANSI C
|
|
||||||
syntax that has been extended with a number of special directives. As a
|
|
||||||
result, interfaces are usually built by grabbing a header file and
|
|
||||||
tweaking it a little bit.'' For C++ interfaces, the tweaking has often
|
|
||||||
proven to amount to more than just a little bit. One user
|
|
||||||
writes:
|
|
||||||
|
|
||||||
<blockquote> ``The problem with swig (when I used it) is that it
|
|
||||||
couldnt handle templates, didnt do func overloading properly etc. For
|
|
||||||
ANSI C libraries this was fine. But for usual C++ code this was a
|
|
||||||
problem. Simple things work. But for anything very complicated (or
|
|
||||||
realistic), one had to write code by hand. I believe Boost.Python doesn't have
|
|
||||||
this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
|
|
||||||
wrap correctly.''<br><i>-Prabhu Ramachandran</i>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
By contrast, Boost.Python doesn't attempt to parse C++ - the problem is simply
|
|
||||||
too complex to do correctly. <a name="sic">Technically</a>, one does
|
|
||||||
write code by hand to use Boost.Python. The goal, however, has been to make
|
|
||||||
that code nearly as simple as listing the names of the classes and
|
|
||||||
member functions you want to expose in Python.
|
|
||||||
|
|
||||||
<h2>SIP</h2>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
|
|
||||||
is a system similar to SWIG, though seemingly more
|
|
||||||
C++-oriented. The author says that like Boost.Python, SIP supports overriding
|
|
||||||
extension class member functions in Python subclasses. It appears to
|
|
||||||
have been designed specifically to directly support some features of
|
|
||||||
PyQt/PyKDE, which is its primary client. Documentation is almost
|
|
||||||
entirely missing at the time of this writing, so a detailed comparison
|
|
||||||
is difficult.
|
|
||||||
|
|
||||||
<h2>ILU</h2>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
href="ftp://ftp.parc.xerox.com/pub/ilu/ilu.html">ILU</a>
|
|
||||||
is a very ambitious project which tries to describe a module's interface
|
|
||||||
(types and functions) in terms of an <a
|
|
||||||
href="ftp://ftp.parc.xerox.com/pub/ilu/2.0b1/manual-html/manual_2.html">Interface
|
|
||||||
Specification Language</a> (ISL) so that it can be uniformly interfaced
|
|
||||||
to a wide range of computer languages, including Common Lisp, C++, C,
|
|
||||||
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
|
|
||||||
header file describing the interface, of which the user is expected to
|
|
||||||
provide an implementation. Unlike Boost.Python, this means that the system
|
|
||||||
imposes implementation details on your C++ code at the deepest level. It
|
|
||||||
is worth noting that some of the C++ names generated by ILU are supposed
|
|
||||||
to be reserved to the C++ implementation. It is unclear from the
|
|
||||||
documentation whether ILU supports overriding C++ virtual functions in Python.
|
|
||||||
|
|
||||||
<h2>GRAD</h2>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</a>
|
|
||||||
is another very ambitious project aimed at generating Python wrappers for
|
|
||||||
interfaces written in ``legacy languages'', among which C++ is the first one
|
|
||||||
implemented. Like SWIG, it aims to parse source code and automatically
|
|
||||||
generate wrappers, though it appears to take a more sophisticated approach
|
|
||||||
to parsing in general and C++ in particular, so it should do a much better
|
|
||||||
job with C++. It appears to support function overloading. The
|
|
||||||
documentation is missing a lot of information I'd like to see, so it is
|
|
||||||
difficult to give an accurate and fair assessment. I am left with the
|
|
||||||
following questions:
|
|
||||||
<ul>
|
|
||||||
<li>Does it support overriding of virtual functions?
|
|
||||||
<li>What about overriding private or protected virtual functions (the documentation indicates
|
|
||||||
that only public interfaces are supported)?
|
|
||||||
<li>Which C++ language constructs are supportd?
|
|
||||||
<li>Does it support implicit conversions between wrapped C++ classes that have
|
|
||||||
an inheritance relationship?
|
|
||||||
<li>Does it support smart pointers?
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
Anyone in the possession of the answers to these questions will earn my
|
|
||||||
gratitude for a write-up <code>;-)</code>
|
|
||||||
|
|
||||||
<h2>Zope ExtensionClasses</h2>
|
|
||||||
<p>
|
|
||||||
<a href="http:http://www.digicool.com/releases/ExtensionClass">
|
|
||||||
ExtensionClasses in Zope</a> use the same underlying mechanism as Boost.Python
|
|
||||||
to support subclassing of extension types in Python, including
|
|
||||||
multiple-inheritance. Both systems support pickling/unpickling of
|
|
||||||
extension class instances in very similar ways. Both systems rely on the
|
|
||||||
same ``<a
|
|
||||||
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
|
|
||||||
Beaudry Hack</a>'' that also inspired Don's MESS System.
|
|
||||||
<p>
|
|
||||||
The major differences are:
|
|
||||||
<ul>
|
|
||||||
<li>Zope is entirely 'C' language-based. It doesn't require a C++
|
|
||||||
compiler, so it's much more portable than Boost.Python, which stresses
|
|
||||||
the limits of even some modern C++ implementations.
|
|
||||||
|
|
||||||
<li>
|
|
||||||
Boost.Python lifts the burden on the user to parse and convert function
|
|
||||||
argument types. Zope provides no such facility.
|
|
||||||
<li>
|
|
||||||
Boost.Python lifts the burden on the user to maintain Python
|
|
||||||
reference-counts.
|
|
||||||
<li>
|
|
||||||
Boost.Python supports function overloading; Zope does not.
|
|
||||||
<li>
|
|
||||||
Boost.Python supplies a simple mechanism for exposing read-only and
|
|
||||||
read/write access to data members of the wrapped C++ type as Python
|
|
||||||
attributes.
|
|
||||||
<li>
|
|
||||||
Writing a Zope ExtensionClass is significantly more complex than
|
|
||||||
exposing a C++ class to python using Boost.Python (mostly a summary of the
|
|
||||||
previous 4 items). <a href=
|
|
||||||
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
|
|
||||||
Zope Example</a> illustrates the differences.
|
|
||||||
<li>
|
|
||||||
Zope's ExtensionClasses are specifically motivated by ``the need for a
|
|
||||||
C-based persistence mechanism''. Boost.Python's are motivated by the desire
|
|
||||||
to simply reflect a C++ API into Python with as little modification as
|
|
||||||
possible.
|
|
||||||
<li>
|
|
||||||
The following Zope restriction does not apply to Boost.Python: ``At most one
|
|
||||||
base extension direct or indirect super class may define C data
|
|
||||||
members. If an extension subclass inherits from multiple base
|
|
||||||
extension classes, then all but one must be mix-in classes that
|
|
||||||
provide extension methods but no data.''
|
|
||||||
<li>
|
|
||||||
Zope requires use of the somewhat funky inheritedAttribute (search for
|
|
||||||
``inheritedAttribute'' on <a
|
|
||||||
href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
|
|
||||||
method to access base class methods. In Boost.Python, base class methods can
|
|
||||||
be accessed in the usual way by writing
|
|
||||||
``<code>BaseClass.method</code>''.
|
|
||||||
<li>
|
|
||||||
Zope supplies some creative but esoteric idioms such as <a href=
|
|
||||||
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
|
|
||||||
Acquisition</a>. No specific support for this is built into Boost.Python.
|
|
||||||
<li>
|
|
||||||
Zope's ComputedAttribute support is designed to be used from Python.
|
|
||||||
<a href="special.html#getter_setter">The analogous feature of
|
|
||||||
Boost.Python</a> can be used from C++ or Python. The feature is arguably
|
|
||||||
easier to use in Boost.Python.
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
Next: <a href="example1.html">A Simple Example Using Boost.Python</a>
|
|
||||||
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided ``as is'' without
|
|
||||||
express or implied warranty, and with no claim as to its suitability
|
|
||||||
for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Mar 6, 2001
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,336 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
|
|
||||||
<title>Cross-extension-module dependencies</title>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
|
|
||||||
<img src="../../../c++boost.gif"
|
|
||||||
alt="c++boost.gif (8819 bytes)"
|
|
||||||
align="center"
|
|
||||||
width="277" height="86">
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h1>Cross-extension-module dependencies</h1>
|
|
||||||
|
|
||||||
It is good programming practice to organize large projects as modules
|
|
||||||
that interact with each other via well defined interfaces. With
|
|
||||||
Boost.Python it is possible to reflect this organization at the C++
|
|
||||||
level at the Python level. This is, each logical C++ module can be
|
|
||||||
organized as a separate Python extension module.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
At first sight this might seem natural and straightforward. However, it
|
|
||||||
is a fairly complex problem to establish cross-extension-module
|
|
||||||
dependencies while maintaining the same ease of use Boost.Python
|
|
||||||
provides for classes that are wrapped in the same extension module. To
|
|
||||||
a large extent this complexity can be hidden from the author of a
|
|
||||||
Boost.Python extension module, but not entirely.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>The recipe</h2>
|
|
||||||
|
|
||||||
Suppose there is an extension module that exposes certain instances of
|
|
||||||
the C++ <tt>std::vector</tt> template library such that it can be used
|
|
||||||
from Python in the following manner:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import std_vector
|
|
||||||
v = std_vector.double([1, 2, 3, 4])
|
|
||||||
v.push_back(5)
|
|
||||||
v.size()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
Suppose the <tt>std_vector</tt> module is done well and reflects all
|
|
||||||
C++ functions that are useful at the Python level, for all C++ built-in
|
|
||||||
data types (<tt>std_vector.int</tt>, <tt>std_vector.long</tt>, etc.).
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Suppose further that there is statistic module with a C++ class that
|
|
||||||
has constructors or member functions that use or return a
|
|
||||||
<tt>std::vector</tt>. For example:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
class xy {
|
|
||||||
public:
|
|
||||||
xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
|
|
||||||
const std::vector<double>& x() const { return m_x; }
|
|
||||||
const std::vector<double>& y() const { return m_y; }
|
|
||||||
double correlation();
|
|
||||||
private:
|
|
||||||
std::vector<double> m_x;
|
|
||||||
std::vector<double> m_y;
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
What is more natural than reusing the <tt>std_vector</tt> extension
|
|
||||||
module to expose these constructors or functions to Python?
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Unfortunately, what seems natural needs a little work in both the
|
|
||||||
<tt>std_vector</tt> and the <tt>statistics</tt> module.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In the <tt>std_vector</tt> extension module,
|
|
||||||
<tt>std::vector<double></tt> is exposed to Python in the usual
|
|
||||||
way with the <tt>class_builder<></tt> template. To also enable the
|
|
||||||
automatic conversion of <tt>std::vector<double></tt> function
|
|
||||||
arguments or return values in other Boost.Python C++ modules, the
|
|
||||||
converters that convert a <tt>std::vector<double></tt> C++ object
|
|
||||||
to a Python object and vice versa (i.e. the <tt>to_python()</tt> and
|
|
||||||
<tt>from_python()</tt> template functions) have to be exported. For
|
|
||||||
example:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/cross_module.hpp>
|
|
||||||
//...
|
|
||||||
class_builder<std::vector<double> > v_double(std_vector_module, "double");
|
|
||||||
export_converters(v_double);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
In the extension module that wraps <tt>class xy</tt> we can now import
|
|
||||||
these converters with the <tt>import_converters<></tt> template.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/cross_module.hpp>
|
|
||||||
//...
|
|
||||||
import_converters<std::vector<double> > v_double_converters("std_vector", "double");
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
That is all. All the attributes that are defined for
|
|
||||||
<tt>std_vector.double</tt> in the <tt>std_vector</tt> Boost.Python
|
|
||||||
module will be available for the returned objects of <tt>xy.x()</tt>
|
|
||||||
and <tt>xy.y()</tt>. Similarly, the constructor for <tt>xy</tt> will
|
|
||||||
accept objects that were created by the <tt>std_vector</tt>module.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Placement of <tt>import_converters<></tt> template instantiations</h2>
|
|
||||||
|
|
||||||
<tt>import_converts<></tt> can be viewed as a drop-in replacement
|
|
||||||
for <tt>class_wrapper<></tt>, and the recommendations for the
|
|
||||||
placement of <tt>class_wrapper<></tt> template instantiations
|
|
||||||
also apply to to <tt>import_converts<></tt>. In particular, it is
|
|
||||||
important that an instantiation of <tt>class_wrapper<></tt> is
|
|
||||||
visible to any code which wraps a C++ function with a <tt>T</tt>,
|
|
||||||
<tt>T*</tt>, const <tt>T&</tt>, etc. parameter or return value.
|
|
||||||
Therefore you may want to group all <tt>class_wrapper<></tt> and
|
|
||||||
<tt>import_converts<></tt> instantiations at the top of your
|
|
||||||
module's init function, then <tt>def()</tt> the member functions later
|
|
||||||
to avoid problems with inter-class dependencies.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Non-copyable types</h2>
|
|
||||||
|
|
||||||
<tt>export_converters()</tt> instantiates C++ template functions that
|
|
||||||
invoke the copy constructor of the wrapped type. For a type that is
|
|
||||||
non-copyable this will result in compile-time error messages. In such a
|
|
||||||
case, <tt>export_converters_noncopyable()</tt> can be used to export
|
|
||||||
the converters that do not involve the copy constructor of the wrapped
|
|
||||||
type. For example:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
class_builder<store> py_store(your_module, "store");
|
|
||||||
export_converters_noncopyable(py_store);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
The corresponding <tt>import_converters<></tt> statement does not
|
|
||||||
need any special attention:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import_converters<store> py_store("noncopyable_export", "store");
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Python module search path</h2>
|
|
||||||
|
|
||||||
The <tt>std_vector</tt> and <tt>statistics</tt> modules can now be used
|
|
||||||
in the following way:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import std_vector
|
|
||||||
import statistics
|
|
||||||
x = std_vector.double([1, 2, 3, 4])
|
|
||||||
y = std_vector.double([2, 4, 6, 8])
|
|
||||||
xy = statistics.xy(x, y)
|
|
||||||
xy.correlation()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
In this example it is clear that Python has to be able to find both the
|
|
||||||
<tt>std_vector</tt> and the <tt>statistics</tt> extension module. In
|
|
||||||
other words, both extension modules need to be in the Python module
|
|
||||||
search path (<tt>sys.path</tt>).
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The situation is not always this obvious. Suppose the
|
|
||||||
<tt>statistics</tt> module has a <tt>random()</tt> function that
|
|
||||||
returns a vector of random numbers with a given length:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import statistics
|
|
||||||
x = statistics.random(5)
|
|
||||||
y = statistics.random(5)
|
|
||||||
xy = statistics.xy(x, y)
|
|
||||||
xy.correlation()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
A naive user will not easily anticipate that the <tt>std_vector</tt>
|
|
||||||
module is used to pass the <tt>x</tt> and <tt>y</tt> vectors around. If
|
|
||||||
the <tt>std_vector</tt> module is in the Python module search path,
|
|
||||||
this form of ignorance is of no harm. On the contrary, we are glad
|
|
||||||
that we do not have to bother the user with details like this.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If the <tt>std_vector</tt> module is not in the Python module search
|
|
||||||
path, a Python exception will be raised:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
Traceback (innermost last):
|
|
||||||
File "foo.py", line 2, in ?
|
|
||||||
x = statistics.random(5)
|
|
||||||
ImportError: No module named std_vector
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
As is the case with any system of a non-trivial complexity, it is
|
|
||||||
important that the setup is consistent and complete.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Two-way module dependencies</h2>
|
|
||||||
|
|
||||||
Boost.Python supports two-way module dependencies. This is best
|
|
||||||
illustrated by a simple example.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Suppose there is a module <tt>ivect</tt> that implements vectors of
|
|
||||||
integers, and a similar module <tt>dvect</tt> that implements vectors
|
|
||||||
of doubles. We want to be able do convert an integer vector to a double
|
|
||||||
vector and vice versa. For example:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import ivect
|
|
||||||
iv = ivect.ivect((1,2,3,4,5))
|
|
||||||
dv = iv.as_dvect()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
The last expression will implicitly import the <tt>dvect</tt> module in
|
|
||||||
order to enable the conversion of the C++ representation of
|
|
||||||
<tt>dvect</tt> to a Python object. The analogous is possible for a
|
|
||||||
<tt>dvect</tt>:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import dvect
|
|
||||||
dv = dvect.dvect((1,2,3,4,5))
|
|
||||||
iv = dv.as_ivect()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
Now the <tt>ivect</tt> module is imported implicitly.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Note that the two-way dependencies are possible because the
|
|
||||||
dependencies are resolved only when needed. This is, the initialization
|
|
||||||
of the <tt>ivect</tt> module does not rely on the <tt>dvect</tt>
|
|
||||||
module, and vice versa. Only if <tt>as_dvect()</tt> or
|
|
||||||
<tt>as_ivect()</tt> is actually invoked will the corresponding module
|
|
||||||
be implicitly imported. This also means that, for example, the
|
|
||||||
<tt>dvect</tt> module does not have to be available at all if
|
|
||||||
<tt>as_dvect()</tt> is never used.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Clarification of compile-time and link-time dependencies</h2>
|
|
||||||
|
|
||||||
Boost.Python's support for resolving cross-module dependencies at
|
|
||||||
runtime does not imply that compile-time dependencies are eliminated.
|
|
||||||
For example, the statistics extension module in the example above will
|
|
||||||
need to <tt>#include <vector></tt>. This is immediately obvious
|
|
||||||
from the definition of <tt>class xy</tt>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If a library is wrapped that consists of both header files and compiled
|
|
||||||
components (e.g. <tt>libdvect.a</tt>, <tt>dvect.lib</tt>, etc.), both
|
|
||||||
the Boost.Python extension module with the
|
|
||||||
<tt>export_converters()</tt> statement and the module with the
|
|
||||||
<tt>import_converters<></tt> statement need to be linked against
|
|
||||||
the object library. Ideally one would build a shared library (e.g.
|
|
||||||
<tt>libdvect.so</tt>, <tt>dvect.dll</tt>, etc.). However, this
|
|
||||||
introduces the issue of having to configure the search path for the
|
|
||||||
dynamic loading correctly. For small libraries it is therefore often
|
|
||||||
more convenient to ignore the fact that the object files are loaded
|
|
||||||
into memory more than once.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Summary of motivation for cross-module support</h2>
|
|
||||||
|
|
||||||
The main purpose of Boost.Python's cross-module support is to allow for
|
|
||||||
a modular system layout. With this support it is straightforward to
|
|
||||||
reflect C++ code organization at the Python level. Without the
|
|
||||||
cross-module support, a multi-purpose module like <tt>std_vector</tt>
|
|
||||||
would be impractical because the entire wrapper code would somehow have
|
|
||||||
to be duplicated in all extension modules that use it, making them
|
|
||||||
harder to maintain and harder to build.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Another motivation for the cross-module support is that two extension
|
|
||||||
modules that wrap the same class cannot both be imported into Python.
|
|
||||||
For example, if there are two modules <tt>A</tt> and <tt>B</tt> that
|
|
||||||
both wrap a given <tt>class X</tt>, this will work:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import A
|
|
||||||
x = A.X()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
This will also work:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import B
|
|
||||||
x = B.X()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
However, this will fail:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import A
|
|
||||||
import B
|
|
||||||
python: /net/cci/rwgk/boost/boost/python/detail/extension_class.hpp:866:
|
|
||||||
static void boost::python::detail::class_registry<X>::register_class(boost::python::detail::extension_class_base *):
|
|
||||||
Assertion `static_class_object == 0' failed.
|
|
||||||
Abort
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
A good solution is to wrap <tt>class X</tt> only once. Depending on the
|
|
||||||
situation, this could be done by module <tt>A</tt> or <tt>B</tt>, or an
|
|
||||||
additional small extension module that only wraps and exports
|
|
||||||
<tt>class X</tt>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Finally, there can be important psychological or political reasons for
|
|
||||||
using the cross-module support. If a group of classes is lumped
|
|
||||||
together with many others in a huge module, the authors will have
|
|
||||||
difficulties in being identified with their work. The situation is
|
|
||||||
much more transparent if the work is represented by a module with a
|
|
||||||
recognizable name. This is not just a question of strong egos, but also
|
|
||||||
of getting credit and funding.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Why not use <tt>export_converters()</tt> universally?</h2>
|
|
||||||
|
|
||||||
There is some overhead associated with the Boost.Python cross-module
|
|
||||||
support. Depending on the platform, the size of the code generated by
|
|
||||||
<tt>export_converters()</tt> is roughly 10%-20% of that generated
|
|
||||||
by <tt>class_builder<></tt>. For a large extension module with
|
|
||||||
many wrapped classes, this could mean a significant difference.
|
|
||||||
Therefore the general recommendation is to use
|
|
||||||
<tt>export_converters()</tt> only for classes that are likely to
|
|
||||||
be used as function arguments or return values in other modules.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
© Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy,
|
|
||||||
use, modify, sell and distribute this document is granted provided this
|
|
||||||
copyright notice appears in all copies. This document is provided "as
|
|
||||||
is" without express or implied warranty, and with no claim as to its
|
|
||||||
suitability for any purpose.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Updated: April 2001
|
|
||||||
|
|
||||||
</div>
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
Given a real Python class 'A', a wrapped C++ class 'B', and this definition:
|
|
||||||
|
|
||||||
class C(A, B):
|
|
||||||
def __init__(self):
|
|
||||||
B.__init__(self)
|
|
||||||
self.x = 1
|
|
||||||
...
|
|
||||||
|
|
||||||
c = C()
|
|
||||||
|
|
||||||
this diagram describes the internal structure of an instance of 'C', including
|
|
||||||
its inheritance relationships. Note that ExtensionClass<B> is derived from
|
|
||||||
Class<ExtensionInstance>, and is in fact identical for all intents and purposes.
|
|
||||||
|
|
||||||
MetaClass<ExtensionInstance>
|
|
||||||
+---------+ +---------+
|
|
||||||
types.ClassType: | | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
+---------+ +---------+
|
|
||||||
^ ^ ^
|
|
||||||
PyClassObject | ExtensionClass<B> | |
|
|
||||||
A: +------------+ | B: +------------+ | |
|
|
||||||
| ob_type -+-+ | ob_type -+-----+ |
|
|
||||||
| | ()<--+- __bases__ | |
|
|
||||||
| | | __dict__ -+->{...} |
|
|
||||||
| | 'B'<-+- __name__ | |
|
|
||||||
+------------+ +------------+ |
|
|
||||||
^ ^ |
|
|
||||||
| | |
|
|
||||||
+-----+ +-------------+ |
|
|
||||||
| | |
|
|
||||||
| | Class<ExtensionInstance> |
|
|
||||||
| | C: +------------+ |
|
|
||||||
| | | ob_type -+------------+
|
|
||||||
tuple:(*, *)<--+- __bases__ |
|
|
||||||
| __dict__ -+->{__module__, <methods, etc.>}
|
|
||||||
'C' <-+- __name__ |
|
|
||||||
+------------+
|
|
||||||
^ (in case of inheritance from more than one
|
|
||||||
| extension class, this vector would contain
|
|
||||||
+---------------+ a pointer to an instance holder for the data
|
|
||||||
| of each corresponding C++ class)
|
|
||||||
| ExtensionInstance
|
|
||||||
| c: +---------------------+ std::vector<InstanceHolderBase>
|
|
||||||
+----+- __class__ | +---+--
|
|
||||||
| m_wrapped_objects -+->| * | ...
|
|
||||||
{'x': 1}<-+- __dict__ | +-|-+--
|
|
||||||
+---------------------+ | InstanceValueHolder<B>
|
|
||||||
| +--------------------------------+
|
|
||||||
+-->| (contains a C++ instance of B) |
|
|
||||||
+--------------------------------+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
In our inheritance test cases in extclass_demo.cpp/test_extclass.py, we have the
|
|
||||||
following C++ inheritance hierarchy:
|
|
||||||
|
|
||||||
+-----+ +----+
|
|
||||||
| A1 | | A2 |
|
|
||||||
+-----+ +----+
|
|
||||||
^ ^ ^ ^ ^
|
|
||||||
| | | | |
|
|
||||||
+-----+ | +---------+-----+
|
|
||||||
| | | |
|
|
||||||
| +---+----------+
|
|
||||||
.......!...... | |
|
|
||||||
: A_callback : +-+--+ +-+--+
|
|
||||||
:............: | B1 | | B2 |
|
|
||||||
+----+ +----+
|
|
||||||
^
|
|
||||||
|
|
|
||||||
+-------+---------+
|
|
||||||
| |
|
|
||||||
+-+-+ ......!.......
|
|
||||||
| C | : B_callback :
|
|
||||||
+---+ :............:
|
|
||||||
|
|
||||||
|
|
||||||
A_callback and B_callback are used as part of the wrapping mechanism but not
|
|
||||||
represented in Python. C is also not represented in Python but is delivered
|
|
||||||
there polymorphically through a smart pointer.
|
|
||||||
|
|
||||||
This is the data structure in Python.
|
|
||||||
|
|
||||||
ExtensionClass<A1>
|
|
||||||
A1: +------------+
|
|
||||||
()<--+- __bases__ |
|
|
||||||
| __dict__ -+->{...}
|
|
||||||
+------------+
|
|
||||||
^
|
|
||||||
| ExtensionInstance
|
|
||||||
| a1: +---------------------+ vec InstanceValueHolder<A1,A_callback>
|
|
||||||
+---------+- __class__ | +---+ +---------------------+
|
|
||||||
| | m_wrapped_objects -+->| *-+-->| contains A_callback |
|
|
||||||
| +---------------------+ +---+ +---------------------+
|
|
||||||
|
|
|
||||||
| ExtensionInstance
|
|
||||||
| pa1_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
|
|
||||||
+---------+- __class__ | +---+ +---+
|
|
||||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ A1
|
|
||||||
| +---------------------+ +---+ +---+ | +---+
|
|
||||||
| +->| |
|
|
||||||
| ExtensionInstance +---+
|
|
||||||
| pb1_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
|
|
||||||
+---------+- __class__ | +---+ +---+
|
|
||||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ B1
|
|
||||||
| +---------------------+ +---+ +---+ | +---+
|
|
||||||
| +->| |
|
|
||||||
| ExtensionInstance +---+
|
|
||||||
| pb2_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
|
|
||||||
+---------+- __class__ | +---+ +---+
|
|
||||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ B2
|
|
||||||
| +---------------------+ +---+ +---+ | +---+
|
|
||||||
| +->| |
|
|
||||||
| +---+
|
|
||||||
| ExtensionClass<A1>
|
|
||||||
| A2: +------------+
|
|
||||||
| ()<--+- __bases__ |
|
|
||||||
| | __dict__ -+->{...}
|
|
||||||
| +------------+
|
|
||||||
| ^
|
|
||||||
| | ExtensionInstance
|
|
||||||
| a2: | +---------------------+ vec InstanceValueHolder<A2>
|
|
||||||
| +-+- __class__ | +---+ +-------------+
|
|
||||||
| | | m_wrapped_objects -+->| *-+-->| contains A2 |
|
|
||||||
| | +---------------------+ +---+ +-------------+
|
|
||||||
| |
|
|
||||||
| | ExtensionInstance
|
|
||||||
| pa2_a2: | +---------------------+ vec InstancePtrHolder<auto_ptr<A2>,A2>
|
|
||||||
| +-+- __class__ | +---+ +---+
|
|
||||||
| | | m_wrapped_objects -+->| *-+-->| *-+-+ A2
|
|
||||||
| | +---------------------+ +---+ +---+ | +---+
|
|
||||||
| | +->| |
|
|
||||||
| | ExtensionInstance +---+
|
|
||||||
| pb1_a2: | +---------------------+ vec InstancePtrHolder<auto_ptr<A2>,A2>
|
|
||||||
| +-+- __class__ | +---+ +---+
|
|
||||||
| | | m_wrapped_objects -+->| *-+-->| *-+-+ B1
|
|
||||||
| | +---------------------+ +---+ +---+ | +---+
|
|
||||||
| | +->| |
|
|
||||||
| | +---+
|
|
||||||
| |
|
|
||||||
| +---------------+------------------------------+
|
|
||||||
| | |
|
|
||||||
+------+-------------------------+-|----------------------------+ |
|
|
||||||
| | | | |
|
|
||||||
| Class<ExtensionInstance> | | ExtensionClass<B1> | | ExtensionClass<B1>
|
|
||||||
| DA1: +------------+ | | B1: +------------+ | | B2: +------------+
|
|
||||||
(*,)<---+- __bases__ | (*,*)<---+- __bases__ | (*,*)<---+- __bases__ |
|
|
||||||
| __dict__ -+->{...} | __dict__ -+->{...} | __dict__ -+->{...}
|
|
||||||
+------------+ +------------+ +------------+
|
|
||||||
^ ^ ^
|
|
||||||
| ExtensionInstance | |
|
|
||||||
| da1: +---------------------+ | vec InstanceValueHolder<A1,A_callback>
|
|
||||||
+-------+- __class__ | | +---+ +---------------------+ |
|
|
||||||
| m_wrapped_objects -+--|-->| *-+-->| contains A_callback | |
|
|
||||||
+---------------------+ | +---+ +---------------------+ |
|
|
||||||
+--------------------------------------+ |
|
|
||||||
| ExtensionInstance |
|
|
||||||
b1: | +---------------------+ vec InstanceValueHolder<B1,B_callback> |
|
|
||||||
+-+- __class__ | +---+ +---------------------+ |
|
|
||||||
| | m_wrapped_objects -+->| *-+-->| contains B_callback | |
|
|
||||||
| +---------------------+ +---+ +---------------------+ |
|
|
||||||
| |
|
|
||||||
| ExtensionInstance |
|
|
||||||
pb1_b1: | +---------------------+ vec InstancePtrHolder<auto_ptr<B1>,B1> |
|
|
||||||
+-+- __class__ | +---+ +---+ |
|
|
||||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ B1 |
|
|
||||||
| +---------------------+ +---+ +---+ | +---+ |
|
|
||||||
| +->| | |
|
|
||||||
| ExtensionInstance +---+ |
|
|
||||||
pc_b1: | +---------------------+ vec InstancePtrHolder<auto_ptr<B1>,B1> |
|
|
||||||
+-+- __class__ | +---+ +---+ |
|
|
||||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ C |
|
|
||||||
| +---------------------+ +---+ +---+ | +---+ |
|
|
||||||
| +->| | |
|
|
||||||
| +---+ |
|
|
||||||
| |
|
|
||||||
| Class<ExtensionInstance> +---------------------------------------+
|
|
||||||
| DB1: +------------+ | ExtensionInstance
|
|
||||||
(*,)<---+- __bases__ | a2: | +---------------------+ vec InstanceValueHolder<A2>
|
|
||||||
| __dict__ -+->{...} +-+- __class__ | +---+ +-------------+
|
|
||||||
+------------+ | m_wrapped_objects -+->| *-+-->| contains A2 |
|
|
||||||
^ +---------------------+ +---+ +-------------+
|
|
||||||
| ExtensionInstance
|
|
||||||
db1: | +---------------------+ vec InstanceValueHolder<B1,B_callback>
|
|
||||||
+-+- __class__ | +---+ +----------------------+
|
|
||||||
| m_wrapped_objects -+-->| *-+-->| contains B1_callback |
|
|
||||||
+---------------------+ +---+ +----------------------+
|
|
||||||
120
doc/enums.html
120
doc/enums.html
@@ -1,120 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
Wrapping enums
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
|
||||||
Wrapping enums
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p>Because there is in general no way to deduce that a value of arbitrary type T
|
|
||||||
is an enumeration constant, the Boost Python Library cannot automatically
|
|
||||||
convert enum values to and from Python. To handle this case, you need to decide
|
|
||||||
how you want the enum to show up in Python (since Python doesn't have
|
|
||||||
enums). Once you have done that, you can write some simple
|
|
||||||
<code>from_python()</code> and <code>to_python()</code> functions.
|
|
||||||
|
|
||||||
<p>If you are satisfied with a Python int as a way to represent your enum
|
|
||||||
values, we provide a shorthand for these functions. You just need to cause
|
|
||||||
<code>boost::python::enum_as_int_converters<EnumType></code> to be
|
|
||||||
instantiated, where
|
|
||||||
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>Explicit instantiation:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
template class boost::python::enum_as_int_converters<my_enum>;
|
|
||||||
</blockquote></pre>
|
|
||||||
|
|
||||||
Some buggy C++ implementations require a class to be instantiated in the same
|
|
||||||
namespace in which it is defined. In that case, the simple incantation above becomes:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
...
|
|
||||||
} // close my_namespace
|
|
||||||
|
|
||||||
// drop into namespace python and explicitly instantiate
|
|
||||||
namespace boost { namespace python {
|
|
||||||
template class enum_as_int_converters<my_enum_type>;
|
|
||||||
}} // namespace boost::python
|
|
||||||
|
|
||||||
namespace my_namespace { // re-open my_namespace
|
|
||||||
...
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
|
|
||||||
<li>If you have such an implementation, you may find this technique more convenient
|
|
||||||
<blockquote><pre>
|
|
||||||
// instantiate as base class in any namespace
|
|
||||||
struct EnumTypeConverters
|
|
||||||
: boost::python::enum_as_int_converters<EnumType>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
</blockquote></pre>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>Either of the above is equivalent to the following declarations:
|
|
||||||
<blockquote><pre>
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
|
||||||
|
|
||||||
MyEnumType from_python(PyObject* x, boost::python::type<MyEnumType>)
|
|
||||||
{
|
|
||||||
return static_cast<MyEnum>(
|
|
||||||
from_python(x, boost::python::type<long>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
MyEnumType from_python(PyObject* x, boost::python::type<const MyEnumType&>)
|
|
||||||
{
|
|
||||||
return static_cast<MyEnum>(
|
|
||||||
from_python(x, boost::python::type<long>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject* to_python(MyEnumType x)
|
|
||||||
{
|
|
||||||
return to_python(static_cast<long>(x));
|
|
||||||
}
|
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>This technique defines the conversions of
|
|
||||||
<code>MyEnumType</code> in terms of the conversions for the built-in
|
|
||||||
<code>long</code> type.
|
|
||||||
|
|
||||||
You may also want to add a bunch of lines like this to your module
|
|
||||||
initialization. These bind the corresponding enum values to the appropriate
|
|
||||||
names so they can be used from Python:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
mymodule.add(boost::python::make_ref(enum_value_1), "enum_value_1");
|
|
||||||
mymodule.add(boost::python::make_ref(enum_value_2), "enum_value_2");
|
|
||||||
...
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
You can also add these to an extension class definition, if your enum happens to
|
|
||||||
be local to a class and you want the analogous interface in Python:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
my_class_builder.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
|
||||||
my_class_builder.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
|
||||||
...
|
|
||||||
</pre></blockquote>
|
|
||||||
<p>
|
|
||||||
Next: <a href="pointers.html">Pointers and Smart Pointers</a>
|
|
||||||
Previous: <a href="building.html">Building an Extension Module</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided ``as
|
|
||||||
is'' without express or implied warranty, and with no claim as to
|
|
||||||
its suitability for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Mar 6, 2001
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
A Simple Example
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
|
||||||
"c++boost.gif (8819 bytes)">
|
|
||||||
</h1>
|
|
||||||
<h1>
|
|
||||||
A Simple Example
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Suppose we have the following C++ API which we want to expose in
|
|
||||||
Python:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A couple of simple C++ functions that we want to expose to Python.
|
|
||||||
std::string greet() { return "hello, world"; }
|
|
||||||
int square(int number) { return number * number; }
|
|
||||||
}
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Here is the C++ code for a python module called <tt>getting_started1</tt>
|
|
||||||
which exposes the API.
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("getting_started1");
|
|
||||||
|
|
||||||
// Add regular functions to the module.
|
|
||||||
this_module.def(greet, "greet");
|
|
||||||
this_module.def(square, "square");
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
That's it! If we build this shared library and put it on our <code>
|
|
||||||
PYTHONPATH</code> we can now access our C++ functions from
|
|
||||||
Python.
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> import getting_started1
|
|
||||||
>>> print getting_started1.greet()
|
|
||||||
hello, world
|
|
||||||
>>> number = 11
|
|
||||||
>>> print number, '*', number, '=', getting_started1.square(number)
|
|
||||||
11 * 11 = 121
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
Next: <a href="exporting_classes.html">Exporting Classes</a>
|
|
||||||
Previous: <a href="comparisons.html">Comparisons with other systems</a> Up:
|
|
||||||
<a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability
|
|
||||||
for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Mar 6, 2000
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
Exporting Classes
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
|
||||||
"c++boost.gif (8819 bytes)">
|
|
||||||
</h1>
|
|
||||||
<h1>
|
|
||||||
Exporting Classes
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Now let's expose a C++ class to Python:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A friendly class.
|
|
||||||
class hello
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
hello(const std::string& country) { this->country = country; }
|
|
||||||
std::string greet() const { return "Hello from " + country; }
|
|
||||||
private:
|
|
||||||
std::string country;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A function taking a hello object as an argument.
|
|
||||||
std::string invite(const hello& w) {
|
|
||||||
return w.greet() + "! Please come soon!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</blockquote></pre> <p>
|
|
||||||
To expose the class, we use a <tt>class_builder</tt> in addition to the
|
|
||||||
<tt>module_builder</tt> from the previous example. Class member functions
|
|
||||||
are exposed by using the <tt>def()</tt> member function on the
|
|
||||||
<tt>class_builder</tt>:
|
|
||||||
<blockquote><pre>
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(getting_started2)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("getting_started2");
|
|
||||||
|
|
||||||
// Create the Python type object for our extension class.
|
|
||||||
python::class_builder<hello> hello_class(this_module, "hello");
|
|
||||||
|
|
||||||
// Add the __init__ function.
|
|
||||||
hello_class.def(python::constructor<std::string>());
|
|
||||||
// Add a regular member function.
|
|
||||||
hello_class.def(&hello::greet, "greet");
|
|
||||||
|
|
||||||
// Add invite() as a regular function to the module.
|
|
||||||
this_module.def(invite, "invite");
|
|
||||||
|
|
||||||
// Even better, invite() can also be made a member of hello_class!!!
|
|
||||||
hello_class.def(invite, "invite");
|
|
||||||
}
|
|
||||||
</blockquote></pre>
|
|
||||||
<p>
|
|
||||||
Now we can use the class normally from Python:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
>>> from getting_started2 import *
|
|
||||||
>>> hi = hello('California')
|
|
||||||
>>> hi.greet()
|
|
||||||
'Hello from California'
|
|
||||||
>>> invite(hi)
|
|
||||||
'Hello from California! Please come soon!'
|
|
||||||
>>> hi.invite()
|
|
||||||
'Hello from California! Please come soon!'
|
|
||||||
</blockquote></pre>
|
|
||||||
|
|
||||||
Notes:<ul>
|
|
||||||
<li> We expose the class' constructor by calling <tt>def()</tt> on the
|
|
||||||
<tt>class_builder</tt> with an argument whose type is
|
|
||||||
<tt>constructor<</tt><i>params</i><tt>></tt>, where <i>params</i>
|
|
||||||
matches the list of constructor argument types:
|
|
||||||
|
|
||||||
|
|
||||||
<li>Regular member functions are defined by calling <tt>def()</tt> with a
|
|
||||||
member function pointer and its Python name:
|
|
||||||
|
|
||||||
<li>Any function added to a class whose initial argument matches the class (or
|
|
||||||
any base) will act like a member function in Python.
|
|
||||||
|
|
||||||
<li>To define a nested class, just pass the enclosing
|
|
||||||
<tt>class_builder</tt> (instead of a <tt>module_builder</tt>) as the
|
|
||||||
first argument to the nested <tt>class_builder</tt>'s constructor.
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
We can even make a subclass of <code>hello.world</code>:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
>>> class wordy(hello):
|
|
||||||
... def greet(self):
|
|
||||||
... return hello.greet(self) + ', where the weather is fine'
|
|
||||||
...
|
|
||||||
>>> hi2 = wordy('Florida')
|
|
||||||
>>> hi2.greet()
|
|
||||||
'Hello from Florida, where the weather is fine'
|
|
||||||
>>> invite(hi2)
|
|
||||||
'Hello from Florida! Please come soon!'
|
|
||||||
</blockquote></pre>
|
|
||||||
<p>
|
|
||||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
|
||||||
|
|
||||||
Of course, you may now have a slightly empty feeling in the pit of
|
|
||||||
your little pythonic stomach. Perhaps you wanted to see the following
|
|
||||||
<tt>wordy</tt> invitation:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
'Hello from Florida, where the weather is fine! Please come soon!'
|
|
||||||
</blockquote></pre>
|
|
||||||
|
|
||||||
After all, <tt>invite</tt> calls <tt>hello::greet()</tt>, and you
|
|
||||||
reimplemented that in your Python subclass, <tt>wordy</tt>. If so, <a
|
|
||||||
href= "overriding.html">read on</a>...
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Next: <a href="overriding.html">Overridable virtual functions</a>
|
|
||||||
Previous: <a href="example1.html">A Simple Example</a> Up:
|
|
||||||
<a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability
|
|
||||||
for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Mar 6, 2001
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
||||||
<title>
|
|
||||||
A Brief Introduction to writing Python extension modules
|
|
||||||
</title>
|
|
||||||
<h1>
|
|
||||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
|
||||||
width="277" height="86">
|
|
||||||
</h1>
|
|
||||||
<h1>
|
|
||||||
A Brief Introduction to writing Python extension modules
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Interfacing any language to Python involves building a module which can
|
|
||||||
be loaded by the Python interpreter, but which isn't written in Python.
|
|
||||||
This is known as an <em>extension module</em>. Many of the <a href=
|
|
||||||
"http://www.python.org/doc/current/lib/lib.html">built-in Python
|
|
||||||
libraries</a> are constructed in 'C' this way; Python even supplies its
|
|
||||||
<a href="http://www.python.org/doc/current/lib/types.html">fundamental
|
|
||||||
types</a> using the same mechanism. An extension module can be statically
|
|
||||||
linked with the Python interpreter, but it more commonly resides in a
|
|
||||||
shared library or DLL.
|
|
||||||
<p>
|
|
||||||
As you can see from <a href=
|
|
||||||
"http://www.python.org/doc/current/ext/ext.html"> The Python Extending
|
|
||||||
and Embedding Tutorial</a>, writing an extension module normally means
|
|
||||||
worrying about
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="http://www.python.org/doc/current/ext/refcounts.html">
|
|
||||||
maintaining reference counts</a>
|
|
||||||
<li>
|
|
||||||
<a href="http://www.python.org/doc/current/ext/callingPython.html"> how
|
|
||||||
to call back into Python</a>
|
|
||||||
<li>
|
|
||||||
<a href="http://www.python.org/doc/current/ext/parseTuple.html">
|
|
||||||
function argument parsing and typechecking</a>
|
|
||||||
</ul>
|
|
||||||
This last item typically occupies a great deal of code in an extension
|
|
||||||
module. Remember that Python is a completely dynamic language. A callable
|
|
||||||
object receives its arguments in a tuple; it is up to that object to extract
|
|
||||||
those arguments from the tuple, check their types, and raise appropriate
|
|
||||||
exceptions. There are numerous other tedious details that need to be
|
|
||||||
managed; too many to mention here. The Boost Python Library is designed to
|
|
||||||
lift most of that burden.<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Another obstacle that most people run into eventually when extending
|
|
||||||
Python is that there's no way to make a true Python class in an extension
|
|
||||||
module. The typical solution is to create a new Python type in the
|
|
||||||
extension module, and then write an additional module in 100% Python. The
|
|
||||||
Python module defines a Python class which dispatches to an instance of
|
|
||||||
the extension type, which it contains. This allows users to write
|
|
||||||
subclasses of the class in the Python module, almost as though they were
|
|
||||||
sublcassing the extension type. Aside from being tedious, it's not really
|
|
||||||
the same as having a true class, because there's no way for the user to
|
|
||||||
override a method of the extension type which is called from the
|
|
||||||
extension module. Boost.Python solves this problem by taking advantage of <a
|
|
||||||
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
|
|
||||||
feature</a> to provide objects which look, walk, and hiss almost exactly
|
|
||||||
like regular Python classes. Boost.Python classes are actually cleaner than
|
|
||||||
Python classes in some subtle ways; a more detailed discussion will
|
|
||||||
follow (someday).</p>
|
|
||||||
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
|
|
||||||
href="index.html">Top</a> </p>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability for
|
|
||||||
any purpose.</p>
|
|
||||||
|
|
||||||
193
doc/index.html
193
doc/index.html
@@ -1,193 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
The Boost Python Library (Boost.Python)
|
|
||||||
</title>
|
|
||||||
<h1>
|
|
||||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
|
|
||||||
align="center" height="86"><br>The Boost Python Library (Boost.Python)
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h2>Synopsis</h2>
|
|
||||||
<p>
|
|
||||||
Use the Boost Python Library to quickly and easily export a C++ library to <a
|
|
||||||
href="http://www.python.org">Python</a> such that the Python interface is
|
|
||||||
very similar to the C++ interface. It is designed to be minimally
|
|
||||||
intrusive on your C++ design. In most cases, you should not have to alter
|
|
||||||
your C++ classes in any way in order to use them with Boost.Python. The system
|
|
||||||
<em>should</em> simply ``reflect'' your C++ classes and functions into
|
|
||||||
Python. The major features of Boost.Python include support for:
|
|
||||||
<ul>
|
|
||||||
<li><a href="inheritance.html">Subclassing extension types in Python</a>
|
|
||||||
<li><a href="overriding.html">Overriding virtual functions in Python</a>
|
|
||||||
<li><a href="overloading.html">[Member] function Overloading</a>
|
|
||||||
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
|
|
||||||
</ul>
|
|
||||||
among others.
|
|
||||||
|
|
||||||
|
|
||||||
<h2>Supported Platforms</h2>
|
|
||||||
<p>Boost.Python is known to have been tested in the following configurations:
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Against <a href="http://www.python/org/2.2.1">Python 2.2.1</a> using
|
|
||||||
the following compilers (Note that pickling doesn't work with Python
|
|
||||||
2.2 due to a core language bug;
|
|
||||||
<a href="http://www.python/org/2.2.1">2.2.1</a> fixes that).
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a
|
|
||||||
href="http://msdn.microsoft.com/vstudio/downloads/updates/sp/vs6/sp5/default.asp">MSVC++6sp5</a>. All
|
|
||||||
tests pass.
|
|
||||||
|
|
||||||
<li><a href="http://msdn.microsoft.com/visualc/">MSVC++7 (Visual
|
|
||||||
Studio .NET)</a>. All tests pass.
|
|
||||||
|
|
||||||
<li><a href="http://www.metrowerks.com/products/windows/">Metrowerks
|
|
||||||
CodeWarrior Pro7.2 for Windows</a>. All tests pass.
|
|
||||||
|
|
||||||
<li><a href="http://gcc.gnu.org">GCC 3.0.4</a> under <a
|
|
||||||
href="www.cygwin.com">Cygwin</a>. All tests pass.
|
|
||||||
|
|
||||||
<li><a href="http://gcc.gnu.org">GCC 2.95.2</a> under <a
|
|
||||||
href="www.mingw.org">MinGW</a>. Comprehensive test fails at
|
|
||||||
runtime due to a compiler code-generation bug. Other tests seem to
|
|
||||||
work.
|
|
||||||
|
|
||||||
<li><a
|
|
||||||
href="http://developer.intel.com/software/products/compilers/c50/">Intel
|
|
||||||
C++ 6.0</a> beta: Comprehensive test fails to link due to a
|
|
||||||
linker bug. Other tests seem to work.
|
|
||||||
|
|
||||||
<li><a
|
|
||||||
href="http://developer.intel.com/software/products/compilers/c50/">Intel
|
|
||||||
C++ 5.0</a> Comprehensive test fails at runtime due to an
|
|
||||||
exception-handling bug. Other tests seem to work.
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<li>Against Python 2.0 using the following compilers:
|
|
||||||
<ul>
|
|
||||||
<li><a
|
|
||||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>.
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<li>Against Python 1.5.2 using the following compiler/library combinations:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a
|
|
||||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
|
|
||||||
|
|
||||||
<li><a
|
|
||||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>/<a
|
|
||||||
href="http://www.stlport.org">STLport 4.0</a>
|
|
||||||
|
|
||||||
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a> [by <a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich
|
|
||||||
Koethe</a>]
|
|
||||||
|
|
||||||
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a>/<a href="http://www.stlport.org">STLport 4.0</a>
|
|
||||||
|
|
||||||
<li>Compaq C++ V6.2-024 for Digital UNIX V5.0 Rev. 910 (an <a
|
|
||||||
href="http://www.edg.com/">EDG</a>-based compiler) with <a
|
|
||||||
href="http://www.stlport.org/beta.html">STLport-4.1b3</a> [by <a
|
|
||||||
href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve</a>]
|
|
||||||
|
|
||||||
<li>An upcoming release of <a href="http://www.metrowerks.com/products/windows/">Metrowerks CodeWarrior
|
|
||||||
Pro6 for Windows</a> (the first release has a bug that's fatal to Boost.Python)
|
|
||||||
</ul>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2>Credits</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="../../../people/dave_abrahams.htm">David Abrahams</a> originated
|
|
||||||
and wrote most of the library, and continues to coordinate development.
|
|
||||||
|
|
||||||
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
|
|
||||||
had independently developed a similar system. When he discovered Boost.Python,
|
|
||||||
he generously contributed countless hours of coding and much insight into
|
|
||||||
improving it. He is responsible for an early version of the support for <a
|
|
||||||
href="overloading.html">function overloading</a> and wrote the support for
|
|
||||||
<a href="inheritance.html#implicit_conversion">reflecting C++ inheritance
|
|
||||||
relationships</a>. He has helped to improve error-reporting from both
|
|
||||||
Python and C++, and has designed an extremely easy-to-use way of
|
|
||||||
exposing <a href="special.html#numeric">numeric operators</a>, including
|
|
||||||
a way to avoid explicit coercion by means of overloading.
|
|
||||||
|
|
||||||
<li><a href="http://cci.lbl.gov/staff/ralf_grosse-kunstleve.html">Ralf W.
|
|
||||||
Grosse-Kunstleve</a> contributed <a href="pickle.html">pickle support</a>
|
|
||||||
and numerous other small improvements. He's working on a way to allow
|
|
||||||
types exported by multiple modules to interact.
|
|
||||||
|
|
||||||
<li>The members of the boost mailing list and the Python community
|
|
||||||
supplied 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.
|
|
||||||
|
|
||||||
<li>The development of Boost.Python wouldn't have been possible without
|
|
||||||
the generous support of <a href="http://www.dragonsys.com/">Dragon
|
|
||||||
Systems/Lernout and Hauspie, Inc</a> who supported its development as an
|
|
||||||
open-source project.
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2>Table of Contents</h2>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li><a href="extending.html">A Brief Introduction to writing Python
|
|
||||||
extension modules</a>
|
|
||||||
|
|
||||||
<li><a href="comparisons.html">Comparisons between Boost.Python and other
|
|
||||||
systems for extending Python</a>
|
|
||||||
|
|
||||||
<li><a href="example1.html">A Simple Example</a>
|
|
||||||
|
|
||||||
<li><a href="exporting_classes.html">Exporting Classes</a>
|
|
||||||
|
|
||||||
<li><a href="overriding.html">Overridable Virtual Functions</a>
|
|
||||||
|
|
||||||
<li><a href="overloading.html">Function Overloading</a>
|
|
||||||
|
|
||||||
<li><a href="inheritance.html">Inheritance</a>
|
|
||||||
|
|
||||||
<li><a href="special.html">Special Method and Operator Support</a>
|
|
||||||
|
|
||||||
<li><a href="under-the-hood.html">A Peek Under the Hood</a>
|
|
||||||
|
|
||||||
<li><a href="building.html">Building an Extension Module</a>
|
|
||||||
|
|
||||||
<li><a href="pickle.html">Pickle Support</a>
|
|
||||||
|
|
||||||
<li><a href="cross_module.html">Cross-Extension-Module Dependencies</a>
|
|
||||||
|
|
||||||
<li><a href="enums.html">Wrapping Enums</a>
|
|
||||||
|
|
||||||
<li><a href="pointers.html">Pointers and Smart Pointers</a>
|
|
||||||
|
|
||||||
<li><a href="data_structures.txt">Internal Data Structures</a>
|
|
||||||
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Documentation is a major ongoing project; assistance is greatly
|
|
||||||
appreciated! In the meantime, useful examples of every Boost.Python feature should
|
|
||||||
be evident in the regression test files <code>test/comprehensive.[<a
|
|
||||||
href="../test/comprehensive.py">py</a>/<a
|
|
||||||
href="../test/comprehensive.hpp">hpp</a>/<a
|
|
||||||
href="../test/comprehensive.cpp">cpp</a>]</code>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Questions should be directed to <a href=
|
|
||||||
"http://www.yahoogroups.com/list/boost">the boost mailing list</a>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided ``as is'' without
|
|
||||||
express or implied warranty, and with no claim as to its suitability for
|
|
||||||
any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Mar 6, 2001
|
|
||||||
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
Inheritance
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Inheritance
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h2>Inheritance in Python</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Boost.Python extension classes support single and multiple-inheritance in
|
|
||||||
Python, just like regular Python classes. You can arbitrarily mix
|
|
||||||
built-in Python classes with extension classes in a derived class'
|
|
||||||
tuple of bases. Whenever a Boost.Python extension class is among the bases for a
|
|
||||||
new class in Python, the result is an extension class:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> class MyPythonClass:
|
|
||||||
... def f(): return 'MyPythonClass.f()'
|
|
||||||
...
|
|
||||||
>>> import my_extension_module
|
|
||||||
>>> class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
|
|
||||||
... '''This is an extension class'''
|
|
||||||
... pass
|
|
||||||
...
|
|
||||||
>>> x = Derived()
|
|
||||||
>>> x.f()
|
|
||||||
'MyPythonClass.f()'
|
|
||||||
>>> x.g()
|
|
||||||
'MyExtensionClass.g()'
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
|
||||||
<p>
|
|
||||||
Boost.Python also allows us to represent C++ inheritance relationships so that
|
|
||||||
wrapped derived classes may be passed where values, pointers, or
|
|
||||||
references to a base class are expected as arguments. The
|
|
||||||
<code>declare_base</code> member function of
|
|
||||||
<code>class_builder<></code> is used to establish the relationship
|
|
||||||
between base and derived classes:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
#include <memory> // for std::auto_ptr<>
|
|
||||||
|
|
||||||
struct Base {
|
|
||||||
virtual ~Base() {}
|
|
||||||
virtual const char* name() const { return "Base"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Derived : Base {
|
|
||||||
Derived() : x(-1) {}
|
|
||||||
virtual const char* name() const { return "Derived"; }
|
|
||||||
int x;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::auto_ptr<Base> derived_as_base() {
|
|
||||||
return std::auto_ptr<Base>(new Derived);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* get_name(const Base& b) {
|
|
||||||
return b.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_derived_x(const Derived& d) {
|
|
||||||
return d.x;
|
|
||||||
}
|
|
||||||
<hr>
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
|
|
||||||
// namespace alias for code brevity
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(my_module)
|
|
||||||
{
|
|
||||||
python::module_builder my_module("my_module");
|
|
||||||
|
|
||||||
python::class_builder<Base> base_class(my_module, "Base");
|
|
||||||
base_class.def(python::constructor<void>());
|
|
||||||
|
|
||||||
python::class_builder<Derived> derived_class(my_module, "Derived");
|
|
||||||
derived_class.def(python::constructor<void>());
|
|
||||||
<b>// Establish the inheritance relationship between Base and Derived
|
|
||||||
derived_class.declare_base(base_class);</b>
|
|
||||||
|
|
||||||
my_module.def(derived_as_base, "derived_as_base");
|
|
||||||
my_module.def(get_name, "get_name");
|
|
||||||
my_module.def(get_derived_x, "get_derived_x");
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Then, in Python:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> from my_module import *
|
|
||||||
>>> base = Base()
|
|
||||||
>>> derived = Derived()
|
|
||||||
>>> get_name(base)
|
|
||||||
'Base'
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<i>objects of wrapped class Derived may be passed where Base is expected</i>
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> get_name(derived)
|
|
||||||
'Derived'
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<i>objects of wrapped class Derived can be passed where Derived is
|
|
||||||
expected but where type information has been lost.</i>
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> get_derived_x(derived_as_base())
|
|
||||||
-1
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h2>Inheritance Without Virtual Functions</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If for some reason your base class has no virtual functions but you still want
|
|
||||||
to represent the inheritance relationship between base and derived classes,
|
|
||||||
pass the special symbol <code>boost::python::without_downcast</code> as the 2nd parameter
|
|
||||||
to <code>declare_base</code>:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
struct Base2 {};
|
|
||||||
struct Derived2 { int f(); };
|
|
||||||
<hr>
|
|
||||||
...
|
|
||||||
python::class_builder<Base> base2_class(my_module, "Base2");
|
|
||||||
base2_class.def(python::constructor<void>());
|
|
||||||
|
|
||||||
python::class_builder<Derived2> derived2_class(my_module, "Derived2");
|
|
||||||
derived2_class.def(python::constructor<void>());
|
|
||||||
derived_class.declare_base(base_class, <b>python::without_downcast</b>);
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>This approach will allow <code>Derived2</code> objects to be passed where
|
|
||||||
<code>Base2</code> is expected, but does not attempt to implicitly convert (downcast)
|
|
||||||
smart-pointers to <code>Base2</code> into <code>Derived2</code> pointers,
|
|
||||||
references, or values.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Next: <a href="special.html">Special Method and Operator Support</a>
|
|
||||||
Previous: <a href="overloading.html">Function Overloading</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability
|
|
||||||
for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Nov 26, 2000
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,326 +0,0 @@
|
|||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
||||||
<title>A New Type Conversion Mechanism for Boost.Python</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
|
||||||
|
|
||||||
<p><img border="0" src="../../../c++boost.gif" width="277" height="86"
|
|
||||||
alt="boost logo"></p>
|
|
||||||
|
|
||||||
<h1>A New Type Conversion Mechanism for Boost.Python</h1>
|
|
||||||
|
|
||||||
<p>By <a href="../../../people/dave_abrahams.htm">David Abrahams</a>.
|
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
|
||||||
|
|
||||||
This document describes a redesign of the mechanism for automatically
|
|
||||||
converting objects between C++ and Python. The current implementation
|
|
||||||
uses two functions for any type <tt>T</tt>:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
U from_python(PyObject*, type<T>);
|
|
||||||
void to_python(V);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
where U is convertible to T and T is convertible to V. These functions
|
|
||||||
are at the heart of C++/Python interoperability in Boost.Python, so
|
|
||||||
why would we want to change them? There are many reasons:
|
|
||||||
|
|
||||||
<h3>Bugs</h3>
|
|
||||||
<p>Firstly, the current mechanism relies on a common C++ compiler
|
|
||||||
bug. This is not just embarrassing: as compilers get to be more
|
|
||||||
conformant, the library stops working. The issue, in detail, is the
|
|
||||||
use of inline friend functions in templates to generate
|
|
||||||
conversions. It is a very powerful, and legal technique as long as
|
|
||||||
it's used correctly:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
template <class Derived>
|
|
||||||
struct add_some_functions
|
|
||||||
{
|
|
||||||
friend <i>return-type</i> some_function1(..., Derived <i>cv-*-&-opt</i>, ...);
|
|
||||||
friend <i>return-type</i> some_function2(..., Derived <i>cv-*-&-opt</i>, ...);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct some_template : add_some_functions<some_template<T> >
|
|
||||||
{
|
|
||||||
};
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
The <tt>add_some_functions</tt> template generates free functions
|
|
||||||
which operate on <tt>Derived</tt>, or on related types. Strictly
|
|
||||||
speaking the related types are not just cv-qualified <tt>Derived</tt>
|
|
||||||
values, pointers and/or references. Section 3.4.2 in the standard
|
|
||||||
describes exactly which types you must use as parameters to these
|
|
||||||
functions if you want the functions to be found
|
|
||||||
(there is also a less-technical description in section 11.5.1 of
|
|
||||||
C++PL3 <a href="#ref_1">[1]</a>). Suffice it to say that
|
|
||||||
with the current design, the <tt>from_python</tt> and
|
|
||||||
<tt>to_python</tt> functions are not supposed to be callable under any
|
|
||||||
conditions!
|
|
||||||
|
|
||||||
<h3>Compilation and Linking Time</h3>
|
|
||||||
|
|
||||||
The conversion functions generated for each wrapped class using the
|
|
||||||
above technique are not function templates, but regular functions. The
|
|
||||||
upshot is that they must <i>all</i> be generated regardless of whether
|
|
||||||
they are actually used. Generating all of those functions can slow
|
|
||||||
down module compilation, and resolving the references can slow down
|
|
||||||
linking.
|
|
||||||
|
|
||||||
<h3>Efficiency</h3>
|
|
||||||
|
|
||||||
The conversion functions are primarily used in (member) function
|
|
||||||
wrappers to convert the arguments and return values. Being functions,
|
|
||||||
converters have no interface which allows us to ask "will the
|
|
||||||
conversion succeed?" without calling the function. Since the
|
|
||||||
return value of the function must be the object to be passed as an
|
|
||||||
argument, Boost.Python currently uses C++ exception-handling to detect
|
|
||||||
an unsuccessful conversion. It's not a particularly good use of
|
|
||||||
exception-handling, since the failure is not handled very far from
|
|
||||||
where it occurred. More importantly, it means that C++ exceptions are
|
|
||||||
thrown during overload resolution as we seek an overload that matches
|
|
||||||
the arguments passed. Depending on the implementation, this approach
|
|
||||||
can result in significant slowdowns.
|
|
||||||
|
|
||||||
<p>It is also unclear that the current library generates a minimal
|
|
||||||
amount of code for any type conversion. Many of the conversion
|
|
||||||
functions are nontrivial, and partly because of compiler limitations,
|
|
||||||
they are declared <tt>inline</tt>. Also, we could have done a better
|
|
||||||
job separating the type-specific conversion code from the code which
|
|
||||||
is type-independent.
|
|
||||||
|
|
||||||
<h3>Cross-module Support</h3>
|
|
||||||
|
|
||||||
The current strategy requires every module to contain the definition
|
|
||||||
of conversions it uses. In general, a new module can never supply
|
|
||||||
conversion code which is used by another module. Ralf Grosse-Kunstleve
|
|
||||||
designed a clever system which imports conversions directly from one
|
|
||||||
library into another using some explicit declarations, but it has some
|
|
||||||
disadvantages also:
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>The system Ullrich Koethe designed for implicit conversion between
|
|
||||||
wrapped classes related through inheritance does not currently work if
|
|
||||||
the classes are defined in separate modules.
|
|
||||||
|
|
||||||
<li>The writer of the importing module is required to know the name of
|
|
||||||
the module supplying the imported conversions.
|
|
||||||
|
|
||||||
<li>There can be only one way to extract any given C++ type from a
|
|
||||||
Python object in a given module.
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
The first item might be addressed by moving Boost.Python into a shared
|
|
||||||
library, but the other two cannot. Ralf turned the limitation in item
|
|
||||||
two into a feature: the required module is loaded implicitly when a
|
|
||||||
conversion it defines is invoked. We will probably want to provide
|
|
||||||
that functionality anyway, but it's not clear that we should require
|
|
||||||
the declaration of all such conversions. The final item is a more
|
|
||||||
serious limitation. If, for example, new numeric types are defined in
|
|
||||||
separate modules, and these types can all be converted to
|
|
||||||
<tt>double</tt>s, we have to choose just one conversion method.
|
|
||||||
|
|
||||||
<h3>Ease-of-use</h3>
|
|
||||||
|
|
||||||
One persistent source of confusion for users of Boost.Python has been
|
|
||||||
the fact that conversions for a class are not be visible at
|
|
||||||
compile-time until the declaration of that class has been seen. When
|
|
||||||
the user tries to expose a (member) function operating on or returning
|
|
||||||
an instance of the class in question, compilation fails...even though
|
|
||||||
the user goes on to expose the class in the same translation unit!
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The new system lifts all compile-time checks for the existence of
|
|
||||||
particular type conversions and replaces them with runtime checks, in
|
|
||||||
true Pythonic style. While this might seem cavalier, the compile-time
|
|
||||||
checks are actually not much use in the current system if many classes
|
|
||||||
are wrapped in separate modules, since the checks are based only on
|
|
||||||
the user's declaration that the conversions exist.
|
|
||||||
|
|
||||||
<h2>The New Design</h2>
|
|
||||||
|
|
||||||
<h3>Motivation</h3>
|
|
||||||
|
|
||||||
The new design was heavily influenced by a desire to generate as
|
|
||||||
little code as possible in extension modules. Some of Boost.Python's
|
|
||||||
clients are enormous projects where link time is proportional to the
|
|
||||||
amount of object code, and there are many Python extension modules. As
|
|
||||||
such, we try to keep type-specific conversion code out of modules
|
|
||||||
other than the one the converters are defined in, and rely as much as
|
|
||||||
possible on centralized control through a shared library.
|
|
||||||
|
|
||||||
<h3>The Basics</h3>
|
|
||||||
|
|
||||||
The library contains a <tt>registry</tt> which maps runtime type
|
|
||||||
identifiers (actually an extension of <tt>std::type_info</tt> which
|
|
||||||
preserves references and constness) to entries containing type
|
|
||||||
converters. An <tt>entry</tt> can contain only one converter from C++ to Python
|
|
||||||
(<tt>wrapper</tt>), but many converters from Python to C++
|
|
||||||
(<tt>unwrapper</tt>s). <font color="#ff0000">What should happen if
|
|
||||||
multiple modules try to register wrappers for the same type?</font>. Wrappers
|
|
||||||
and unwrappers are known as <tt>body</tt> objects, and are accessed
|
|
||||||
by the user and the library (in its function-wrapping code) through
|
|
||||||
corresponding <tt>handle</tt> (<tt>wrap<T></tt> and
|
|
||||||
<tt>unwrap<T></tt>) objects. The <tt>handle</tt> objects are
|
|
||||||
extremely lightweight, and delegate <i>all</i> of their operations to
|
|
||||||
the corresponding <tt>body</tt>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
When a <tt>handle</tt> object is constructed, it accesses the
|
|
||||||
registry to find a corresponding <tt>body</tt> that can convert the
|
|
||||||
handle's constructor argument. Actually the registry record for any
|
|
||||||
type
|
|
||||||
<tt>T</tt>used in a module is looked up only once and stored in a
|
|
||||||
static <tt>registration<T></tt> object for efficiency. For
|
|
||||||
example, if the handle is an <tt>unwrap<Foo&></tt> object,
|
|
||||||
the <tt>entry</tt> for <tt>Foo&</tt> is looked up in the
|
|
||||||
<tt>registry</tt>, and each <tt>unwrapper</tt> it contains is queried
|
|
||||||
to determine if it can convert the
|
|
||||||
<tt>PyObject*</tt> with which the <tt>unwrap</tt> was constructed. If
|
|
||||||
a body object which can perform the conversion is found, a pointer to
|
|
||||||
it is stored in the handle. A body object may at any point store
|
|
||||||
additional data in the handle to speed up the conversion process.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Now that the handle has been constructed, the user can ask it whether
|
|
||||||
the conversion can be performed. All handles can be tested as though
|
|
||||||
they were convertible to <tt>bool</tt>; a <tt>true</tt> value
|
|
||||||
indicates success. If the user forges ahead and tries to do the
|
|
||||||
conversion without checking when no conversion is possible, an
|
|
||||||
exception will be thrown as usual. The conversion itself is performed
|
|
||||||
by the body object.
|
|
||||||
|
|
||||||
<h3>Handling complex conversions</h3>
|
|
||||||
|
|
||||||
<p>Some conversions may require a dynamic allocation. For example,
|
|
||||||
when a Python tuple is converted to a <tt>std::vector<double>
|
|
||||||
const&</tt>, we need some storage into which to construct the
|
|
||||||
vector so that a reference to it can be formed. Furthermore, multiple
|
|
||||||
conversions of the same type may need to be "active"
|
|
||||||
simultaneously, so we can't keep a single copy of the storage
|
|
||||||
anywhere. We could keep the storage in the <tt>body</tt> object, and
|
|
||||||
have the body clone itself in case the storage is used, but in that
|
|
||||||
case the storage in the body which lives in the registry is never
|
|
||||||
used. If the storage was actually an object of the target type (the
|
|
||||||
safest way in C++), we'd have to find a way to construct one for the
|
|
||||||
body in the registry, since it may not have a default constructor.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The most obvious way out of this quagmire is to allocate the object using a
|
|
||||||
<i>new-expression</i>, and store a pointer to it in the handle. Since
|
|
||||||
the <tt>body</tt> object knows everything about the data it needs to
|
|
||||||
allocate (if any), it is also given responsibility for destroying that
|
|
||||||
data. When the <tt>handle</tt> is destroyed it asks the <tt>body</tt>
|
|
||||||
object to tear down any data it may have stored there. In many ways,
|
|
||||||
you can think of the <tt>body</tt> as a "dynamically-determined
|
|
||||||
vtable" for the handle.
|
|
||||||
|
|
||||||
<h3>Eliminating Redundancy</h3>
|
|
||||||
|
|
||||||
If you look at the current Boost.Python code, you'll see that there
|
|
||||||
are an enormous number of conversion functions generated for each
|
|
||||||
wrapped class. For a given class <tt>T</tt>, functions are generated
|
|
||||||
to extract the following types <tt>from_python</tt>:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
T*
|
|
||||||
T const*
|
|
||||||
T const* const&
|
|
||||||
T* const&
|
|
||||||
T&
|
|
||||||
T const&
|
|
||||||
T
|
|
||||||
std::auto_ptr<T>&
|
|
||||||
std::auto_ptr<T>
|
|
||||||
std::auto_ptr<T> const&
|
|
||||||
boost::shared_ptr<T>&
|
|
||||||
boost::shared_ptr<T>
|
|
||||||
boost::shared_ptr<T> const&
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
Most of these are implemented in terms of just a few conversions, and
|
|
||||||
<t>if you're lucky</t>, they will be inlined and cause no extra
|
|
||||||
overhead. In the new system, however, a significant amount of data
|
|
||||||
will be associated with each type that needs to be converted. We
|
|
||||||
certainly don't want to register a separate unwrapper object for all
|
|
||||||
of the above types.
|
|
||||||
|
|
||||||
<p>Fortunately, much of the redundancy can be eliminated. For example,
|
|
||||||
if we generate an unwrapper for <tt>T&</tt>, we don't need an
|
|
||||||
unwrapper for <tt>T const&</tt> or <tt>T</tt>. Accordingly, the user's
|
|
||||||
request to wrap/unwrap a given type is translated at compile-time into
|
|
||||||
a request which helps to eliminate redundancy. The rules used to
|
|
||||||
<tt>unwrap</tt> a type are:
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li> Treat built-in types specially: when unwrapping a value or
|
|
||||||
constant reference to one of these, use a value for the target
|
|
||||||
type. It will bind to a const reference if neccessary, and more
|
|
||||||
importantly, avoids having to dynamically allocate room for
|
|
||||||
an lvalue of types which can be cheaply copied.
|
|
||||||
<li>
|
|
||||||
Reduce everything else to a reference to an un-cv-qualified type
|
|
||||||
where possible. Since cv-qualification is lost on Python
|
|
||||||
anyway, there's no point in trying to convert to a
|
|
||||||
<tt>const&</tt>. <font color="#ff0000">What about conversions
|
|
||||||
to values like the tuple->vector example above? It seems to me
|
|
||||||
that we don't want to make a <tt>vector<double>&</tt>
|
|
||||||
(non-const) converter available for that case. We may need to
|
|
||||||
rethink this slightly.</font>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>To handle the problem described above in item 2, we modify the
|
|
||||||
procedure slightly. To unwrap any non-scalar <tt>T</tt>, we seek an
|
|
||||||
unwrapper for <tt>add_reference<T>::type</tt>. Unwrappers for
|
|
||||||
<tt>T const&</tt> always return <tt>T&</tt>, and are
|
|
||||||
registered under both <tt>T &</tt> and
|
|
||||||
<tt>T const&</tt>.
|
|
||||||
|
|
||||||
<p>For compilers not supporting partial specialization, unwrappers for
|
|
||||||
<tt>T const&</tt> must return <tt>T const&</tt>
|
|
||||||
(since constness can't be stripped), but a separate unwrapper object
|
|
||||||
need to be registered for <tt>T &</tt> and
|
|
||||||
<tt>T const&</tt> anyway, for the same reasons.
|
|
||||||
|
|
||||||
<font color="#ff0000">We may want to make it possible to compile as
|
|
||||||
though partial specialization were unavailable even on compilers where
|
|
||||||
it is available, in case modules could be compiled by different
|
|
||||||
compilers with compatible ABIs (e.g. Intel C++ and MSVC6).</font>
|
|
||||||
|
|
||||||
<h3>Efficient Argument Conversion</h3>
|
|
||||||
|
|
||||||
Since type conversions are primarily used in function wrappers, an
|
|
||||||
optimization is provided for the case where a group of conversions are
|
|
||||||
used together. Each <tt>handle</tt> class has a corresponding
|
|
||||||
"<tt>_more</tt>" class which does the same job, but has a
|
|
||||||
trivial destructor. Instead of asking each "<tt>_more</tt>"
|
|
||||||
handle to destroy its own body, it is linked into an endogenous list
|
|
||||||
managed by the first (ordinary) handle. The <tt>wrap</tt> and
|
|
||||||
<tt>unwrap</tt> destructors are responsible for traversing that list
|
|
||||||
and asking each <tt>body</tt> class to tear down its
|
|
||||||
<tt>handle</tt>. This mechanism is also used to determine if all of
|
|
||||||
the argument/return-value conversions can succeed with a single
|
|
||||||
function call in the function wrapping code. <font color="#ff0000">We
|
|
||||||
might need to handle return values in a separate step for Python
|
|
||||||
callbacks, since the availablility of a conversion won't be known
|
|
||||||
until the result object is retrieved.</font>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<hr>
|
|
||||||
<h2>References</h2>
|
|
||||||
|
|
||||||
<p><a name="ref_1">[1]</a>B. Stroustrup, The C++ Programming Language
|
|
||||||
Special Edition Addison-Wesley, ISBN 0-201-70073-5.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->19 December 2001<!--webbot bot="Timestamp" endspan i-checksum="31283" --></p>
|
|
||||||
<p>© Copyright David Abrahams, 2001</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
This hierarchy contains converter handle classes.
|
|
||||||
|
|
||||||
|
|
||||||
+-------------+
|
|
||||||
| noncopyable |
|
|
||||||
+-------------+
|
|
||||||
^
|
|
||||||
| A common base class used so that
|
|
||||||
+--------+--------+ conversions can be linked into a
|
|
||||||
| conversion_base | chain for efficient argument
|
|
||||||
+-----------------+ conversion
|
|
||||||
^
|
|
||||||
|
|
|
||||||
+---------+-----------+
|
|
||||||
| |
|
|
||||||
+-----------+----+ +------+-------+ only used for
|
|
||||||
| unwrap_more<T> | | wrap_more<T> | chaining, and don't manage any
|
|
||||||
+----------------+ +--------------+ resources.
|
|
||||||
^ ^
|
|
||||||
| |
|
|
||||||
+-----+-----+ +-------+-+ These converters are what users
|
|
||||||
| unwrap<T> | | wrap<T> | actually touch, but they do so
|
|
||||||
+-----------+ +---------+ through a type generator which
|
|
||||||
minimizes the number of converters
|
|
||||||
that must be generated, so they
|
|
||||||
|
|
||||||
|
|
||||||
Each unwrap<T>, unwrap_more<T>, wrap<T>, wrap_more<T> converter holds
|
|
||||||
a reference to an appropriate converter object
|
|
||||||
|
|
||||||
This hierarchy contains converter body classes
|
|
||||||
|
|
||||||
Exposes use/release which
|
|
||||||
are needed in case the converter
|
|
||||||
+-----------+ in the registry needs to be
|
|
||||||
| converter | cloned. That occurs when a
|
|
||||||
+-----------+ unwrap target type is not
|
|
||||||
^ contained within the Python object.
|
|
||||||
|
|
|
||||||
+------------------+-----+
|
|
||||||
| |
|
|
||||||
+--------+-------+ Exposes |
|
|
||||||
| unwrapper_base | convertible() |
|
|
||||||
+----------------+ |
|
|
||||||
^ |
|
|
||||||
| |
|
|
||||||
+--------+----+ +-----+-----+
|
|
||||||
| unwrapper<T>| | wrapper<T>|
|
|
||||||
+-------------+ +-----------+
|
|
||||||
Exposes T convert(PyObject*) Exposes PyObject* convert(T)
|
|
||||||
|
|
||||||
|
|
||||||
unwrap:
|
|
||||||
|
|
||||||
constructed with a PyObject*, whose reference count is
|
|
||||||
incremented.
|
|
||||||
|
|
||||||
find the registry entry for the target type
|
|
||||||
|
|
||||||
look in the collection of converters for one which claims to be
|
|
||||||
able to convert the PyObject to the target type.
|
|
||||||
|
|
||||||
stick a pointer to the unwrapper in the unwrap object
|
|
||||||
|
|
||||||
when unwrap is queried for convertibility, it checks to see
|
|
||||||
if it has a pointer to an unwrapper.
|
|
||||||
|
|
||||||
on conversion, the unwrapper is asked to allocate an
|
|
||||||
implementation if the unwrap object isn't already holding
|
|
||||||
one. The unwrap object "takes ownership" of the unwrapper's
|
|
||||||
implementation. No memory allocation will actually take place
|
|
||||||
unless this is a value conversion.
|
|
||||||
|
|
||||||
on destruction, the unwrapper is asked to free any implementation
|
|
||||||
held by the unwrap object. No memory deallocation actually
|
|
||||||
takes place unless this is a value conversion
|
|
||||||
|
|
||||||
on destruction, the reference count on the held PyObject is
|
|
||||||
decremented.
|
|
||||||
|
|
||||||
We need to make sure that by default, you can't instantiate
|
|
||||||
callback<> for reference and pointer return types: although the
|
|
||||||
unwrappers may exist, they may convert by-value, which would cause
|
|
||||||
the referent to be destroyed upon return.
|
|
||||||
|
|
||||||
wrap:
|
|
||||||
|
|
||||||
find the registry entry for the source type
|
|
||||||
|
|
||||||
see if there is a converter. If found, stick a pointer to it in
|
|
||||||
the wrap object.
|
|
||||||
|
|
||||||
when queried for convertibility, it checks to see if it has a
|
|
||||||
pointer to a converter.
|
|
||||||
|
|
||||||
on conversion, a reference to the target PyObject is held by the
|
|
||||||
converter. Generally, the PyObject will have been created by the
|
|
||||||
converter, but in certain cases it may be a pre-existing object,
|
|
||||||
whose reference count will have been incremented.
|
|
||||||
|
|
||||||
when a wrap<T> x is used to return from a C++ function,
|
|
||||||
x.release() is returned so that x no longer holds a reference to
|
|
||||||
the PyObject when destroyed.
|
|
||||||
|
|
||||||
Otherwise, on destruction, any PyObject still held has its
|
|
||||||
reference-count decremented.
|
|
||||||
|
|
||||||
|
|
||||||
When a converter is created by the user, the appropriate element must
|
|
||||||
be added to the registry; when it is destroyed, it must be removed
|
|
||||||
from the registry.
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
Function Overloading
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Function Overloading
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h2>An Example</h2>
|
|
||||||
<p>
|
|
||||||
To expose overloaded functions in Python, simply <code>def()</code> each
|
|
||||||
one with the same Python name:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
inline int f1() { return 3; }
|
|
||||||
inline int f2(int x) { return x + 1; }
|
|
||||||
|
|
||||||
class X {
|
|
||||||
public:
|
|
||||||
X() : m_value(0) {}
|
|
||||||
X(int n) : m_value(n) {}
|
|
||||||
int value() const { return m_value; }
|
|
||||||
void value(int v) { m_value = v; }
|
|
||||||
private:
|
|
||||||
int m_value;
|
|
||||||
};
|
|
||||||
...
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(overload_demo)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
boost::python::module_builder overload_demo("overload_demo");
|
|
||||||
// Overloaded functions at module scope
|
|
||||||
overload_demo.def(f1, "f");
|
|
||||||
overload_demo.def(f2, "f");
|
|
||||||
|
|
||||||
boost::python::class_builder<X> x_class(overload_demo, "X");
|
|
||||||
// Overloaded constructors
|
|
||||||
x_class.def(boost::python::constructor<>());
|
|
||||||
x_class.def(boost::python::constructor<int>());
|
|
||||||
|
|
||||||
// Overloaded member functions
|
|
||||||
x_class.def((int (X::*)() const)&X::value, "value");
|
|
||||||
x_class.def((void (X::*)(int))&X::value, "value");
|
|
||||||
...
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Now in Python:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> from overload_demo import *
|
|
||||||
>>> x0 = X()
|
|
||||||
>>> x1 = X(1)
|
|
||||||
>>> x0.value()
|
|
||||||
0
|
|
||||||
>>> x1.value()
|
|
||||||
1
|
|
||||||
>>> x0.value(3)
|
|
||||||
>>> x0.value()
|
|
||||||
3
|
|
||||||
>>> X('hello')
|
|
||||||
TypeError: No overloaded functions match (X, string). Candidates are:
|
|
||||||
void (*)()
|
|
||||||
void (*)(int)
|
|
||||||
>>> f()
|
|
||||||
3
|
|
||||||
>>> f(4)
|
|
||||||
5
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h2>Discussion</h2>
|
|
||||||
<p>
|
|
||||||
Notice that overloading in the Python module was produced three ways:<ol>
|
|
||||||
<li>by combining the non-overloaded C++ functions <code>int f1()</code>
|
|
||||||
and <code>int f2(int)</code> and exposing them as <code>f</code> in Python.
|
|
||||||
<li>by exposing the overloaded constructors of <code>class X</code>
|
|
||||||
<li>by exposing the overloaded member functions <code>X::value</code>.
|
|
||||||
</ol>
|
|
||||||
<p>
|
|
||||||
Techniques 1. and 3. above are really alternatives. In case 3, you need
|
|
||||||
to form a pointer to each of the overloaded functions. The casting
|
|
||||||
syntax shown above is one way to do that in C++. Case 1 does not require
|
|
||||||
complicated-looking casts, but may not be viable if you can't change
|
|
||||||
your C++ interface. N.B. There's really nothing unsafe about casting an
|
|
||||||
overloaded (member) function address this way: the compiler won't let
|
|
||||||
you write it at all unless you get it right.
|
|
||||||
|
|
||||||
<h2>An Alternative to Casting</h2>
|
|
||||||
<p>
|
|
||||||
This approach is not neccessarily better, but may be preferable for some
|
|
||||||
people who have trouble writing out the types of (member) function
|
|
||||||
pointers or simply prefer to avoid all casts as a matter of principle:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
// Forwarding functions for X::value
|
|
||||||
inline void set_x_value(X& self, int v) { self.value(v); }
|
|
||||||
inline int get_x_value(X& self) { return self.value(); }
|
|
||||||
...
|
|
||||||
// Overloaded member functions
|
|
||||||
x_class.def(set_x_value, "value");
|
|
||||||
x_class.def(get_x_value, "value");
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>Here we are taking advantage of the ability to expose C++ functions at
|
|
||||||
namespace scope as Python member functions.
|
|
||||||
|
|
||||||
<h2>Overload Resolution</h2>
|
|
||||||
<p>
|
|
||||||
The function overload resolution mechanism works as follows:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
|
|
||||||
<li>Attribute lookup for extension classes proceeds in <a
|
|
||||||
href="http://www.python.org/doc/current/tut/node11.html#SECTION0011510000000000000000">the
|
|
||||||
usual Python way</a> using a depth-first, left-to-right search. When a
|
|
||||||
class is found which has a matching attribute, only functions overloaded
|
|
||||||
in the context of that class are candidates for overload resolution. In
|
|
||||||
this sense, overload resolution mirrors the C++ mechanism, where a name
|
|
||||||
in a derived class ``hides'' all functions with the same name from a base
|
|
||||||
class.
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<li>Within a name-space context (extension class or module), overloaded
|
|
||||||
functions are tried in the same order they were
|
|
||||||
<code>def()</code>ed. The first function whose signature can be made to
|
|
||||||
match each argument passed is the one which is ultimately called.
|
|
||||||
This means in particular that you cannot overload the same function on
|
|
||||||
both ``<code>int</code>'' and ``<code>float</code>'' because Python
|
|
||||||
automatically converts either of the two types into the other one.
|
|
||||||
If the ``<code>float</code>'' overload is found first, it is used
|
|
||||||
also used for arguments of type ``<code>int</code>'' as well, and the
|
|
||||||
``<code>int</code>'' version of the function is never invoked.
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Next: <a href="inheritance.html">Inheritance</a>
|
|
||||||
Previous: <a href="overriding.html">Overridable Virtual Functions</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided ``as
|
|
||||||
is'' without express or implied warranty, and with no claim as to
|
|
||||||
its suitability for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Mar 6, 2001
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
||||||
|
|
||||||
<title>Overridable Virtual Functions</title>
|
|
||||||
|
|
||||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
|
||||||
width="277" height="86">
|
|
||||||
|
|
||||||
<h1>Overridable Virtual Functions</h1>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In the <a href="exporting_classes.html">previous example</a> we exposed a simple
|
|
||||||
C++ class in Python and showed that we could write a subclass. We even
|
|
||||||
redefined one of the functions in our derived class. Now we will learn
|
|
||||||
how to make the function behave virtually <em>when called from C++</em>.
|
|
||||||
|
|
||||||
|
|
||||||
<h2><a name="overriding_example">Example</a></h2>
|
|
||||||
|
|
||||||
<p>In this example, it is assumed that <code>hello::greet()</code> is a virtual
|
|
||||||
member function:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
class hello
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
hello(const std::string& country) { this->country = country; }
|
|
||||||
<b>virtual</b> std::string greet() const { return "Hello from " + country; }
|
|
||||||
virtual ~hello(); // Good practice
|
|
||||||
...
|
|
||||||
};
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
We'll need a derived class<a href="#why_derived">*</a> to help us
|
|
||||||
dispatch the call to Python. In our derived class, we need the following
|
|
||||||
elements:
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
|
|
||||||
<li><a name="derived_1">A</a> <code>PyObject*</code> data member (usually
|
|
||||||
called <tt>self</tt>) that holds a pointer to the Python object corresponding
|
|
||||||
to our C++ <tt>hello</tt> instance.
|
|
||||||
|
|
||||||
<li><a name="derived_2">For</a> each exposed constructor of the
|
|
||||||
base class <tt>T</tt>, a constructor which takes the same parameters preceded by an initial
|
|
||||||
<code>PyObject*</code> argument. The initial argument should be stored in the <tt>self</tt> data
|
|
||||||
member described above.
|
|
||||||
|
|
||||||
<li><a name="derived_3">If</a> the class being wrapped is ever returned <i>by
|
|
||||||
value</i> from a wrapped function, be sure you do the same for the
|
|
||||||
<tt>T</tt>'s copy constructor: you'll need a constructor taking arguments
|
|
||||||
<tt>(PyObject*, const T&)</tt>.
|
|
||||||
|
|
||||||
<li><a name="derived_4">An</a> implementation of each virtual function you may
|
|
||||||
wish to override in Python which uses
|
|
||||||
<tt>callback<</tt><i>return-type</i><tt>>::call_method(self, "</tt><i>name</i><tt>", </tt><i>args...</i><tt>)</tt> to call
|
|
||||||
the Python override.
|
|
||||||
|
|
||||||
<li><a name="derived_5">For</a> each non-pure virtual function meant to be
|
|
||||||
overridable from Python, a static member function (or a free function) taking
|
|
||||||
a reference or pointer to the <tt>T</tt> as the first parameter and which
|
|
||||||
forwards any additional parameters neccessary to the <i>default</i>
|
|
||||||
implementation of the virtual function. See also <a href="#private">this
|
|
||||||
note</a> if the base class virtual function is private.
|
|
||||||
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
struct hello_callback : hello
|
|
||||||
{
|
|
||||||
// hello constructor storing initial self_ parameter
|
|
||||||
hello_callback(PyObject* self_, const std::string& x) // <a href="#derived_2">2</a>
|
|
||||||
: hello(x), self(self_) {}
|
|
||||||
|
|
||||||
// In case hello is returned by-value from a wrapped function
|
|
||||||
hello_callback(PyObject* self_, const hello& x) // <a href="#derived_3">3</a>
|
|
||||||
: hello(x), self(self_) {}
|
|
||||||
|
|
||||||
// Override greet to call back into Python
|
|
||||||
std::string greet() const // <a href="#derived_4">4</a>
|
|
||||||
{ return boost::python::callback<std::string>::call_method(self, "greet"); }
|
|
||||||
|
|
||||||
// Supplies the default implementation of greet
|
|
||||||
static std::string <a name= "default_implementation">default_greet</a>(const hello& self_) const // <a href="#derived_5">5</a>
|
|
||||||
{ return self_.hello::greet(); }
|
|
||||||
private:
|
|
||||||
PyObject* self; // <a href="#derived_1">1</a>
|
|
||||||
};
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Finally, we add <tt>hello_callback</tt> to the <tt>
|
|
||||||
class_builder<></tt> declaration in our module initialization
|
|
||||||
function, and when we define the function, we must tell Boost.Python about the default
|
|
||||||
implementation:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
// Create the <a name=
|
|
||||||
"hello_class">Python type object</a> for our extension class
|
|
||||||
boost::python::class_builder<hello<strong>,hello_callback></strong> hello_class(hello, "hello");
|
|
||||||
// Add a virtual member function
|
|
||||||
hello_class.def(&hello::greet, "greet", &<b>hello_callback::default_greet</b>);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Now our Python subclass of <tt>hello</tt> behaves as expected:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
>>> class wordy(hello):
|
|
||||||
... def greet(self):
|
|
||||||
... return hello.greet(self) + ', where the weather is fine'
|
|
||||||
...
|
|
||||||
>>> hi2 = wordy('Florida')
|
|
||||||
>>> hi2.greet()
|
|
||||||
'Hello from Florida, where the weather is fine'
|
|
||||||
>>> invite(hi2)
|
|
||||||
'Hello from Florida, where the weather is fine! Please come soon!'
|
|
||||||
</pre></blockquote>
|
|
||||||
<p>
|
|
||||||
<a name="why_derived">*</a>You may ask, "Why do we need this derived
|
|
||||||
class? This could have been designed so that everything gets done right
|
|
||||||
inside of <tt>hello</tt>." One of the goals of Boost.Python is to be
|
|
||||||
minimally intrusive on an existing C++ design. In principle, it should be
|
|
||||||
possible to expose the interface for a 3rd party library without changing
|
|
||||||
it. To unintrusively hook into the virtual functions so that a Python
|
|
||||||
override may be called, we must use a derived class.
|
|
||||||
|
|
||||||
<h2>Pure Virtual Functions</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
A pure virtual function with no implementation is actually a lot easier to
|
|
||||||
deal with than a virtual function with a default implementation. First of
|
|
||||||
all, you obviously don't need to <a href="#default_implementation"> supply
|
|
||||||
a default implementation</a>. Secondly, you don't need to call
|
|
||||||
<tt>def()</tt> on the <tt>extension_class<></tt> instance
|
|
||||||
for the virtual function. In fact, you wouldn't <em>want</em> to: if the
|
|
||||||
corresponding attribute on the Python class stays undefined, you'll get an
|
|
||||||
<tt>AttributeError</tt> in Python when you try to call the function,
|
|
||||||
indicating that it should have been implemented. For example:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
struct baz {
|
|
||||||
<strong>virtual</strong> int pure(int) = 0;
|
|
||||||
int calls_pure(int x) { return pure(x) + 1000; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct baz_callback {
|
|
||||||
int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(foobar)
|
|
||||||
{
|
|
||||||
boost::python::module_builder foobar("foobar");
|
|
||||||
boost::python::class_builder<baz,baz_callback> baz_class("baz");
|
|
||||||
baz_class.def(&baz::calls_pure, "calls_pure");
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Now in Python:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> from foobar import baz
|
|
||||||
>>> x = baz()
|
|
||||||
>>> x.pure(1)
|
|
||||||
Traceback (innermost last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
AttributeError: pure
|
|
||||||
>>> x.calls_pure(1)
|
|
||||||
Traceback (innermost last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
AttributeError: pure
|
|
||||||
>>> class mumble(baz):
|
|
||||||
... def pure(self, x): return x + 1
|
|
||||||
...
|
|
||||||
>>> y = mumble()
|
|
||||||
>>> y.pure(99)
|
|
||||||
100
|
|
||||||
>>> y.calls_pure(99)
|
|
||||||
1100
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<a name="private"><h2>Private Non-Pure Virtual Functions</h2></a>
|
|
||||||
|
|
||||||
<p>This is one area where some minor intrusiveness on the wrapped library is
|
|
||||||
required. Once it has been overridden, the only way to call the base class
|
|
||||||
implementation of a private virtual function is to make the derived class a
|
|
||||||
friend of the base class. You didn't hear it from me, but most C++
|
|
||||||
implementations will allow you to change the declaration of the base class in
|
|
||||||
this limited way without breaking binary compatibility (though it will certainly
|
|
||||||
break the <a
|
|
||||||
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<p>
|
|
||||||
Next: <a href="overloading.html">Function Overloading</a>
|
|
||||||
Previous: <a href="exporting_classes.html">Exporting Classes</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability for
|
|
||||||
any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Mar 21, 2001
|
|
||||||
|
|
||||||
272
doc/pickle.html
272
doc/pickle.html
@@ -1,272 +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="../../../c++boost.gif"
|
|
||||||
alt="c++boost.gif (8819 bytes)"
|
|
||||||
align="center"
|
|
||||||
width="277" height="86">
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h1>Boost.Python Pickle Support</h1>
|
|
||||||
|
|
||||||
Pickle is a Python module for object serialization, also known
|
|
||||||
as persistence, marshalling, or flattening.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
It is often necessary to save and restore the contents of an object to
|
|
||||||
a file. One approach to this problem is to write a pair of functions
|
|
||||||
that read and write data from a file in a special format. A powerful
|
|
||||||
alternative approach is to use Python's pickle module. Exploiting
|
|
||||||
Python's ability for introspection, the pickle module recursively
|
|
||||||
converts nearly arbitrary Python objects into a stream of bytes that
|
|
||||||
can be written to a file.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The Boost Python Library supports the pickle module by emulating the
|
|
||||||
interface implemented by Jim Fulton's ExtensionClass module that is
|
|
||||||
included in the
|
|
||||||
<a href="http://www.zope.org/"
|
|
||||||
>ZOPE</a>
|
|
||||||
distribution.
|
|
||||||
This interface is similar to that for regular Python classes as
|
|
||||||
described in detail in the
|
|
||||||
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
|
|
||||||
>Python Library Reference for pickle.</a>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>The Boost.Python Pickle Interface</h2>
|
|
||||||
|
|
||||||
At the user level, the Boost.Python pickle interface involves three special
|
|
||||||
methods:
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>
|
|
||||||
<strong><tt>__getinitargs__</tt></strong>
|
|
||||||
<dd>
|
|
||||||
When an instance of a Boost.Python extension class is pickled, the
|
|
||||||
pickler tests if the instance has a <tt>__getinitargs__</tt> method.
|
|
||||||
This method must return a Python tuple (it is most convenient to use
|
|
||||||
a boost::python::tuple). When the instance is restored by the
|
|
||||||
unpickler, the contents of this tuple are used as the arguments for
|
|
||||||
the class constructor.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If <tt>__getinitargs__</tt> is not defined, the class constructor
|
|
||||||
will be called without arguments.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<dt>
|
|
||||||
<strong><tt>__getstate__</tt></strong>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
When an instance of a Boost.Python extension class is pickled, the
|
|
||||||
pickler tests if the instance has a <tt>__getstate__</tt> method.
|
|
||||||
This method should return a Python object representing the state of
|
|
||||||
the instance.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If <tt>__getstate__</tt> is not defined, the instance's
|
|
||||||
<tt>__dict__</tt> is pickled (if it is not empty).
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<dt>
|
|
||||||
<strong><tt>__setstate__</tt></strong>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
When an instance of a Boost.Python extension class is restored by the
|
|
||||||
unpickler, it is first constructed using the result of
|
|
||||||
<tt>__getinitargs__</tt> as arguments (see above). Subsequently the
|
|
||||||
unpickler tests if the new instance has a <tt>__setstate__</tt>
|
|
||||||
method. If so, this method is called with the result of
|
|
||||||
<tt>__getstate__</tt> (a Python object) as the argument.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If <tt>__setstate__</tt> is not defined, the result of
|
|
||||||
<tt>__getstate__</tt> must be a Python dictionary. The items of this
|
|
||||||
dictionary are added to the instance's <tt>__dict__</tt>.
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
If both <tt>__getstate__</tt> and <tt>__setstate__</tt> are defined,
|
|
||||||
the Python object returned by <tt>__getstate__</tt> need not be a
|
|
||||||
dictionary. The <tt>__getstate__</tt> and <tt>__setstate__</tt> methods
|
|
||||||
can do what they want.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Pitfalls and Safety Guards</h2>
|
|
||||||
|
|
||||||
In Boost.Python extension modules with many extension classes,
|
|
||||||
providing complete pickle support for all classes would be a
|
|
||||||
significant overhead. In general complete pickle support should only be
|
|
||||||
implemented for extension classes that will eventually be pickled.
|
|
||||||
However, the author of a Boost.Python extension module might not
|
|
||||||
anticipate correctly which classes need support for pickle.
|
|
||||||
Unfortunately, the pickle protocol described above has two important
|
|
||||||
pitfalls that the end user of a Boost.Python extension module might not
|
|
||||||
be aware of:
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>
|
|
||||||
<strong>Pitfall 1:</strong>
|
|
||||||
Both <tt>__getinitargs__</tt> and <tt>__getstate__</tt> are not defined.
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
In this situation the unpickler calls the class constructor without
|
|
||||||
arguments and then adds the <tt>__dict__</tt> that was pickled by
|
|
||||||
default to that of the new instance.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
However, most C++ classes wrapped with Boost.Python will have member
|
|
||||||
data that are not restored correctly by this procedure. To alert the
|
|
||||||
user to this problem, a safety guard is provided. If both
|
|
||||||
<tt>__getinitargs__</tt> and <tt>__getstate__</tt> are not defined,
|
|
||||||
Boost.Python tests if the class has an attribute
|
|
||||||
<tt>__dict_defines_state__</tt>. An exception is raised if this
|
|
||||||
attribute is not defined:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
In the rare cases where this is not the desired behavior, the safety
|
|
||||||
guard can deliberately be disabled. The corresponding C++ code for
|
|
||||||
this is, e.g.:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
class_builder<your_class> py_your_class(your_module, "your_class");
|
|
||||||
py_your_class.dict_defines_state();
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
It is also possible to override the safety guard at the Python level.
|
|
||||||
E.g.:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import your_bpl_module
|
|
||||||
class your_class(your_bpl_module.your_class):
|
|
||||||
__dict_defines_state__ = 1
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<dt>
|
|
||||||
<strong>Pitfall 2:</strong>
|
|
||||||
<tt>__getstate__</tt> is defined and the instance's <tt>__dict__</tt> is not empty.
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
The author of a Boost.Python extension class might provide a
|
|
||||||
<tt>__getstate__</tt> method without considering the possibilities
|
|
||||||
that:
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
his class is used in Python as a base class. Most likely the
|
|
||||||
<tt>__dict__</tt> of instances of the derived class needs to be
|
|
||||||
pickled in order to restore the instances correctly.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<li>
|
|
||||||
the user adds items to the instance's <tt>__dict__</tt> directly.
|
|
||||||
Again, the <tt>__dict__</tt> of the instance then needs to be
|
|
||||||
pickled.
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
|
|
||||||
To alert the user to this highly unobvious problem, a safety guard is
|
|
||||||
provided. If <tt>__getstate__</tt> is defined and the instance's
|
|
||||||
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has
|
|
||||||
an attribute <tt>__getstate_manages_dict__</tt>. An exception is
|
|
||||||
raised if this attribute is not defined:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
To resolve this problem, it should first be established that the
|
|
||||||
<tt>__getstate__</tt> and <tt>__setstate__</tt> methods manage the
|
|
||||||
instances's <tt>__dict__</tt> correctly. Note that this can be done
|
|
||||||
both at the C++ and the Python level. Finally, the safety guard
|
|
||||||
should intentionally be overridden. E.g. in C++:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
class_builder<your_class> py_your_class(your_module, "your_class");
|
|
||||||
py_your_class.getstate_manages_dict();
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
In Python:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
import your_bpl_module
|
|
||||||
class your_class(your_bpl_module.your_class):
|
|
||||||
__getstate_manages_dict__ = 1
|
|
||||||
def __getstate__(self):
|
|
||||||
# your code here
|
|
||||||
def __setstate__(self, state):
|
|
||||||
# your code here
|
|
||||||
</pre>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Practical Advice</h2>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Avoid using <tt>__getstate__</tt> if the instance can also be
|
|
||||||
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
|
|
||||||
avoids Pitfall 2.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<li>
|
|
||||||
If <tt>__getstate__</tt> is required, include the instance's
|
|
||||||
<tt>__dict__</tt> in the Python object that is returned.
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Examples</h2>
|
|
||||||
|
|
||||||
There are three files in <tt>boost/libs/python/example</tt> that
|
|
||||||
show how so provide pickle support.
|
|
||||||
|
|
||||||
<h3><a href="../example/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>
|
|
||||||
|
|
||||||
The C++ class in this example can be fully restored by passing the
|
|
||||||
appropriate argument to the constructor. Therefore it is sufficient
|
|
||||||
to define the pickle interface method <tt>__getinitargs__</tt>.
|
|
||||||
|
|
||||||
<h3><a href="../example/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>
|
|
||||||
|
|
||||||
The C++ class in this example contains member data that cannot be
|
|
||||||
restored by any of the constructors. Therefore it is necessary to
|
|
||||||
provide the <tt>__getstate__</tt>/<tt>__setstate__</tt> pair of
|
|
||||||
pickle interface methods.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For simplicity, the <tt>__dict__</tt> is not included in the result
|
|
||||||
of <tt>__getstate__</tt>. This is not generally recommended, but a
|
|
||||||
valid approach if it is anticipated that the object's
|
|
||||||
<tt>__dict__</tt> will always be empty. Note that the safety guards
|
|
||||||
will catch the cases where this assumption is violated.
|
|
||||||
|
|
||||||
<h3><a href="../example/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>
|
|
||||||
|
|
||||||
This example is similar to <a
|
|
||||||
href="../example/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the
|
|
||||||
object's <tt>__dict__</tt> is included in the result of
|
|
||||||
<tt>__getstate__</tt>. This requires more code but is unavoidable
|
|
||||||
if the object's <tt>__dict__</tt> is not always empty.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
© Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy,
|
|
||||||
use, modify, sell and distribute this document is granted provided this
|
|
||||||
copyright notice appears in all copies. This document is provided "as
|
|
||||||
is" without express or implied warranty, and with no claim as to its
|
|
||||||
suitability for any purpose.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Updated: March 21, 2001
|
|
||||||
</div>
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<title>
|
|
||||||
Pointers
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
|
||||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Pointers
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h2><a name="problem">The Problem With Pointers</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In general, raw pointers passed to or returned from functions are problematic
|
|
||||||
for Boost.Python because pointers have too many potential meanings. Is it an iterator?
|
|
||||||
A pointer to a single element? An array? When used as a return value, is the
|
|
||||||
caller expected to manage (delete) the pointed-to object or is the pointer
|
|
||||||
really just a reference? If the latter, what happens to Python references to the
|
|
||||||
referent when some C++ code deletes it?
|
|
||||||
<p>
|
|
||||||
There are a few cases in which pointers are converted automatically:
|
|
||||||
<ul>
|
|
||||||
|
|
||||||
<li>Both const- and non-const pointers to wrapped class instances can be passed
|
|
||||||
<i>to</i> C++ functions.
|
|
||||||
|
|
||||||
<li>Values of type <code>const char*</code> are interpreted as
|
|
||||||
null-terminated 'C' strings and when passed to or returned from C++ functions are
|
|
||||||
converted from/to Python strings.
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Can you avoid the problem?</h3>
|
|
||||||
|
|
||||||
<p>My first piece of advice to anyone with a case not covered above is
|
|
||||||
``find a way to avoid the problem.'' For example, if you have just one
|
|
||||||
or two functions that return a pointer to an individual <code>const
|
|
||||||
T</code>, and <code>T</code> is a wrapped class, you may be able to write a ``thin
|
|
||||||
converting wrapper'' over those two functions as follows:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
const Foo* f(); // original function
|
|
||||||
const Foo& f_wrapper() { return *f(); }
|
|
||||||
...
|
|
||||||
my_module.def(f_wrapper, "f");
|
|
||||||
</pre></blockquote>
|
|
||||||
<p>
|
|
||||||
Foo must have a public copy constructor for this technique to work, since Boost.Python
|
|
||||||
converts <code>const T&</code> values <code>to_python</code> by copying the <code>T</code>
|
|
||||||
value into a new extension instance.
|
|
||||||
|
|
||||||
<h2>Dealing with the problem</h2>
|
|
||||||
|
|
||||||
<p>The first step in handling the remaining cases is to figure out what the pointer
|
|
||||||
means. Several potential solutions are provided in the examples that follow:
|
|
||||||
|
|
||||||
<h3>Returning a pointer to a wrapped type</h3>
|
|
||||||
|
|
||||||
<h4>Returning a const pointer</h4>
|
|
||||||
|
|
||||||
<p>If you have lots of functions returning a <code>const T*</code> for some
|
|
||||||
wrapped <code>T</code>, you may want to provide an automatic
|
|
||||||
<code>to_python</code> conversion function so you don't have to write lots of
|
|
||||||
thin wrappers. You can do this simply as follows:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
|
||||||
PyObject* to_python(const Foo* p) {
|
|
||||||
return to_python(*p); // convert const Foo* in terms of const Foo&
|
|
||||||
}
|
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<h4>If you can't (afford to) copy the referent, or the pointer is non-const</h4>
|
|
||||||
|
|
||||||
<p>If the wrapped type doesn't have a public copy constructor, if copying is
|
|
||||||
<i>extremely</i> costly (remember, we're dealing with Python here), or if the
|
|
||||||
pointer is non-const and you really need to be able to modify the referent from
|
|
||||||
Python, you can use the following dangerous trick. Why dangerous? Because python
|
|
||||||
can not control the lifetime of the referent, so it may be destroyed by your C++
|
|
||||||
code before the last Python reference to it disappears:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
|
||||||
PyObject* to_python(Foo* p)
|
|
||||||
{
|
|
||||||
return boost::python::python_extension_class_converters<Foo>::smart_ptr_to_python(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject* to_python(const Foo* p)
|
|
||||||
{
|
|
||||||
return to_python(const_cast<Foo*>(p));
|
|
||||||
}
|
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
This will cause the Foo* to be treated as though it were an owning smart
|
|
||||||
pointer, even though it's not. Be sure you don't use the reference for anything
|
|
||||||
from Python once the pointer becomes invalid, though. Don't worry too much about
|
|
||||||
the <code>const_cast<></code> above: Const-correctness is completely lost
|
|
||||||
to Python anyway!
|
|
||||||
|
|
||||||
<h3>[In/]Out Parameters and Immutable Types</h3>
|
|
||||||
|
|
||||||
<p>If you have an interface that uses non-const pointers (or references) as
|
|
||||||
in/out parameters to types which in Python are immutable (e.g. int, string),
|
|
||||||
there simply is <i>no way</i> to get the same interface in Python. You must
|
|
||||||
resort to transforming your interface with simple thin wrappers as shown below:
|
|
||||||
<blockquote><pre>
|
|
||||||
const void f(int* in_out_x); // original function
|
|
||||||
const int f_wrapper(int in_x) { f(in_x); return in_x; }
|
|
||||||
...
|
|
||||||
my_module.def(f_wrapper, "f");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>Of course, [in/]out parameters commonly occur only when there is already a
|
|
||||||
return value. You can handle this case by returning a Python tuple:
|
|
||||||
<blockquote><pre>
|
|
||||||
typedef unsigned ErrorCode;
|
|
||||||
const char* f(int* in_out_x); // original function
|
|
||||||
...
|
|
||||||
#include <boost/python/objects.hpp>
|
|
||||||
const boost::python::tuple f_wrapper(int in_x) {
|
|
||||||
const char* s = f(in_x);
|
|
||||||
return boost::python::tuple(s, in_x);
|
|
||||||
}
|
|
||||||
...
|
|
||||||
my_module.def(f_wrapper, "f");
|
|
||||||
</pre></blockquote>
|
|
||||||
<p>Now, in Python:
|
|
||||||
<blockquote><pre>
|
|
||||||
>>> str,out_x = f(3)
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Previous: <a href="enums.html">Enums</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability
|
|
||||||
for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Nov 26, 2000
|
|
||||||
</div>
|
|
||||||
|
|
||||||
106
doc/richcmp.html
106
doc/richcmp.html
@@ -1,106 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
||||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
|
|
||||||
<title>Rich Comparisons</title>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
|
|
||||||
<img src="../../../c++boost.gif"
|
|
||||||
alt="c++boost.gif (8819 bytes)"
|
|
||||||
align="center"
|
|
||||||
width="277" height="86">
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h1>Rich Comparisons</h1>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
In Python versions up to and including Python 2.0, support for
|
|
||||||
implementing comparisons on user-defined classes and extension types
|
|
||||||
was quite simple. Classes could implement a <tt>__cmp__</tt> method
|
|
||||||
that was given two instances of a class as arguments, and could only
|
|
||||||
return <tt>0</tt> if they were equal or <tt>+1</tt> or <tt>-1</tt> if
|
|
||||||
they were not. The method could not raise an exception or return
|
|
||||||
anything other than an integer value.
|
|
||||||
In Python 2.1, <b>Rich Comparisons</b> were added (see
|
|
||||||
<a href="http://python.sourceforge.net/peps/pep-0207.html">PEP 207</a>).
|
|
||||||
Python classes can now individually overload each of the <, <=,
|
|
||||||
>, >=, ==, and != operations.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For more detailed information, search for "rich comparison"
|
|
||||||
<a href="http://www.python.org/doc/current/ref/customization.html"
|
|
||||||
>here</a>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Boost.Python supports both automatic overloading and manual overloading
|
|
||||||
of the Rich Comparison operators. The <b>compile-time</b> support is
|
|
||||||
independent of the Python version that is used when compiling
|
|
||||||
Boost.Python extension modules. That is, <tt>op_lt</tt> for example can
|
|
||||||
always be used, and the C++ <tt>operator<</tt> will always be bound
|
|
||||||
to the Python method <tt>__lt__</tt>. However, the <b>run-time</b>
|
|
||||||
behavior will depend on the Python version.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
With Python versions before 2.1, the Rich Comparison operators will not
|
|
||||||
be called by Python when any of the six comparison operators
|
|
||||||
(<tt><</tt>, <tt><=</tt>, <tt>==</tt>, <tt>!=</tt>,
|
|
||||||
<tt>></tt>, <tt>>=</tt>) is used in an expression. The only way
|
|
||||||
to access the corresponding methods is to call them explicitly, e.g.
|
|
||||||
<tt>a.__lt__(b)</tt>. Only with Python versions 2.1 or higher will
|
|
||||||
expressions like <tt>a < b</tt> work as expected.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
To support Rich Comparisions, the Python C API was modified between
|
|
||||||
Python versions 2.0 and 2.1. A new slot was introduced in the
|
|
||||||
<tt>PyTypeObject</tt> structure: <tt>tp_richcompare</tt>. For backwards
|
|
||||||
compatibility, a flag (<tt>Py_TPFLAGS_HAVE_RICHCOMPARE</tt>) has to be
|
|
||||||
set to signal to the Python interpreter that Rich Comparisions are
|
|
||||||
supported by a particular type.
|
|
||||||
There is only one flag for all the six comparison operators.
|
|
||||||
When any of the six operators is wrapped automatically or
|
|
||||||
manually, Boost.Python will set this flag. Attempts to use comparison
|
|
||||||
operators at the Python level that are not defined at the C++ level
|
|
||||||
will then lead to an <tt>AttributeError</tt> when the Python 2.1
|
|
||||||
(or higher) interpreter tries, e.g., <tt>a.__lt__(b)</tt>. That
|
|
||||||
is, in general all six operators should be supplied. Automatically
|
|
||||||
wrapped operators and manually wrapped operators can be mixed. For
|
|
||||||
example:<pre>
|
|
||||||
boost::python::class_builder<code> py_code(this_module, "code");
|
|
||||||
|
|
||||||
py_code.def(boost::python::constructor<>());
|
|
||||||
py_code.def(boost::python::constructor<int>());
|
|
||||||
py_code.def(boost::python::operators<( boost::python::op_eq
|
|
||||||
| boost::python::op_ne)>());
|
|
||||||
py_code.def(NotImplemented, "__lt__");
|
|
||||||
py_code.def(NotImplemented, "__le__");
|
|
||||||
py_code.def(NotImplemented, "__gt__");
|
|
||||||
py_code.def(NotImplemented, "__ge__");
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<tt>NotImplemented</tt> is a simple free function that (currently) has
|
|
||||||
to be provided by the user. For example:<pre>
|
|
||||||
boost::python::ref
|
|
||||||
NotImplemented(const code&, const code&) {
|
|
||||||
return
|
|
||||||
boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
See also:
|
|
||||||
<ul>
|
|
||||||
<li><a href="../example/richcmp1.cpp"><tt>../example/richcmp1.cpp</tt></a>
|
|
||||||
<li><a href="../example/richcmp2.cpp"><tt>../example/richcmp2.cpp</tt></a>
|
|
||||||
<li><a href="../example/richcmp3.cpp"><tt>../example/richcmp3.cpp</tt></a>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
© Copyright Nicholas K. Sauter & Ralf W. Grosse-Kunstleve 2001.
|
|
||||||
Permission to copy, use, modify, sell and distribute this document is
|
|
||||||
granted provided this copyright notice appears in all copies. This
|
|
||||||
document is provided "as is" without express or implied warranty, and
|
|
||||||
with no claim as to its suitability for any purpose.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Updated: July 2001
|
|
||||||
|
|
||||||
</div>
|
|
||||||
973
doc/special.html
973
doc/special.html
@@ -1,973 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
||||||
<title>
|
|
||||||
Special Method and Operator Support
|
|
||||||
</title>
|
|
||||||
<div>
|
|
||||||
<h1>
|
|
||||||
<img width="277" height="86" id="_x0000_i1025" align="middle" src=
|
|
||||||
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Special Method and
|
|
||||||
Operator Support
|
|
||||||
</h1>
|
|
||||||
<h2>
|
|
||||||
Overview
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
Boost.Python supports all of the standard <a href=
|
|
||||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
|
||||||
special method names</a> supported by real Python class instances <em>
|
|
||||||
except</em> <code>__complex__</code> (more on the reasons <a href=
|
|
||||||
"#reasons">below</a>). In addition, it can quickly and easily expose
|
|
||||||
suitable C++ functions and operators as Python operators. The following
|
|
||||||
categories of special method names are supported:
|
|
||||||
<ul>
|
|
||||||
<li><a href="#general">Basic Customization</a>
|
|
||||||
<li><a href="#numeric">Numeric Operators</a>
|
|
||||||
<li><a href="#sequence_and_mapping">Sequence and Mapping protocols</a>
|
|
||||||
<li><a href="#getter_setter">Attribute Getters and Setters</a>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2><a name="general">Basic Customization</a></h2>
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Python provides a number of special operators for basic customization of a
|
|
||||||
class. Only a brief description is provided below; more complete
|
|
||||||
documentation can be found <a
|
|
||||||
href="http://www.python.org/doc/current/ref/customization.html">here</a>.
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__init__</tt></b>(<i>self</i>)
|
|
||||||
<dd>
|
|
||||||
Initialize the class instance. For extension classes not subclassed in
|
|
||||||
Python, <code> __init__</code> is defined by
|
|
||||||
|
|
||||||
<pre> my_class.def(boost::python::constructor<...>())</pre>
|
|
||||||
|
|
||||||
(see section <a href="example1.html">"A Simple Example Using Boost.Python"</a>).<p>
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__del__</tt></b>(<i>self</i>)
|
|
||||||
<dd>
|
|
||||||
Called when the extension instance is about to be destroyed. For extension classes
|
|
||||||
not subclassed in Python, <code> __del__</code> is always defined automatically by
|
|
||||||
means of the class' destructor.
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__repr__</tt></b>(<i>self</i>)
|
|
||||||
<dd>
|
|
||||||
Create a string representation from which the object can be
|
|
||||||
reconstructed.
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__str__</tt></b>(<i>self</i>)
|
|
||||||
<dd>
|
|
||||||
Create a string representation which is suitable for printing.
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__lt__</tt></b>(<i>self, other</i>)
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__le__</tt></b>(<i>self, other</i>)
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__eq__</tt></b>(<i>self, other</i>)
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__ne__</tt></b>(<i>self, other</i>)
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__gt__</tt></b>(<i>self, other</i>)
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__ge__</tt></b>(<i>self, other</i>)
|
|
||||||
<dd>
|
|
||||||
Rich Comparison methods.
|
|
||||||
New in Python 2.1.
|
|
||||||
See <a href="richcmp.html">Rich Comparisons</a>.
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__cmp__</tt></b>(<i>self, other</i>)
|
|
||||||
<dd>
|
|
||||||
Three-way compare function.
|
|
||||||
See <a href="richcmp.html">Rich Comparisons</a>.
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__hash__</tt></b>(<i>self</i>)
|
|
||||||
<dd>
|
|
||||||
Called for the key object for dictionary operations, and by the
|
|
||||||
built-in function hash(). Should return a 32-bit integer usable as a
|
|
||||||
hash value for dictionary operations (only allowed if __cmp__ is also
|
|
||||||
defined)
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__nonzero__</tt></b>(<i>self</i>)
|
|
||||||
<dd>
|
|
||||||
called if the object is used as a truth value (e.g. in an if
|
|
||||||
statement)
|
|
||||||
<dt>
|
|
||||||
<b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>)
|
|
||||||
<dd>
|
|
||||||
Called when the instance is ``called'' as a function; if this method
|
|
||||||
is defined, <code><var>x</var>(arg1, arg2, ...)</code> is a shorthand for
|
|
||||||
<code><var>x</var>.__call__(arg1, arg2, ...)</code>.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
If we have a suitable C++ function that supports any of these features,
|
|
||||||
we can export it like any other function, using its Python special name.
|
|
||||||
For example, suppose that class <code>Foo</code> provides a string
|
|
||||||
conversion function:
|
|
||||||
<blockquote><pre>
|
|
||||||
std::string to_string(Foo const& f)
|
|
||||||
{
|
|
||||||
std::ostringstream s;
|
|
||||||
s << f;
|
|
||||||
return s.str();
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
This function would be wrapped like this:
|
|
||||||
<blockquote><pre>
|
|
||||||
boost::python::class_builder<Foo> foo_class(my_module, "Foo");
|
|
||||||
foo_class.def(&to_string, "__str__");
|
|
||||||
</pre></blockquote>
|
|
||||||
Note that Boost.Python also supports <em>automatic wrapping</em> of
|
|
||||||
<code>__str__</code> and <code>__cmp__</code>. This is explained in the <a
|
|
||||||
href="#numeric">next section</a> and the <a href="#numeric_table">Table of
|
|
||||||
Automatically Wrapped Methods</a>.
|
|
||||||
|
|
||||||
<h2><a name="numeric">Numeric Operators</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Numeric operators can be exposed manually, by <code>def</code>ing C++
|
|
||||||
[member] functions that support the standard Python <a
|
|
||||||
href="http://www.python.org/doc/current/ref/numeric-types.html">numeric
|
|
||||||
protocols</a>. This is the same basic technique used to expose
|
|
||||||
<code>to_string()</code> as <code>__str__()</code> above, and is <a
|
|
||||||
href="#numeric_manual">covered in detail below</a>. Boost.Python also supports
|
|
||||||
<i>automatic wrapping</i> of numeric operators whenever they have already
|
|
||||||
been defined in C++.
|
|
||||||
|
|
||||||
<h3><a name="numeric_auto">Exposing C++ Operators Automatically</a></h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Supose we wanted to expose a C++ class
|
|
||||||
<code>BigNum</code> which supports addition. That is, in C++ we can write:
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum a, b, c;
|
|
||||||
...
|
|
||||||
c = a + b;
|
|
||||||
</pre></blockquote>
|
|
||||||
<p>
|
|
||||||
To enable the same functionality in Python, we first wrap the <code>
|
|
||||||
BigNum</code> class as usual:
|
|
||||||
<blockquote><pre>
|
|
||||||
boost::python::class_builder<BigNum> bignum_class(my_module, "BigNum");
|
|
||||||
bignum_class.def(boost::python::constructor<>());
|
|
||||||
...
|
|
||||||
</pre></blockquote>
|
|
||||||
Then we export the addition operator like this:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def(boost::python::operators<boost::python::op_add>());
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
Since BigNum also supports subtraction, multiplication, and division, we
|
|
||||||
want to export those also. This can be done in a single command by
|
|
||||||
``or''ing the operator identifiers together (a complete list of these
|
|
||||||
identifiers and the corresponding operators can be found in the <a href=
|
|
||||||
"#numeric_table">Table of Automatically Wrapped Methods</a>):
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>());
|
|
||||||
</pre></blockquote>
|
|
||||||
[Note that the or-expression must be enclosed in parentheses.]
|
|
||||||
|
|
||||||
<p>This form of operator definition can be used to wrap unary and
|
|
||||||
homogeneous binary operators (a <i>homogeneous</i> operator has left and
|
|
||||||
right operands of the same type). Now suppose that our C++ library also
|
|
||||||
supports addition of BigNums and plain integers:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum a, b;
|
|
||||||
int i;
|
|
||||||
...
|
|
||||||
a = b + i;
|
|
||||||
a = i + b;
|
|
||||||
</pre></blockquote>
|
|
||||||
To wrap these heterogeneous operators, we need to specify a different type for
|
|
||||||
one of the operands. This is done using the <code>right_operand</code>
|
|
||||||
and <code>left_operand</code> templates:
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>());
|
|
||||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>());
|
|
||||||
</pre></blockquote>
|
|
||||||
Boost.Python uses overloading to register several variants of the same
|
|
||||||
operation (more on this in the context of <a href="#coercion">
|
|
||||||
coercion</a>). Again, several operators can be exported at once:
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(),
|
|
||||||
boost::python::right_operand<int>());
|
|
||||||
bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(),
|
|
||||||
boost::python::left_operand<int>());
|
|
||||||
</pre></blockquote>
|
|
||||||
The type of the operand not mentioned is taken from the class being wrapped. In
|
|
||||||
our example, the class object is <code>bignum_class</code>, and thus the
|
|
||||||
other operand's type is ``<code>BigNum const&</code>''. You can override
|
|
||||||
this default by explicitly specifying a type in the <code>
|
|
||||||
operators</code> template:
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def(boost::python::operators<boost::python::op_add, BigNum>(), boost::python::right_operand<int>());
|
|
||||||
</pre></blockquote>
|
|
||||||
<p>
|
|
||||||
Note that automatic wrapping uses the <em>expression</em>
|
|
||||||
``<code>left + right</code>'' and can be used uniformly
|
|
||||||
regardless of whether the C++ operators are supplied as free functions
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum operator+(BigNum, BigNum)
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
or as member functions
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum::operator+(BigNum).
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For the Python built-in functions <code>pow()</code> and
|
|
||||||
<code>abs()</code>, there is no corresponding C++ operator. Instead,
|
|
||||||
automatic wrapping attempts to wrap C++ functions of the same name. This
|
|
||||||
only works if those functions are known in namespace
|
|
||||||
<code>python</code>. On some compilers (e.g. MSVC) it might be
|
|
||||||
necessary to add a using declaration prior to wrapping:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
namespace boost { namespace python {
|
|
||||||
using my_namespace::pow;
|
|
||||||
using my_namespace::abs;
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<h3><a name="numeric_manual">Wrapping Numeric Operators Manually</a></h3>
|
|
||||||
<p>
|
|
||||||
In some cases, automatic wrapping of operators may be impossible or
|
|
||||||
undesirable. Suppose, for example, that the modulo operation for BigNums
|
|
||||||
is defined by a set of functions called <code>mod()</code>:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum mod(BigNum const& left, BigNum const& right);
|
|
||||||
BigNum mod(BigNum const& left, int right);
|
|
||||||
BigNum mod(int left, BigNum const& right);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For automatic wrapping of the modulo function, <code>operator%()</code> would be needed.
|
|
||||||
Therefore, the <code>mod()</code>-functions must be wrapped manually. That is, we have
|
|
||||||
to export them explicitly with the Python special name "__mod__":
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def((BigNum (*)(BigNum const&, BigNum const&))&mod, "__mod__");
|
|
||||||
bignum_class.def((BigNum (*)(BigNum const&, int))&mod, "__mod__");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The third form of <code>mod()</code> (with <code>int</code> as left operand) cannot
|
|
||||||
be wrapped directly. We must first create a function <code>rmod()</code> with the
|
|
||||||
operands reversed:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum rmod(BigNum const& right, int left)
|
|
||||||
{
|
|
||||||
return mod(left, right);
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
This function must be wrapped under the name "__rmod__" (standing for "reverse mod"):
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def(&rmod, "__rmod__");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
Many of the possible operator names can be found in the <a href=
|
|
||||||
"#numeric_table">Table of Automatically Wrapped Methods</a>. Special treatment is
|
|
||||||
necessary to export the <a href="#ternary_pow">ternary pow</a> operator.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Automatic and manual wrapping can be mixed arbitrarily. Note that you
|
|
||||||
cannot overload the same operator for a given extension class on both
|
|
||||||
``<code>int</code>'' and ``<code>float</code>'', because Python implicitly
|
|
||||||
converts these types into each other. Thus, the overloaded variant
|
|
||||||
found first (be it ``<code>int</code>`` or ``<code>float</code>'') will be
|
|
||||||
used for either of the two types.
|
|
||||||
|
|
||||||
<h3><a name="inplace">Inplace Operators</a></h3>
|
|
||||||
<p>
|
|
||||||
Boost.Python can also be used to expose inplace numeric operations
|
|
||||||
(i.e., <code>+=</code> and so forth). These operators must be wrapped
|
|
||||||
manually, as described in the previous section. For example, suppose
|
|
||||||
the class BigNum has an <code>operator+=</code>:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum& operator+= (BigNum const& right);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
This can be exposed by first writing a wrapper function:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum& iadd (BigNum& self, const BigNum& right)
|
|
||||||
{
|
|
||||||
return self += right;
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
and then exposing the wrapper with
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def(&iadd, "__iadd__");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3><a name="coercion">Coercion</a></h3>
|
|
||||||
|
|
||||||
|
|
||||||
Plain Python can only execute operators with identical types on the left
|
|
||||||
and right hand side. If it encounters an expression where the types of
|
|
||||||
the left and right operand differ, it tries to coerce these types to a
|
|
||||||
common type before invoking the actual operator. Implementing good
|
|
||||||
coercion functions can be difficult if many type combinations must be
|
|
||||||
supported.
|
|
||||||
<p>
|
|
||||||
Boost.Python solves this problem the same way that C++ does: with <em><a
|
|
||||||
href="overloading.html">overloading</a></em>. This technique drastically
|
|
||||||
simplifies the code neccessary to support operators: you just register
|
|
||||||
operators for all desired type combinations, and Boost.Python automatically
|
|
||||||
ensures that the correct function is called in each case; there is no
|
|
||||||
need for user-defined coercion functions. To enable operator
|
|
||||||
overloading, Boost.Python provides a standard coercion which is <em>implicitly
|
|
||||||
registered</em> whenever automatic operator wrapping is used.
|
|
||||||
<p>
|
|
||||||
If you wrap all operator functions manually, but still want to use
|
|
||||||
operator overloading, you have to register the standard coercion
|
|
||||||
function explicitly:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
// this is not necessary if automatic operator wrapping is used
|
|
||||||
bignum_class.def_standard_coerce();
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
If you encounter a situation where you absolutely need a customized
|
|
||||||
coercion, you can still define the "__coerce__" operator manually. The signature
|
|
||||||
of a coercion function should look like one of the following (the first is
|
|
||||||
the safest):
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
boost::python::tuple custom_coerce(boost::python::reference left, boost::python::reference right);
|
|
||||||
boost::python::tuple custom_coerce(PyObject* left, PyObject* right);
|
|
||||||
PyObject* custom_coerce(PyObject* left, PyObject* right);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
The resulting <code>tuple</code> must contain two elements which
|
|
||||||
represent the values of <code>left</code> and <code>right</code>
|
|
||||||
converted to the same type. Such a function is wrapped as usual:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
// this must be called before any use of automatic operator
|
|
||||||
// wrapping or a call to some_class.def_standard_coerce()
|
|
||||||
some_class.def(&custom_coerce, "__coerce__");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
Note that the standard coercion (defined by use of automatic
|
|
||||||
operator wrapping on a <code>class_builder</code> or a call to
|
|
||||||
<code>class_builder::def_standard_coerce()</code>) will never be applied if
|
|
||||||
a custom coercion function has been registered. Therefore, in
|
|
||||||
your coercion function you should call
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
boost::python::standard_coerce(left, right);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
for all cases that you don't want to handle yourself.
|
|
||||||
|
|
||||||
<h3><a name="ternary_pow">The Ternary <code>pow()</code> Operator</a></h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In addition to the usual binary <code>pow(x, y)</code> operator (meaning
|
|
||||||
<i>x<sup>y</sup></i>), Python also provides a ternary variant that implements
|
|
||||||
<i>x<sup>y</sup> <b>mod</b> z</i>, presumably using a more efficient algorithm than
|
|
||||||
concatenation of power and modulo operators. Automatic operator wrapping
|
|
||||||
can only be used with the binary variant. Ternary <code>pow()</code> must
|
|
||||||
always be wrapped manually. For a homgeneous ternary <code>pow()</code>,
|
|
||||||
this is done as usual:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum power(BigNum const& first, BigNum const& second, BigNum const& modulus);
|
|
||||||
typedef BigNum (ternary_function1)(const BigNum&, const BigNum&, const BigNum&);
|
|
||||||
...
|
|
||||||
bignum_class.def((ternary_function1)&power, "__pow__");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
If you want to support this function with non-uniform argument
|
|
||||||
types, wrapping is a little more involved. Suppose you have to wrap:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum power(BigNum const& first, int second, int modulus);
|
|
||||||
BigNum power(int first, BigNum const& second, int modulus);
|
|
||||||
BigNum power(int first, int second, BigNum const& modulus);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
The first variant can be wrapped as usual:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
typedef BigNum (ternary_function2)(const BigNum&, int, int);
|
|
||||||
bignum_class.def((ternary_function2)&power, "__pow__");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
In the second variant, however, <code>BigNum</code> appears only as second
|
|
||||||
argument, and in the last one it's the third argument. These functions
|
|
||||||
must be presented to Boost.Python such that that the <code>BigNum</code>
|
|
||||||
argument appears in first position:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
BigNum rpower(BigNum const& second, int first, int modulus)
|
|
||||||
{
|
|
||||||
return power(first, second, modulus);
|
|
||||||
}
|
|
||||||
|
|
||||||
BigNum rrpower(BigNum const& modulus, int first, int second)
|
|
||||||
{
|
|
||||||
return power(first, second, modulus);
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>These functions must be wrapped under the names "__rpow__" and "__rrpow__"
|
|
||||||
respectively:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
bignum_class.def((ternary_function2)&rpower, "__rpow__");
|
|
||||||
bignum_class.def((ternary_function2)&rrpower, "__rrpow__");
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
Note that "__rrpow__" is an extension not present in plain Python.
|
|
||||||
|
|
||||||
<h2><a name="numeric_table">Table of Automatically Wrapped Methods</a></h2>
|
|
||||||
<p>
|
|
||||||
Boost.Python can automatically wrap the following <a href=
|
|
||||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
|
||||||
special methods</a>:
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<table summary="special numeric methods" cellpadding="5" border="1"
|
|
||||||
width="100%">
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<b>Python Operator Name</b>
|
|
||||||
<td align="center">
|
|
||||||
<b>Python Expression</b>
|
|
||||||
<td align="center">
|
|
||||||
<b>C++ Operator Id</b>
|
|
||||||
<td align="center">
|
|
||||||
<b>C++ Expression Used For Automatic Wrapping</b><br>
|
|
||||||
with <code>cpp_left = from_python(left,
|
|
||||||
type<Left>())</code>,<br>
|
|
||||||
<code>cpp_right = from_python(right,
|
|
||||||
type<Right>())</code>,<br>
|
|
||||||
and <code>cpp_oper = from_python(oper, type<Oper>())</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__add__, __radd__</code>
|
|
||||||
<td>
|
|
||||||
<code>left + right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_add</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left + cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__sub__, __rsub__</code>
|
|
||||||
<td>
|
|
||||||
<code>left - right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_sub</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left - cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__mul__, __rmul__</code>
|
|
||||||
<td>
|
|
||||||
<code>left * right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_mul</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left * cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__div__, __rdiv__</code>
|
|
||||||
<td>
|
|
||||||
<code>left / right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_div</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left / cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__mod__, __rmod__</code>
|
|
||||||
<td>
|
|
||||||
<code>left % right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_mod</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left % cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__divmod__, __rdivmod__</code>
|
|
||||||
<td>
|
|
||||||
<code>(quotient, remainder)<br>
|
|
||||||
= divmod(left, right)</code>
|
|
||||||
<td>
|
|
||||||
<code>op_divmod</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left / cpp_right</code>
|
|
||||||
<br><code>cpp_left % cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__pow__, __rpow__</code>
|
|
||||||
<td>
|
|
||||||
<code>pow(left, right)</code><br>
|
|
||||||
(binary power)
|
|
||||||
<td>
|
|
||||||
<code>op_pow</code>
|
|
||||||
<td>
|
|
||||||
<code>pow(cpp_left, cpp_right)</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__rrpow__</code>
|
|
||||||
<td>
|
|
||||||
<code>pow(left, right, modulo)</code><br>
|
|
||||||
(ternary power modulo)
|
|
||||||
<td colspan="2">
|
|
||||||
no automatic wrapping, <a href="#ternary_pow">special treatment</a>
|
|
||||||
required
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__lshift__, __rlshift__</code>
|
|
||||||
<td>
|
|
||||||
<code>left << right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_lshift</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left << cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__rshift__, __rrshift__</code>
|
|
||||||
<td>
|
|
||||||
<code>left >> right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_rshift</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left >> cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__and__, __rand__</code>
|
|
||||||
<td>
|
|
||||||
<code>left & right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_and</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left & cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__xor__, __rxor__</code>
|
|
||||||
<td>
|
|
||||||
<code>left ^ right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_xor</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left ^ cpp_right</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__or__, __ror__</code>
|
|
||||||
<td>
|
|
||||||
<code>left | right</code>
|
|
||||||
<td>
|
|
||||||
<code>op_or</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left | cpp_right</code>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__cmp__, __rcmp__</code>
|
|
||||||
<td>
|
|
||||||
<code>cmp(left, right)</code><br>
|
|
||||||
<br>See <a href="richcmp.html">Rich Comparisons</a>.
|
|
||||||
<td>
|
|
||||||
<code>op_cmp</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left < cpp_right </code>
|
|
||||||
<br><code>cpp_right < cpp_left</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__lt__</code>
|
|
||||||
<br><code>__le__</code>
|
|
||||||
<br><code>__eq__</code>
|
|
||||||
<br><code>__ne__</code>
|
|
||||||
<br><code>__gt__</code>
|
|
||||||
<br><code>__ge__</code>
|
|
||||||
<td>
|
|
||||||
<code>left < right</code>
|
|
||||||
<br><code>left <= right</code>
|
|
||||||
<br><code>left == right</code>
|
|
||||||
<br><code>left != right</code>
|
|
||||||
<br><code>left > right</code>
|
|
||||||
<br><code>left >= right</code>
|
|
||||||
<br>See <a href="richcmp.html">Rich Comparisons</a>
|
|
||||||
<td>
|
|
||||||
<code>op_lt</code>
|
|
||||||
<br><code>op_le</code>
|
|
||||||
<br><code>op_eq</code>
|
|
||||||
<br><code>op_ne</code>
|
|
||||||
<br><code>op_gt</code>
|
|
||||||
<br><code>op_ge</code>
|
|
||||||
<td>
|
|
||||||
<code>cpp_left < cpp_right </code>
|
|
||||||
<br><code>cpp_left <= cpp_right </code>
|
|
||||||
<br><code>cpp_left == cpp_right </code>
|
|
||||||
<br><code>cpp_left != cpp_right </code>
|
|
||||||
<br><code>cpp_left > cpp_right </code>
|
|
||||||
<br><code>cpp_left >= cpp_right </code>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__neg__</code>
|
|
||||||
<td>
|
|
||||||
<code>-oper </code> (unary negation)
|
|
||||||
<td>
|
|
||||||
<code>op_neg</code>
|
|
||||||
<td>
|
|
||||||
<code>-cpp_oper</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__pos__</code>
|
|
||||||
<td>
|
|
||||||
<code>+oper </code> (identity)
|
|
||||||
<td>
|
|
||||||
<code>op_pos</code>
|
|
||||||
<td>
|
|
||||||
<code>+cpp_oper</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__abs__</code>
|
|
||||||
<td>
|
|
||||||
<code>abs(oper) </code> (absolute value)
|
|
||||||
<td>
|
|
||||||
<code>op_abs</code>
|
|
||||||
<td>
|
|
||||||
<code>abs(cpp_oper)</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__invert__</code>
|
|
||||||
<td>
|
|
||||||
<code>~oper </code> (bitwise inversion)
|
|
||||||
<td>
|
|
||||||
<code>op_invert</code>
|
|
||||||
<td>
|
|
||||||
<code>~cpp_oper</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__int__</code>
|
|
||||||
<td>
|
|
||||||
<code>int(oper) </code> (integer conversion)
|
|
||||||
<td>
|
|
||||||
<code>op_int</code>
|
|
||||||
<td>
|
|
||||||
<code>long(cpp_oper)</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__long__</code>
|
|
||||||
<td>
|
|
||||||
<code>long(oper) </code><br>
|
|
||||||
(infinite precision integer conversion)
|
|
||||||
<td>
|
|
||||||
<code>op_long</code>
|
|
||||||
<td>
|
|
||||||
<code>PyLong_FromLong(cpp_oper)</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__float__</code>
|
|
||||||
<td>
|
|
||||||
<code>float(oper) </code> (float conversion)
|
|
||||||
<td>
|
|
||||||
<code>op_float</code>
|
|
||||||
<td>
|
|
||||||
<code>double(cpp_oper)</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__str__</code>
|
|
||||||
<td>
|
|
||||||
<code>str(oper) </code> (string conversion)
|
|
||||||
<td>
|
|
||||||
<code>op_str</code>
|
|
||||||
<td>
|
|
||||||
<code>std::ostringstream s; s << oper;</code>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>__coerce__</code>
|
|
||||||
<td>
|
|
||||||
<code>coerce(left, right)</code>
|
|
||||||
<td colspan="2">
|
|
||||||
usually defined automatically, otherwise <a href="#coercion">
|
|
||||||
special treatment</a> required
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h2><a name="sequence_and_mapping">Sequence and Mapping Operators</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Sequence and mapping operators let wrapped objects behave in accordance
|
|
||||||
to Python's iteration and access protocols. These protocols differ
|
|
||||||
considerably from the ones found in C++. For example, Python's typical
|
|
||||||
iteration idiom looks like
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
for i in S:
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
while in C++ one writes
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
for (iterator i = S.begin(), end = S.end(); i != end; ++i)
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>One could try to wrap C++ iterators in order to carry the C++ idiom into
|
|
||||||
Python. However, this does not work very well because
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>It leads to
|
|
||||||
non-uniform Python code (wrapped sequences support a usage different from
|
|
||||||
Python built-in sequences) and
|
|
||||||
|
|
||||||
<li>Iterators (e.g. <code>std::vector::iterator</code>) are often implemented as plain C++
|
|
||||||
pointers which are <a href="pointers.html#problem">problematic</a> for any automatic
|
|
||||||
wrapping system.
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
It is a better idea to support the standard <a
|
|
||||||
href="http://www.python.org/doc/current/ref/sequence-types.html">Python
|
|
||||||
sequence and mapping protocols</a> for your wrapped containers. These
|
|
||||||
operators have to be wrapped manually because there are no corresponding
|
|
||||||
C++ operators that could be used for automatic wrapping. The Python
|
|
||||||
documentation lists the relevant <a href=
|
|
||||||
"http://www.python.org/doc/current/ref/sequence-types.html">
|
|
||||||
container operators</a>. In particular, expose __getitem__, __setitem__
|
|
||||||
and remember to raise the appropriate Python exceptions
|
|
||||||
(<code>PyExc_IndexError</code> for sequences,
|
|
||||||
<code>PyExc_KeyError</code> for mappings) when the requested item is not
|
|
||||||
present.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In the following example, we expose <code>std::map<std::size_t,std::string></code>:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
typedef std::map<std::size_t, std::string> StringMap;
|
|
||||||
|
|
||||||
// A helper function for dealing with errors. Throw a Python exception
|
|
||||||
// if p == m.end().
|
|
||||||
void throw_key_error_if_end(
|
|
||||||
const StringMap& m,
|
|
||||||
StringMap::const_iterator p,
|
|
||||||
std::size_t key)
|
|
||||||
{
|
|
||||||
if (p == m.end())
|
|
||||||
{
|
|
||||||
PyErr_SetObject(PyExc_KeyError, boost::python::converters::to_python(key));
|
|
||||||
boost::python::throw_error_already_set();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define some simple wrapper functions which match the Python protocol
|
|
||||||
// for __getitem__, __setitem__, and __delitem__. Just as in Python, a
|
|
||||||
// free function with a ``self'' first parameter makes a fine class method.
|
|
||||||
|
|
||||||
const std::string& get_item(const StringMap& self, std::size_t key)
|
|
||||||
{
|
|
||||||
const StringMap::const_iterator p = self.find(key);
|
|
||||||
throw_key_error_if_end(self, p, key);
|
|
||||||
return p->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the item corresponding to key in the map.
|
|
||||||
void StringMapPythonClass::set_item(StringMap& self, std::size_t key, const std::string& value)
|
|
||||||
{
|
|
||||||
self[key] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deletes the item corresponding to key from the map.
|
|
||||||
void StringMapPythonClass::del_item(StringMap& self, std::size_t key)
|
|
||||||
{
|
|
||||||
const StringMap::iterator p = self.find(key);
|
|
||||||
throw_key_error_if_end(self, p, key);
|
|
||||||
self.erase(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
class_builder<StringMap> string_map(my_module, "StringMap");
|
|
||||||
string_map.def(boost::python::constructor<>());
|
|
||||||
string_map.def(&StringMap::size, "__len__");
|
|
||||||
string_map.def(get_item, "__getitem__");
|
|
||||||
string_map.def(set_item, "__setitem__");
|
|
||||||
string_map.def(del_item, "__delitem__");
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Then in Python:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> m = StringMap()
|
|
||||||
>>> m[1]
|
|
||||||
Traceback (innermost last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
KeyError: 1
|
|
||||||
>>> m[1] = 'hello'
|
|
||||||
>>> m[1]
|
|
||||||
'hello'
|
|
||||||
>>> del m[1]
|
|
||||||
>>> m[1] # prove that it's gone
|
|
||||||
Traceback (innermost last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
KeyError: 1
|
|
||||||
>>> del m[2]
|
|
||||||
Traceback (innermost last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
KeyError: 2
|
|
||||||
>>> len(m)
|
|
||||||
0
|
|
||||||
>>> m[0] = 'zero'
|
|
||||||
>>> m[1] = 'one'
|
|
||||||
>>> m[2] = 'two'
|
|
||||||
>>> m[3] = 'three'
|
|
||||||
>>> len(m)
|
|
||||||
4
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h2><a name="getter_setter">Customized Attribute Access</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Just like built-in Python classes, Boost.Python extension classes support <a
|
|
||||||
href="http://www.python.org/doc/current/ref/attribute-access.html">special
|
|
||||||
the usual attribute access methods</a> <code>__getattr__</code>,
|
|
||||||
<code>__setattr__</code>, and <code>__delattr__</code>.
|
|
||||||
Because writing these functions can
|
|
||||||
be tedious in the common case where the attributes being accessed are
|
|
||||||
known statically, Boost.Python checks the special names
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code>__getattr__<em><name></em>__</code>
|
|
||||||
<li>
|
|
||||||
<code>__setattr__<em><name></em>__</code>
|
|
||||||
<li>
|
|
||||||
<code>__delattr__<em><name></em>__</code>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
to provide functional access to the attribute <em><name></em>. This
|
|
||||||
facility can be used from C++ or entirely from Python. For example, the
|
|
||||||
following shows how we can implement a ``computed attribute'' in Python:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> class Range(AnyBoost.PythonExtensionClass):
|
|
||||||
... def __init__(self, start, end):
|
|
||||||
... self.start = start
|
|
||||||
... self.end = end
|
|
||||||
... def __getattr__length__(self):
|
|
||||||
... return self.end - self.start
|
|
||||||
...
|
|
||||||
>>> x = Range(3, 9)
|
|
||||||
>>> x.length
|
|
||||||
6
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<h4>
|
|
||||||
Direct Access to Data Members
|
|
||||||
</h4>
|
|
||||||
<p>
|
|
||||||
Boost.Python uses the special <code>
|
|
||||||
__xxxattr__<em><name></em>__</code> functionality described above
|
|
||||||
to allow direct access to data members through the following special
|
|
||||||
functions on <code>class_builder<></code> and <code>
|
|
||||||
extension_class<></code>:
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code>def_getter(<em>pointer-to-member</em>, <em>name</em>)</code> //
|
|
||||||
read access to the member via attribute <em>name</em>
|
|
||||||
<li>
|
|
||||||
<code>def_setter(<em>pointer-to-member</em>, <em>name</em>)</code> //
|
|
||||||
write access to the member via attribute <em>name</em>
|
|
||||||
<li>
|
|
||||||
<code>def_readonly(<em>pointer-to-member</em>, <em>name</em>)</code>
|
|
||||||
// read-only access to the member via attribute <em>name</em>
|
|
||||||
<li>
|
|
||||||
<code>def_read_write(<em>pointer-to-member</em>, <em>
|
|
||||||
name</em>)</code> // read/write access to the member via attribute
|
|
||||||
<em>name</em>
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
Note that the first two functions, used alone, may produce surprising
|
|
||||||
behavior. For example, when <code>def_getter()</code> is used, the
|
|
||||||
default functionality for <code>setattr()</code> and <code>
|
|
||||||
delattr()</code> remains in effect, operating on items in the extension
|
|
||||||
instance's name-space (i.e., its <code>__dict__</code>). For that
|
|
||||||
reason, you'll usually want to stick with <code>def_readonly</code> and
|
|
||||||
<code>def_read_write</code>.
|
|
||||||
<p>
|
|
||||||
For example, to expose a <code>std::pair<int,long></code> we
|
|
||||||
might write:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
typedef std::pair<int,long> Pil;
|
|
||||||
int first(const Pil& x) { return x.first; }
|
|
||||||
long second(const Pil& x) { return x.second; }
|
|
||||||
...
|
|
||||||
my_module.def(first, "first");
|
|
||||||
my_module.def(second, "second");
|
|
||||||
|
|
||||||
class_builder<Pil> pair_int_long(my_module, "Pair");
|
|
||||||
pair_int_long.def(boost::python::constructor<>());
|
|
||||||
pair_int_long.def(boost::python::constructor<int,long>());
|
|
||||||
pair_int_long.def_read_write(&Pil::first, "first");
|
|
||||||
pair_int_long.def_read_write(&Pil::second, "second");
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Now your Python class has attributes <code>first</code> and <code>
|
|
||||||
second</code> which, when accessed, actually modify or reflect the
|
|
||||||
values of corresponding data members of the underlying C++ object. Now
|
|
||||||
in Python:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
>>> x = Pair(3,5)
|
|
||||||
>>> x.first
|
|
||||||
3
|
|
||||||
>>> x.second
|
|
||||||
5
|
|
||||||
>>> x.second = 8
|
|
||||||
>>> x.second
|
|
||||||
8
|
|
||||||
>>> second(x) # Prove that we're not just changing the instance __dict__
|
|
||||||
8
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<h2>
|
|
||||||
<a name="reasons">And what about <code>__complex__</code>?</a>
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
That, dear reader, is one problem we don't know how to solve. The
|
|
||||||
Python source contains the following fragment, indicating the
|
|
||||||
special-case code really is hardwired:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
/* XXX Hack to support classes with __complex__ method */
|
|
||||||
if (PyInstance_Check(r)) { ...
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
Next: <a href="under-the-hood.html">A Peek Under the Hood</a>
|
|
||||||
Previous: <a href="inheritance.html">Inheritance</a>
|
|
||||||
Up: <a href= "index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams and Ullrich Köthe 2000.
|
|
||||||
Permission to copy, use, modify, sell and distribute this document is
|
|
||||||
granted provided this copyright notice appears in all copies. This
|
|
||||||
document is provided ``as is'' without express or implied
|
|
||||||
warranty, and with no claim as to its suitability for any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Nov 26, 2000
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
||||||
<title>
|
|
||||||
A Peek Under the Hood
|
|
||||||
</title>
|
|
||||||
<h1>
|
|
||||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
|
||||||
width="277" height="86">
|
|
||||||
</h1>
|
|
||||||
<h1>
|
|
||||||
A Peek Under the Hood
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Declaring a <code>class_builder<T></code> causes the instantiation
|
|
||||||
of an <code>extension_class<T></code> to which it forwards all
|
|
||||||
member function calls and which is doing most of the real work.
|
|
||||||
<code>extension_class<T></code> is a subclass of <code>
|
|
||||||
PyTypeObject</code>, the <code> struct</code> which Python's 'C' API uses
|
|
||||||
to describe a type. <a href="example1.html#world_class">An instance of the
|
|
||||||
<code>extension_class<></code></a> becomes the Python type object
|
|
||||||
corresponding to <code>hello::world</code>. When we <a href=
|
|
||||||
"example1.html#add_world_class">add it to the module</a> it goes into the
|
|
||||||
module's dictionary to be looked up under the name "world".
|
|
||||||
<p>
|
|
||||||
Boost.Python uses C++'s template argument deduction mechanism to determine the
|
|
||||||
types of arguments to functions (except constructors, for which we must
|
|
||||||
<a href="example1.html#Constructor_example">provide an argument list</a>
|
|
||||||
because they can't be named in C++). Then, it calls the appropriate
|
|
||||||
overloaded functions <code>PyObject*
|
|
||||||
to_python(</code><em>S</em><code>)</code> and <em>
|
|
||||||
S'</em><code>from_python(PyObject*,
|
|
||||||
type<</code><em>S</em><code>>)</code> which convert between any C++
|
|
||||||
type <em>S</em> and a <code>PyObject*</code>, the type which represents a
|
|
||||||
reference to any Python object in its 'C' API. The <a href=
|
|
||||||
"example1.html#world_class"><code>extension_class<T></code></a>
|
|
||||||
template defines a whole raft of these conversions (for <code>T, T*,
|
|
||||||
T&, std::auto_ptr<T></code>, etc.), using the same inline
|
|
||||||
friend function technique employed by <a href="../../utility/operators.htm">the boost operators
|
|
||||||
library</a>.
|
|
||||||
<p>
|
|
||||||
Because the <code>to_python</code> and <code>from_python</code> functions
|
|
||||||
for a user-defined class are defined by <code>
|
|
||||||
extension_class<T></code>, it is important that an instantiation of
|
|
||||||
<code> extension_class<T></code> is visible to any code which wraps
|
|
||||||
a C++ function with a <code>T, T*, const T&</code>, etc. parameter or
|
|
||||||
return value. In particular, you may want to create all of the classes at
|
|
||||||
the top of your module's init function, then <code>def</code> the member
|
|
||||||
functions later to avoid problems with inter-class dependencies.
|
|
||||||
<p>
|
|
||||||
Next: <a href="building.html">Building a Module with Boost.Python</a>
|
|
||||||
Previous: <a href="special.html">Special Method and Operator Support</a>
|
|
||||||
Up: <a href="index.html">Top</a>
|
|
||||||
<p>
|
|
||||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
|
||||||
sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its suitability for
|
|
||||||
any purpose.
|
|
||||||
<p>
|
|
||||||
Updated: Nov 26, 2000
|
|
||||||
|
|
||||||
@@ -1,233 +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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</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 -->
|
|
||||||
1 April, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,31 +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 - 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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
<h2 align="center">Acknowledgments</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
{{text}}
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,31 +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 - Bibliography</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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
<h2 align="center">Bibliography</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
{{bibliographical information}}
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,62 +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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</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>{{Introductory text}}</p>
|
|
||||||
|
|
||||||
<h2><a name="functions"></a>Functions</h2>
|
|
||||||
<pre>
|
|
||||||
<a name="call-spec"></a>call
|
|
||||||
</pre>
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}</dt>
|
|
||||||
<dt><b>Effects:</b> {{text}}</dt>
|
|
||||||
<dt><b>Postconditions:</b> {{text}}</dt>
|
|
||||||
<dt><b>Returns:</b> {{text}}</dt>
|
|
||||||
<dt><b>Throws:</b> {{text}}</dt>
|
|
||||||
<dt><b>Complexity:</b> {{text}}</dt>
|
|
||||||
<dt><b>Rationale:</b> {{text}}</dt>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example(s)</h2>
|
|
||||||
|
|
||||||
<p>{{Example(s)}}</p>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</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,337 +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/class.hpp>,
|
|
||||||
<boost/python/class_fwd.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Headers <boost/python/class.hpp>,
|
|
||||||
<boost/python/class_fwd.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="#class_-spec">Class template <code>class_</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#class_-spec-synopsis">Class <code>class_</code>
|
|
||||||
synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#class_-spec-ctors">Class <code>class_</code>
|
|
||||||
constructors</a>
|
|
||||||
|
|
||||||
<dt><a href="#class_-spec-modifiers">Class <code>class_</code>
|
|
||||||
modifier functions</a>
|
|
||||||
|
|
||||||
<dt><a href="#class_-spec-observers">Class <code>class_</code>
|
|
||||||
observer functions</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#bases-spec">Class template <code>bases</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#bases-spec-synopsis">Class <code>bases</code>
|
|
||||||
synopsis</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#args-spec">Class template <code>args</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#args-spec-synopsis">Class <code>args</code>
|
|
||||||
synopsis</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example(s)</a>
|
|
||||||
</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, and the <code>args</code> and <code>bases</code>
|
|
||||||
utility class templates in the anonymous namespace (the latter definitions
|
|
||||||
will probably be moved in a future release).
|
|
||||||
|
|
||||||
<p><code><boost/python/class_fwd.hpp></code> contains a forward
|
|
||||||
declaration of the <code>class_</code> class template.
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="class_-spec"></a>Class template <code>class_<T, Bases, <a
|
|
||||||
href="HolderGenerator.html">HolderGenerator</a>></code></h3>
|
|
||||||
|
|
||||||
<p>Creates a Python class associated with the C++ type passed as its first
|
|
||||||
parameter. Its template arguments are:<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
|
|
||||||
<table border="1" summary="class_ template parameters">
|
|
||||||
<tr>
|
|
||||||
<th>Parameter
|
|
||||||
|
|
||||||
<th>Requirements
|
|
||||||
|
|
||||||
<th>Default
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>T</code>
|
|
||||||
|
|
||||||
<td>A class type.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>Bases</code>
|
|
||||||
|
|
||||||
<td>An <a href="../../../mpl/doc/Sequences.html">MPL sequence</a> of
|
|
||||||
C++ base classes of <code>T</code>.
|
|
||||||
|
|
||||||
<td>An unspecified empty sequence
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>HolderGenerator</code>
|
|
||||||
|
|
||||||
<td>A model of <code><a href=
|
|
||||||
"HolderGenerator.html">HolderGenerator</a></code>.
|
|
||||||
|
|
||||||
<td><code>boost::python::objects::value_holder_generator</code>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h4><a name="class_-spec-synopsis"></a>Class template <code>class_</code>
|
|
||||||
synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
|
|
||||||
template <class T
|
|
||||||
, class Bases = <i>none</i>
|
|
||||||
, class HolderGenerator = objects::value_holder_generator>
|
|
||||||
class class_
|
|
||||||
{
|
|
||||||
class_();
|
|
||||||
class_(char const* name);
|
|
||||||
|
|
||||||
template <class F>
|
|
||||||
class_& def(char const* name, F f);
|
|
||||||
|
|
||||||
template <class Fn, class CallPolicy>
|
|
||||||
class_& def(char const* name, Fn fn, CallPolicy policy);
|
|
||||||
|
|
||||||
template <class Args>
|
|
||||||
class_& def_init(Args const& = Args());
|
|
||||||
|
|
||||||
class_& def_init();
|
|
||||||
|
|
||||||
ref object() const;
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="class_-spec-ctors"></a>Class template <code>class_</code>
|
|
||||||
constructors</h4>
|
|
||||||
<pre>
|
|
||||||
class_()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> The platform's <code>std::type_info::name()</code>
|
|
||||||
implementation produces a string which corresponds to the type's
|
|
||||||
declaration in C++
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Constructs a <code>class_</code> object which
|
|
||||||
generates a Boost.Python extension class with the same name as
|
|
||||||
<code>T</code>.
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Many platforms can generate reasonable names for
|
|
||||||
Python classes without user intervention.
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
class_(char const* name)
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>name</code> is a ntbs which conforms to
|
|
||||||
Python's <a href=
|
|
||||||
"http://www.python.org/doc/2.2/ref/identifiers.html">identifier
|
|
||||||
naming rules</a>.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Constructs a <code>class_</code> object which
|
|
||||||
generates a Boost.Python extension class named <code>name</code>.
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Gives the user full control over class naming.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="class_-spec-modifiers"></a>Class template <code>class_</code>
|
|
||||||
modifier functions</h4>
|
|
||||||
<pre>
|
|
||||||
template <class F>
|
|
||||||
class_& def(char const* name, F f)
|
|
||||||
|
|
||||||
template <class Fn, class CallPolicy>
|
|
||||||
class_& def(char const* name, Fn f, CallPolicy policy)
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>f</code> is a non-null pointer-to-function or
|
|
||||||
pointer-to-member-function. <code>name</code> is a ntbs which conforms to
|
|
||||||
Python's <a href=
|
|
||||||
"http://www.python.org/doc/2.2/ref/identifiers.html">identifier
|
|
||||||
naming rules</a>. In the first form, the return type of
|
|
||||||
<code>f</code> is not a reference and is not a pointer other
|
|
||||||
than <code>char const*</code> or <code>PyObject*</code>. In the
|
|
||||||
second form <code>policy</code> is a model of <a
|
|
||||||
href="CallPolicies.html">CallPolicies</a>.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Adds the result of <code><a href=
|
|
||||||
"make_function.html#make_function-spec">make_function</a>(f)</code> to
|
|
||||||
the Boost.Python extension class being defined, with the given
|
|
||||||
<code>name</code>. If the extension class already has an attribute named
|
|
||||||
<code><i>name</i></code>, the usual <a href=
|
|
||||||
"overloading.html">overloading procedure</a> applies.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code>*this</code>
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
template <class Args>
|
|
||||||
class_& def_init(Args const& argument_types)
|
|
||||||
|
|
||||||
class_& def_init()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> in the first form, argument_types must be an <a
|
|
||||||
href="../../../mpl/doc/Sequences.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>T(a1, a2</code>... <code>aN</code>) is valid. In the second form,
|
|
||||||
the expression <code>T()</code> must be valid.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Adds the result of <code><a href=
|
|
||||||
"make_function.html#make_constructor-spec">make_constructor</a><T,Args,HolderGenerator>()</code>
|
|
||||||
to the Boost.Python extension class being defined with the name
|
|
||||||
"__init__". If the 2nd form is used, an unspecified empty <a href=
|
|
||||||
"../../../mpl/doc/Sequences.html">MPL sequence</a> type is substituted
|
|
||||||
for <code>Args</code>. If the extension class already has an "__init__"
|
|
||||||
attribute, the usual <a href="http:overloading.html">overloading
|
|
||||||
procedure</a> applies.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code>*this</code>
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Allows users to easily expose a class' constructor
|
|
||||||
to Python.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="class_-spec-observers"></a>Class template <code>class_</code>
|
|
||||||
observer functions</h4>
|
|
||||||
<pre>
|
|
||||||
ref object() const;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Returns:</b> A <code>ref</code> object which holds a reference to
|
|
||||||
the Boost.Python extension class object created by the
|
|
||||||
<code>class_</code> constructor.
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Mostly not needed by users, since <code><a href=
|
|
||||||
"module.html#add-spec">module::add</a>()</code> uses this to insert the
|
|
||||||
extension class in the module.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h3><a name="args-spec"></a>Class template
|
|
||||||
<code>args<T1, T2,</code>...<code>TN></code></h3>
|
|
||||||
|
|
||||||
<p>Essentially an alias for <code>boost::mpl::type_list</code> which users
|
|
||||||
can use in <code>def_init</code> calls to make their code more readable.
|
|
||||||
Currently it is in the global unnammed namespace, but that will probably
|
|
||||||
change.
|
|
||||||
|
|
||||||
<h4><a name="args-spec-synopsis"></a>Class template <code>args</code>
|
|
||||||
synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
template <T1 = <i>unspecified</i>,...TN = <i>unspecified</i>>
|
|
||||||
struct args : ::boost::mpl::type_list<T1,...TN>::type
|
|
||||||
{};
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h3><a name="bases-spec"></a>Class template
|
|
||||||
<code>bases<T1, T2,</code>...<code>TN></code></h3>
|
|
||||||
|
|
||||||
<p>Essentially an alias for <code>boost::mpl::type_list</code> which users
|
|
||||||
can use in <code>class_<</code>...<code>></code> instantiations to
|
|
||||||
make their code more readable. Currently it is in the global unnammed
|
|
||||||
namespace, but that will probably change.
|
|
||||||
|
|
||||||
<h4><a name="bases-spec-synopsis"></a>Class template <code>bases</code>
|
|
||||||
synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
template <T1 = <i>unspecified</i>,...TN = <i>unspecified</i>>
|
|
||||||
struct bases : ::boost::mpl::type_list<T1,...TN>::type
|
|
||||||
{};
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example(s)</h2>
|
|
||||||
|
|
||||||
<p>Given a C++ class declaration:
|
|
||||||
<pre>
|
|
||||||
class Foo : public Bar, public Baz
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Foo(int, char const*);
|
|
||||||
Foo(double);
|
|
||||||
|
|
||||||
std::string const& name() { return m_name; }
|
|
||||||
void name(char const*);
|
|
||||||
private:
|
|
||||||
...
|
|
||||||
};
|
|
||||||
</pre>
|
|
||||||
A corresponding Boost.Python extension class can be created with:
|
|
||||||
<pre>
|
|
||||||
using namespace boost::python;
|
|
||||||
ref foo =
|
|
||||||
class_<Foo,bases<Bar,Baz> >()
|
|
||||||
.def_init(args<int,char const*>())
|
|
||||||
.def_init(args<double>())
|
|
||||||
.def("get_name", &Foo::get_name, return_internal_reference<>())
|
|
||||||
.def("set_name", &Foo::set_name)
|
|
||||||
.object();
|
|
||||||
</pre>
|
|
||||||
Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,90 +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 - 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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</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-public">Public Library 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>Boost.Python 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 Boost.Python.</p>
|
|
||||||
<table summary="application defined macros" cellspacing="10" width="100%">
|
|
||||||
<tr>
|
|
||||||
<td><b>Macro</b></td>
|
|
||||||
<td><b>Meaning</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{macro}}</td>
|
|
||||||
<td>{{meaning}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{macro}}</td>
|
|
||||||
<td>{{meaning}}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<h2><a name="lib-defined-public"></a>Public Library Defined Macros</h2>
|
|
||||||
<p>These macros are defined by Boost.Python but are expected to be used by application
|
|
||||||
code.</p>
|
|
||||||
<table summary="public library defined macros" cellspacing="10" width="100%">
|
|
||||||
<tr>
|
|
||||||
<td><b>Macro</b></td>
|
|
||||||
<td><b>Meaning</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{macro}}</td>
|
|
||||||
<td>{{meaning}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{macro}}</td>
|
|
||||||
<td>{{meaning}}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<h2><a name="lib-defined-impl"></a>Library Defined Implementation Macros</h2>
|
|
||||||
<p>These macros are defined by Boost.Python and are implementation details of interest
|
|
||||||
only to implementers.</p>
|
|
||||||
<table summary="library defined implementation macros" cellspacing="10" width="100%">
|
|
||||||
<tr>
|
|
||||||
<td><b>Macro</b></td>
|
|
||||||
<td><b>Meaning</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{macro}}</td>
|
|
||||||
<td>{{meaning}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{macro}}</td>
|
|
||||||
<td>{{meaning}}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,135 +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/copy_const_reference.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header
|
|
||||||
<boost/python/copy_const_reference.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="#copy_const_reference-spec">Class
|
|
||||||
<code>copy_const_reference</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#copy_const_reference-spec-synopsis">Class
|
|
||||||
<code>copy_const_reference</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#copy_const_reference-spec-metafunctions">Class
|
|
||||||
<code>copy_const_reference</code> metafunctions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</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=
|
|
||||||
"ResultConverterGenerator.html">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.
|
|
||||||
|
|
||||||
<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><b>Returns:</b> <code>typedef <a href=
|
|
||||||
"to_python_value.html#to_python_value-spec">to_python_value</a><T>
|
|
||||||
type;</code>
|
|
||||||
</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_INIT(my_module)
|
|
||||||
{
|
|
||||||
module m("my_module")
|
|
||||||
.add(
|
|
||||||
class_<Bar>()
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
class_<Foo>()
|
|
||||||
.def_init(args<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 -->
|
|
||||||
15 February, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,135 +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/copy_non_const_reference.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header
|
|
||||||
<boost/python/copy_non_const_reference.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="#copy_non_const_reference-spec">Class
|
|
||||||
<code>copy_non_const_reference</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#copy_non_const_reference-spec-synopsis">Class
|
|
||||||
<code>copy_non_const_reference</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#copy_non_const_reference-spec-metafunctions">Class
|
|
||||||
<code>copy_non_const_reference</code> metafunctions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</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=
|
|
||||||
"ResultConverterGenerator.html">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.
|
|
||||||
|
|
||||||
<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><b>Returns:</b> <code>typedef <a href=
|
|
||||||
"to_python_value.html#to_python_value-spec">to_python_value</a><T>
|
|
||||||
type;</code>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example</h2>
|
|
||||||
|
|
||||||
<p>C++ code:
|
|
||||||
<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_INIT(my_module)
|
|
||||||
{
|
|
||||||
module m("my_module")
|
|
||||||
.add(
|
|
||||||
class_<Bar>()
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
class_<Foo>()
|
|
||||||
.def_init(args<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 -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</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=
|
|
||||||
"ResultConverterGenerator.html">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 -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,34 +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 - 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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
<h2 align="center">Definitions</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
<dl class="definitions">
|
|
||||||
<dt><b>{{term}}:</b> {{definition}}</dt>
|
|
||||||
<dt><b>{{term}}:</b> {{definition}}</dt>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,232 +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 - <{{header}}></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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/errors.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="#class-spec">Class <code>error_already_set</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#error_already_set-spec-synopsis">Class
|
|
||||||
<code>error_already_set</code> synopsis</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#functions">Functions</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#handle_exception-spec">handle_exception</a>
|
|
||||||
|
|
||||||
<dt><a href="#expect_non_null-spec">expect_non_null</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Examples</a>
|
|
||||||
</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.
|
|
||||||
|
|
||||||
<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>.
|
|
||||||
|
|
||||||
<h4><a name="class-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=
|
|
||||||
"../../../function/doc/reference.html#functionN">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><b>Effects:</b> The first form calls <code>f()</code> inside a
|
|
||||||
<code>try</code> block whose <code>catch</code> clauses set an
|
|
||||||
appropriate Python exception for the C++ exception caught, returning
|
|
||||||
<code>true</code> if an exception was caught, <code>false</code>
|
|
||||||
otherwise. The second form passes a function which rethrows the exception
|
|
||||||
currently being handled to the first form.
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> No exception is being handled
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> nothing
|
|
||||||
|
|
||||||
<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 neccessary 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: <a href=
|
|
||||||
"make_function.html#make_function-spec">make_function()</a>, <a href=
|
|
||||||
"make_function.html#make_constructor-spec">make_constructor()</a>, <a
|
|
||||||
href="module.html#def-spec">module::def</a> and <a href=
|
|
||||||
"class.html#def-spec">class_::def</a>). 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.
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
<a name="expect_non_null-spec">PyObject* expect_non_null(PyObject* x);</a>
|
|
||||||
|
|
||||||
template <class T> T* expect_non_null(T* x);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="expect_non_null-semantics">
|
|
||||||
<dt><b>Returns:</b> <code>x</code>
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> <code><a href=
|
|
||||||
"#error_already_set-spec">error_already_set()</a></code> iff <code>x ==
|
|
||||||
0</code>.
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Simplifies error-handling when calling many
|
|
||||||
functions in the <a href=
|
|
||||||
"http://www.python.org/doc/2.2/api/api.html">Python/C API</a>, which
|
|
||||||
return 0 on error.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Examples</h2>
|
|
||||||
<pre>
|
|
||||||
#include <string>
|
|
||||||
#include <boost/python/errors.hpp>
|
|
||||||
#include <boost/python/reference.hpp>
|
|
||||||
|
|
||||||
// Returns a std::string which has the same value as obj's "__name__"
|
|
||||||
// attribute.
|
|
||||||
std::string get_name(boost::python::ref obj)
|
|
||||||
{
|
|
||||||
// throws if there's no __name__ attribute
|
|
||||||
PyObject* p = boost::python::expect_non_null(
|
|
||||||
PyObject_GetAttrString(obj.get(), "__name__"));
|
|
||||||
|
|
||||||
// throws if it's not a Python string
|
|
||||||
std::string result(
|
|
||||||
boost::python::expect_non_null(
|
|
||||||
PyString_AsString(p)));
|
|
||||||
|
|
||||||
Py_XDECREF(p); // Done with p
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Demonstrate form 1 of handle_exception
|
|
||||||
//
|
|
||||||
|
|
||||||
// Place a Python Int object whose value is 1 if a and b have
|
|
||||||
// identical "__name__" attributes, 0 otherwise.
|
|
||||||
void same_name_impl(PyObject*& result, PyObject* a, PyObject* b)
|
|
||||||
{
|
|
||||||
result = PyInt_FromLong(
|
|
||||||
get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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), a1, 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(boost::python::ref(a1)) == get_name(boost::python::ref(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 -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,38 +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 - 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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
<h2 align="center">Frequently Asked Questions (FAQs)</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#question1">{{question}}</a></dt>
|
|
||||||
<dt><a href="#question2">{{question}}</a></dt>
|
|
||||||
</dl>
|
|
||||||
<h2><a name="question1"></a>{{question}}</h2>
|
|
||||||
<p>{{answer}}</p>
|
|
||||||
<h2><a name="question2"></a>{{question}}</h2>
|
|
||||||
<p>{{answer}}</p>
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,367 +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="http://www.boost.org"><img height="86"
|
|
||||||
width="277" alt="C++ Boost" src="../c++boost.gif"
|
|
||||||
border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 class="c1">Boost.Python</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 -->
|
|
||||||
4 April, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p class="c3">© Copyright <a href=
|
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.
|
|
||||||
|
|
||||||
@@ -1,166 +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/from_python.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/from_python.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="#from_python-spec">Class
|
|
||||||
Template<code>from_python</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#from_python-spec-synopsis">Class Template
|
|
||||||
<code>from_python</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#from_python-spec-ctors">Class Template
|
|
||||||
<code>from_python</code> constructor</a>
|
|
||||||
|
|
||||||
<dt><a href="#from_python-spec-observers">Class Template
|
|
||||||
<code>from_python</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/from_python.hpp></code> introduces a class
|
|
||||||
template <code>from_python<T></code> for extracting a C++ object of
|
|
||||||
type <code>T</code> from a Python object.
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="from_python-spec"></a>Class Template
|
|
||||||
<code>from_python<class T></code></h3>
|
|
||||||
|
|
||||||
<p><code>from_python<T></code> is the type used internally by
|
|
||||||
Boost.Python to extract C++ function arguments from a Python argument tuple
|
|
||||||
when calling a wrapped function. It can also be used directly to make
|
|
||||||
similar conversions in other contexts.
|
|
||||||
|
|
||||||
<h4><a name="from_python-spec-synopsis"></a>Class Template
|
|
||||||
<code>from_python</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
template <class T>
|
|
||||||
struct from_python : private <a href=
|
|
||||||
"../../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
|
||||||
// from_python<T> meets the <a href=
|
|
||||||
"NonCopyable.html">NonCopyable</a> requirements
|
|
||||||
{
|
|
||||||
from_python(PyObject*);
|
|
||||||
bool convertible() const;
|
|
||||||
<i>convertible-to-T</i> operator()(PyObject*) const;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="from_python-spec-ctors"></a>Class Template
|
|
||||||
<code>from_python</code> constructor</h4>
|
|
||||||
<pre>
|
|
||||||
from_python(PyObject* p);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>p != 0</code>
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Constructs a <code>from_python</code> object suitable
|
|
||||||
for extracting a C++ object of type <code>T</code> from <code>p</code>.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="from_python-spec-observers"></a>Class Template
|
|
||||||
<code>from_python</code> observer functions</h4>
|
|
||||||
<pre>
|
|
||||||
bool convertible() const;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Returns:</b> <code>false</code> if the conversion cannot succeed.
|
|
||||||
This indicates that either:
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<ol>
|
|
||||||
<li>No <code>from_python_converter</code> was registered for
|
|
||||||
<code>T</code>, or
|
|
||||||
|
|
||||||
<li>any such converter rejected the constructor argument
|
|
||||||
<code>p</code> by returning <code>0</code> from its
|
|
||||||
<code>convertible()</code> function
|
|
||||||
</ol>
|
|
||||||
Note that conversion may still fail in <code>operator()</code> due to
|
|
||||||
an exception.
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> nothing
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Because <code>from_python<></code> is used in
|
|
||||||
overload resolution, and throwing an exception can be slow, it is useful
|
|
||||||
to be able to rule out a broad class of unsuccessful conversions without
|
|
||||||
throwing an exception.
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
<i>convertible-to-T</i> operator()(PyObject* p) const;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>*p</code> refers to the same object which was
|
|
||||||
passed to the constructor, and <code>convertible()</code> returns
|
|
||||||
<code>true</code>.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> performs the conversion
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> an object convertible to <code>T</code>.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example</h2>
|
|
||||||
<pre>
|
|
||||||
#include <string>
|
|
||||||
#include <boost/python/from_python.hpp>
|
|
||||||
|
|
||||||
// If a std::string can be extracted from p, return its
|
|
||||||
// length. Otherwise, return 0.
|
|
||||||
std::size_t length_if_string(PyObject* p)
|
|
||||||
{
|
|
||||||
from_python<std::string> converter(p);
|
|
||||||
if (!converter.convertible())
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return converter().size();
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,288 +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 - <{{header}}></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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <{{header}}></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="#macro-spec">{{macro name}}</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#values">Values</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#value-spec">{{value name}}</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#types">Types</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#type-spec">{{type name}}</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#class-spec">Class <code>{{name}}</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#class-spec-synopsis">Class <code>{{name}}</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#class-spec-ctors">Class <code>{{name}}</code>
|
|
||||||
constructors and destructor</a>
|
|
||||||
|
|
||||||
<dt><a href="#class-spec-comparisons">Class <code>{{name}}</code> comparison functions</a>
|
|
||||||
|
|
||||||
<dt><a href="#class-spec-modifiers">Class <code>{{name}}</code> modifier functions</a>
|
|
||||||
|
|
||||||
<dt><a href="#class-spec-observers">Class <code>{{name}}</code> observer functions</a>
|
|
||||||
|
|
||||||
<dt><a href="#class-spec-statics">Class <code>{{name}}</code> static functions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#functions">Functions</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#function-spec">{{function name}}</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#objects">Objects</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#object-spec">{{object name}}</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example(s)</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<p>{{Introductory text}}
|
|
||||||
|
|
||||||
<h2><a name="macros"></a>Macros</h2>
|
|
||||||
|
|
||||||
<p><a name="macro-spec"></a>{{Macro specifications}}
|
|
||||||
|
|
||||||
<h2><a name="values"></a>Values</h2>
|
|
||||||
|
|
||||||
<p><a name="value-spec"></a>{{Value specifications}}
|
|
||||||
|
|
||||||
<h2><a name="types"></a>Types</h2>
|
|
||||||
|
|
||||||
<p><a name="type-spec"></a>{{Type specifications}}
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="class-spec"></a>Class <code>{{name}}</code></h3>
|
|
||||||
|
|
||||||
<p>{{class overview text}}
|
|
||||||
|
|
||||||
<h4><a name="class-spec-synopsis"></a>Class <code>{{name}}</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
class {{name}}
|
|
||||||
{
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="class-spec-ctors"></a>Class <code>{{name}}</code> constructors and
|
|
||||||
destructor</h4>
|
|
||||||
<pre>
|
|
||||||
{{constructor}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Complexity:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> {{text}}
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
{{destructor}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Complexity:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> {{text}}
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="class-spec-comparisons"></a>Class <code>{{name}}</code> comparison
|
|
||||||
functions</h4>
|
|
||||||
<pre>
|
|
||||||
{{function}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Complexity:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> {{text}}
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="class-spec-modifiers"></a>Class <code>{{name}}</code> modifier
|
|
||||||
functions</h4>
|
|
||||||
<pre>
|
|
||||||
{{function}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Complexity:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> {{text}}
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="class-spec-observers"></a>Class <code>{{name}}</code> observer
|
|
||||||
functions</h4>
|
|
||||||
<pre>
|
|
||||||
{{function}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Complexity:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> {{text}}
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="class-spec-statics"></a>Class <code>{{name}}</code> static functions</h4>
|
|
||||||
<pre>
|
|
||||||
{{function}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Complexity:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> {{text}}
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="functions"></a>Functions</h2>
|
|
||||||
<pre>
|
|
||||||
|
|
||||||
|
|
||||||
<a name="function-spec"></a>{{function}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Postconditions:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Throws:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Complexity:</b> {{text}}
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> {{text}}
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="objects"></a>Objects</h2>
|
|
||||||
|
|
||||||
<p><a name="object-spec"></a>{{Object specifications}}
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example(s)</h2>
|
|
||||||
|
|
||||||
<p>{{Example(s)}}
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,41 +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</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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
<h2 align="center">Index</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
<h2>Contents</h2>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="overview.html">Overview</a></dt>
|
|
||||||
<dt><a href="reference.html">Reference</a></dt>
|
|
||||||
<dt><a href="configuration.html">Configuration Information</a></dt>
|
|
||||||
<dt><a href="rationale.html">Rationale</a></dt>
|
|
||||||
<dt><a href="definitions.html">Definitions</a></dt>
|
|
||||||
<dt><a href="faq.html">Frequently Asked Questions (FAQs)</a></dt>
|
|
||||||
<dt><a href="bibliography.html">Bibliography</a></dt>
|
|
||||||
<dt><a href="acknowledgments.html">Acknowledgments</a></dt>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,279 +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/lvalue_from_python.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/lvalue_from_python.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="#lvalue_from_python-spec">Class Template <code>lvalue_from_python</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
|
|
||||||
<dt><a href="#lvalue_from_python-spec-synopsis">Class Template
|
|
||||||
<code>lvalue_from_python</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#lvalue_from_python-spec-ctors">Class Template
|
|
||||||
<code>lvalue_from_python</code> constructor</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#get_member-spec">Class Template <code>get_member</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
|
|
||||||
<dt><a href="#get_member-spec-synopsis">Class Template
|
|
||||||
<code>get_member</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#get_member-spec-statics">Class Template
|
|
||||||
<code>get_member</code> static functions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<code><boost/python/lvalue_from_python.hpp></code> supplies
|
|
||||||
a facility for extracting C++ objects from within instances of a
|
|
||||||
given Python type. This is typically useful for dealing with
|
|
||||||
"traditional" Python extension types.
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="lvalue_from_python-spec"></a>Class template <code>lvalue_from_python</code></h3>
|
|
||||||
|
|
||||||
<p>Class template <code>lvalue_from_python</code> will register
|
|
||||||
from_python converters which extract a references and pointers to
|
|
||||||
a C++ type which is held within an object of a given Python
|
|
||||||
type. Its template arguments are:
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
|
|
||||||
<table border="1" summary="lvalue_from_python template parameters">
|
|
||||||
<caption>
|
|
||||||
<b><code>lvalue_from_python</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>Requirements
|
|
||||||
|
|
||||||
<th>Description
|
|
||||||
|
|
||||||
<th>Default
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>python_type</code>
|
|
||||||
|
|
||||||
<td>A compile-time constant <code><a
|
|
||||||
href="http://www.python.org/doc/2.2/ext/dnt-type-methods.html">PyTypeObject</a>*</code>
|
|
||||||
|
|
||||||
<td>The Python type of instances convertible by this
|
|
||||||
converter. Python subtypes are also convertible.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>Value</code>
|
|
||||||
|
|
||||||
<td>A non-reference type.
|
|
||||||
|
|
||||||
<td>The C++ type to be extracted
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>PythonObject</code>
|
|
||||||
|
|
||||||
<td>initial <code>sizeof(PyObject)</code> bytes are
|
|
||||||
layout-compatible with <code>PyObject</code>.
|
|
||||||
|
|
||||||
<td>The C++ type used to hold Python instances of
|
|
||||||
<code>python_type</code>.
|
|
||||||
|
|
||||||
<td><code>Value</code>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>Extract</code>
|
|
||||||
|
|
||||||
<td><code>Value& v = Extract::execute(x);</code>
|
|
||||||
|
|
||||||
<td>A type whose static <code>execute</code> function extracts a <code>Value</code> reference from within an object of type <code>PythonObject</code>.
|
|
||||||
|
|
||||||
<td>An unspecified type whose <code>execute</code> function consists of <code>return x;</code>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
If only the first two template arguments are supplied, these
|
|
||||||
converters extract the entire <code>PythonObject</code> as a
|
|
||||||
whole.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
If the lifetime of the <code>lvalue_from_python</code> object ends
|
|
||||||
before the last attempt to convert to one its target types, the
|
|
||||||
behavior is undefined. The easiest way to ensure correct behavior
|
|
||||||
is to declare an <code>lvalue_from_python</code> instance as a
|
|
||||||
static local in a <a
|
|
||||||
href="module.html#BOOST_PYTHON_MODULE_INIT-spec">module init
|
|
||||||
function</a>, as shown in the <a href="#examples">example</a>
|
|
||||||
below.
|
|
||||||
|
|
||||||
<h4><a name="lvalue_from_python-spec-synopsis"></a>Class template <code>lvalue_from_python</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
template <
|
|
||||||
PyTypeObject const* python_type
|
|
||||||
, class Value
|
|
||||||
, class PythonObject = Value
|
|
||||||
, class Extract = <i>unspecified</i>
|
|
||||||
>
|
|
||||||
class lvalue_from_python
|
|
||||||
{
|
|
||||||
lvalue_from_python();
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="lvalue_from_python-spec-ctors"></a>Class template <code>lvalue_from_python</code> constructor</h4>
|
|
||||||
<pre>
|
|
||||||
lvalue_from_python();
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Registers from_python converters which
|
|
||||||
extract
|
|
||||||
<code>Value&</code>, <code>Value const&</code>,
|
|
||||||
<code>Value*</code>, or <code>Value const*</code> from Python
|
|
||||||
objects of type <code>python_type</code> using
|
|
||||||
<code>Extract::execute()</code>.
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h3><a name="get_member-spec"></a>Class template <code>get_member</code></h3>
|
|
||||||
|
|
||||||
<p><code>get_member</code> can be used with
|
|
||||||
<code>lvalue_from_python</code> in the common case where the C++
|
|
||||||
type to be extracted is a member of the Python object.
|
|
||||||
|
|
||||||
<h4><a name="get_member-spec-synopsis"></a>Class template <code>get_member</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
template <class Class, class Member, Member (Class::*mp)>
|
|
||||||
struct get_member
|
|
||||||
{
|
|
||||||
static Member& execute(Class& c);
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="get_member-spec-statics"></a>Class template <code>get_member</code> static functions</h4>
|
|
||||||
<pre>
|
|
||||||
Member& execute(Class& c);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code>c.*mp</code>
|
|
||||||
|
|
||||||
</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.
|
|
||||||
|
|
||||||
<h3>C++ module definition</h3>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/reference.hpp>
|
|
||||||
#include <boost/python/module.hpp>
|
|
||||||
|
|
||||||
// definition lifted from the Python docs
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
} noddy_NoddyObject;
|
|
||||||
|
|
||||||
using namespace boost::python;
|
|
||||||
static ref cache;
|
|
||||||
|
|
||||||
bool is_cached(noddy_NoddyObject* x)
|
|
||||||
{
|
|
||||||
return x == cache.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_cache(noddy_NoddyObject* x)
|
|
||||||
{
|
|
||||||
cache.reset((PyObject*)x, ref::increment_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(noddy_cache)
|
|
||||||
{
|
|
||||||
module noddy_cache("noddy_cache")
|
|
||||||
.def("is_cached", is_cached)
|
|
||||||
.def("set_cache", set_cache)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
</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 -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,146 +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/make_function.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/make_function.hpp></h2>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2>Contents</h2>
|
|
||||||
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#introduction">Introduction</a>
|
|
||||||
|
|
||||||
<dt><a href="#functions">Functions</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#make_function-spec">make_function</a>
|
|
||||||
|
|
||||||
<dt><a href="#make_constructor-spec">make_constructor</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</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>class_<>::<a href=
|
|
||||||
"class.html#class_-spec-modifiers">def</a></code>, <code>class_<>::<a
|
|
||||||
href="module.html#module-spec-modifiers">def</a></code>, and
|
|
||||||
<code>class_<>::<a href=
|
|
||||||
"class.html#class_-spec-modifiers">def_init</a></code> to produce Python
|
|
||||||
callable objects which wrap C++ functions and member functions.
|
|
||||||
|
|
||||||
<h2><a name="functions"></a>Functions</h2>
|
|
||||||
<pre>
|
|
||||||
<a name="make_function-spec">template <class F></a>
|
|
||||||
objects::function* make_function(F f)</a>
|
|
||||||
|
|
||||||
template <class F, class Policies>
|
|
||||||
objects::function* make_function(F f, Policies const& policies)
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>F</code> is a function pointer or member
|
|
||||||
function pointer type
|
|
||||||
|
|
||||||
<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>. If <code>policies</code> are supplied, it
|
|
||||||
must be a model of <a href="CallPolicies.html">CallPolicies</a>, and will
|
|
||||||
be applied to the function as described <a href=
|
|
||||||
"CallPolicies.html">here</a>.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> A pointer convertible to <code>PyObject*</code> which
|
|
||||||
refers to the new Python callable object.
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
<a name=
|
|
||||||
"make_constructor-spec">template <class T, class ArgList, class Generator>
|
|
||||||
objects::function* make_constructor();</a>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="make_constructor-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>T</code> is a class type. <code>ArgList</code>
|
|
||||||
is an <a href="../../../mpl/doc/Sequences.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><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. The result is
|
|
||||||
installed in the extension class object.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> The new Python callable object
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example</h2>
|
|
||||||
|
|
||||||
<p>C++ function exposed below returns a callable object wrapping one of two
|
|
||||||
functions.
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/make_function.hpp>
|
|
||||||
#include <boost/python/module.hpp>
|
|
||||||
|
|
||||||
char const* foo() { return "foo"; }
|
|
||||||
char const* bar() { return "bar"; }
|
|
||||||
|
|
||||||
PyObject* choose_function(bool selector)
|
|
||||||
{
|
|
||||||
if (selector)
|
|
||||||
return boost::python::make_function(foo);
|
|
||||||
else
|
|
||||||
return boost::python::make_function(bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(make_function_test)
|
|
||||||
{
|
|
||||||
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 -->
|
|
||||||
14 February 2002 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,130 +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/manage_new_object.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header
|
|
||||||
<boost/python/manage_new_object.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="#manage_new_object-spec">Class
|
|
||||||
<code>manage_new_object</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#manage_new_object-spec-synopsis">Class
|
|
||||||
<code>manage_new_object</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#manage_new_object-spec-metafunctions">Class
|
|
||||||
<code>manage_new_object</code> metafunctions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</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=
|
|
||||||
"ResultConverterGenerator.html">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.
|
|
||||||
|
|
||||||
<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><b>Returns:</b> <code>typedef <a href=
|
|
||||||
"to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a><T>
|
|
||||||
type;</code>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example</h2>
|
|
||||||
|
|
||||||
<p>In C++:
|
|
||||||
<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_INIT(my_module)
|
|
||||||
{
|
|
||||||
module m("my_module")
|
|
||||||
.def("make_foo", make_foo)
|
|
||||||
.add(
|
|
||||||
class_<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 -->
|
|
||||||
14 February 2002 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,262 +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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</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_INIT-spec">BOOST_PYTHON_MODULE_INIT</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#module-spec">Class <code>module</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#module-spec-synopsis">Class <code>module</code>
|
|
||||||
synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#module-spec-ctors">Class <code>module</code>
|
|
||||||
constructor</a>
|
|
||||||
|
|
||||||
<dt><a href="#module-spec-modifiers">Class <code>module</code>
|
|
||||||
modifier functions</a>
|
|
||||||
|
|
||||||
<dt><a href="#module-spec-observers">Class <code>module</code>
|
|
||||||
observer functions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example(s)</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<p>{{Introductory text}}
|
|
||||||
|
|
||||||
<h2><a name="macros"></a>Macros</h2>
|
|
||||||
|
|
||||||
<p><a name=
|
|
||||||
"BOOST_PYTHON_MODULE_INIT-spec"><code>BOOST_PYTHON_MODULE_INIT(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>
|
|
||||||
void init<i>name</i>()
|
|
||||||
{
|
|
||||||
...
|
|
||||||
</pre>
|
|
||||||
Boost.Python modules should be initialized with
|
|
||||||
<pre>
|
|
||||||
BOOST_PYTHON_MODULE_INIT(<i>name</i>)
|
|
||||||
{
|
|
||||||
...
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="module-spec">Class <code>module</code></a></h3>
|
|
||||||
|
|
||||||
<p>This class represents the Python extension module under construction. It
|
|
||||||
provides functions for adding attributes and for retrieving the underlying
|
|
||||||
Python module object.
|
|
||||||
|
|
||||||
<h4><a name="module-spec-synopsis"></a>Class <code>module</code>
|
|
||||||
synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
class module : public module_base
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
module(const char* name);
|
|
||||||
|
|
||||||
// modifier functions
|
|
||||||
module& setattr(const char* name, PyObject*);
|
|
||||||
module& setattr(const char* name, PyTypeObject*);
|
|
||||||
module& setattr(const char* name, ref const&);
|
|
||||||
|
|
||||||
module& add(PyTypeObject* x);
|
|
||||||
template <class T, class Bases, class HolderGenerator>
|
|
||||||
module& add(class_<T,Bases,HolderGenerator> const& c);
|
|
||||||
|
|
||||||
template <class Fn>
|
|
||||||
module& def(char const* name, Fn fn);
|
|
||||||
template <class Fn, class ResultHandler>
|
|
||||||
module& def(char const* name, Fn fn, ResultHandler handler);
|
|
||||||
|
|
||||||
// observer function
|
|
||||||
ref object() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="module-spec-ctors">Class <code>module</code></a>
|
|
||||||
constructor</h4>
|
|
||||||
<pre>
|
|
||||||
module(const char* name);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>name</code> is a ntbs whose value matches the
|
|
||||||
argument passed to <a href=
|
|
||||||
"#BOOST_PYTHON_MODULE_INIT-spec">BOOST_PYTHON_MODULE_INIT</a>.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Creates a <code>module</code> object representing a
|
|
||||||
Python module named <code>name</code>.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="module-spec-modifiers">Class <code>module</code></a> modifier
|
|
||||||
functions</h4>
|
|
||||||
<pre>
|
|
||||||
module& setattr(const char* name, PyObject* obj);
|
|
||||||
module& setattr(const char* name, PyTypeObject* obj);
|
|
||||||
module& setattr(const char* name, ref const& r);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code>name</code> is a ntbs which conforms to
|
|
||||||
Python's <a href=
|
|
||||||
"http://www.python.org/doc/2.2/ref/identifiers.html">identifier
|
|
||||||
naming rules</a>. In the first two forms, <code>obj</code> is non-null.
|
|
||||||
In the third form, <code>r.get()</code> is non-null.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Adds the given Python object to the module. If the
|
|
||||||
object is a product of <code><a href=
|
|
||||||
"make_function.html#make_function-spec">make_function</a>()</code>, the
|
|
||||||
usual <a href="overloading.html">overloading procedure</a> applies.
|
|
||||||
In the first two forms, ownership of a reference to obj is transferred
|
|
||||||
from caller to callee, even if an exception is thrown.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code>*this</code>
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
module& add(PyTypeObject* x);
|
|
||||||
|
|
||||||
template <class T, class Bases, class HolderGenerator>
|
|
||||||
module& add(class_<T,Bases,HolderGenerator> const& c);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> In the first form, <code>x</code> is non-null
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> The first form adds the Python type object named by
|
|
||||||
<code>x</code> to the Python module under construction, with the name
|
|
||||||
given by the type's <code><a href=
|
|
||||||
"http://www.python.org/doc/2.2/ext/dnt-type-methods.html">tp_name</a></code>
|
|
||||||
field. The second form adds the extension class object being constructed
|
|
||||||
by <code>c</code> to the module, with the same name that was passed to
|
|
||||||
<code>c</code>'s constructor.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code>*this</code>
|
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Provides a way to set type attributes in the module
|
|
||||||
without having to explicitly specify the name.
|
|
||||||
</dl>
|
|
||||||
<pre>
|
|
||||||
template <class Fn>
|
|
||||||
module& def(char const* name, Fn f);
|
|
||||||
|
|
||||||
template <class Fn, class ResultHandler>
|
|
||||||
module& def(char const* name, Fn f, ResultHandler handler);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
|
|
||||||
<dt><b>Requires:</b> <code>f</code> is a non-null pointer-to-function or
|
|
||||||
pointer-to-member-function. <code>name</code> is a ntbs which conforms to
|
|
||||||
Python's <a href=
|
|
||||||
"http://www.python.org/doc/2.2/ref/identifiers.html">identifier
|
|
||||||
naming rules</a>. In the first form, the return type of
|
|
||||||
<code>f</code> is not a reference and is not a pointer other
|
|
||||||
than <code>char const*</code> or <code>PyObject*</code>. In the
|
|
||||||
second form <code>policy</code> is a model of <a
|
|
||||||
href="CallPolicy.html">CallPolicy</a>.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Adds the result of <code><a href=
|
|
||||||
"make_function.html#make_function-spec">make_function</a>(f)</code> to
|
|
||||||
the extension module being defined, with the given <code>name</code>. If
|
|
||||||
the module already has an attribute named <code><i>name</i></code>, the
|
|
||||||
usual <a href="http:overloading.html">overloading procedure</a> applies.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code>*this</code>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h4><a name="module-spec-observers">Class <code>module</code></a> observer
|
|
||||||
functions</h4>
|
|
||||||
<pre>
|
|
||||||
ref object() const;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Returns:</b> A <code>ref</code> object which holds a reference to
|
|
||||||
the Python module object created by the <code>module</code> constructor.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example(s)</h2>
|
|
||||||
|
|
||||||
<p>C++ module definition:
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/module.hpp>
|
|
||||||
|
|
||||||
char const* greet()
|
|
||||||
{
|
|
||||||
return "hello, Boost.Python!";
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(boost_greet)
|
|
||||||
{
|
|
||||||
module("boost_greet")
|
|
||||||
.def("greet", greet);
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
Interactive Python:
|
|
||||||
<pre>
|
|
||||||
>>> import boost_greet
|
|
||||||
>>> boost_greet.greet()
|
|
||||||
'hello, Boost.Python!'
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
14 February, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,47 +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 - Overview</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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
<h2 align="center">Overview</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="#introduction">Introduction</a></dt>
|
|
||||||
<dt><a href="#topic1">First topic</a></dt>
|
|
||||||
<dt><a href="#topic2">Second topic</a></dt>
|
|
||||||
<dt><a href="#footnotes">Footnotes</a></dt>
|
|
||||||
</dl>
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
<p>{{text}}</p>
|
|
||||||
<h2><a name="topic1"></a>First Topic</h2>
|
|
||||||
<p>{{text}}</p>
|
|
||||||
<h2><a name="topic2"></a>Second Topic</h2>
|
|
||||||
<p>{{text}}</p>
|
|
||||||
<h2><a name="footnotes"></a>Footnotes</h2>
|
|
||||||
<dl>
|
|
||||||
<dt><a name="footnote1" class="footnote">(1)</a> {{text}}</dt>
|
|
||||||
<dt><a name="footnote2" class="footnote">(2)</a> {{text}}</dt>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,47 +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 - Rationale</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="http://www.boost.org"><img height="86" width="277" alt="C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
</td>
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
<h2 align="center">Rationale</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="#introduction">Introduction</a></dt>
|
|
||||||
<dt><a href="#topic1">First topic</a></dt>
|
|
||||||
<dt><a href="#topic2">Second topic</a></dt>
|
|
||||||
<dt><a href="#footnotes">Footnotes</a></dt>
|
|
||||||
</dl>
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
<p>{{text}}</p>
|
|
||||||
<h2><a name="topic1"></a>First Topic</h2>
|
|
||||||
<p>{{text}}</p>
|
|
||||||
<h2><a name="topic2"></a>Second Topic</h2>
|
|
||||||
<p>{{text}}</p>
|
|
||||||
<h2><a name="footnotes"></a>Footnotes</h2>
|
|
||||||
<dl>
|
|
||||||
<dt><a name="footnote1" class="footnote">(1)</a> {{text}}</dt>
|
|
||||||
<dt><a name="footnote2" class="footnote">(2)</a> {{text}}</dt>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
|
||||||
<p><i>© Copyright <a href="../../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
|
||||||
2002. All Rights Reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,383 +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 - Reference</title>
|
|
||||||
|
|
||||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
|
||||||
"reference">
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="300">
|
|
||||||
<h3><a href="http://www.boost.org"><img height="86" width="277" alt=
|
|
||||||
"C++ Boost" src="../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Reference</h2>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2>Contents</h2>
|
|
||||||
|
|
||||||
<dl class="Reference">
|
|
||||||
<dt><a href="#high_level">High Level Components</a>
|
|
||||||
|
|
||||||
<dt><a href="#framework">Framework Elements</a>
|
|
||||||
|
|
||||||
<dt><a href="#utilities">Utilities</a>
|
|
||||||
|
|
||||||
<dt><a href="#by_name">Index By Name</a>
|
|
||||||
</dl>
|
|
||||||
<a name="high_level"></a>
|
|
||||||
|
|
||||||
<h2>High Level Components</h2>
|
|
||||||
|
|
||||||
<dl class="index">
|
|
||||||
<dd>
|
|
||||||
<a name="general_purpose"></a>
|
|
||||||
|
|
||||||
<h3>General Purpose</h3>
|
|
||||||
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="class.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="class.html#class_-spec">class_</a>
|
|
||||||
|
|
||||||
<dt><a href="class.html#bases-spec">bases</a>
|
|
||||||
|
|
||||||
<dt><a href="class.html#args-spec">args</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="errors.html">errors.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="errors.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"errors.html#error_already_set-spec">error_already_set</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="errors.html#functions">Functions</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"errors.html#handle_exception-spec">handle_exception</a>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"errors.html#expect_non_null-spec">expect_non_null</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="make_function.html">make_function.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="make_function.html#classes">Functions</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"make_function.html#make_function-spec">make_function</a>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"make_.html#make_constructor-spec">make_constructor</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="module.html">module.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="module.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="module.html#module-spec">module</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="objects.html">objects.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="objects.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="objects.html#xxx-spec">not yet documented</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="reference_hpp.html">reference.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="reference_hpp.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="reference_hpp.html#reference-spec">reference</a>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="reference_hpp.html#types">Types</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="reference_hpp.html#ref-spec">ref</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
<a name="type_conversion"></a>
|
|
||||||
|
|
||||||
<h3>To/From Python Type Conversion</h3>
|
|
||||||
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="from_python.html">from_python.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="from_python.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"from_python.html#from_python-spec">from_python</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="to_python_converter.html">to_python_converter.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="to_python_converter.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"to_python_converter.html#to_python_converter-spec">to_python_converter</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="to_python_indirect.html">to_python_indirect.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="to_python_indirect.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="to_python_value.html">to_python_value.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="to_python_value.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"to_python_value.html#to_python_value-spec">to_python_value</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="type_from_python.html">type_from_python.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="type_from_python.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"type_from_python.html#type_from_python-spec">type_from_python</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="value_from_python.html">value_from_python.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="value_from_python.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"value_from_python.html#value_from_python-spec">value_from_python</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
<a name="models_of_call_policies"></a>
|
|
||||||
|
|
||||||
<h3>Models of CallPolicies</h3>
|
|
||||||
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"default_call_policies.html">default_call_policies.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="default_call_policies.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"default_call_policies.html#default_call_policies-spec">default_call_policies</a>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"default_call_policies.html#default_result_converter-spec">default_result_converter</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"return_internal_reference.html">return_internal_reference.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="return_internal_reference.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"return_internal_reference.html#return_internal_reference-spec">
|
|
||||||
return_internal_reference</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="return_value_policy.html">return_value_policy.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="return_value_policy.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"return_value_policy.html#return_value_policy-spec">return_value_policy</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"with_custodian_and_ward.html">with_custodian_and_ward.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="with_custodian_and_ward.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"with_custodian_and_ward.html#with_custodian_and_ward-spec">with_custodian_and_ward</a>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"with_custodian_and_ward.html#with_custodian_and_ward_postcall-spec">
|
|
||||||
with_custodian_and_ward_postcall</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
<a name="return_handler_generators"></a>
|
|
||||||
|
|
||||||
<h3>Models of ReturnHandlerGenerator</h3>
|
|
||||||
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="copy_const_reference.html">copy_const_reference.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="copy_const_reference.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"copy_const_reference.html#copy_const_reference-spec">copy_const_reference</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"copy_non_const_reference.html">copy_non_const_reference.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="copy_non_const_reference.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"copy_non_const_reference.html#copy_non_const_reference-spec">
|
|
||||||
copy_non_const_reference</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="manage_new_object.html">manage_new_object.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="manage_new_object.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"manage_new_object.html#manage_new_object-spec">manage_new_object</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"reference_existing_object.html">reference_existing_object.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="reference_existing_object.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"reference_existing_object.html#reference_existing_object-spec">
|
|
||||||
reference_existing_object</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"lvalue_from_python.html">reference_from_python.hpp</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href="lvalue_from_python.html#classes">Classes</a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="index">
|
|
||||||
<dt><a href=
|
|
||||||
"lvalue_from_python.html#reference_from_python-spec">reference_from_python</a>
|
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"lvalue_from_python.html#get_member-spec">get_member</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,161 +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/reference_existing_object.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header
|
|
||||||
<boost/python/reference_existing_object.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="#reference_existing_object-spec">Class
|
|
||||||
<code>reference_existing_object</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#reference_existing_object-spec-synopsis">Class
|
|
||||||
<code>reference_existing_object</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#reference_existing_object-spec-metafunctions">Class
|
|
||||||
<code>reference_existing_object</code> metafunctions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="reference_existing_object-spec"></a>Class
|
|
||||||
<code>reference_existing_object</code></h3>
|
|
||||||
|
|
||||||
<p><code>reference_existing_object</code> is a model of <a href=
|
|
||||||
"ResultConverterGenerator.html">ResultConverterGenerator</a> which can be
|
|
||||||
used to wrap C++ functions which return a reference or pointer to a C++
|
|
||||||
object. When the wrapped function is called, the value referenced by its
|
|
||||||
return value is not copied. A new Python object is created which contains a
|
|
||||||
pointer to the referent, and no attempt is made to ensure that the lifetime
|
|
||||||
of the referent is at least as long as that of the corresponding Python
|
|
||||||
object. Thus, it can be <font color="#ff0000"><b>highly
|
|
||||||
dangerous</b></font> to use <code>reference_existing_object</code> without
|
|
||||||
additional lifetime management from such models of <a href=
|
|
||||||
"CallPolicies.html">CallPolicies</a> as <a href=
|
|
||||||
"with_custodian_and_ward.html#with_custodian_and_ward-spec">with_custodian_and_ward</a>.
|
|
||||||
This class is used in the implementation of <a href=
|
|
||||||
"return_internal_reference.html#return_internal_reference-spec">return_internal_reference</a>.
|
|
||||||
|
|
||||||
<h4><a name="reference_existing_object-spec-synopsis"></a>Class
|
|
||||||
<code>reference_existing_object</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
struct reference_existing_object
|
|
||||||
{
|
|
||||||
template <class T> struct apply;
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="reference_existing_object-spec-metafunctions"></a>Class
|
|
||||||
<code>reference_existing_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> or
|
|
||||||
<code>U*</code>for some <code>U</code>.
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code>typedef <a href=
|
|
||||||
"to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a><T,V>
|
|
||||||
type</code>, where <code>V</code> is a <a href=
|
|
||||||
"to_python_indirect.html#HolderObjectGenerator">HolderObjectGenerator</a>
|
|
||||||
which constructs an instance holder containing an <i>unowned</i>
|
|
||||||
<code>U*</code> pointing to the referent of the wrapped function's return
|
|
||||||
value.
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example</h2>
|
|
||||||
|
|
||||||
<p>In C++:
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/module.hpp>
|
|
||||||
#include <boost/python/class.hpp>
|
|
||||||
#include <boost/python/reference_existing_object.hpp>
|
|
||||||
#include <boost/python/return_value_policy.hpp>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
// classes to wrap
|
|
||||||
struct Singleton
|
|
||||||
{
|
|
||||||
Singleton() : x(0) {}
|
|
||||||
|
|
||||||
int exchange(int n) // set x and return the old value
|
|
||||||
{
|
|
||||||
std::swap(n, x);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int x;
|
|
||||||
};
|
|
||||||
|
|
||||||
Singleton& get_it()
|
|
||||||
{
|
|
||||||
static Singleton just_one;
|
|
||||||
return just_one;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapper code
|
|
||||||
using namespace boost::python;
|
|
||||||
BOOST_PYTHON_MODULE_INIT(singleton)
|
|
||||||
{
|
|
||||||
module m("singleton")
|
|
||||||
.def("get_it", get_it)
|
|
||||||
.add(
|
|
||||||
class_<Singleton>()
|
|
||||||
.def("exchange", &Singleton::exchange)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
In Python:
|
|
||||||
<pre>
|
|
||||||
>>> import singleton
|
|
||||||
>>> s1 = singleton.get_it()
|
|
||||||
>>> s2 = singleton.get_it()
|
|
||||||
>>> id(s1) == id(s2) # s1 and s2 are not the same object
|
|
||||||
0
|
|
||||||
>>> s1.exchange(42) # but they reference the same C++ Singleton
|
|
||||||
0
|
|
||||||
>>> s2.exchange(99)
|
|
||||||
42
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
14 February 2002 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,210 +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/return_internal_reference.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/return_internal_reference.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="#return_internal_reference-spec">Class Template <code>return_internal_reference</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
|
|
||||||
<dt><a href="#return_internal_reference-spec-synopsis">Class Template
|
|
||||||
<code>return_internal_reference</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#return_internal_reference-spec-statics">Class
|
|
||||||
<code>return_internal_reference</code> static functions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<code>return_internal_reference</code> instantiations are models of <a href=
|
|
||||||
"CallPolicies.html">CallPolicies</a> which allow pointers and
|
|
||||||
references to objects held internally by a free or member function
|
|
||||||
argument or from the target of a member function to be returned
|
|
||||||
safely without making a copy of the referent. The default for its
|
|
||||||
first template argument handles the common case where the
|
|
||||||
containing object is the target (<code>*this</code>) of a wrapped
|
|
||||||
member function.
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="return_internal_reference-spec"></a>Class template <code>return_internal_reference</code></h3>
|
|
||||||
|
|
||||||
|
|
||||||
<table border="1" summary="return_internal_reference template parameters">
|
|
||||||
<caption>
|
|
||||||
<b><code>return_internal_reference</code> template parameters</b>
|
|
||||||
</caption>
|
|
||||||
<tr>
|
|
||||||
<th>Parameter
|
|
||||||
|
|
||||||
<th>Requirements
|
|
||||||
|
|
||||||
<th>Description
|
|
||||||
|
|
||||||
<th>Default
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>owner_arg</code>
|
|
||||||
|
|
||||||
<td>A positive compile-time constant of type
|
|
||||||
<code>std::size_t</code>.
|
|
||||||
|
|
||||||
<td>The index of the parameter which contains the object to
|
|
||||||
which the reference or pointer is being returned. If used to
|
|
||||||
wrap a member function, parameter 1 is the target object
|
|
||||||
(<code>*this</code>). Note that if the target Python object
|
|
||||||
type doesn't support weak references, a Python
|
|
||||||
<code>TypeError</code> exception will be raised when the
|
|
||||||
function being wrapped is called.
|
|
||||||
|
|
||||||
<td>1
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>Base</code>
|
|
||||||
|
|
||||||
<td>A model of <a href="CallPolicies.html">CallPolicies</a>
|
|
||||||
|
|
||||||
<td>Used for policy composition. Any
|
|
||||||
<code>result_converter</code> it supplies will be overridden by
|
|
||||||
<code>return_internal_reference</code>, but its
|
|
||||||
<code>precall</code> and <code>postcall</code> policies are
|
|
||||||
composed as described here <a
|
|
||||||
href="CallPolicies.html#composition">CallPolicies</a>.
|
|
||||||
|
|
||||||
<td><code><a href="default_call_policies.html#default_call_policies-spec">default_call_policies</a></code>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h4><a name="return_internal_reference-spec-synopsis"></a>Class template <code>return_internal_reference</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
template <std::size_t owner_arg = 1, class Base = default_call_policies>
|
|
||||||
struct return_internal_reference : Base
|
|
||||||
{
|
|
||||||
static PyObject* postcall(PyObject*, PyObject* result);
|
|
||||||
typedef <a href="reference_existing_object.html#reference_existing_object-spec">reference_existing_object</a> result_converter;
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="default_call_policies-spec-statics"></a>Class
|
|
||||||
<code>default_call_policies</code> static functions</h4>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
PyObject* postcall(PyObject* args, PyObject* result);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
<dt><b>Requires:</b> <code><a href="http://www.python.org/doc/2.2/api/tupleObjects.html#l2h-476">PyTuple_Check</a>(args) != 0</code>
|
|
||||||
|
|
||||||
<dt><b>Returns:</b> <code><a href="with_custodian_and_ward.html#with_custodian_and_ward_postcall-spec-statics">with_custodian_and_ward_postcall::postcall(args, result)</a></code>
|
|
||||||
</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/return_internal_reference.hpp>
|
|
||||||
|
|
||||||
class Bar
|
|
||||||
{
|
|
||||||
Bar(int x) : x(x) {}
|
|
||||||
int get_x() const { return x; }
|
|
||||||
void set_x(int x) { this->x = x; }
|
|
||||||
private:
|
|
||||||
int x;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Foo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Foo(int x) : b(x) {}
|
|
||||||
|
|
||||||
// Returns an internal reference
|
|
||||||
Bar const& get_bar() const { return b; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Bar b;
|
|
||||||
};
|
|
||||||
|
|
||||||
using namespace boost::python;
|
|
||||||
BOOST_PYTHON_MODULE_INIT(internal_refs)
|
|
||||||
{
|
|
||||||
module m("internal_refs")
|
|
||||||
.add(
|
|
||||||
class_<Bar>()
|
|
||||||
.def("get_x", &Bar::get_x)
|
|
||||||
.def("set_x", &Bar::set_x)
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
class_<Foo>()
|
|
||||||
.def_init(args<int>())
|
|
||||||
.def("get_bar", &Foo::get_bar
|
|
||||||
, return_internal_reference<>())
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h3>Python code</h3>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
>>> from internal_refs import *
|
|
||||||
>>> f = Foo(3)
|
|
||||||
>>> b1 = f.get_bar()
|
|
||||||
>>> b2 = f.get_bar()
|
|
||||||
>>> b1.get_x()
|
|
||||||
3
|
|
||||||
>>> b2.get_x()
|
|
||||||
3
|
|
||||||
>>> b1.set_x(42)
|
|
||||||
>>> b2.get_x()
|
|
||||||
42
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
15 February, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,148 +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/return_value_policy.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/return_value_policy.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="#return_value_policy-spec">Class Template <code>return_value_policy</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
|
|
||||||
<dt><a href="#return_value_policy-spec-synopsis">Class Template
|
|
||||||
<code>return_value_policy</code> synopsis</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<code>return_value_policy</code> instantiations are simply models
|
|
||||||
of <a href=
|
|
||||||
"CallPolicies.html">CallPolicies</a> which are composed of a <a href=
|
|
||||||
"ResultConverterGenerator.html">ResultConverterGenerator</a> and optional <code>Base</code> <a href=
|
|
||||||
"CallPolicies.html">CallPolicies</a>.
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="return_value_policy-spec"></a>Class template <code>return_value_policy</code></h3>
|
|
||||||
|
|
||||||
|
|
||||||
<table border="1" summary="return_value_policy template parameters">
|
|
||||||
<caption>
|
|
||||||
<b><code>return_value_policy</code> template parameters</b>
|
|
||||||
</caption>
|
|
||||||
<tr>
|
|
||||||
<th>Parameter
|
|
||||||
|
|
||||||
<th>Requirements
|
|
||||||
|
|
||||||
<th>Default
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>ResultConverterGenerator</code>
|
|
||||||
|
|
||||||
<td>A model of <a href=
|
|
||||||
"ResultConverterGenerator.html">ResultConverterGenerator</a>.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>Base</code>
|
|
||||||
|
|
||||||
<td>A model of <a href="CallPolicies.html">CallPolicies</a>
|
|
||||||
|
|
||||||
<td><code><a href="default_call_policies.html#default_call_policies-spec">default_call_policies</a></code>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h4><a name="return_value_policy-spec-synopsis"></a>Class template <code>return_value_policy</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
template <class ResultConverterGenerator, class Base = default_call_policies>
|
|
||||||
struct return_value_policy : Base
|
|
||||||
{
|
|
||||||
typedef ResultConverterGenerator result_converter;
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<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_INIT(my_module)
|
|
||||||
{
|
|
||||||
module m("my_module")
|
|
||||||
.add(
|
|
||||||
class_<Bar>()
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
class_<Foo>()
|
|
||||||
.def_init(args<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 -->
|
|
||||||
15 February, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,189 +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/to_python_converter.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/to_python_converter.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="#to_python_converter-spec">Class Template <code>to_python_converter</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
|
|
||||||
<dt><a href="#to_python_converter-spec-synopsis">Class Template
|
|
||||||
<code>to_python_converter</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#to_python_converter-spec-ctors">Class Template
|
|
||||||
<code>to_python_converter</code> constructor</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<code>to_python_converter</code> registers a conversion from
|
|
||||||
objects of a given C++ type into a Python object.
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="to_python_converter-spec"></a>Class template <code>to_python_converter</code></h3>
|
|
||||||
|
|
||||||
<code>to_python_converter</code> adds a wrapper around a static
|
|
||||||
member function of its second template parameter, handling
|
|
||||||
low-level details such as insertion into the converter registry.
|
|
||||||
|
|
||||||
<table border="1" summary="to_python_converter template parameters">
|
|
||||||
<caption>
|
|
||||||
<b><code>to_python_converter</code> template parameters</b><br>
|
|
||||||
In the table below, <b><code>x</code></b> denotes an object of type <code>T</code>
|
|
||||||
</caption>
|
|
||||||
<tr>
|
|
||||||
<th>Parameter
|
|
||||||
|
|
||||||
<th>Requirements
|
|
||||||
|
|
||||||
<th>Description
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>T</code>
|
|
||||||
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<td>The C++ type of the source object in the conversion
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>Conversion</code>
|
|
||||||
|
|
||||||
<td><code>PyObject* p = Conversion::convert(x)</code>,<br>
|
|
||||||
if <code>p == 0</code>, <code><a href="http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71">PyErr_Occurred</a>() != 0</code>.
|
|
||||||
|
|
||||||
<td>A class type whose static member function
|
|
||||||
<code>convert</code> does the real work of the conversion.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h4><a name="to_python_converter-spec-synopsis"></a>Class template <code>to_python_converter</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
template <class T, class Conversion>
|
|
||||||
struct to_python_converter
|
|
||||||
{
|
|
||||||
to_python_converter();
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="to_python_converter-spec-ctors"></a>Class template <code>to_python_converter</code> constructor</h4>
|
|
||||||
<pre>
|
|
||||||
to_python_converter();
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Registers a to_python converter which uses
|
|
||||||
<code>Conversion::convert()</code> to do its work.
|
|
||||||
|
|
||||||
</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 placed the corresponding
|
|
||||||
declarations in <code>"noddy.h"</code>. Because
|
|
||||||
<code>noddy_NoddyObject</code> is the ultimate trivial extension type,
|
|
||||||
the example is a bit contrived: it wraps a function for which all
|
|
||||||
information is contained in the <i>type</i> of its return value.
|
|
||||||
|
|
||||||
<h3>C++ module definition</h3>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
#include <boost/python/reference.hpp>
|
|
||||||
#include <boost/python/module.hpp>
|
|
||||||
#include "noddy.h"
|
|
||||||
|
|
||||||
struct tag {};
|
|
||||||
tag make_tag() { return tag(); }
|
|
||||||
|
|
||||||
using namespace boost::python;
|
|
||||||
|
|
||||||
struct tag_to_noddy
|
|
||||||
{
|
|
||||||
static PyObject* convert(tag const& x)
|
|
||||||
{
|
|
||||||
return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(to_python_converter)
|
|
||||||
{
|
|
||||||
module to_python("to_python_converter")
|
|
||||||
.def("make_tag", make_tag)
|
|
||||||
;
|
|
||||||
to_python_converter<tag, tag_to_noddy>();
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h3>Python code</h3>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
>>> import to_python_converter
|
|
||||||
>>> def always_none():
|
|
||||||
... return None
|
|
||||||
...
|
|
||||||
>>> def choose_function(x):
|
|
||||||
... if (x % 2 != 0):
|
|
||||||
... return to_python_converter.make_tag
|
|
||||||
... else:
|
|
||||||
... return always_none
|
|
||||||
...
|
|
||||||
>>> a = [ choose_function(x) for x in range(5) ]
|
|
||||||
>>> b = [ f() for f in a ]
|
|
||||||
>>> type(b[0])
|
|
||||||
<type 'NoneType'>
|
|
||||||
>>> type(b[1])
|
|
||||||
<type 'Noddy'>
|
|
||||||
>>> type(b[2])
|
|
||||||
<type 'NoneType'>
|
|
||||||
>>> type(b[3])
|
|
||||||
<type 'Noddy'>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
05 November, 2001
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,194 +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/to_python_indirect.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="../../../../c++boost.gif" border="0"></a></h3>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<h1 align="center">Boost.Python</h1>
|
|
||||||
|
|
||||||
<h2 align="center">Header <boost/python/to_python_indirect.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="#to_python_indirect-spec">Class Template <code>to_python_indirect</code></a>
|
|
||||||
|
|
||||||
<dd>
|
|
||||||
<dl class="page-index">
|
|
||||||
|
|
||||||
<dt><a href="#to_python_indirect-spec-synopsis">Class Template
|
|
||||||
<code>to_python_indirect</code> synopsis</a>
|
|
||||||
|
|
||||||
<dt><a href="#to_python_indirect-spec-observers">Class Template
|
|
||||||
<code>to_python_indirect</code> observer functions</a>
|
|
||||||
|
|
||||||
<dt><a href="#to_python_indirect-spec-statics">Class Template
|
|
||||||
<code>to_python_indirect</code> static functions</a>
|
|
||||||
</dl>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
|
||||||
</dl>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<code><boost/python/to_python_indirect.hpp></code> supplies
|
|
||||||
a way to construct new Python objects that hold wrapped C++ class
|
|
||||||
instances via a pointer or smart pointer.
|
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
|
||||||
|
|
||||||
<h3><a name="to_python_indirect-spec"></a>Class template <code>to_python_indirect</code></h3>
|
|
||||||
<p>Class template <code>to_python_indirect</code> converts objects
|
|
||||||
of its first argument type to python as extension class instances, using the ownership policy provided by its 2nd argument.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
|
|
||||||
<table border="1" summary="to_python_indirect template parameters">
|
|
||||||
<caption>
|
|
||||||
<b><code>to_python_indirect</code> Requirements</b><br>
|
|
||||||
|
|
||||||
In the table below, <b><code>x</code></b> denotes an object of
|
|
||||||
type <code>T</code>, <b><code>h</code></b> denotes an
|
|
||||||
object of type
|
|
||||||
<code>boost::python::objects::instance_holder*</code>, and
|
|
||||||
<b><code>p</code></b> denotes an object of type
|
|
||||||
<code>U*</code>.
|
|
||||||
|
|
||||||
</caption>
|
|
||||||
<tr>
|
|
||||||
<th>Parameter
|
|
||||||
|
|
||||||
<th>Requirements
|
|
||||||
|
|
||||||
<th>Description
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>T</code>
|
|
||||||
|
|
||||||
<td>Either <code>U</code> <i>cv</i><code>&</code>
|
|
||||||
(where <i>cv</i> is any optional cv-qualification) or a <a
|
|
||||||
href="Dereferenceable.html">Dereferenceable</a> type such that
|
|
||||||
<code>*x</code> is convertible to <code>U const&</code>, where
|
|
||||||
<code>U</code> is a class type.
|
|
||||||
|
|
||||||
<td>A type deferencing a C++ class exposed to Python using
|
|
||||||
class template <code><a
|
|
||||||
href="class.html#class_-spec">class_</a></code>.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><code>MakeHolder</code>
|
|
||||||
|
|
||||||
<td>h = MakeHolder::execute(p);
|
|
||||||
|
|
||||||
<td>A class whose static <code>execute()</code> creates an
|
|
||||||
<code>instance_holder</code>.
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
Instantiations of <code>to_python_indirect</code> are models of <a
|
|
||||||
href="ResultConverter.html">ResultConverter</a>.
|
|
||||||
|
|
||||||
|
|
||||||
<h4><a name="to_python_indirect-spec-synopsis"></a>Class template <code>to_python_indirect</code> synopsis</h4>
|
|
||||||
<pre>
|
|
||||||
namespace boost { namespace python
|
|
||||||
{
|
|
||||||
template <class T, class MakeHolder>
|
|
||||||
struct to_python_indirect
|
|
||||||
{
|
|
||||||
static bool convertible();
|
|
||||||
PyObject* operator()(T ptr_or_reference) const;
|
|
||||||
private:
|
|
||||||
static PyTypeObject* type();
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4><a name="to_python_indirect-spec-observers"></a>Class template <code>to_python_indirect</code> observers</h4>
|
|
||||||
<pre>
|
|
||||||
PyObject* operator()(T x) const;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dl class="function-semantics">
|
|
||||||
|
|
||||||
<dt><b>Requires:</b> <code>x</code> refers to an object (if it
|
|
||||||
is a pointer type, it is non-null). <code>convertible() ==
|
|
||||||
true</code>.
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Creates an appropriately-typed Boost.Python
|
|
||||||
extension class instance, uses <code>MakeHolder</code> to create
|
|
||||||
an <code>instance_holder</code> from <code>x</code>, installs
|
|
||||||
the <code>instance_holder</code> in the new extension class
|
|
||||||
instance, and returns a pointer to it.
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
<h4><a name="to_python_indirect-spec-statics"></a>Class template <code>to_python_indirect</code> statics</h4>
|
|
||||||
<pre>
|
|
||||||
bool convertible();
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<dt><b>Effects:</b> Returns <code>true</code> iff any module has
|
|
||||||
registered a Python type corresponding to <code>U</code>.
|
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example</h2>
|
|
||||||
|
|
||||||
This example replicates the functionality of <a
|
|
||||||
href="reference_existing_object.html#reference_existing_object-spec">reference_existing_object</a>,
|
|
||||||
but without some of the compile-time error checking.
|
|
||||||
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
|
|
||||||
struct make_reference_holder
|
|
||||||
{
|
|
||||||
typedef boost::python::objects::instance_holder* result_type;
|
|
||||||
template <class T>
|
|
||||||
static result_type execute(T* p)
|
|
||||||
{
|
|
||||||
return new boost::python::objects::pointer_holder<T*, T>(p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct reference_existing_object
|
|
||||||
{
|
|
||||||
// metafunction returning the <a href="ResultConverter.html">ResultConverter</a>
|
|
||||||
template <class T>
|
|
||||||
struct apply
|
|
||||||
{
|
|
||||||
typedef boost::python::to_python_indirect<T,make_reference_holder> type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
16 February, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
|
||||||
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
To get started with the Boost Python Library, use the examples
|
|
||||||
getting_started1.cpp and getting_started2.cpp.
|
|
||||||
|
|
||||||
Examples for providing pickle support can be found in:
|
|
||||||
pickle1.cpp
|
|
||||||
pickle2.cpp
|
|
||||||
pickle3.cpp
|
|
||||||
See also: libs/python/doc/pickle.html
|
|
||||||
|
|
||||||
Other advanced concepts are introduced by:
|
|
||||||
abstract.cpp
|
|
||||||
simple_vector.cpp
|
|
||||||
do_it_yourself_convts.cpp
|
|
||||||
|
|
||||||
Examples for the cross-module support are provided by:
|
|
||||||
noncopyable_export.cpp
|
|
||||||
noncopyable_import.cpp
|
|
||||||
dvect.cpp
|
|
||||||
ivect.cpp
|
|
||||||
See also: libs/python/doc/cross_module.html
|
|
||||||
|
|
||||||
The files example1.cpp and rwgk1.cpp are obsolete. They are only
|
|
||||||
included because the Visual Studio project in the build directory still
|
|
||||||
refers to them.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
// Example by Ullrich Koethe
|
|
||||||
#include "boost/python/class_builder.hpp"
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct Abstract
|
|
||||||
{
|
|
||||||
virtual std::string test() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Abstract_callback: Abstract
|
|
||||||
{
|
|
||||||
Abstract_callback(PyObject * self)
|
|
||||||
: m_self(self)
|
|
||||||
{}
|
|
||||||
|
|
||||||
std::string test()
|
|
||||||
{
|
|
||||||
return boost::python::callback<std::string>::call_method(m_self, "test");
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject * m_self;
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(abstract)
|
|
||||||
{
|
|
||||||
boost::python::module_builder a("abstract");
|
|
||||||
|
|
||||||
boost::python::class_builder<Abstract, Abstract_callback>
|
|
||||||
a_class(a, "Abstract");
|
|
||||||
a_class.def(boost::python::constructor<>()); // wrap a constructor
|
|
||||||
a_class.def(&Abstract::test, "test");
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
/*
|
|
||||||
|
|
||||||
This example shows how to convert a class from and to native
|
|
||||||
Python objects, such as tuples.
|
|
||||||
|
|
||||||
We do not want to expose the helper class MillerIndex as an
|
|
||||||
Extension Class. However, in order to simplify the wrapper code,
|
|
||||||
we want to define from_python() and to_python() functions for
|
|
||||||
class MillerIndex.
|
|
||||||
|
|
||||||
Consider the alternatives:
|
|
||||||
|
|
||||||
- Expose MillerIndex as an Extension Class.
|
|
||||||
We need a constructor MillerIndex(python::tuple).
|
|
||||||
Python function calls become more complex:
|
|
||||||
foo(MillerIndex((1,2,3)) instead of foo((1,2,3))
|
|
||||||
We need a method such as MillerIndex().as_tuple().
|
|
||||||
|
|
||||||
- Define a wrapper function for each function that we
|
|
||||||
want to expose, e.g.:
|
|
||||||
void add(const IndexingSet& ixset, const python::tuple PyMIx)
|
|
||||||
|
|
||||||
The first alternative introduces a new type that the user has to
|
|
||||||
deal with. Other modules using Miller indices might organize them in
|
|
||||||
different ways, for example to increase runtime efficiency for
|
|
||||||
important procedures. This means, the user has to know how to
|
|
||||||
convert between the different kinds of Miller index representations.
|
|
||||||
This can quickly become a nuisance. Relying on native Python data
|
|
||||||
structures minimizes the number of special types the user has to
|
|
||||||
learn and convert. Of course, this argument is only valid for
|
|
||||||
small and relatively simply classes.
|
|
||||||
|
|
||||||
If there are many member functions with MillerIndex arguments, the
|
|
||||||
second alternative is impractical, and concentrating the conversion
|
|
||||||
mechanism in one central place is essential for code
|
|
||||||
maintainability. An added benefit is that more convenient (smarter)
|
|
||||||
conversion functions can be provided without cluttering the rest of
|
|
||||||
the wrapper code.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// The helper class.
|
|
||||||
//
|
|
||||||
class MillerIndex {
|
|
||||||
public:
|
|
||||||
int v[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
// The main class. Imagine that there are MANY member functions
|
|
||||||
// like add() and get().
|
|
||||||
//
|
|
||||||
class IndexingSet {
|
|
||||||
private:
|
|
||||||
std::vector<MillerIndex> VMIx;
|
|
||||||
public:
|
|
||||||
void add(const MillerIndex& MIx) { VMIx.push_back(MIx); }
|
|
||||||
MillerIndex get(std::size_t i) const { return VMIx[i]; }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
|
||||||
|
|
||||||
// Convert a Python tuple to a MillerIndex object.
|
|
||||||
//
|
|
||||||
MillerIndex from_python(PyObject* p, python::type<const MillerIndex&>)
|
|
||||||
{
|
|
||||||
python::tuple tup
|
|
||||||
= python::tuple(python::ref(p, python::ref::increment_count));
|
|
||||||
if (tup.size() != 3) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"expecting exactly 3 values in tuple.");
|
|
||||||
python::throw_error_already_set();
|
|
||||||
}
|
|
||||||
MillerIndex result;
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
result.v[i] = from_python(tup[i].get(), python::type<int>());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Similar conversion for MillerIndex objects passed by value.
|
|
||||||
// Not actually used, but included to show the principle.
|
|
||||||
//
|
|
||||||
MillerIndex from_python(PyObject* p, python::type<MillerIndex>)
|
|
||||||
{
|
|
||||||
return from_python(p, python::type<const MillerIndex&>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a MillerIndex object to a Python tuple.
|
|
||||||
//
|
|
||||||
PyObject* to_python(const MillerIndex& hkl)
|
|
||||||
{
|
|
||||||
python::tuple result(3);
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
result.set_item(i, python::ref(to_python(hkl.v[i])));
|
|
||||||
return result.reference().release();
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(do_it_yourself_convts)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("do_it_yourself_convts");
|
|
||||||
|
|
||||||
// Create the Python type object for our extension class.
|
|
||||||
python::class_builder<IndexingSet> ixset_class(this_module, "IndexingSet");
|
|
||||||
|
|
||||||
// Add the __init__ function.
|
|
||||||
ixset_class.def(python::constructor<>());
|
|
||||||
// Add the member functions.
|
|
||||||
ixset_class.def(&IndexingSet::add, "add");
|
|
||||||
ixset_class.def(&IndexingSet::get, "get");
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
// See root/libs/python/doc/cross_module.html for an introduction.
|
|
||||||
|
|
||||||
#include "dvect.h"
|
|
||||||
#include "ivect.h"
|
|
||||||
#include <boost/python/cross_module.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
# include "dvect_conversions.cpp"
|
|
||||||
# include "ivect_conversions.cpp"
|
|
||||||
|
|
||||||
vects::ivect dvect_as_ivect(const vects::dvect& dv)
|
|
||||||
{
|
|
||||||
vects::ivect iv(dv.size());
|
|
||||||
vects::ivect::iterator iviter = iv.begin();
|
|
||||||
for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast<int>(dv[i]);
|
|
||||||
return iv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
|
||||||
# include <windows.h>
|
|
||||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
= _set_se_translator(structured_exception_translator);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(dvect)
|
|
||||||
{
|
|
||||||
python::module_builder this_module("dvect");
|
|
||||||
|
|
||||||
python::class_builder<vects::dvect> dvect_class(this_module, "dvect");
|
|
||||||
python::export_converters(dvect_class);
|
|
||||||
|
|
||||||
python::import_converters<vects::ivect> ivect_converters("ivect", "ivect");
|
|
||||||
|
|
||||||
dvect_class.def(python::constructor<python::tuple>());
|
|
||||||
dvect_class.def(&vects::dvect::as_tuple, "as_tuple");
|
|
||||||
dvect_class.def(dvect_as_ivect, "as_ivect");
|
|
||||||
|
|
||||||
# include "dvect_defs.cpp"
|
|
||||||
# include "ivect_defs.cpp"
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#ifndef DVECT_H
|
|
||||||
#define DVECT_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
|
|
||||||
namespace vects {
|
|
||||||
|
|
||||||
struct dvect : public std::vector<double>
|
|
||||||
{
|
|
||||||
dvect() : std::vector<double>() {}
|
|
||||||
dvect(std::size_t n) : std::vector<double>(n) {}
|
|
||||||
dvect(boost::python::tuple tuple) : std::vector<double>(tuple.size())
|
|
||||||
{
|
|
||||||
std::vector<double>::iterator v_it = begin();
|
|
||||||
for (int i = 0; i < tuple.size(); i++)
|
|
||||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
|
||||||
boost::python::type<double>());
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::python::tuple as_tuple() const
|
|
||||||
{
|
|
||||||
boost::python::tuple t(size());
|
|
||||||
for (int i = 0; i < size(); i++)
|
|
||||||
t.set_item(i,
|
|
||||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DVECT_H
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
// basics first: const reference converters
|
|
||||||
boost::python::tuple const_dvect_reference_as_tuple(const vects::dvect& dv)
|
|
||||||
{
|
|
||||||
return dv.as_tuple();
|
|
||||||
}
|
|
||||||
|
|
||||||
// to_python smart pointer conversions
|
|
||||||
std::auto_ptr<vects::dvect> dvect_as_auto_ptr(const vects::dvect& dv)
|
|
||||||
{
|
|
||||||
return std::auto_ptr<vects::dvect>(new vects::dvect(dv));
|
|
||||||
}
|
|
||||||
boost::shared_ptr<vects::dvect> dvect_as_shared_ptr(const vects::dvect& dv)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<vects::dvect>(new vects::dvect(dv));
|
|
||||||
}
|
|
||||||
|
|
||||||
// smart pointers passed by value
|
|
||||||
boost::python::ref auto_ptr_value_dvect_as_tuple(std::auto_ptr<vects::dvect> dv)
|
|
||||||
{
|
|
||||||
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return dv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
boost::python::ref shared_ptr_value_dvect_as_tuple(boost::shared_ptr<vects::dvect> dv)
|
|
||||||
{
|
|
||||||
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return dv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
|
|
||||||
// smart pointers passed by reference
|
|
||||||
boost::python::ref auto_ptr_reference_dvect_as_tuple(std::auto_ptr<vects::dvect>& dv)
|
|
||||||
{
|
|
||||||
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return dv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
boost::python::ref shared_ptr_reference_dvect_as_tuple(boost::shared_ptr<vects::dvect>& dv)
|
|
||||||
{
|
|
||||||
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return dv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
|
|
||||||
// smart pointers passed by const reference
|
|
||||||
boost::python::ref auto_ptr_const_reference_dvect_as_tuple(const std::auto_ptr<vects::dvect>& dv)
|
|
||||||
{
|
|
||||||
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return dv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
boost::python::ref shared_ptr_const_reference_dvect_as_tuple(const boost::shared_ptr<vects::dvect>& dv)
|
|
||||||
{
|
|
||||||
if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return dv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
this_module.def(dvect_as_auto_ptr, "dvect_as_auto_ptr");
|
|
||||||
this_module.def(dvect_as_shared_ptr, "dvect_as_shared_ptr");
|
|
||||||
|
|
||||||
this_module.def(const_dvect_reference_as_tuple, "const_dvect_reference_as_tuple");
|
|
||||||
|
|
||||||
this_module.def(auto_ptr_value_dvect_as_tuple, "auto_ptr_value_dvect_as_tuple");
|
|
||||||
this_module.def(shared_ptr_value_dvect_as_tuple, "shared_ptr_value_dvect_as_tuple");
|
|
||||||
|
|
||||||
this_module.def(auto_ptr_reference_dvect_as_tuple, "auto_ptr_reference_dvect_as_tuple");
|
|
||||||
this_module.def(shared_ptr_reference_dvect_as_tuple, "shared_ptr_reference_dvect_as_tuple");
|
|
||||||
|
|
||||||
this_module.def(auto_ptr_const_reference_dvect_as_tuple, "auto_ptr_const_reference_dvect_as_tuple");
|
|
||||||
this_module.def(shared_ptr_const_reference_dvect_as_tuple, "shared_ptr_const_reference_dvect_as_tuple");
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace hello {
|
|
||||||
class world
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
world(int) {}
|
|
||||||
~world() {}
|
|
||||||
const char* get() const { return "hi, world"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t length(const world& x) { return strlen(x.get()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
|
|
||||||
// Python requires an exported function called init<module-name> in every
|
|
||||||
// extension module. This is where we build the module contents.
|
|
||||||
BOOST_PYTHON_MODULE_INIT(hello)
|
|
||||||
{
|
|
||||||
// create an object representing this extension module
|
|
||||||
boost::python::module_builder hello("hello");
|
|
||||||
|
|
||||||
// Create the Python type object for our extension class
|
|
||||||
boost::python::class_builder<hello::world> world_class(hello, "world");
|
|
||||||
|
|
||||||
// Add the __init__ function
|
|
||||||
world_class.def(boost::python::constructor<int>());
|
|
||||||
// Add a regular member function
|
|
||||||
world_class.def(&hello::world::get, "get");
|
|
||||||
|
|
||||||
// Add a regular function to the module
|
|
||||||
hello.def(hello::length, "length");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Win32 DLL boilerplate
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <windows.h>
|
|
||||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A couple of simple C++ functions that we want to expose to Python.
|
|
||||||
std::string greet() { return "hello, world"; }
|
|
||||||
int square(int number) { return number * number; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
// Python requires an exported function called init<module-name> in every
|
|
||||||
// extension module. This is where we build the module contents.
|
|
||||||
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("getting_started1");
|
|
||||||
|
|
||||||
// Add regular functions to the module.
|
|
||||||
this_module.def(greet, "greet");
|
|
||||||
this_module.def(square, "square");
|
|
||||||
}
|
|
||||||
catch(...) {
|
|
||||||
boost::python::handle_exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A friendly class.
|
|
||||||
class hello
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
hello(const std::string& country) { this->country = country; }
|
|
||||||
std::string greet() const { return "Hello from " + country; }
|
|
||||||
private:
|
|
||||||
std::string country;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A function taking a hello object as an argument.
|
|
||||||
std::string invite(const hello& w) {
|
|
||||||
return w.greet() + "! Please come soon!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(getting_started2)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("getting_started2");
|
|
||||||
|
|
||||||
// Create the Python type object for our extension class.
|
|
||||||
python::class_builder<hello> hello_class(this_module, "hello");
|
|
||||||
|
|
||||||
// Add the __init__ function.
|
|
||||||
hello_class.def(python::constructor<std::string>());
|
|
||||||
// Add a regular member function.
|
|
||||||
hello_class.def(&hello::greet, "greet");
|
|
||||||
|
|
||||||
// Add invite() as a regular function to the module.
|
|
||||||
this_module.def(invite, "invite");
|
|
||||||
|
|
||||||
// Even better, invite() can also be made a member of hello_class!!!
|
|
||||||
hello_class.def(invite, "invite");
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
// See root/libs/python/doc/cross_module.html for an introduction.
|
|
||||||
|
|
||||||
#include "dvect.h"
|
|
||||||
#include "ivect.h"
|
|
||||||
#include <boost/python/cross_module.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
# include "dvect_conversions.cpp"
|
|
||||||
# include "ivect_conversions.cpp"
|
|
||||||
|
|
||||||
vects::dvect ivect_as_dvect(const vects::ivect& iv)
|
|
||||||
{
|
|
||||||
vects::dvect dv(iv.size());
|
|
||||||
vects::dvect::iterator dviter = dv.begin();
|
|
||||||
for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast<double>(iv[i]);
|
|
||||||
return dv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
|
||||||
# include <windows.h>
|
|
||||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
= _set_se_translator(structured_exception_translator);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(ivect)
|
|
||||||
{
|
|
||||||
python::module_builder this_module("ivect");
|
|
||||||
|
|
||||||
python::class_builder<vects::ivect> ivect_class(this_module, "ivect");
|
|
||||||
python::export_converters(ivect_class);
|
|
||||||
|
|
||||||
python::import_converters<vects::dvect> dvect_converters("dvect", "dvect");
|
|
||||||
|
|
||||||
ivect_class.def(python::constructor<python::tuple>());
|
|
||||||
ivect_class.def(&vects::ivect::as_tuple, "as_tuple");
|
|
||||||
ivect_class.def(ivect_as_dvect, "as_dvect");
|
|
||||||
|
|
||||||
# include "dvect_defs.cpp"
|
|
||||||
# include "ivect_defs.cpp"
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#ifndef IVECT_H
|
|
||||||
#define IVECT_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
|
|
||||||
namespace vects {
|
|
||||||
|
|
||||||
struct ivect : public std::vector<int>
|
|
||||||
{
|
|
||||||
ivect() : std::vector<int>() {}
|
|
||||||
ivect(std::size_t n) : std::vector<int>(n) {}
|
|
||||||
ivect(boost::python::tuple tuple) : std::vector<int>(tuple.size())
|
|
||||||
{
|
|
||||||
std::vector<int>::iterator v_it = begin();
|
|
||||||
for (int i = 0; i < tuple.size(); i++)
|
|
||||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
|
||||||
boost::python::type<int>());
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::python::tuple as_tuple() const
|
|
||||||
{
|
|
||||||
boost::python::tuple t(size());
|
|
||||||
for (int i = 0; i < size(); i++)
|
|
||||||
t.set_item(i,
|
|
||||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // IVECT_H
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
// basics first: const reference converters
|
|
||||||
boost::python::tuple const_ivect_reference_as_tuple(const vects::ivect& iv)
|
|
||||||
{
|
|
||||||
return iv.as_tuple();
|
|
||||||
}
|
|
||||||
|
|
||||||
// to_python smart pointer conversions
|
|
||||||
std::auto_ptr<vects::ivect> ivect_as_auto_ptr(const vects::ivect& iv)
|
|
||||||
{
|
|
||||||
return std::auto_ptr<vects::ivect>(new vects::ivect(iv));
|
|
||||||
}
|
|
||||||
boost::shared_ptr<vects::ivect> ivect_as_shared_ptr(const vects::ivect& iv)
|
|
||||||
{
|
|
||||||
return boost::shared_ptr<vects::ivect>(new vects::ivect(iv));
|
|
||||||
}
|
|
||||||
|
|
||||||
// smart pointers passed by value
|
|
||||||
boost::python::ref auto_ptr_value_ivect_as_tuple(std::auto_ptr<vects::ivect> iv)
|
|
||||||
{
|
|
||||||
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return iv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
boost::python::ref shared_ptr_value_ivect_as_tuple(boost::shared_ptr<vects::ivect> iv)
|
|
||||||
{
|
|
||||||
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return iv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
|
|
||||||
// smart pointers passed by reference
|
|
||||||
boost::python::ref auto_ptr_reference_ivect_as_tuple(std::auto_ptr<vects::ivect>& iv)
|
|
||||||
{
|
|
||||||
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return iv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
boost::python::ref shared_ptr_reference_ivect_as_tuple(boost::shared_ptr<vects::ivect>& iv)
|
|
||||||
{
|
|
||||||
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return iv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
|
|
||||||
// smart pointers passed by const reference
|
|
||||||
boost::python::ref auto_ptr_const_reference_ivect_as_tuple(const std::auto_ptr<vects::ivect>& iv)
|
|
||||||
{
|
|
||||||
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return iv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
boost::python::ref shared_ptr_const_reference_ivect_as_tuple(const boost::shared_ptr<vects::ivect>& iv)
|
|
||||||
{
|
|
||||||
if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count);
|
|
||||||
return iv->as_tuple().reference();
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
this_module.def(ivect_as_auto_ptr, "ivect_as_auto_ptr");
|
|
||||||
this_module.def(ivect_as_shared_ptr, "ivect_as_shared_ptr");
|
|
||||||
|
|
||||||
this_module.def(const_ivect_reference_as_tuple, "const_ivect_reference_as_tuple");
|
|
||||||
|
|
||||||
this_module.def(auto_ptr_value_ivect_as_tuple, "auto_ptr_value_ivect_as_tuple");
|
|
||||||
this_module.def(shared_ptr_value_ivect_as_tuple, "shared_ptr_value_ivect_as_tuple");
|
|
||||||
|
|
||||||
this_module.def(auto_ptr_reference_ivect_as_tuple, "auto_ptr_reference_ivect_as_tuple");
|
|
||||||
this_module.def(shared_ptr_reference_ivect_as_tuple, "shared_ptr_reference_ivect_as_tuple");
|
|
||||||
|
|
||||||
this_module.def(auto_ptr_const_reference_ivect_as_tuple, "auto_ptr_const_reference_ivect_as_tuple");
|
|
||||||
this_module.def(shared_ptr_const_reference_ivect_as_tuple, "shared_ptr_const_reference_ivect_as_tuple");
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
/*
|
|
||||||
This example shows how convert a nested Python tuple.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
boost::python::list
|
|
||||||
show_nested_tuples(boost::python::tuple outer)
|
|
||||||
{
|
|
||||||
boost::python::list result;
|
|
||||||
for (int i = 0; i < outer.size(); i++) {
|
|
||||||
boost::python::tuple inner(
|
|
||||||
BOOST_PYTHON_CONVERSION::from_python(outer[i].get(),
|
|
||||||
boost::python::type<boost::python::tuple>()));
|
|
||||||
for (int j = 0; j < inner.size(); j++) {
|
|
||||||
double x = BOOST_PYTHON_CONVERSION::from_python(inner[j].get(),
|
|
||||||
boost::python::type<double>());
|
|
||||||
char buf[128];
|
|
||||||
sprintf(buf, "(%d,%d) %.6g", i, j, x);
|
|
||||||
result.append(BOOST_PYTHON_CONVERSION::to_python(std::string(buf)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(nested)
|
|
||||||
{
|
|
||||||
boost::python::module_builder this_module("nested");
|
|
||||||
this_module.def(show_nested_tuples, "show_nested_tuples");
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#ifndef NONCOPYABLE_H
|
|
||||||
#define NONCOPYABLE_H
|
|
||||||
|
|
||||||
class store
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
store(const store&) { } // Disable the copy constructor.
|
|
||||||
int number;
|
|
||||||
public:
|
|
||||||
store(const int i) : number(i) { }
|
|
||||||
int recall() const { return number; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // NONCOPYABLE_H
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
// See root/libs/python/doc/cross_module.html for an introduction.
|
|
||||||
|
|
||||||
#include <boost/python/cross_module.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
#include "noncopyable.h"
|
|
||||||
|
|
||||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
|
||||||
# include <windows.h>
|
|
||||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
= _set_se_translator(structured_exception_translator);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(noncopyable_export)
|
|
||||||
{
|
|
||||||
python::module_builder this_module("noncopyable_export");
|
|
||||||
|
|
||||||
python::class_builder<store> store_class(this_module, "store");
|
|
||||||
python::export_converters_noncopyable(store_class);
|
|
||||||
|
|
||||||
store_class.def(python::constructor<int>());
|
|
||||||
store_class.def(&store::recall, "recall");
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
// See root/libs/python/doc/cross_module.html for an introduction.
|
|
||||||
|
|
||||||
#include <boost/python/cross_module.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
#include "noncopyable.h"
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A function with store objects as both input and output parameters.
|
|
||||||
// Because the copy constructor is disabled, we cannot pass a store
|
|
||||||
// object by value. Instead, we pass a smart pointer.
|
|
||||||
std::auto_ptr<store> add_stores(const store& s1, const store& s2)
|
|
||||||
{
|
|
||||||
int sum = s1.recall() + s2.recall();
|
|
||||||
std::auto_ptr<store> ss = std::auto_ptr<store>(new store(sum));
|
|
||||||
return ss;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef BOOST_MSVC // fixes for JIT debugging
|
|
||||||
# include <windows.h>
|
|
||||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
|
|
||||||
= _set_se_translator(structured_exception_translator);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(noncopyable_import)
|
|
||||||
{
|
|
||||||
python::module_builder this_module("noncopyable_import");
|
|
||||||
|
|
||||||
python::import_converters<store>
|
|
||||||
dvect_converters("noncopyable_export", "store");
|
|
||||||
|
|
||||||
// Imagine all the additional classes with member functions
|
|
||||||
// that have store objects as input and output parameters.
|
|
||||||
// Lots and lots of them.
|
|
||||||
// However, to keep this example simple, we only define a
|
|
||||||
// module-level function.
|
|
||||||
this_module.def(add_stores, "add_stores");
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
/*
|
|
||||||
This example shows how to make an Extension Class "pickleable".
|
|
||||||
|
|
||||||
The world class below can be fully restored by passing the
|
|
||||||
appropriate argument to the constructor. Therefore it is sufficient
|
|
||||||
to define the pickle interface method __getinitargs__.
|
|
||||||
|
|
||||||
For more information refer to boost/libs/python/doc/pickle.html.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A friendly class.
|
|
||||||
class world
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::string country;
|
|
||||||
int secret_number;
|
|
||||||
public:
|
|
||||||
world(const std::string& country) : secret_number(0) {
|
|
||||||
this->country = country;
|
|
||||||
}
|
|
||||||
std::string greet() const { return "Hello from " + country + "!"; }
|
|
||||||
std::string get_country() const { return country; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Support for pickle.
|
|
||||||
python::ref world_getinitargs(const world& w) {
|
|
||||||
python::tuple result(1);
|
|
||||||
result.set_item(0, w.get_country());
|
|
||||||
return result.reference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(pickle1)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("pickle1");
|
|
||||||
|
|
||||||
// Create the Python type object for our extension class.
|
|
||||||
python::class_builder<world> world_class(this_module, "world");
|
|
||||||
|
|
||||||
// Add the __init__ function.
|
|
||||||
world_class.def(python::constructor<std::string>());
|
|
||||||
// Add a regular member function.
|
|
||||||
world_class.def(&world::greet, "greet");
|
|
||||||
|
|
||||||
// Support for pickle.
|
|
||||||
world_class.def(world_getinitargs, "__getinitargs__");
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
/*
|
|
||||||
This example shows how to make an Extension Class "pickleable".
|
|
||||||
|
|
||||||
The world class below contains member data (secret_number) that
|
|
||||||
cannot be restored by any of the constructors. Therefore it is
|
|
||||||
necessary to provide the __getstate__/__setstate__ pair of pickle
|
|
||||||
interface methods.
|
|
||||||
|
|
||||||
For simplicity, the __dict__ is not included in the result of
|
|
||||||
__getstate__. This is not generally recommended, but a valid
|
|
||||||
approach if it is anticipated that the object's __dict__ will
|
|
||||||
always be empty. Note that safety guard are provided to catch the
|
|
||||||
cases where this assumption is not true.
|
|
||||||
|
|
||||||
pickle3.cpp shows how to include the object's __dict__ in the
|
|
||||||
result of __getstate__.
|
|
||||||
|
|
||||||
For more information refer to boost/libs/python/doc/pickle.html.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A friendly class.
|
|
||||||
class world
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
world(const std::string& country) : secret_number(0) {
|
|
||||||
this->country = country;
|
|
||||||
}
|
|
||||||
std::string greet() const { return "Hello from " + country + "!"; }
|
|
||||||
std::string get_country() const { return country; }
|
|
||||||
void set_secret_number(int number) { secret_number = number; }
|
|
||||||
int get_secret_number() const { return secret_number; }
|
|
||||||
private:
|
|
||||||
std::string country;
|
|
||||||
int secret_number;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Support for pickle.
|
|
||||||
|
|
||||||
using BOOST_PYTHON_CONVERSION::from_python;
|
|
||||||
|
|
||||||
python::ref world_getinitargs(const world& w) {
|
|
||||||
python::tuple result(1);
|
|
||||||
result.set_item(0, w.get_country());
|
|
||||||
return result.reference(); // returning the reference avoids the copying.
|
|
||||||
}
|
|
||||||
|
|
||||||
python::ref world_getstate(const world& w) {
|
|
||||||
python::tuple result(1);
|
|
||||||
result.set_item(0, w.get_secret_number());
|
|
||||||
return result.reference(); // returning the reference avoids the copying.
|
|
||||||
}
|
|
||||||
|
|
||||||
void world_setstate(world& w, python::tuple state) {
|
|
||||||
if (state.size() != 1) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"Unexpected argument in call to __setstate__.");
|
|
||||||
python::throw_error_already_set();
|
|
||||||
}
|
|
||||||
int number = from_python(state[0].get(), python::type<int>());
|
|
||||||
if (number != 42)
|
|
||||||
w.set_secret_number(number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(pickle2)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("pickle2");
|
|
||||||
|
|
||||||
// Create the Python type object for our extension class.
|
|
||||||
python::class_builder<world> world_class(this_module, "world");
|
|
||||||
|
|
||||||
// Add the __init__ function.
|
|
||||||
world_class.def(python::constructor<std::string>());
|
|
||||||
// Add a regular member function.
|
|
||||||
world_class.def(&world::greet, "greet");
|
|
||||||
world_class.def(&world::get_secret_number, "get_secret_number");
|
|
||||||
world_class.def(&world::set_secret_number, "set_secret_number");
|
|
||||||
|
|
||||||
// Support for pickle.
|
|
||||||
world_class.def(world_getinitargs, "__getinitargs__");
|
|
||||||
world_class.def(world_getstate, "__getstate__");
|
|
||||||
world_class.def(world_setstate, "__setstate__");
|
|
||||||
}
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
/*
|
|
||||||
This example shows how to make an Extension Class "pickleable".
|
|
||||||
|
|
||||||
The world class below contains member data (secret_number) that
|
|
||||||
cannot be restored by any of the constructors. Therefore it is
|
|
||||||
necessary to provide the __getstate__/__setstate__ pair of pickle
|
|
||||||
interface methods.
|
|
||||||
|
|
||||||
The object's __dict__ is included in the result of __getstate__.
|
|
||||||
This requires more code (compare with pickle2.cpp), but is
|
|
||||||
unavoidable if the object's __dict__ is not always empty.
|
|
||||||
|
|
||||||
For more information refer to boost/libs/python/doc/pickle.html.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
namespace boost { namespace python {
|
|
||||||
|
|
||||||
ref getattr(PyObject* o, const std::string& attr_name) {
|
|
||||||
return ref(PyObject_GetAttrString(o, const_cast<char*>(attr_name.c_str())));
|
|
||||||
}
|
|
||||||
ref getattr(const ref& r, const std::string& attr_name) {
|
|
||||||
return getattr(r.get(), attr_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A friendly class.
|
|
||||||
class world
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
world(const std::string& country) : secret_number(0) {
|
|
||||||
this->country = country;
|
|
||||||
}
|
|
||||||
std::string greet() const { return "Hello from " + country + "!"; }
|
|
||||||
std::string get_country() const { return country; }
|
|
||||||
void set_secret_number(int number) { secret_number = number; }
|
|
||||||
int get_secret_number() const { return secret_number; }
|
|
||||||
private:
|
|
||||||
std::string country;
|
|
||||||
int secret_number;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Support for pickle.
|
|
||||||
python::ref world_getinitargs(const world& w) {
|
|
||||||
python::tuple result(1);
|
|
||||||
result.set_item(0, w.get_country());
|
|
||||||
return result.reference(); // returning the reference avoids the copying.
|
|
||||||
}
|
|
||||||
|
|
||||||
python::ref world_getstate(python::tuple const & args,
|
|
||||||
python::dictionary const & keywords);
|
|
||||||
|
|
||||||
PyObject* world_setstate(python::tuple const & args,
|
|
||||||
python::dictionary const & keywords);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(pickle3)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("pickle3");
|
|
||||||
|
|
||||||
// Create the Python type object for our extension class.
|
|
||||||
python::class_builder<world> world_class(this_module, "world");
|
|
||||||
|
|
||||||
// Add the __init__ function.
|
|
||||||
world_class.def(python::constructor<std::string>());
|
|
||||||
// Add a regular member function.
|
|
||||||
world_class.def(&world::greet, "greet");
|
|
||||||
world_class.def(&world::get_secret_number, "get_secret_number");
|
|
||||||
world_class.def(&world::set_secret_number, "set_secret_number");
|
|
||||||
|
|
||||||
// Support for pickle.
|
|
||||||
world_class.def(world_getinitargs, "__getinitargs__");
|
|
||||||
world_class.def_raw(world_getstate, "__getstate__");
|
|
||||||
world_class.def_raw(world_setstate, "__setstate__");
|
|
||||||
world_class.getstate_manages_dict();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using BOOST_PYTHON_CONVERSION::from_python;
|
|
||||||
using boost::python::type;
|
|
||||||
using boost::python::ref;
|
|
||||||
using boost::python::tuple;
|
|
||||||
using boost::python::list;
|
|
||||||
using boost::python::dictionary;
|
|
||||||
using boost::python::getattr;
|
|
||||||
|
|
||||||
ref world_getstate(tuple const & args, dictionary const & keywords)
|
|
||||||
{
|
|
||||||
if(args.size() != 1 || keywords.size() != 0) {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
|
|
||||||
boost::python::throw_error_already_set();
|
|
||||||
}
|
|
||||||
const world& w = from_python(args[0].get(), type<const world&>());
|
|
||||||
ref mydict = getattr(args[0], "__dict__");
|
|
||||||
tuple result(2);
|
|
||||||
// store the object's __dict__
|
|
||||||
result.set_item(0, mydict);
|
|
||||||
// store the internal state of the C++ object
|
|
||||||
result.set_item(1, w.get_secret_number());
|
|
||||||
return result.reference(); // returning the reference avoids the copying.
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject* world_setstate(tuple const & args, dictionary const & keywords)
|
|
||||||
{
|
|
||||||
if(args.size() != 2 || keywords.size() != 0) {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
|
|
||||||
boost::python::throw_error_already_set();
|
|
||||||
}
|
|
||||||
world& w = from_python(args[0].get(), type<world&>());
|
|
||||||
ref mydict = getattr(args[0], "__dict__");
|
|
||||||
tuple state = from_python(args[1].get(), type<tuple>());
|
|
||||||
if (state.size() != 2) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"Unexpected argument in call to __setstate__.");
|
|
||||||
python::throw_error_already_set();
|
|
||||||
}
|
|
||||||
// restore the object's __dict__
|
|
||||||
dictionary odict = from_python(mydict.get(), type<dictionary>());
|
|
||||||
const dictionary& pdict = from_python(state[0].get(), type<const dictionary&>());
|
|
||||||
list pkeys(pdict.keys());
|
|
||||||
for (int i = 0; i < pkeys.size(); i++) {
|
|
||||||
ref k(pkeys[i]);
|
|
||||||
//odict[k] = pdict[k]; // XXX memory leak!
|
|
||||||
odict[k] = pdict.get_item(k); // this does not leak.
|
|
||||||
}
|
|
||||||
// restore the internal state of the C++ object
|
|
||||||
int number = from_python(state[1].get(), type<int>());
|
|
||||||
if (number != 42)
|
|
||||||
w.set_secret_number(number);
|
|
||||||
return python::detail::none();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter
|
|
||||||
// This example shows how to use rich comparisons for a vector type.
|
|
||||||
// It also shows how to template the entire wrapping of a std::vector.
|
|
||||||
// See vector_wrapper.h.
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
#include "vector_wrapper.h"
|
|
||||||
|
|
||||||
namespace vects {
|
|
||||||
|
|
||||||
struct dvect : public std::vector<double>
|
|
||||||
{
|
|
||||||
dvect() : std::vector<double>() {}
|
|
||||||
dvect(size_t n) : std::vector<double>(n) {}
|
|
||||||
dvect(boost::python::tuple tuple) : std::vector<double>(tuple.size())
|
|
||||||
{
|
|
||||||
std::vector<double>::iterator v_it = begin();
|
|
||||||
for (std::size_t i = 0; i < tuple.size(); i++)
|
|
||||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
|
||||||
boost::python::type<double>());
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::python::tuple as_tuple() const
|
|
||||||
{
|
|
||||||
boost::python::tuple t(size());
|
|
||||||
for (std::size_t i = 0; i < size(); i++)
|
|
||||||
t.set_item(i,
|
|
||||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
# define DVECT_BINARY_OPERATORS(oper) \
|
|
||||||
friend std::vector<bool> \
|
|
||||||
operator##oper(const dvect& lhs, const dvect& rhs) \
|
|
||||||
{ \
|
|
||||||
if (lhs.size() != rhs.size()) { \
|
|
||||||
PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \
|
|
||||||
boost::python::throw_error_already_set(); \
|
|
||||||
} \
|
|
||||||
std::vector<bool> result(lhs.size()); \
|
|
||||||
for (std::size_t i=0; i<lhs.size(); i++) { \
|
|
||||||
result[i] = (lhs[i] ##oper rhs[i]); \
|
|
||||||
} \
|
|
||||||
return result; \
|
|
||||||
}
|
|
||||||
DVECT_BINARY_OPERATORS(<)
|
|
||||||
DVECT_BINARY_OPERATORS(<=)
|
|
||||||
DVECT_BINARY_OPERATORS(==)
|
|
||||||
DVECT_BINARY_OPERATORS(!=)
|
|
||||||
DVECT_BINARY_OPERATORS(>)
|
|
||||||
DVECT_BINARY_OPERATORS(>=)
|
|
||||||
# undef VECTOR_BINARY_OPERATORS
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace <anonymous>
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void init_module(boost::python::module_builder& this_module)
|
|
||||||
{
|
|
||||||
(void) example::wrap_vector(this_module, "vector_of_bool", bool());
|
|
||||||
|
|
||||||
boost::python::class_builder<vects::dvect> py_dvect(this_module, "dvect");
|
|
||||||
|
|
||||||
py_dvect.def(boost::python::constructor<boost::python::tuple>());
|
|
||||||
py_dvect.def(&vects::dvect::as_tuple, "as_tuple");
|
|
||||||
|
|
||||||
const long
|
|
||||||
comp_operators = ( boost::python::op_lt | boost::python::op_le
|
|
||||||
| boost::python::op_eq | boost::python::op_ne
|
|
||||||
| boost::python::op_gt | boost::python::op_ge);
|
|
||||||
py_dvect.def(boost::python::operators<comp_operators>());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace <anonymous>
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(richcmp1)
|
|
||||||
{
|
|
||||||
boost::python::module_builder this_module("richcmp1");
|
|
||||||
// The actual work is done in a separate function in order
|
|
||||||
// to suppress a bogus VC60 warning.
|
|
||||||
init_module(this_module);
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
// This example shows how to use rich comparisons for a type that
|
|
||||||
// does not support all six operators (<, <=, ==, !=, >, >=).
|
|
||||||
// To keep the example simple, we are using a "code" type does
|
|
||||||
// not really require rich comparisons. __cmp__ would be sufficient.
|
|
||||||
// However, with a more complicated type the main point of this
|
|
||||||
// example would be in danger of getting lost.
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// suppose operator< and operator> are not meaningful for code
|
|
||||||
class code {
|
|
||||||
public:
|
|
||||||
code(int c = 0) : m_code(c) {}
|
|
||||||
inline friend bool operator==(const code& lhs, const code& rhs) {
|
|
||||||
return lhs.m_code == rhs.m_code;
|
|
||||||
}
|
|
||||||
inline friend bool operator!=(const code& lhs, const code& rhs) {
|
|
||||||
return lhs.m_code != rhs.m_code;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
int m_code;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if PYTHON_API_VERSION >= 1010
|
|
||||||
boost::python::ref
|
|
||||||
NotImplemented(const code&, const code&) {
|
|
||||||
return
|
|
||||||
boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void init_module(boost::python::module_builder& this_module)
|
|
||||||
{
|
|
||||||
boost::python::class_builder<code> py_code(this_module, "code");
|
|
||||||
|
|
||||||
py_code.def(boost::python::constructor<>());
|
|
||||||
py_code.def(boost::python::constructor<int>());
|
|
||||||
py_code.def(boost::python::operators<( boost::python::op_eq
|
|
||||||
| boost::python::op_ne)>());
|
|
||||||
#if PYTHON_API_VERSION >= 1010
|
|
||||||
py_code.def(NotImplemented, "__lt__");
|
|
||||||
py_code.def(NotImplemented, "__le__");
|
|
||||||
py_code.def(NotImplemented, "__gt__");
|
|
||||||
py_code.def(NotImplemented, "__ge__");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace <anonymous>
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(richcmp2)
|
|
||||||
{
|
|
||||||
boost::python::module_builder this_module("richcmp2");
|
|
||||||
// The actual work is done in a separate function in order
|
|
||||||
// to suppress a bogus VC60 warning.
|
|
||||||
init_module(this_module);
|
|
||||||
}
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter.
|
|
||||||
// Comprehensive operator overloading for two vector types and scalars.
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
#include "vector_wrapper.h"
|
|
||||||
#include "dvect.h"
|
|
||||||
#include "ivect.h"
|
|
||||||
|
|
||||||
#define VECT_VECT_OPERATORS(result_type, vect_type1, oper, vect_type2) \
|
|
||||||
namespace vects { \
|
|
||||||
result_type \
|
|
||||||
operator##oper (const vect_type1& lhs, const vect_type2& rhs) { \
|
|
||||||
if (lhs.size() != rhs.size()) { \
|
|
||||||
PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \
|
|
||||||
boost::python::throw_error_already_set(); \
|
|
||||||
} \
|
|
||||||
result_type result(lhs.size()); \
|
|
||||||
for (std::size_t i=0; i<lhs.size(); i++) { \
|
|
||||||
result[i] = (lhs[i] ##oper rhs[i]); \
|
|
||||||
} \
|
|
||||||
return result; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VECT_SCALAR_OPERATORS(result_type, vect_type, oper, scalar_type) \
|
|
||||||
namespace vects { \
|
|
||||||
result_type \
|
|
||||||
operator##oper (const vect_type& lhs, const scalar_type& rhs) { \
|
|
||||||
result_type result(lhs.size()); \
|
|
||||||
for (std::size_t i=0; i<lhs.size(); i++) { \
|
|
||||||
result[i] = (lhs[i] ##oper rhs ); \
|
|
||||||
} \
|
|
||||||
return result; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SCALAR_VECT_OPERATORS(result_type, scalar_type, oper, vect_type) \
|
|
||||||
namespace vects { \
|
|
||||||
result_type \
|
|
||||||
operator##oper (const scalar_type& lhs, const vect_type& rhs) { \
|
|
||||||
result_type result(rhs.size()); \
|
|
||||||
for (std::size_t i=0; i<rhs.size(); i++) { \
|
|
||||||
result[i] = (lhs ##oper rhs[i]); \
|
|
||||||
} \
|
|
||||||
return result; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MATH_VECT_VECT_OPERATORS(result_type, vect_type1, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(result_type, vect_type1, +, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(result_type, vect_type1, -, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(result_type, vect_type1, *, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(result_type, vect_type1, /, vect_type2)
|
|
||||||
|
|
||||||
#define COMP_VECT_VECT_OPERATORS(vect_type1, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, <, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, <=, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, ==, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, !=, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, >, vect_type2) \
|
|
||||||
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, >=, vect_type2)
|
|
||||||
|
|
||||||
#define MATH_VECT_SCALAR_OPERATORS(result_type, vect_type, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(result_type, vect_type, +, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(result_type, vect_type, -, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(result_type, vect_type, *, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(result_type, vect_type, /, scalar_type)
|
|
||||||
|
|
||||||
#define COMP_VECT_SCALAR_OPERATORS(vect_type, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, <, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, <=, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, ==, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, !=, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, >, scalar_type) \
|
|
||||||
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, >=, scalar_type)
|
|
||||||
|
|
||||||
#define MATH_SCALAR_VECT_OPERATORS(result_type, scalar_type, vect_type) \
|
|
||||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, +, vect_type) \
|
|
||||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, -, vect_type) \
|
|
||||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, *, vect_type) \
|
|
||||||
SCALAR_VECT_OPERATORS(result_type, scalar_type, /, vect_type)
|
|
||||||
|
|
||||||
MATH_VECT_VECT_OPERATORS(dvect, dvect, dvect)
|
|
||||||
COMP_VECT_VECT_OPERATORS( dvect, dvect)
|
|
||||||
MATH_VECT_SCALAR_OPERATORS(dvect, dvect, double)
|
|
||||||
COMP_VECT_SCALAR_OPERATORS( dvect, double)
|
|
||||||
MATH_SCALAR_VECT_OPERATORS(dvect, double, dvect)
|
|
||||||
// comparison operators not needed since Python uses reflection
|
|
||||||
|
|
||||||
MATH_VECT_VECT_OPERATORS(ivect, ivect, ivect)
|
|
||||||
COMP_VECT_VECT_OPERATORS( ivect, ivect)
|
|
||||||
MATH_VECT_SCALAR_OPERATORS(ivect, ivect, int)
|
|
||||||
COMP_VECT_SCALAR_OPERATORS( ivect, int)
|
|
||||||
MATH_SCALAR_VECT_OPERATORS(ivect, int, ivect)
|
|
||||||
// comparison operators not needed since Python uses reflection
|
|
||||||
|
|
||||||
MATH_VECT_VECT_OPERATORS(dvect, dvect, ivect)
|
|
||||||
COMP_VECT_VECT_OPERATORS( dvect, ivect)
|
|
||||||
MATH_VECT_VECT_OPERATORS(dvect, ivect, dvect)
|
|
||||||
COMP_VECT_VECT_OPERATORS( ivect, dvect)
|
|
||||||
|
|
||||||
#undef VECT_VECT_OPERATORS
|
|
||||||
#undef SCALAR_VECT_OPERATORS
|
|
||||||
#undef VECT_SCALAR_OPERATORS
|
|
||||||
#undef MATH_VECT_VECT_OPERATORS
|
|
||||||
#undef COMP_VECT_VECT_OPERATORS
|
|
||||||
#undef MATH_VECT_SCALAR_OPERATORS
|
|
||||||
#undef COMP_VECT_SCALAR_OPERATORS
|
|
||||||
#undef MATH_SCALAR_VECT_OPERATORS
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void init_module(boost::python::module_builder& this_module)
|
|
||||||
{
|
|
||||||
(void) example::wrap_vector(this_module, "vector_of_bool", bool());
|
|
||||||
|
|
||||||
const long
|
|
||||||
math_operators ( boost::python::op_mul | boost::python::op_add
|
|
||||||
| boost::python::op_div | boost::python::op_sub);
|
|
||||||
const long
|
|
||||||
comp_operators = ( boost::python::op_lt | boost::python::op_le
|
|
||||||
| boost::python::op_eq | boost::python::op_ne
|
|
||||||
| boost::python::op_gt | boost::python::op_ge);
|
|
||||||
|
|
||||||
boost::python::class_builder<vects::dvect>
|
|
||||||
dvect_class(this_module, "dvect");
|
|
||||||
boost::python::class_builder<vects::ivect>
|
|
||||||
ivect_class(this_module, "ivect");
|
|
||||||
|
|
||||||
dvect_class.def(boost::python::constructor<boost::python::tuple>());
|
|
||||||
dvect_class.def(&vects::dvect::as_tuple,"as_tuple");
|
|
||||||
|
|
||||||
dvect_class.def(boost::python::operators<math_operators>());
|
|
||||||
dvect_class.def(boost::python::operators<math_operators>(),
|
|
||||||
boost::python::right_operand<double>() );
|
|
||||||
dvect_class.def(boost::python::operators<math_operators>(),
|
|
||||||
boost::python::left_operand<double>() );
|
|
||||||
dvect_class.def(boost::python::operators<math_operators>(),
|
|
||||||
boost::python::right_operand<vects::ivect>() );
|
|
||||||
|
|
||||||
dvect_class.def(boost::python::operators<comp_operators>());
|
|
||||||
dvect_class.def(boost::python::operators<comp_operators>(),
|
|
||||||
boost::python::right_operand<double>() );
|
|
||||||
// left_operand not needed since Python uses reflection
|
|
||||||
dvect_class.def(boost::python::operators<comp_operators>(),
|
|
||||||
boost::python::right_operand<vects::ivect>() );
|
|
||||||
|
|
||||||
ivect_class.def(boost::python::constructor<boost::python::tuple>());
|
|
||||||
ivect_class.def(&vects::ivect::as_tuple,"as_tuple");
|
|
||||||
|
|
||||||
ivect_class.def(boost::python::operators<math_operators>());
|
|
||||||
ivect_class.def(boost::python::operators<math_operators>(),
|
|
||||||
boost::python::right_operand<int>() );
|
|
||||||
ivect_class.def(boost::python::operators<math_operators>(),
|
|
||||||
boost::python::left_operand<int>() );
|
|
||||||
ivect_class.def(boost::python::operators<math_operators>(),
|
|
||||||
boost::python::right_operand<vects::dvect>() );
|
|
||||||
|
|
||||||
ivect_class.def(boost::python::operators<comp_operators>());
|
|
||||||
ivect_class.def(boost::python::operators<comp_operators>(),
|
|
||||||
boost::python::right_operand<int>() );
|
|
||||||
// left_operand not needed since Python uses reflection
|
|
||||||
ivect_class.def(boost::python::operators<comp_operators>(),
|
|
||||||
boost::python::right_operand<vects::dvect>() );
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace <anonymous>
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(richcmp3)
|
|
||||||
{
|
|
||||||
boost::python::module_builder this_module("richcmp3");
|
|
||||||
// The actual work is done in a separate function in order
|
|
||||||
// to suppress a bogus VC60 warning.
|
|
||||||
init_module(this_module);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#include <string>
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A couple of simple C++ functions that we want to expose to Python.
|
|
||||||
std::string greet() { return "hello, world"; }
|
|
||||||
int square(int number) { return number * number; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
// Python requires an exported function called init<module-name> in every
|
|
||||||
// extension module. This is where we build the module contents.
|
|
||||||
BOOST_PYTHON_MODULE_INIT(rwgk1)
|
|
||||||
{
|
|
||||||
// Create an object representing this extension module.
|
|
||||||
python::module_builder this_module("rwgk1");
|
|
||||||
|
|
||||||
// Add regular functions to the module.
|
|
||||||
this_module.def(greet, "greet");
|
|
||||||
this_module.def(square, "square");
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
// Example by Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
#include <boost/python/class_builder.hpp>
|
|
||||||
namespace python = boost::python;
|
|
||||||
|
|
||||||
namespace { // Avoid cluttering the global namespace.
|
|
||||||
|
|
||||||
// A wrapper is used to define additional constructors.
|
|
||||||
//
|
|
||||||
struct vector_double_wrapper: std::vector<double>
|
|
||||||
{
|
|
||||||
// Tell the compiler how to convert a base class object to
|
|
||||||
// this wrapper object.
|
|
||||||
vector_double_wrapper(PyObject*, const std::vector<double>& vd)
|
|
||||||
: std::vector<double>(vd) {}
|
|
||||||
|
|
||||||
vector_double_wrapper(PyObject* self)
|
|
||||||
: std::vector<double>() {}
|
|
||||||
|
|
||||||
vector_double_wrapper(PyObject* self, int n)
|
|
||||||
: std::vector<double>(n) {}
|
|
||||||
|
|
||||||
vector_double_wrapper(PyObject* self, python::tuple tuple)
|
|
||||||
: std::vector<double>(tuple.size())
|
|
||||||
{
|
|
||||||
std::vector<double>::iterator vd = begin();
|
|
||||||
for (int i = 0; i < tuple.size(); i++)
|
|
||||||
vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
|
||||||
python::type<double>());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void raise_vector_IndexError() {
|
|
||||||
PyErr_SetString(PyExc_IndexError, "vector index out of range");
|
|
||||||
python::throw_error_already_set();
|
|
||||||
}
|
|
||||||
|
|
||||||
double getitem(const std::vector<double>& vd, std::size_t key) {
|
|
||||||
if (key >= vd.size()) raise_vector_IndexError();
|
|
||||||
return vd[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
void setitem(std::vector<double>& vd, std::size_t key, double d) {
|
|
||||||
if (key >= vd.size()) raise_vector_IndexError();
|
|
||||||
std::vector<double>::iterator vditer = vd.begin();
|
|
||||||
vditer[key] = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delitem(std::vector<double>& vd, std::size_t key) {
|
|
||||||
if (key >= vd.size()) raise_vector_IndexError();
|
|
||||||
std::vector<double>::iterator vditer = vd.begin();
|
|
||||||
vd.erase(vditer + key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert vector_double to a regular Python tuple.
|
|
||||||
//
|
|
||||||
python::tuple as_tuple(const std::vector<double>& vd)
|
|
||||||
{
|
|
||||||
python::tuple t(vd.size());
|
|
||||||
for (int i = 0; i < vd.size(); i++) t.set_item(i,
|
|
||||||
python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i])));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function returning a vector_double object to Python.
|
|
||||||
//
|
|
||||||
std::vector<double> foo(int n)
|
|
||||||
{
|
|
||||||
std::vector<double> vd(n);
|
|
||||||
std::vector<double>::iterator vditer = vd.begin();
|
|
||||||
for (int i = 0; i < n; i++) vditer[i] = double(i);
|
|
||||||
return vd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same as foo(), but avoid copying on return.
|
|
||||||
//
|
|
||||||
std::auto_ptr<std::vector<double> > bar(int n)
|
|
||||||
{
|
|
||||||
std::auto_ptr<std::vector<double> > vdptr(new std::vector<double>(n));
|
|
||||||
std::vector<double>::iterator vditer = vdptr->begin();
|
|
||||||
for (int i = 0; i < n; i++) vditer[i] = double(10 * i);
|
|
||||||
return vdptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE_INIT(simple_vector)
|
|
||||||
{
|
|
||||||
python::module_builder this_module("simple_vector");
|
|
||||||
|
|
||||||
python::class_builder<std::vector<double>, vector_double_wrapper>
|
|
||||||
vector_double(this_module, "vector_double");
|
|
||||||
|
|
||||||
vector_double.def(python::constructor<int>());
|
|
||||||
vector_double.def(python::constructor<>());
|
|
||||||
vector_double.def(python::constructor<python::tuple>());
|
|
||||||
vector_double.def(&std::vector<double>::size, "__len__");
|
|
||||||
vector_double.def(getitem, "__getitem__");
|
|
||||||
vector_double.def(setitem, "__setitem__");
|
|
||||||
vector_double.def(delitem, "__delitem__");
|
|
||||||
vector_double.def(as_tuple, "as_tuple");
|
|
||||||
|
|
||||||
this_module.def(foo, "foo");
|
|
||||||
this_module.def(bar, "bar");
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Example by Ullrich Koethe
|
|
||||||
r'''>>> from abstract import *
|
|
||||||
>>> class A(Abstract):
|
|
||||||
... def __init__(self, text):
|
|
||||||
... Abstract.__init__(self) # call the base class constructor
|
|
||||||
... self.text = text
|
|
||||||
... def test(self): # implement abstract function
|
|
||||||
... return self.text
|
|
||||||
...
|
|
||||||
>>> a = A("Hello")
|
|
||||||
>>> a.test()
|
|
||||||
'Hello'
|
|
||||||
'''
|
|
||||||
|
|
||||||
def run(args = None):
|
|
||||||
if args is not None:
|
|
||||||
import sys
|
|
||||||
sys.argv = args
|
|
||||||
import doctest, test_abstract
|
|
||||||
return doctest.testmod(test_abstract)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
sys.exit(run()[0])
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
r'''>>> import tst_noncopyable
|
|
||||||
>>> tst_noncopyable.f()
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
>>> import tst_dvect1
|
|
||||||
>>> tst_dvect1.f()
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
>>> import tst_ivect1
|
|
||||||
>>> tst_ivect1.f()
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
>>> import sys
|
|
||||||
>>> if ("--broken-auto-ptr" in sys.argv):
|
|
||||||
... broken_auto_ptr = 1
|
|
||||||
... else:
|
|
||||||
... broken_auto_ptr = 0
|
|
||||||
>>> import tst_dvect2
|
|
||||||
>>> tst_dvect2.f(broken_auto_ptr)
|
|
||||||
1. auto_ptr_value_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. auto_ptr_value_ivect_as_tuple
|
|
||||||
None
|
|
||||||
1. auto_ptr_value_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. auto_ptr_value_dvect_as_tuple
|
|
||||||
None
|
|
||||||
1. shared_ptr_value_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. shared_ptr_value_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. shared_ptr_value_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. shared_ptr_value_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. auto_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. auto_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. auto_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. auto_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. shared_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. shared_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. shared_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. shared_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. auto_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. auto_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. auto_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. auto_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. shared_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. shared_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. shared_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. shared_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
>>> import tst_ivect2
|
|
||||||
>>> tst_ivect2.f(broken_auto_ptr)
|
|
||||||
1. auto_ptr_value_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. auto_ptr_value_dvect_as_tuple
|
|
||||||
None
|
|
||||||
1. auto_ptr_value_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. auto_ptr_value_ivect_as_tuple
|
|
||||||
None
|
|
||||||
1. shared_ptr_value_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. shared_ptr_value_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. shared_ptr_value_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. shared_ptr_value_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. auto_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. auto_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. auto_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. auto_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. shared_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. shared_ptr_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. shared_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. shared_ptr_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. auto_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. auto_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. auto_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. auto_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
1. shared_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
2. shared_ptr_const_reference_dvect_as_tuple
|
|
||||||
(1.0, 2.0, 3.0, 4.0, 5.0)
|
|
||||||
1. shared_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
2. shared_ptr_const_reference_ivect_as_tuple
|
|
||||||
(1, 2, 3, 4, 5)
|
|
||||||
'''
|
|
||||||
|
|
||||||
def run(args = None):
|
|
||||||
if args is not None:
|
|
||||||
import sys
|
|
||||||
sys.argv = args
|
|
||||||
import doctest, test_cross_module
|
|
||||||
return doctest.testmod(test_cross_module)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
sys.exit(run()[0])
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
r'''>>> import do_it_yourself_convts
|
|
||||||
>>> ixset = do_it_yourself_convts.IndexingSet()
|
|
||||||
>>> ixset.add((1,2,3))
|
|
||||||
>>> ixset.add((4,5,6))
|
|
||||||
>>> ixset.add((7,8,9))
|
|
||||||
>>> print ixset.get(0)
|
|
||||||
(1, 2, 3)
|
|
||||||
>>> print ixset.get(1)
|
|
||||||
(4, 5, 6)
|
|
||||||
>>> print ixset.get(2)
|
|
||||||
(7, 8, 9)
|
|
||||||
'''
|
|
||||||
|
|
||||||
def run(args = None):
|
|
||||||
if args is not None:
|
|
||||||
import sys
|
|
||||||
sys.argv = args
|
|
||||||
import doctest, test_do_it_yourself_convts
|
|
||||||
return doctest.testmod(test_do_it_yourself_convts)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
sys.exit(run()[0])
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
r'''
|
|
||||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
|
||||||
// distribute this software is granted provided this copyright notice appears
|
|
||||||
// in all copies. This software is provided "as is" without express or implied
|
|
||||||
// warranty, and with no claim as to its suitability for any purpose.
|
|
||||||
//
|
|
||||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
|
||||||
// producing this work.
|
|
||||||
|
|
||||||
That's it! If we build this shared library and put it on our PYTHONPATH we can
|
|
||||||
now access our C++ class and function from Python.
|
|
||||||
|
|
||||||
>>> import hello
|
|
||||||
>>> hi_world = hello.world(3)
|
|
||||||
>>> hi_world.get()
|
|
||||||
'hi, world'
|
|
||||||
>>> hello.length(hi_world)
|
|
||||||
9
|
|
||||||
|
|
||||||
We can even make a subclass of hello.world:
|
|
||||||
|
|
||||||
|
|
||||||
>>> class my_subclass(hello.world):
|
|
||||||
... def get(self):
|
|
||||||
... return 'hello, world'
|
|
||||||
...
|
|
||||||
>>> y = my_subclass(2)
|
|
||||||
>>> y.get()
|
|
||||||
'hello, world'
|
|
||||||
|
|
||||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
|
||||||
|
|
||||||
>>> hello.length(y)
|
|
||||||
9
|
|
||||||
|
|
||||||
Of course, you may now have a slightly empty feeling in the pit of your little
|
|
||||||
pythonic stomach. Perhaps you feel your subclass deserves to have a length() of
|
|
||||||
12? If so, read on...
|
|
||||||
'''
|
|
||||||
from hello import *
|
|
||||||
|
|
||||||
def run(args = None):
|
|
||||||
if args is not None:
|
|
||||||
import sys
|
|
||||||
sys.argv = args
|
|
||||||
import doctest, test_example1
|
|
||||||
return doctest.testmod(test_example1)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
sys.exit(run()[0])
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user