mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 06:02:14 +00:00
Compare commits
95 Commits
svn-tags/d
...
boost-1.34
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87451007b9 | ||
|
|
6c1e7decfa | ||
|
|
2851325748 | ||
|
|
bd606e5017 | ||
|
|
a5706ec3b0 | ||
|
|
a346c577cf | ||
|
|
217e4ca8f8 | ||
|
|
f2f47f85c0 | ||
|
|
b130c93af6 | ||
|
|
13432b504f | ||
|
|
0739bb7df8 | ||
|
|
c253c5cc9c | ||
|
|
8f263e1fdb | ||
|
|
a6125a3632 | ||
|
|
a784bfc0f8 | ||
|
|
b8937d0bae | ||
|
|
4827ae73d5 | ||
|
|
8eddc7aa37 | ||
|
|
98a468dadc | ||
|
|
ea4e6c0a4c | ||
|
|
7cd7f6d8ee | ||
|
|
4c39e8c990 | ||
|
|
6c6f654fbe | ||
|
|
b7eaea096e | ||
|
|
904ae8604c | ||
|
|
44d53c448b | ||
|
|
e61401d27e | ||
|
|
be7ca7d269 | ||
|
|
47b4b4efbb | ||
|
|
4fa07f2b3d | ||
|
|
c880e7d69d | ||
|
|
c73ad50286 | ||
|
|
0910710ac4 | ||
|
|
04c528138b | ||
|
|
1b66cd9643 | ||
|
|
c2dd9fa833 | ||
|
|
b085121369 | ||
|
|
fa219bce9b | ||
|
|
10b85d67e7 | ||
|
|
ca91dc828e | ||
|
|
3a53c1dec0 | ||
|
|
da8e309957 | ||
|
|
2bd9141d4a | ||
|
|
c3bda6a903 | ||
|
|
d61909d3ea | ||
|
|
1755dad7e6 | ||
|
|
3b392c99be | ||
|
|
24ba93607b | ||
|
|
49d4aac8ec | ||
|
|
545be29ad3 | ||
|
|
8553c109c7 | ||
|
|
315c3d50ee | ||
|
|
d5219979a4 | ||
|
|
d42054f3a0 | ||
|
|
72b06e70ee | ||
|
|
375cc3aa93 | ||
|
|
4eb286a034 | ||
|
|
a824230155 | ||
|
|
1bc3750ab3 | ||
|
|
36abcee847 | ||
|
|
b8b7768eb7 | ||
|
|
7ad9dc6c64 | ||
|
|
decc34551a | ||
|
|
5acb44ede0 | ||
|
|
ef62f87963 | ||
|
|
b5c893381f | ||
|
|
815969bf8b | ||
|
|
0d57e9e808 | ||
|
|
7ba6a00617 | ||
|
|
e70bbe4791 | ||
|
|
7ff0f62729 | ||
|
|
95f0b39c90 | ||
|
|
23057688f9 | ||
|
|
029618f719 | ||
|
|
38f7a4e9b6 | ||
|
|
326c871224 | ||
|
|
924eeccd53 | ||
|
|
4a63cf4843 | ||
|
|
1d65b74273 | ||
|
|
3c1ae689a7 | ||
|
|
a99bd50e52 | ||
|
|
8b178594ff | ||
|
|
786aeef998 | ||
|
|
45e4cf506f | ||
|
|
8fb6e1f48d | ||
|
|
ecf70b05f2 | ||
|
|
c54acdb9db | ||
|
|
489dae2b58 | ||
|
|
f852ce6f7b | ||
|
|
e500919d25 | ||
|
|
7a645a6d8a | ||
|
|
fa2185e5ab | ||
|
|
5cc33461dd | ||
|
|
7b93f2fdc5 | ||
|
|
219743964d |
Binary file not shown.
@@ -1,98 +0,0 @@
|
||||
# Copyright David Abrahams 2001-2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Boost.Python library Jamfile
|
||||
|
||||
|
||||
# declare the location of this subproject relative to the root
|
||||
subproject libs/python/build ;
|
||||
|
||||
# bring in the rules for python
|
||||
import python ;
|
||||
|
||||
if [ check-python-config ]
|
||||
{
|
||||
|
||||
local bpl-linkflags ;
|
||||
|
||||
if $(UNIX) && ( $(OS) = AIX )
|
||||
{
|
||||
bpl-linkflags = <linkflags>"-e initlibboost_python" ;
|
||||
}
|
||||
|
||||
# Enabling intrinsics (/0i) or maximize speed (/02) seem to cause
|
||||
# internal compiler errors with this toolset.
|
||||
local msvc-stlport-workarounds
|
||||
= <optimization>off "<cxxflags>-Ogty -O1 -Gs" ;
|
||||
|
||||
local sources =
|
||||
numeric.cpp
|
||||
list.cpp
|
||||
long.cpp
|
||||
dict.cpp
|
||||
tuple.cpp
|
||||
str.cpp
|
||||
slice.cpp
|
||||
|
||||
aix_init_module.cpp
|
||||
converter/from_python.cpp
|
||||
converter/registry.cpp
|
||||
converter/type_id.cpp
|
||||
object/enum.cpp
|
||||
object/class.cpp
|
||||
object/function.cpp
|
||||
object/inheritance.cpp
|
||||
object/life_support.cpp
|
||||
object/pickle_support.cpp
|
||||
errors.cpp
|
||||
module.cpp
|
||||
converter/builtin_converters.cpp
|
||||
converter/arg_to_python_base.cpp
|
||||
object/iterator.cpp
|
||||
object/stl_iterator.cpp
|
||||
object_protocol.cpp
|
||||
object_operators.cpp
|
||||
wrapper.cpp
|
||||
exec.cpp
|
||||
import.cpp
|
||||
;
|
||||
|
||||
dll boost_python
|
||||
: ../src/$(sources)
|
||||
: $(BOOST_PYTHON_V2_PROPERTIES)
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
$(bpl-linkflags)
|
||||
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
||||
<darwin><*><linkflags>-bind_at_load
|
||||
<gcc-3_3-darwin><*><linkflags>-bind_at_load
|
||||
;
|
||||
|
||||
template extension
|
||||
: <dll>boost_python
|
||||
: <sysinclude>../../..
|
||||
;
|
||||
|
||||
lib boost_python
|
||||
: # sources
|
||||
../src/$(sources)
|
||||
|
||||
: # requirements
|
||||
$(BOOST_PYTHON_V2_PROPERTIES)
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
<define>BOOST_STATIC_LIB
|
||||
$(bpl-linkflags)
|
||||
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
||||
;
|
||||
|
||||
stage bin-stage : <dll>boost_python <lib>boost_python
|
||||
: <tag><debug>"_debug"
|
||||
<tag><debug-python>"_pydebug"
|
||||
:
|
||||
debug release
|
||||
;
|
||||
|
||||
install python lib
|
||||
: <dll>boost_python <lib>boost_python
|
||||
;
|
||||
}
|
||||
@@ -7,26 +7,25 @@ import modules ;
|
||||
|
||||
import python ;
|
||||
|
||||
if [ python.configured ] {
|
||||
if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] )
|
||||
{
|
||||
# Attempt default configuration of python
|
||||
import toolset : using ;
|
||||
using python ;
|
||||
|
||||
if ! [ python.configured ]
|
||||
{
|
||||
ECHO "WARNING: No python installation configured and autoconfiguration" ;
|
||||
ECHO " failed. See http://www.boost.org/libs/python/doc/building.html" ;
|
||||
ECHO " for configuration instructions or pass --without-python to" ;
|
||||
ECHO " suppress this message and silently skip all Boost.Python targets" ;
|
||||
}
|
||||
}
|
||||
|
||||
if [ python.configured ] {
|
||||
|
||||
project boost/python
|
||||
: source-location ../src
|
||||
: requirements
|
||||
#<include>$(PYTHON_PATH)/include
|
||||
# $(lib_condition)<library-path>$(PYTHON_PATH)/libs
|
||||
# <link>shared:<library>$(PYTHON_LIB)
|
||||
# <define>$(defines)
|
||||
#: usage-requirements # requirement that will be propageted to *users* of this library
|
||||
# <include>$(PYTHON_PATH)/include
|
||||
|
||||
# We have a bug which causes us to conclude that conditionalized
|
||||
# properties in this section are not free.
|
||||
# $(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||
# <shared>true:<find-library>$(PYTHON_LIB)
|
||||
|
||||
# <library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||
# <library>$(PYTHON_LIB)
|
||||
;
|
||||
|
||||
lib boost_python
|
||||
@@ -39,7 +38,6 @@ lib boost_python
|
||||
str.cpp
|
||||
slice.cpp
|
||||
|
||||
aix_init_module.cpp
|
||||
converter/from_python.cpp
|
||||
converter/registry.cpp
|
||||
converter/type_id.cpp
|
||||
@@ -63,21 +61,28 @@ lib boost_python
|
||||
: # requirements
|
||||
<link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
# On Linux, we don't link to Python library itself. If
|
||||
# Boost.Python is used for extension, all Python
|
||||
# symbols are available in Python interpreter.
|
||||
# If Boost.Python is used for extending, client
|
||||
# is required to link to /python//python itself.
|
||||
# On Windows, all code using Python has to link
|
||||
# to python import library. The 'python_for_extension'
|
||||
# is the target that's setup to provide either just
|
||||
# include paths, or import library.
|
||||
|
||||
# On Windows, all code using Python has to link to the Python
|
||||
# import library.
|
||||
#
|
||||
# On *nix we never link libboost_python to libpython. When
|
||||
# extending Python, all Python symbols are provided by the
|
||||
# Python interpreter executable. When embedding Python, the
|
||||
# client executable is expected to explicitly link to
|
||||
# /python//python (the target representing libpython) itself.
|
||||
#
|
||||
# python_for_extensions is a target defined by Boost.Build to
|
||||
# provide the Python include paths, and on Windows, the Python
|
||||
# import library, as usage requirements.
|
||||
<library>/python//python_for_extensions
|
||||
|
||||
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
|
||||
|
||||
: # default build
|
||||
<link>shared
|
||||
: # usage requirements
|
||||
<link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<link>shared:<define>BOOST_PYTHON_DYNAMIC_LIB
|
||||
<link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
|
||||
;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -95,10 +95,6 @@ LINK32=link.exe
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\aix_init_module.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\converter\arg_to_python_base.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -214,10 +210,6 @@ SOURCE=..\..\src\exec.cpp
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\aix_init_module.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\boost\python\detail\api_placeholder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
23
doc/Jamfile
Normal file
23
doc/Jamfile
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright David Abrahams 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
import docutils ;
|
||||
|
||||
import path ;
|
||||
sources = building.rst ;
|
||||
bases = $(sources:S=) ;
|
||||
|
||||
# This is a path relative to the html/ subdirectory where the
|
||||
# generated output will eventually be moved.
|
||||
stylesheet = "--stylesheet=../../../rst.css" ;
|
||||
|
||||
for local b in $(bases)
|
||||
{
|
||||
html $(b) : $(b).rst :
|
||||
|
||||
<docutils-html>"-gdt --source-url="./$(b).rst" --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript "$(stylesheet)
|
||||
;
|
||||
}
|
||||
|
||||
alias htmls : $(bases) ;
|
||||
stage . : $(bases) ;
|
||||
@@ -5,6 +5,8 @@
|
||||
:version: $Revision$
|
||||
:copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
boostinspect:nolicense
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/* Copyright David Abrahams 2006. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
H1
|
||||
{
|
||||
FONT-SIZE: 200%
|
||||
|
||||
1071
doc/building.html
1071
doc/building.html
File diff suppressed because it is too large
Load Diff
681
doc/building.rst
Normal file
681
doc/building.rst
Normal file
@@ -0,0 +1,681 @@
|
||||
.. Copyright David Abrahams 2006. Distributed under the Boost
|
||||
.. Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at
|
||||
.. http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
==============================================
|
||||
|(logo)|__ Boost.Python Build and Test HOWTO
|
||||
==============================================
|
||||
|
||||
.. |(logo)| image:: ../../../boost.png
|
||||
:alt: Boost C++ Libraries:
|
||||
:class: boost-logo
|
||||
|
||||
__ ../index.htm
|
||||
|
||||
|
||||
.. section-numbering::
|
||||
:depth: 2
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:class: sidebar small
|
||||
|
||||
.. |newer| replace:: *newer*
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
Boost.Python requires `Python 2.2`_ [#2.2]_ *or* |newer|__.
|
||||
|
||||
.. _Python 2.2: http://www.python.org/2.2
|
||||
__ http://www.python.org
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
There are two basic models for combining C++ and Python:
|
||||
|
||||
- extending_, in which the end-user launches the Python interpreter
|
||||
executable and imports Python “extension modules” written in C++.
|
||||
Think of taking a library written in C++ and giving it a Python
|
||||
interface so Python programmers can use it. From Python, these
|
||||
modules look just like regular Python modules.
|
||||
|
||||
- embedding_, in which the end-user launches a program written
|
||||
in C++ that in turn invokes the Python interpreter as a library
|
||||
subroutine. Think of adding scriptability to an existing
|
||||
application.
|
||||
|
||||
.. _extending: http://www.python.org/doc/current/ext/intro.html
|
||||
.. _embedding: http://www.python.org/doc/current/ext/embedding.html
|
||||
|
||||
The key distinction between extending and embedding is the location
|
||||
of the C++ ``main()`` function: in the Python interpreter executable,
|
||||
or in some other program, respectively. Note that even when
|
||||
embedding Python in another program, `extension modules are often
|
||||
the best way to make C/C++ functionality accessible to Python
|
||||
code`__, so the use of extension modules is really at the heart of
|
||||
both models.
|
||||
|
||||
__ http://www.python.org/doc/current/ext/extending-with-embedding.html
|
||||
|
||||
Except in rare cases, extension modules are built as
|
||||
dynamically-loaded libraries with a single entry point, which means
|
||||
you can change them without rebuilding either the other extension
|
||||
modules or the executable containing ``main()``.
|
||||
|
||||
.. _quickstart:
|
||||
|
||||
No-Install Quickstart
|
||||
=====================
|
||||
|
||||
There is no need to “install Boost” in order to get started using
|
||||
Boost.Python. These instructions use Boost.Build_ projects,
|
||||
which will build those binaries as soon as they're needed. Your
|
||||
first tests may take a little longer while you wait for
|
||||
Boost.Python to build, but doing things this way will save you from
|
||||
worrying about build intricacies like which library binaries to use
|
||||
for a specific compiler configuration and figuring out the right
|
||||
compiler options to use yourself.
|
||||
|
||||
.. .. raw:: html
|
||||
|
||||
<div style="width:50%">
|
||||
|
||||
.. Note:: Of course it's possible to use other build systems to
|
||||
build Boost.Python and its extensions, but they are not
|
||||
officially supported by Boost. Moreover **99% of all “I can't
|
||||
build Boost.Python” problems come from trying to use another
|
||||
build system** without first following these instructions.
|
||||
|
||||
If you want to use another system anyway, we suggest that you
|
||||
follow these instructions, and then invoke ``bjam`` with the
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
``-a -o``\ *filename*
|
||||
|
||||
options to dump the build commands it executes to a file, so
|
||||
you can see what your alternate build system needs to do.
|
||||
|
||||
.. .. raw:: html
|
||||
|
||||
</div>
|
||||
|
||||
.. _Boost.Build: ../../../tools/build/index.html
|
||||
|
||||
Basic Procedure
|
||||
---------------
|
||||
|
||||
1. Get Boost; see sections 1 and 2 [`Unix/Linux`__, `Windows`__\ ] of the
|
||||
Boost `Getting Started Guide`_.
|
||||
|
||||
__ ../../../more/getting_started/unix-variants.html#get-boost
|
||||
__ ../../../more/getting_started/windows.html#get-boost
|
||||
|
||||
2. Get the ``bjam`` build driver. See section 5 [`Unix/Linux`__,
|
||||
`Windows`__\ ] of the Boost `Getting Started Guide`_.
|
||||
|
||||
__ ../../../more/getting_started/unix-variants.html#prepare-to-use-a-boost-library-binary
|
||||
__ ../../../more/getting_started/windows.html#prepare-to-use-a-boost-library-binary
|
||||
|
||||
|
||||
3. cd into the ``libs/python/example/quickstart/`` directory of your
|
||||
Boost installation, which contains a small example project.
|
||||
|
||||
4. Invoke ``bjam``. Replace the “\ ``stage``\ “ argument from the
|
||||
example invocation from section 5 of the `Getting Started
|
||||
Guide`_ with “\ ``test``\ ,“ to build all the test targets. Also add
|
||||
the argument “\ ``--verbose-test``\ ” to see the output generated by
|
||||
the tests when they are run.
|
||||
|
||||
On Windows, your ``bjam`` invocation might look something like:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
C:\\boost_1_34_0\\…\\quickstart> **bjam toolset=msvc --verbose-test test**
|
||||
|
||||
and on Unix variants, perhaps,
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
~/boost_1_34_0/…/quickstart$ **bjam toolset=gcc --verbose-test test**
|
||||
|
||||
.. Admonition:: Note to Windows Users
|
||||
|
||||
For the sake of concision, the rest of this guide will use
|
||||
unix-style forward slashes in pathnames instead of the
|
||||
backslashes with which you may be more familiar. The forward
|
||||
slashes should work everywhere except in `Command Prompt`_
|
||||
windows, where you should use backslashes.
|
||||
|
||||
.. _Command Prompt: ../../../more/getting_started/windows.html#command-prompt
|
||||
|
||||
If you followed this procedure successfully, you will have built an
|
||||
extension module called ``extending`` and tested it by running a
|
||||
Python script called ``test_extending.py``. You will also have
|
||||
built and run a simple application called ``embedding`` that embeds
|
||||
python.
|
||||
|
||||
.. _Getting Started Guide: ../../../more/getting_started/index.html
|
||||
|
||||
In Case of Trouble
|
||||
------------------
|
||||
|
||||
If you're seeing lots of compiler and/or linker error messages,
|
||||
it's probably because Boost.Build is having trouble finding your
|
||||
Python installation. You might want to pass the
|
||||
``--debug-configuration`` option to ``bjam`` the first few times
|
||||
you invoke it, to make sure that Boost.Build is correctly locating
|
||||
all the parts of your Python installation. If it isn't, consider
|
||||
`Configuring Boost.Build`_ as detailed below.
|
||||
|
||||
If you're still having trouble, Someone on one of the following
|
||||
mailing lists may be able to help:
|
||||
|
||||
* The `Boost.Build mailing list`__ for issues related to Boost.Build
|
||||
* The Python `C++ Sig`__ for issues specifically related to Boost.Python
|
||||
|
||||
__ ../../../more/mailing_lists.htm#jamboost
|
||||
__ ../../../more/mailing_lists.htm#cplussig
|
||||
|
||||
In Case Everything Seemed to Work
|
||||
---------------------------------
|
||||
|
||||
Rejoice! If you're new to Boost.Python, at this point it might be
|
||||
a good idea to ignore build issues for a while and concentrate on
|
||||
learning the library by going through the tutorial_ and perhaps
|
||||
some of the `reference documentation`_, trying out what you've
|
||||
learned about the API by modifying the quickstart project.
|
||||
|
||||
.. _reference documentation: v2/reference.html
|
||||
.. _tutorial: tutorial/index.html
|
||||
|
||||
Modifying the Example Project
|
||||
-----------------------------
|
||||
|
||||
If you're content to keep your extension module forever in one
|
||||
source file called |extending.cpp|_, inside your Boost
|
||||
distribution, and import it forever as ``extending``, then you can
|
||||
stop here. However, it's likely that you will want to make a few
|
||||
changes. There are a few things you can do without having to learn
|
||||
Boost.Build_ in depth.
|
||||
|
||||
The project you just built is specified in two files in the current
|
||||
directory: |boost-build.jam|_, which tells ``bjam`` where it can
|
||||
find the interpreted code of the Boost build system, and
|
||||
|Jamroot|_, which describes the targets you just built. These
|
||||
files are heavily commented, so they should be easy to modify.
|
||||
Take care, however, to preserve whitespace. Punctuation such as
|
||||
``;`` will not be recognized as intended by ``bjam`` if it is not
|
||||
surrounded by whitespace.
|
||||
|
||||
.. |boost-build.jam| replace:: ``boost-build.jam``
|
||||
.. _boost-build.jam: ../example/quickstart/boost-build.jam
|
||||
|
||||
.. |Jamroot| replace:: ``Jamroot``
|
||||
.. _Jamroot: ../example/quickstart/Jamroot
|
||||
|
||||
.. |extending.cpp| replace:: ``extending.cpp``
|
||||
.. _extending.cpp: ../example/quickstart/extending.cpp
|
||||
|
||||
Relocate the Project
|
||||
....................
|
||||
|
||||
You'll probably want to copy this project elsewhere so you can
|
||||
change it without modifying your Boost distribution. To do that,
|
||||
simply
|
||||
|
||||
a. copy the entire ``libs/python/example/quickstart/`` directory
|
||||
into a new directory.
|
||||
|
||||
b. In the new copies of |boost-build.jam|_ and |Jamroot|_, locate
|
||||
the relative path near the top of the file that is clearly
|
||||
marked by a comment, and edit that path so that it refers to the
|
||||
same directory your Boost distribution as it referred to when
|
||||
the file was in its original location in the
|
||||
``libs/python/example/quickstart/`` directory.
|
||||
|
||||
For example, if you moved the project from
|
||||
``/home/dave/boost_1_34_0/libs/python/example/quickstart`` to
|
||||
``/home/dave/my-project``, you could change the first path in
|
||||
|boost-build.jam|_ from
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
**../../../..**\ /tools/build/v2
|
||||
|
||||
to
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
**/home/dave/boost_1_34_0**\ /tools/build/v2
|
||||
|
||||
and change the first path in |Jamroot|_ from
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
**../../../..**
|
||||
|
||||
to
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
**/home/dave/boost_1_34_0**
|
||||
|
||||
Add New or Change Names of Existing Source Files
|
||||
................................................
|
||||
|
||||
The names of additional source files involved in building your
|
||||
extension module or embedding application can be listed in
|
||||
|Jamroot|_ right alongside ``extending.cpp`` or ``embedding.cpp``
|
||||
respectively. Just be sure to leave whitespace around each
|
||||
filename::
|
||||
|
||||
… file1.cpp file2.cpp file3.cpp …
|
||||
|
||||
Naturally, if you want to change the name of a source file you can
|
||||
tell Boost.Build about it by editing the name in |Jamroot|_.
|
||||
|
||||
Change the Name of your Extension Module
|
||||
........................................
|
||||
|
||||
The name of the extension module is determined by two things:
|
||||
|
||||
1. the name in |Jamroot|_ immediately following ``python-extension``, and
|
||||
2. the name passed to ``BOOST_PYTHON_MODULE`` in |extending.cpp|_.
|
||||
|
||||
To change the name of the extension module from ``extending`` to
|
||||
``hello``, you'd edit |Jamroot|_, changing
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
python-extension **extending** : extending.cpp ;
|
||||
|
||||
to
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
python-extension **hello** : extending.cpp ;
|
||||
|
||||
and you'd edit extending.cpp, changing
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
BOOST_PYTHON_MODULE(\ **extending**\ )
|
||||
|
||||
to
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
BOOST_PYTHON_MODULE(\ **hello**\ )
|
||||
|
||||
Installing Boost.Python on your System
|
||||
======================================
|
||||
|
||||
Since Boost.Python is a separately-compiled (as opposed to
|
||||
`header-only`_) library, its user relies on the services of a
|
||||
Boost.Python library binary.
|
||||
|
||||
.. _header-only: ../../../more/getting_started/windows.html#header-only-libraries
|
||||
|
||||
If you need a regular installation of the Boost.Python library
|
||||
binaries on your system, the Boost `Getting Started Guide`_ will
|
||||
walk you through the steps of creating one. If building binaries
|
||||
from source, you might want to supply the ``--with-python``
|
||||
argument to ``bjam`` (or the ``--with-libraries=python`` argument
|
||||
to ``configure``), so only the Boost.Python binary will be built,
|
||||
rather than all the Boost binaries.
|
||||
|
||||
|
||||
Configuring Boost.Build
|
||||
=======================
|
||||
|
||||
As described in the `Boost.Build reference manual`__, a file called
|
||||
``user-config.jam`` in your home directory [#home-dir]_ is used to
|
||||
specify the tools and libraries available to the build system. You
|
||||
may need to create or edit ``user-config.jam`` to tell Boost.Build
|
||||
how to invoke Python, ``#include`` its headers, and link with its
|
||||
libraries.
|
||||
|
||||
__ http://www.boost.orgdoc/html/bbv2/advanced.html#bbv2.advanced.configuration
|
||||
|
||||
.. Admonition:: Users of Unix-Variant OSes
|
||||
|
||||
If you are using a unix-variant OS and you ran Boost's
|
||||
``configure`` script, it may have generated a
|
||||
``user-config.jam`` for you. [#overwrite]_ If your ``configure``\
|
||||
/\ ``make`` sequence was successful and Boost.Python binaries
|
||||
were built, your ``user-config.jam`` file is probably already
|
||||
correct.
|
||||
|
||||
If you have one fairly “standard” python installation for your
|
||||
platform, you might not need to do anything special to describe it. If
|
||||
you haven't configured python in ``user-config.jam`` (and you don't
|
||||
specify ``--without-python`` on the Boost.Build command line),
|
||||
Boost.Build will automatically execute the equivalent of ::
|
||||
|
||||
import toolset : using ;
|
||||
using python ;
|
||||
|
||||
which automatically looks for Python in the most likely places.
|
||||
However, that only happens when using the Boost.Python project file
|
||||
(e.g. when referred to by another project as in the quickstart_
|
||||
method). If instead you are linking against separately-compiled
|
||||
Boost.Python binaries, you should set up a ``user-config.jam`` file
|
||||
with at least the minimal incantation above.
|
||||
|
||||
Python Configuration Parameters
|
||||
-------------------------------
|
||||
|
||||
If you have several versions of Python installed, or Python is
|
||||
installed in an unusual way, you may want to supply any or all of
|
||||
the following optional parameters to ``using python``.
|
||||
|
||||
version
|
||||
the version of Python to use. Should be in Major.Minor
|
||||
format, for example, ``2.3``. Do not include the subminor
|
||||
version (i.e. *not* ``2.5.1``). If you have multiple Python
|
||||
versions installed, the version will usually be the only
|
||||
configuration argument required.
|
||||
|
||||
cmd-or-prefix
|
||||
preferably, a command that invokes a Python interpreter.
|
||||
Alternatively, the installation prefix for Python libraries and
|
||||
header files. Only use the alternative formulation if there is
|
||||
no appropriate Python executable available.
|
||||
|
||||
includes
|
||||
the ``#include`` paths for Python headers. Normally the correct
|
||||
path(s) will be automatically deduced from ``version`` and/or
|
||||
``cmd-or-prefix``.
|
||||
|
||||
libraries
|
||||
the path to Python library binaries. On MacOS/Darwin,
|
||||
you can also pass the path of the Python framework. Normally the
|
||||
correct path(s) will be automatically deduced from ``version``
|
||||
and/or ``cmd-or-prefix``.
|
||||
|
||||
condition
|
||||
if specified, should be a set of Boost.Build
|
||||
properties that are matched against the build configuration when
|
||||
Boost.Build selects a Python configuration to use. See examples
|
||||
below for details.
|
||||
|
||||
extension-suffix
|
||||
A string to append to the name of extension
|
||||
modules before the true filename extension. You almost certainly
|
||||
don't need to use this. Usually this suffix is only used when
|
||||
targeting a Windows debug build of Python, and will be set
|
||||
automatically for you based on the value of the
|
||||
|python-debugging|_ feature. However, at least one Linux
|
||||
distribution (Ubuntu Feisty Fawn) has a specially configured
|
||||
`python-dbg`__ package that claims to use such a suffix.
|
||||
|
||||
.. |python-debugging| replace:: ``<python-debugging>``
|
||||
|
||||
__ https://wiki.ubuntu.com/PyDbgBuilds
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Note that in the examples below, case and *especially whitespace* are
|
||||
significant.
|
||||
|
||||
- If you have both python 2.5 and python 2.4 installed,
|
||||
``user-config.jam`` might contain::
|
||||
|
||||
using python : 2.5 ; # Make both versions of Python available
|
||||
|
||||
using python : 2.4 ; # To build with python 2.4, add python=2.4
|
||||
# to your command line.
|
||||
|
||||
The first version configured (2.5) becomes the default. To build
|
||||
against python 2.4, add ``python=2.4`` to the ``bjam`` command line.
|
||||
|
||||
- If you have python installed in an unusual location, you might
|
||||
supply the path to the interpreter in the ``cmd-or-prefix``
|
||||
parameter::
|
||||
|
||||
using python : : /usr/local/python-2.6-beta/bin/python ;
|
||||
|
||||
- If you have a separate build of Python for use with a particular
|
||||
toolset, you might supply that toolset in the ``condition``
|
||||
parameter::
|
||||
|
||||
using python ; # use for most toolsets
|
||||
|
||||
# Use with Intel C++ toolset
|
||||
using python
|
||||
: # version
|
||||
: c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
|
||||
: # includes
|
||||
: # libraries
|
||||
: <toolset>intel # condition
|
||||
;
|
||||
|
||||
|
||||
- If you have downloaded the Python sources and built both the
|
||||
normal and the “\ `python debugging`_\ ” builds from source on
|
||||
Windows, you might see::
|
||||
|
||||
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python ;
|
||||
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python_d
|
||||
: # includes
|
||||
: # libs
|
||||
: <python-debugging>on ;
|
||||
|
||||
- You can set up your user-config.jam so a bjam built under Windows
|
||||
can build/test both Windows and Cygwin_ python extensions. Just pass
|
||||
``<target-os>cygwin`` in the ``condition`` parameter
|
||||
for the cygwin python installation::
|
||||
|
||||
# windows installation
|
||||
using python ;
|
||||
|
||||
# cygwin installation
|
||||
using python : : c:\\cygwin\\bin\\python2.5 : : : <target-os>cygwin ;
|
||||
|
||||
when you put target-os=cygwin in your build request, it should build
|
||||
with the cygwin version of python: [#flavor]_
|
||||
|
||||
bjam target-os=cygwin toolset=gcc
|
||||
|
||||
This is supposed to work the other way, too (targeting windows
|
||||
python with a Cygwin_ bjam) but it seems as though the support in
|
||||
Boost.Build's toolsets for building that way is broken at the
|
||||
time of this writing.
|
||||
|
||||
- Note that because of `the way Boost.Build currently selects target
|
||||
alternatives`__, you might have be very explicit in your build
|
||||
requests. For example, given::
|
||||
|
||||
using python : 2.5 ; # a regular windows build
|
||||
using python : 2.4 : : : : <target-os>cygwin ;
|
||||
|
||||
building with ::
|
||||
|
||||
bjam target-os=cygwin
|
||||
|
||||
will yield an error. Instead, you'll need to write::
|
||||
|
||||
bjam target-os=cygwin/python=2.4
|
||||
|
||||
.. _Cygwin: http://cygwin.com
|
||||
|
||||
__ http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection
|
||||
|
||||
Choosing a Boost.Python Library Binary
|
||||
======================================
|
||||
|
||||
If—instead of letting Boost.Build construct and link with the right
|
||||
libraries automatically—you choose to use a pre-built Boost.Python
|
||||
library, you'll need to think about which one to link with. The
|
||||
Boost.Python binary comes in both static and dynamic flavors. Take
|
||||
care to choose the right flavor for your application. [#naming]_
|
||||
|
||||
The Dynamic Binary
|
||||
------------------
|
||||
|
||||
The dynamic library is the safest and most-versatile choice:
|
||||
|
||||
- A single copy of the library code is used by all extension
|
||||
modules built with a given toolset. [#toolset-specific]_
|
||||
|
||||
- The library contains a type conversion registry. Because one
|
||||
registry is shared among all extension modules, instances of a
|
||||
class exposed to Python in one dynamically-loaded extension
|
||||
module can be passed to functions exposed in another such module.
|
||||
|
||||
The Static Binary
|
||||
-----------------
|
||||
|
||||
It might be appropriate to use the static Boost.Python library in
|
||||
any of the following cases:
|
||||
|
||||
- You are extending_ python and the types exposed in your
|
||||
dynamically-loaded extension module don't need to be used by any
|
||||
other Boost.Python extension modules, and you don't care if the
|
||||
core library code is duplicated among them.
|
||||
|
||||
- You are embedding_ python in your application and either:
|
||||
|
||||
- You are targeting a Unix variant OS other than MacOS or AIX,
|
||||
where the dynamically-loaded extension modules can “see” the
|
||||
Boost.Python library symbols that are part of the executable.
|
||||
|
||||
- Or, you have statically linked some Boost.Python extension
|
||||
modules into your application and you don't care if any
|
||||
dynamically-loaded Boost.Python extension modules are able to
|
||||
use the types exposed by your statically-linked extension
|
||||
modules (and vice-versa).
|
||||
|
||||
``#include`` Issues
|
||||
===================
|
||||
|
||||
1. If you should ever have occasion to ``#include "python.h"``
|
||||
directly in a translation unit of a program using Boost.Python,
|
||||
use ``#include "boost/python/detail/wrap_python.hpp"`` instead.
|
||||
It handles several issues necessary for use with Boost.Python,
|
||||
one of which is mentioned in the next section.
|
||||
|
||||
2. Be sure not to ``#include`` any system headers before
|
||||
``wrap_python.hpp``. This restriction is actually imposed by
|
||||
Python, or more properly, by Python's interaction with your
|
||||
operating system. See
|
||||
http://docs.python.org/ext/simpleExample.html for details.
|
||||
|
||||
.. _python-debugging:
|
||||
.. _python debugging:
|
||||
|
||||
Python Debugging Builds
|
||||
=======================
|
||||
|
||||
Python can be built in a special “python debugging” configuration
|
||||
that adds extra checks and instrumentation that can be very useful
|
||||
for developers of extension modules. The data structures used by
|
||||
the debugging configuration contain additional members, so **a
|
||||
Python executable built with python debugging enabled cannot be
|
||||
used with an extension module or library compiled without it, and
|
||||
vice-versa.**
|
||||
|
||||
Since pre-built “python debugging” versions of the Python
|
||||
executable and libraries are not supplied with most distributions
|
||||
of Python, [#get-debug-build]_ and we didn't want to force our users
|
||||
to build them, Boost.Build does not automatically enable python
|
||||
debugging in its ``debug`` build variant (which is the default).
|
||||
Instead there is a special build property called
|
||||
``python-debugging`` that, when used as a build property, will
|
||||
define the right preprocessor symbols and select the right
|
||||
libraries to link with.
|
||||
|
||||
On unix-variant platforms, the debugging versions of Python's data
|
||||
structures will only be used if the symbol ``Py_DEBUG`` is defined.
|
||||
On many windows compilers, when extension modules are built with
|
||||
the preprocessor symbol ``_DEBUG``, Python defaults to force
|
||||
linking with a special debugging version of the Python DLL. Since
|
||||
that symbol is very commonly used even when Python is not present,
|
||||
Boost.Python temporarily undefines _DEBUG when Python.h
|
||||
is #included from ``boost/python/detail/wrap_python.hpp`` - unless
|
||||
``BOOST_DEBUG_PYTHON`` is defined. The upshot is that if you want
|
||||
“python debugging”and you aren't using Boost.Build, you should make
|
||||
sure ``BOOST_DEBUG_PYTHON`` is defined, or python debugging will be
|
||||
suppressed.
|
||||
|
||||
Testing Boost.Python
|
||||
====================
|
||||
|
||||
To run the full test suite for Boost.Python, invoke ``bjam`` in the
|
||||
``libs/python/test`` subdirectory of your Boost distribution.
|
||||
|
||||
Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users
|
||||
=======================================================
|
||||
|
||||
If you are using a version of Python prior to 2.4.1 with a MinGW
|
||||
prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will need to
|
||||
create a MinGW-compatible version of the Python library; the one
|
||||
shipped with Python will only work with a Microsoft-compatible
|
||||
linker. Follow the instructions in the “Non-Microsoft” section of
|
||||
the “Building Extensions: Tips And Tricks” chapter in `Installing
|
||||
Python Modules`__ to create ``libpythonXX.a``, where ``XX``
|
||||
corresponds to the major and minor version numbers of your Python
|
||||
installation.
|
||||
|
||||
__ http://www.python.org/doc/current/inst/index.html
|
||||
|
||||
-----------------------------
|
||||
|
||||
.. [#2.2] Note that although we tested earlier versions of
|
||||
Boost.Python with Python 2.2, and we don't *think* we've done
|
||||
anything to break compatibility, this release of Boost.Python
|
||||
may not have been tested with versions of Python earlier than
|
||||
2.4, so we're not 100% sure that python 2.2 and 2.3 are
|
||||
supported.
|
||||
|
||||
.. [#naming] Information about how to identify the
|
||||
static and dynamic builds of Boost.Python:
|
||||
|
||||
* `on Windows`__
|
||||
* `on Unix variants`__
|
||||
|
||||
__ ../../../more/getting_started/windows.html#library-naming
|
||||
__ ../../../more/getting_started/unix-variants.html#library-naming
|
||||
|
||||
.. [#toolset-specific] Because of the way most \*nix platforms
|
||||
share symbols among dynamically-loaded objects, I'm not certain
|
||||
that extension modules built with different compiler toolsets
|
||||
will always use different copies of the Boost.Python library
|
||||
when loaded into the same Python instance. Not using different
|
||||
libraries could be a good thing if the compilers have compatible
|
||||
ABIs, because extension modules built with the two libraries
|
||||
would be interoperable. Otherwise, it could spell disaster,
|
||||
since an extension module and the Boost.Python library would
|
||||
have different ideas of such things as class layout. I would
|
||||
appreciate someone doing the experiment to find out what
|
||||
happens.
|
||||
|
||||
.. [#overwrite] ``configure`` overwrites the existing
|
||||
``user-config.jam`` in your home directory
|
||||
(if any) after making a backup of the old version.
|
||||
|
||||
.. [#flavor] Note that the ``<target-os>cygwin`` feature is
|
||||
different from the ``<flavor>cygwin`` subfeature of the ``gcc``
|
||||
toolset, and you might need handle both explicitly if you also
|
||||
have a MinGW GCC installed.
|
||||
|
||||
.. [#home-dir] Windows users, your home directory can be
|
||||
found by typing::
|
||||
|
||||
ECHO %HOMEDRIVE%%HOMEPATH%
|
||||
|
||||
into a `command prompt`_ window.
|
||||
|
||||
.. [#get-debug-build] On Unix and similar platforms, a debugging
|
||||
python and associated libraries are built by adding
|
||||
``--with-pydebug`` when configuring the Python build. On
|
||||
Windows, the debugging version of Python is generated by
|
||||
the "Win32 Debug" target of the Visual Studio project in the
|
||||
PCBuild subdirectory of a full Python source code distribution.
|
||||
You may also find
|
||||
@@ -147,7 +147,9 @@
|
||||
|
||||
<dt><a href="v2/faq.html">Frequently Asked Questions (FAQs)</a></dt>
|
||||
|
||||
<dt><a href="../pyste/index.html">Pyste (Boost.Python code generator)</a></dt>
|
||||
<dt><a href="http://www.language-binding.net/pyplusplus/pyplusplus.html">Py++ Boost.Python code generator</a></dt>
|
||||
|
||||
<dt><a href="../pyste/index.html">Pyste Boost.Python code generator (no longer maintained)</a></dt>
|
||||
|
||||
<dt><a href="internals.html">Internals Documentation</a></dt>
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<li>Support for converting <code>void*</code> to/from python,
|
||||
with <code><a
|
||||
href="v2/opaque_pointer_converter.html">opaque_pointer_converter</a></code>
|
||||
href="v2/opaque.html">opaque_pointer_converter</a></code>
|
||||
as the return value policy. Thanks to Niall Douglas for the
|
||||
initial patch.
|
||||
</ul>
|
||||
@@ -219,7 +219,7 @@ BOOST_PYTHON_MODULE(test)
|
||||
|
||||
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
|
||||
Ganßauge</a> has contributed <a href=
|
||||
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
|
||||
"v2/opaque.html">opaque pointer support</a>.<br>
|
||||
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
|
||||
Oliveira</a> has contributed the exciting <a href=
|
||||
"../pyste/index.html">Pyste</a> ("Pie-steh") package.</dd>
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
.. Copyright David Abrahams 2006. Distributed under the Boost
|
||||
.. Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at
|
||||
.. http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
How Runtime Polymorphism is expressed in Boost.Python:
|
||||
-----------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# Copyright Joel de Guzman 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
project boost/libs/python/doc/tutorial/doc ;
|
||||
|
||||
import boostbook : boostbook ;
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Chapter 1. python 1.0</title>
|
||||
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="python/hello.html" title=" Building Hello World">
|
||||
<link rel="next" href="python/hello.html" title="Building Hello World">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -34,7 +31,7 @@
|
||||
<div><p class="copyright">Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="id376848"></a><p>
|
||||
<a name="id3128483"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
@@ -96,10 +93,10 @@
|
||||
code takes on the look of a kind of declarative interface definition language
|
||||
(IDL).
|
||||
</p>
|
||||
<a name="quickstart.hello_world"></a><h2>
|
||||
<a name="id447173"></a>
|
||||
<a name="quickstart.hello_world"></a><h3>
|
||||
<a name="id3090903"></a>
|
||||
Hello World
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Following C/C++ tradition, let's start with the "hello, world". A
|
||||
C++ Function:
|
||||
@@ -136,13 +133,13 @@
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World module
|
||||
from start to finish...</b></span></em></span>
|
||||
<span class="emphasis"><em><span class="bold"><strong>Next stop... Building your Hello World module
|
||||
from start to finish...</strong></span></em></span>
|
||||
</p></blockquote></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><small><p>Last revised: August 31, 2006 at 05:59:58 GMT</p></small></td>
|
||||
<td align="left"><small><p>Last revised: May 18, 2007 at 15:45:45 GMT</p></small></td>
|
||||
<td align="right"><small></small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Embedding</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="object.html" title=" Object Interface">
|
||||
<link rel="prev" href="object.html" title="Object Interface">
|
||||
<link rel="next" href="iterators.html" title="Iterators">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
@@ -42,30 +39,28 @@
|
||||
a lot easier and, in a future version, it may become unnecessary to touch the
|
||||
Python/C API at all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span>
|
||||
</p>
|
||||
<a name="embedding.building_embedded_programs"></a><h2>
|
||||
<a name="id462650"></a>
|
||||
<a name="embedding.building_embedded_programs"></a><h3>
|
||||
<a name="id3150903"></a>
|
||||
Building embedded programs
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
To be able to use embedding in your programs, they have to be linked to both
|
||||
Boost.Python's and Python's static link library.
|
||||
To be able to embed python into your programs, you have to link to both Boost.Python's
|
||||
as well as Python's own runtime library.
|
||||
</p>
|
||||
<p>
|
||||
Boost.Python's static link library comes in two variants. Both are located
|
||||
in Boost's <tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On
|
||||
Windows, the variants are called <tt class="literal">boost_python.lib</tt> (for release
|
||||
builds) and <tt class="literal">boost_python_debug.lib</tt> (for debugging). If you
|
||||
can't find the libraries, you probably haven't built Boost.Python yet. See
|
||||
<a href="../../../../building.html" target="_top">Building and Testing</a> on how to
|
||||
do this.
|
||||
Boost.Python's library comes in two variants. Both are located in Boost's
|
||||
<code class="literal">/libs/python/build/bin-stage</code> subdirectory. On Windows, the
|
||||
variants are called <code class="literal">boost_python.lib</code> (for release builds)
|
||||
and <code class="literal">boost_python_debug.lib</code> (for debugging). If you can't
|
||||
find the libraries, you probably haven't built Boost.Python yet. See <a href="../../../../building.html" target="_top">Building and Testing</a> on how to do this.
|
||||
</p>
|
||||
<p>
|
||||
Python's static link library can be found in the <tt class="literal">/libs</tt> subdirectory
|
||||
Python's library can be found in the <code class="literal">/libs</code> subdirectory
|
||||
of your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
your major Python version number.
|
||||
</p>
|
||||
<p>
|
||||
Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be added
|
||||
Additionally, Python's <code class="literal">/include</code> subdirectory has to be added
|
||||
to your include path.
|
||||
</p>
|
||||
<p>
|
||||
@@ -86,44 +81,49 @@ exe embedded_program # name of the executable
|
||||
<library-path>$(PYTHON_LIB_PATH)
|
||||
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
||||
</pre>
|
||||
<a name="embedding.getting_started"></a><h2>
|
||||
<a name="id462747"></a>
|
||||
<a name="embedding.getting_started"></a><h3>
|
||||
<a name="id3150996"></a>
|
||||
Getting started
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Being able to build is nice, but there is nothing to build yet. Embedding the
|
||||
Python interpreter into one of your C++ programs requires these 4 steps:
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
#include <tt class="literal"><boost/python.hpp></tt><br><br>
|
||||
|
||||
#include
|
||||
<code class="literal"><boost/python.hpp></code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>()
|
||||
to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
to start the interpreter and create the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
module.<br><br>
|
||||
</li>
|
||||
<li>
|
||||
Call other Python C API routines to use the interpreter.<br><br>
|
||||
</li>
|
||||
<li>
|
||||
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
|
||||
to stop the interpreter and release its resources.
|
||||
</li>
|
||||
</ol></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>Note that at this time
|
||||
you must not call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
|
||||
to stop the interpreter. This may be fixed in a future version of boost.python.</strong></span>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
(Of course, there can be other C++ code between all of these steps.)
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em><span class="bold"><b>Now that we can embed the interpreter in
|
||||
our programs, lets see how to put it to use...</b></span></em></span>
|
||||
<span class="emphasis"><em><span class="bold"><strong>Now that we can embed the interpreter in
|
||||
our programs, lets see how to put it to use...</strong></span></em></span>
|
||||
</p></blockquote></div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
|
||||
<p>
|
||||
As you probably already know, objects in Python are reference-counted. Naturally,
|
||||
the <tt class="literal">PyObject</tt>s of the Python/C API are also reference-counted.
|
||||
the <code class="literal">PyObject</code>s of the Python/C API are also reference-counted.
|
||||
There is a difference however. While the reference-counting is fully automatic
|
||||
in Python, the Python/C API requires you to do it <a href="http://www.python.org/doc/current/api/refcounts.html" target="_top">by
|
||||
hand</a>. This is messy and especially hard to get right in the presence
|
||||
@@ -131,240 +131,106 @@ exe embedded_program # name of the executable
|
||||
and <a href="../../../../v2/object.html" target="_top">object</a> class templates to
|
||||
automate the process.
|
||||
</p>
|
||||
<a name="using_the_interpreter.reference_counting_handles_and_objects"></a><h2>
|
||||
<a name="id462914"></a>
|
||||
Reference-counting handles and objects
|
||||
</h2>
|
||||
<p>
|
||||
There are two ways in which a function in the Python/C API can return a
|
||||
<tt class="literal">PyObject*</tt>: as a <span class="emphasis"><em>borrowed reference</em></span>
|
||||
or as a <span class="emphasis"><em>new reference</em></span>. Which of these a function uses,
|
||||
is listed in that function's documentation. The two require slightely different
|
||||
approaches to reference-counting but both can be 'handled' by Boost.Python.
|
||||
</p>
|
||||
<p>
|
||||
For a function returning a <span class="emphasis"><em>borrowed reference</em></span> we'll
|
||||
have to tell the <tt class="literal">handle</tt> that the <tt class="literal">PyObject*</tt>
|
||||
is borrowed with the aptly named <a href="../../../../v2/handle.html#borrowed-spec" target="_top">borrowed</a>
|
||||
function. Two functions returning borrowed references are <a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a>
|
||||
and <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594" target="_top">PyModule_GetDict</a>.
|
||||
The former returns a reference to an already imported module, the latter
|
||||
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||
namespace of the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
module:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
For a function returning a <span class="emphasis"><em>new reference</em></span> we can just
|
||||
create a <tt class="literal">handle</tt> out of the raw <tt class="literal">PyObject*</tt>
|
||||
without wrapping it in a call to borrowed. One such function that returns
|
||||
a new reference is <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
which we'll discuss in the next section.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>,
|
||||
so why haven't we been using any template parameters?</b></span><br> <br>
|
||||
<tt class="literal">handle</tt> has a single template parameter specifying the
|
||||
type of the managed object. This type is <tt class="literal">PyObject</tt> 99%
|
||||
of the time, so the parameter was defaulted to <tt class="literal">PyObject</tt>
|
||||
for convenience. Therefore we can use the shorthand <tt class="literal">handle<></tt>
|
||||
instead of the longer, but equivalent, <tt class="literal">handle<PyObject></tt>.
|
||||
</p>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h2>
|
||||
<a name="id463241"></a>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h3>
|
||||
<a name="id3151190"></a>
|
||||
Running Python code
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
To run Python code from C++ there is a family of functions in the API starting
|
||||
with the PyRun prefix. You can find the full list of these functions <a href="http://www.python.org/doc/current/api/veryhigh.html" target="_top">here</a>. They
|
||||
all work similarly so we will look at only one of them, namely:
|
||||
Boost.python provides three related functions to run Python code from C++.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">PyObject</span><span class="special">*</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="keyword">char</span> <span class="special">*</span><span class="identifier">str</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">start</span><span class="special">,</span> <span class="identifier">PyObject</span> <span class="special">*</span><span class="identifier">globals</span><span class="special">,</span> <span class="identifier">PyObject</span> <span class="special">*</span><span class="identifier">locals</span><span class="special">)</span>
|
||||
<span class="identifier">object</span> <span class="identifier">eval</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">expression</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
|
||||
<span class="identifier">object</span> <span class="identifier">exec</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">code</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
|
||||
<span class="identifier">object</span> <span class="identifier">exec_file</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">filename</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
|
||||
</pre>
|
||||
<p>
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
takes the code to execute as a null-terminated (C-style) string in its <tt class="literal">str</tt>
|
||||
parameter. The function returns a new reference to a Python object. Which
|
||||
object is returned depends on the <tt class="literal">start</tt> paramater.
|
||||
eval evaluates the given expression and returns the resulting value. exec
|
||||
executes the given code (typically a set of statements) returning the result,
|
||||
and exec_file executes the code contained in the given file.
|
||||
</p>
|
||||
<p>
|
||||
The <tt class="literal">start</tt> parameter is the start symbol from the Python
|
||||
grammar to use for interpreting the code. The possible values are:
|
||||
</p>
|
||||
<div class="informaltable">
|
||||
<h4>
|
||||
<a name="id463420"></a>
|
||||
<span class="table-title">Start symbols</span>
|
||||
</h4>
|
||||
<table class="table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a></th>
|
||||
<th>for
|
||||
interpreting isolated expressions</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a></td>
|
||||
<td>for
|
||||
interpreting sequences of statements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a></td>
|
||||
<td>for
|
||||
interpreting a single statement</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>
|
||||
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>,
|
||||
the input string must contain a single expression and its result is returned.
|
||||
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>,
|
||||
the string can contain an abitrary number of statements and None is returned.
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a>
|
||||
works in the same way as <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||
but only accepts a single statement.
|
||||
</p>
|
||||
<p>
|
||||
Lastly, the <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters
|
||||
are Python dictionaries containing the globals and locals of the context
|
||||
in which to run the code. For most intents and purposes you can use the namespace
|
||||
dictionary of the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
The <code class="literal">globals</code> and <code class="literal">locals</code> parameters are
|
||||
Python dictionaries containing the globals and locals of the context in which
|
||||
to run the code. For most intents and purposes you can use the namespace
|
||||
dictionary of the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
module for both parameters.
|
||||
</p>
|
||||
<p>
|
||||
We have already seen how to get the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
module's namespace so let's run some Python code in it:
|
||||
Boost.python provides a function to import a module:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
|
||||
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
|
||||
<span class="string">"hello = file('hello.txt', 'w')\n"</span>
|
||||
<span class="string">"hello.write('Hello world!')\n"</span>
|
||||
<span class="string">"hello.close()"</span>
|
||||
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
|
||||
<span class="special">));</span>
|
||||
<span class="identifier">object</span> <span class="identifier">import</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
Because the Python/C API doesn't know anything about <tt class="literal">object</tt>s,
|
||||
we used the object's <tt class="literal">ptr</tt> member function to retrieve the
|
||||
<tt class="literal">PyObject*</tt>.
|
||||
import imports a python module (potentially loading it into the running process
|
||||
first), and returns it.
|
||||
</p>
|
||||
<p>
|
||||
Let's import the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
module and run some Python code in its namespace:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"hello = file('hello.txt', 'w')\n"</span>
|
||||
<span class="string">"hello.write('Hello world!')\n"</span>
|
||||
<span class="string">"hello.close()"</span><span class="special">,</span>
|
||||
<span class="identifier">main_namespace</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
This should create a file called 'hello.txt' in the current directory containing
|
||||
a phrase that is well-known in programming circles.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Note</b></span> that we wrap
|
||||
the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
in a (nameless) <tt class="literal">handle</tt> even though we are not interested
|
||||
in it. If we didn't do this, the the returned object would be kept alive
|
||||
unnecessarily. Unless you want to be a Dr. Frankenstein, always wrap <tt class="literal">PyObject*</tt>s
|
||||
in <tt class="literal">handle</tt>s.
|
||||
</p>
|
||||
<a name="using_the_interpreter.beyond_handles"></a><h2>
|
||||
<a name="id463926"></a>
|
||||
Beyond handles
|
||||
</h2>
|
||||
<a name="using_the_interpreter.manipulating_python_objects"></a><h3>
|
||||
<a name="id3151717"></a>
|
||||
Manipulating Python objects
|
||||
</h3>
|
||||
<p>
|
||||
It's nice that <tt class="literal">handle</tt> manages the reference counting details
|
||||
for us, but other than that it doesn't do much. Often we'd like to have a
|
||||
more useful class to manipulate Python objects. But we have already seen
|
||||
such a class above, and in the <a href="object.html" target="_top">previous section</a>:
|
||||
the aptly named <tt class="literal">object</tt> class and it's derivatives. We've
|
||||
already seen that they can be constructed from a <tt class="literal">handle</tt>.
|
||||
Often we'd like to have a class to manipulate Python objects. But we have
|
||||
already seen such a class above, and in the <a href="object.html" target="_top">previous
|
||||
section</a>: the aptly named <code class="literal">object</code> class and its
|
||||
derivatives. We've already seen that they can be constructed from a <code class="literal">handle</code>.
|
||||
The following examples should further illustrate this fact:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
|
||||
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
|
||||
<span class="string">"result = 5 ** 2"</span>
|
||||
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
|
||||
<span class="special">));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"result = 5 ** 2"</span><span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">);</span>
|
||||
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
Here we create a dictionary object for the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
module's namespace. Then we assign 5 squared to the result variable and read
|
||||
this variable from the dictionary. Another way to achieve the same result
|
||||
is to let <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
return the result directly with <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>:
|
||||
is to use eval instead, which returns the result directly:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">handle</span><span class="special"><>(</span>
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">"5 ** 2"</span>
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span>
|
||||
<span class="special">));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5 ** 2"</span><span class="special">);</span>
|
||||
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s
|
||||
member function to return the wrapped <tt class="literal">PyObject*</tt> is called
|
||||
<tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes sense
|
||||
if you take into account the different functions that <tt class="literal">object</tt>
|
||||
and <tt class="literal">handle</tt> perform.
|
||||
</p>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h2>
|
||||
<a name="id464549"></a>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h3>
|
||||
<a name="id3152050"></a>
|
||||
Exception handling
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
function returns a null pointer. Constructing a <tt class="literal">handle</tt>
|
||||
out of this null pointer throws <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>,
|
||||
so basically, the Python exception is automatically translated into a C++
|
||||
exception when using <tt class="literal">handle</tt>:
|
||||
If an exception occurs in the evaluation of the python expression, <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>
|
||||
is thrown:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">try</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">object</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">handle</span><span class="special"><>(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
<span class="string">"5/0"</span>
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span>
|
||||
<span class="special">));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5/0"</span><span class="special">);</span>
|
||||
<span class="comment">// execution will never get here:
|
||||
</span> <span class="keyword">int</span> <span class="identifier">five_divided_by_zero</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
|
||||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// handle the exception in some way
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
The <tt class="literal">error_already_set</tt> exception class doesn't carry any
|
||||
The <code class="literal">error_already_set</code> exception class doesn't carry any
|
||||
information in itself. To find out more about the Python exception that occurred,
|
||||
you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception
|
||||
handling functions</a> of the Python/C API in your catch-statement. This
|
||||
@@ -374,7 +240,7 @@ exe embedded_program # name of the executable
|
||||
exceptions</a>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
|
||||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">PyErr_ExceptionMatches</span><span class="special">(</span><span class="identifier">PyExc_ZeroDivisionError</span><span class="special">))</span>
|
||||
<span class="special">{</span>
|
||||
@@ -391,23 +257,6 @@ exe embedded_program # name of the executable
|
||||
(To retrieve even more information from the exception you can use some of
|
||||
the other exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)
|
||||
</p>
|
||||
<p>
|
||||
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception
|
||||
when it is constructed, you can use the <a href="../../../../v2/handle.html#allow_null-spec" target="_top">allow_null</a>
|
||||
function in the same way you'd use borrowed:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">allow_null</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
<span class="string">"5/0"</span>
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span>
|
||||
<span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))));</span>
|
||||
|
||||
<span class="keyword">if</span> <span class="special">(!</span><span class="identifier">result</span><span class="special">)</span>
|
||||
<span class="comment">// Python exception occurred
|
||||
</span><span class="keyword">else</span>
|
||||
<span class="comment">// everything went okay, it's safe to use the result
|
||||
</span></pre>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exception Translation</title>
|
||||
<title>Exception Translation</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="iterators.html" title="Iterators">
|
||||
<link rel="next" href="techniques.html" title=" General Techniques">
|
||||
<link rel="next" href="techniques.html" title="General Techniques">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exposing Classes</title>
|
||||
<title>Exposing Classes</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="hello.html" title=" Building Hello World">
|
||||
<link rel="prev" href="hello.html" title="Building Hello World">
|
||||
<link rel="next" href="functions.html" title="Functions">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
@@ -67,9 +64,9 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Here, we wrote a C++ class wrapper that exposes the member functions <tt class="literal">greet</tt>
|
||||
and <tt class="literal">set</tt>. Now, after building our module as a shared library,
|
||||
we may use our class <tt class="literal">World</tt> in Python. Here's a sample Python
|
||||
Here, we wrote a C++ class wrapper that exposes the member functions <code class="literal">greet</code>
|
||||
and <code class="literal">set</code>. Now, after building our module as a shared library,
|
||||
we may use our class <code class="literal">World</code> in Python. Here's a sample Python
|
||||
session:
|
||||
</p>
|
||||
<p>
|
||||
@@ -85,7 +82,7 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.constructors"></a>Constructors</h3></div></div></div>
|
||||
<p>
|
||||
Our previous example didn't have any explicit constructors. Since <tt class="literal">World</tt>
|
||||
Our previous example didn't have any explicit constructors. Since <code class="literal">World</code>
|
||||
is declared as a plain struct, it has an implicit default constructor. Boost.Python
|
||||
exposes the default constructor by default, which is why we were able to
|
||||
write
|
||||
@@ -109,9 +106,9 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
This time <tt class="literal">World</tt> has no default constructor; our previous
|
||||
This time <code class="literal">World</code> has no default constructor; our previous
|
||||
wrapping code would fail to compile when the library tried to expose it.
|
||||
We have to tell <tt class="literal">class_<World></tt> about the constructor
|
||||
We have to tell <code class="literal">class_<World></code> about the constructor
|
||||
we want to expose instead.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -127,13 +124,13 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
<tt class="literal">init<std::string>()</tt> exposes the constructor taking
|
||||
in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
|
||||
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").
|
||||
<code class="literal">init<std::string>()</code> exposes the constructor taking
|
||||
in a <code class="literal">std::string</code> (in Python, constructors are spelled
|
||||
"<code class="literal">"<span class="underline">_init</span>_"</code>").
|
||||
</p>
|
||||
<p>
|
||||
We can expose additional constructors by passing more <tt class="literal">init<...></tt>s
|
||||
to the <tt class="literal">def()</tt> member function. Say for example we have
|
||||
We can expose additional constructors by passing more <code class="literal">init<...></code>s
|
||||
to the <code class="literal">def()</code> member function. Say for example we have
|
||||
another World constructor taking in two doubles:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -145,13 +142,13 @@
|
||||
</pre>
|
||||
<p>
|
||||
On the other hand, if we do not wish to expose any constructors at all, we
|
||||
may use <tt class="literal">no_init</tt> instead:
|
||||
may use <code class="literal">no_init</code> instead:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Abstract</span><span class="special">>(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
|
||||
This actually adds an <code class="literal"><span class="underline">_init</span>_</code>
|
||||
method which always raises a Python RuntimeError exception.
|
||||
</p>
|
||||
</div>
|
||||
@@ -161,8 +158,8 @@
|
||||
<p>
|
||||
Data members may also be exposed to Python so that they can be accessed as
|
||||
attributes of the corresponding Python class. Each data member that we wish
|
||||
to be exposed may be regarded as <span class="bold"><b>read-only</b></span>
|
||||
or <span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:
|
||||
to be exposed may be regarded as <span class="bold"><strong>read-only</strong></span>
|
||||
or <span class="bold"><strong>read-write</strong></span>. Consider this class <code class="literal">Var</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Var</span>
|
||||
@@ -173,7 +170,7 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Our C++ <tt class="literal">Var</tt> class and its data members can be exposed
|
||||
Our C++ <code class="literal">Var</code> class and its data members can be exposed
|
||||
to Python:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -194,8 +191,8 @@
|
||||
<span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
|
||||
</pre>
|
||||
<p>
|
||||
Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span>
|
||||
while <tt class="literal">value</tt> is exposed as <span class="bold"><b>read-write</b></span>.
|
||||
Note that <code class="literal">name</code> is exposed as <span class="bold"><strong>read-only</strong></span>
|
||||
while <code class="literal">value</code> is exposed as <span class="bold"><strong>read-write</strong></span>.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">'e'</span> <span class="comment"># can't change name
|
||||
@@ -227,7 +224,7 @@
|
||||
<p>
|
||||
However, in Python attribute access is fine; it doesn't neccessarily break
|
||||
encapsulation to let users handle attributes directly, because the attributes
|
||||
can just be a different syntax for a method call. Wrapping our <tt class="literal">Num</tt>
|
||||
can just be a different syntax for a method call. Wrapping our <code class="literal">Num</code>
|
||||
class using Boost.Python:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -248,8 +245,8 @@
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!
|
||||
</span></pre>
|
||||
<p>
|
||||
Take note that the class property <tt class="literal">rovalue</tt> is exposed as
|
||||
<span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
|
||||
Take note that the class property <code class="literal">rovalue</code> is exposed as
|
||||
<span class="bold"><strong>read-only</strong></span> since the <code class="literal">rovalue</code>
|
||||
setter member function is not passed in:
|
||||
</p>
|
||||
<p>
|
||||
@@ -276,7 +273,7 @@
|
||||
<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
|
||||
</pre>
|
||||
<p>
|
||||
And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt>
|
||||
And a set of C++ functions operating on <code class="literal">Base</code> and <code class="literal">Derived</code>
|
||||
object instances:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -285,7 +282,7 @@
|
||||
<span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
We've seen how we can wrap the base class <tt class="literal">Base</tt>:
|
||||
We've seen how we can wrap the base class <code class="literal">Base</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||
@@ -293,8 +290,8 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now we can inform Boost.Python of the inheritance relationship between <tt class="literal">Derived</tt>
|
||||
and its base class <tt class="literal">Base</tt>. Thus:
|
||||
Now we can inform Boost.Python of the inheritance relationship between <code class="literal">Derived</code>
|
||||
and its base class <code class="literal">Base</code>. Thus:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="special">>(</span><span class="string">"Derived"</span><span class="special">)</span>
|
||||
@@ -310,15 +307,15 @@
|
||||
member functions)
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt>
|
||||
<span class="bold"><strong>If</strong></span> Base is polymorphic, <code class="literal">Derived</code>
|
||||
objects which have been passed to Python via a pointer or reference to
|
||||
<tt class="literal">Base</tt> can be passed where a pointer or reference to
|
||||
<tt class="literal">Derived</tt> is expected.
|
||||
<code class="literal">Base</code> can be passed where a pointer or reference to
|
||||
<code class="literal">Derived</code> is expected.
|
||||
</li>
|
||||
</ol></div>
|
||||
<p>
|
||||
Now, we shall expose the C++ free functions <tt class="literal">b</tt> and <tt class="literal">d</tt>
|
||||
and <tt class="literal">factory</tt>:
|
||||
Now, we shall expose the C++ free functions <code class="literal">b</code> and <code class="literal">d</code>
|
||||
and <code class="literal">factory</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span>
|
||||
@@ -326,11 +323,11 @@
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Note that free function <tt class="literal">factory</tt> is being used to generate
|
||||
new instances of class <tt class="literal">Derived</tt>. In such cases, we use
|
||||
<tt class="literal">return_value_policy<manage_new_object></tt> to instruct
|
||||
Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
|
||||
in a new Python <tt class="literal">Base</tt> object until the the Python object
|
||||
Note that free function <code class="literal">factory</code> is being used to generate
|
||||
new instances of class <code class="literal">Derived</code>. In such cases, we use
|
||||
<code class="literal">return_value_policy<manage_new_object></code> to instruct
|
||||
Python to adopt the pointer to <code class="literal">Base</code> and hold the instance
|
||||
in a new Python <code class="literal">Base</code> object until the the Python object
|
||||
is destroyed. We shall see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
|
||||
policies</a> later.
|
||||
</p>
|
||||
@@ -346,7 +343,7 @@
|
||||
<p>
|
||||
In this section, we shall learn how to make functions behave polymorphically
|
||||
through virtual functions. Continuing our example, let us add a virtual function
|
||||
to our <tt class="literal">Base</tt> class:
|
||||
to our <code class="literal">Base</code> class:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||
@@ -359,11 +356,11 @@
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing
|
||||
C++ design. In principle, it should be possible to expose the interface for
|
||||
a 3rd party library without changing it. It is not ideal to add anything
|
||||
to our class <tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when
|
||||
to our class <code class="computeroutput"><span class="identifier">Base</span></code>. Yet, when
|
||||
you have a virtual function that's going to be overridden in Python and called
|
||||
polymorphically <span class="bold"><b>from C++</b></span>, we'll need to
|
||||
polymorphically <span class="bold"><strong>from C++</strong></span>, we'll need to
|
||||
add some scaffoldings to make things work properly. What we'll do is write
|
||||
a class wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt>
|
||||
a class wrapper that derives from <code class="computeroutput"><span class="identifier">Base</span></code>
|
||||
that will unintrusively hook into the virtual functions so that a Python
|
||||
override may be called:
|
||||
</p>
|
||||
@@ -377,21 +374,24 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>,
|
||||
we also multiply- inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
|
||||
The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
|
||||
Notice too that in addition to inheriting from <code class="computeroutput"><span class="identifier">Base</span></code>,
|
||||
we also multiply- inherited <code class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></code> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
|
||||
The <code class="computeroutput"><span class="identifier">wrapper</span></code> template makes
|
||||
the job of wrapping classes that are meant to overridden in Python, easier.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt> as:<br> <br> <tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to write
|
||||
<code class="computeroutput"><span class="identifier">f</span></code> as:<br> <br>
|
||||
<code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <code class="computeroutput"><span class="identifier">f</span></code>
|
||||
in effect calls the corresponding method of the Python object through <code class="computeroutput"><span class="identifier">get_override</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt>
|
||||
in effect calls the corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.
|
||||
</p>
|
||||
<p>
|
||||
Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:
|
||||
Finally, exposing <code class="computeroutput"><span class="identifier">Base</span></code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||
@@ -399,14 +399,18 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
<tt class="computeroutput"><span class="identifier">pure_virtual</span></tt> signals Boost.Python
|
||||
that the function <tt class="computeroutput"><span class="identifier">f</span></tt> is a
|
||||
<code class="computeroutput"><span class="identifier">pure_virtual</span></code> signals Boost.Python
|
||||
that the function <code class="computeroutput"><span class="identifier">f</span></code> is a
|
||||
pure virtual function.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>member function and methods</b></span><br>
|
||||
<br> Python, like many object oriented languages uses the term <span class="bold"><b>methods</b></span>. Methods correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>member function and
|
||||
methods</strong></span><br> <br> Python, like many object oriented languages
|
||||
uses the term <span class="bold"><strong>methods</strong></span>. Methods correspond
|
||||
roughly to C++'s <span class="bold"><strong>member functions</strong></span>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
@@ -414,7 +418,7 @@
|
||||
<p>
|
||||
We've seen in the previous section how classes with pure virtual functions
|
||||
are wrapped using Boost.Python's <a href="../../../../v2/wrapper.html" target="_top">class
|
||||
wrapper</a> facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual
|
||||
wrapper</a> facilities. If we wish to wrap <span class="bold"><strong>non</strong></span>-pure-virtual
|
||||
functions instead, the mechanism is a bit different.
|
||||
</p>
|
||||
<p>
|
||||
@@ -429,8 +433,8 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
had a pure virtual function <tt class="literal">f</tt>. If, however, its member
|
||||
function <tt class="literal">f</tt> was not declared as pure virtual:
|
||||
had a pure virtual function <code class="literal">f</code>. If, however, its member
|
||||
function <code class="literal">f</code> was not declared as pure virtual:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||
@@ -456,15 +460,16 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now,
|
||||
we have to check if there is an override for <tt class="computeroutput"><span class="identifier">f</span></tt>.
|
||||
If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to rewrite
|
||||
the line with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:<br> <br> <tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
|
||||
Notice how we implemented <code class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></code>. Now,
|
||||
we have to check if there is an override for <code class="computeroutput"><span class="identifier">f</span></code>.
|
||||
If none, then we call <code class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></code>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to rewrite
|
||||
the line with the <code class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></code> as:<br> <br> <code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Finally, exposing:
|
||||
</p>
|
||||
@@ -474,10 +479,10 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Take note that we expose both <tt class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
|
||||
of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
|
||||
to its default implementation <tt class="literal">default_f</tt>. There's a special
|
||||
<tt class="literal">def</tt> function for this purpose.
|
||||
Take note that we expose both <code class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></code> and <code class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></code>. Boost.Python needs to keep track
|
||||
of 1) the dispatch function <code class="literal">f</code> and 2) the forwarding function
|
||||
to its default implementation <code class="literal">default_f</code>. There's a special
|
||||
<code class="literal">def</code> function for this purpose.
|
||||
</p>
|
||||
<p>
|
||||
In Python, the results would be as expected:
|
||||
@@ -493,14 +498,14 @@
|
||||
<span class="special">>>></span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
|
||||
</pre>
|
||||
<p>
|
||||
Calling <tt class="literal">base.f()</tt>:
|
||||
Calling <code class="literal">base.f()</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
|
||||
<span class="number">0</span>
|
||||
</pre>
|
||||
<p>
|
||||
Calling <tt class="literal">derived.f()</tt>:
|
||||
Calling <code class="literal">derived.f()</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
|
||||
@@ -510,17 +515,17 @@
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
|
||||
<a name="class_operators_special_functions.python_operators"></a><h2>
|
||||
<a name="id453009"></a>
|
||||
<a name="class_operators_special_functions.python_operators"></a><h3>
|
||||
<a name="id3142031"></a>
|
||||
Python Operators
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
C is well known for the abundance of operators. C++ extends this to the extremes
|
||||
by allowing operator overloading. Boost.Python takes advantage of this and
|
||||
makes it easy to wrap C++ operator-powered classes.
|
||||
</p>
|
||||
<p>
|
||||
Consider a file position class <tt class="literal">FilePos</tt> and a set of operators
|
||||
Consider a file position class <code class="literal">FilePos</code> and a set of operators
|
||||
that take on FilePos instances:
|
||||
</p>
|
||||
<p>
|
||||
@@ -553,16 +558,16 @@
|
||||
<p>
|
||||
The code snippet above is very clear and needs almost no explanation at all.
|
||||
It is virtually the same as the operators' signatures. Just take note that
|
||||
<tt class="literal">self</tt> refers to FilePos object. Also, not every class
|
||||
<tt class="literal">T</tt> that you might need to interact with in an operator
|
||||
expression is (cheaply) default-constructible. You can use <tt class="literal">other<T>()</tt>
|
||||
in place of an actual <tt class="literal">T</tt> instance when writing "self
|
||||
<code class="literal">self</code> refers to FilePos object. Also, not every class
|
||||
<code class="literal">T</code> that you might need to interact with in an operator
|
||||
expression is (cheaply) default-constructible. You can use <code class="literal">other<T>()</code>
|
||||
in place of an actual <code class="literal">T</code> instance when writing "self
|
||||
expressions".
|
||||
</p>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h2>
|
||||
<a name="id453761"></a>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h3>
|
||||
<a name="id3142715"></a>
|
||||
Special Methods
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python
|
||||
supports all of the standard special method names supported by real Python
|
||||
@@ -588,12 +593,11 @@
|
||||
<p>
|
||||
Need we say more?
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>? Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt>
|
||||
requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>
|
||||
to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt> is used by the method defined by
|
||||
<tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> What is the business of <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code>? Well, the method <code class="computeroutput"><span class="identifier">str</span></code> requires the <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code> to do its work (i.e. <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code>
|
||||
is used by the method defined by <code class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Functions</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="exposing.html" title=" Exposing Classes">
|
||||
<link rel="next" href="object.html" title=" Object Interface">
|
||||
<link rel="prev" href="exposing.html" title="Exposing Classes">
|
||||
<link rel="next" href="object.html" title="Object Interface">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -46,7 +43,7 @@
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
But before you do, you might want to fire up Python 2.2 or later and type
|
||||
<tt class="literal">>>> import this</tt>.
|
||||
<code class="literal">>>> import this</code>.
|
||||
</p>
|
||||
<pre class="programlisting">>>> import this
|
||||
The Zen of Python, by Tim Peters
|
||||
@@ -65,7 +62,7 @@ In the face of ambiguity, refuse the temptation to guess.
|
||||
There should be one-- and preferably only one --obvious way to do it
|
||||
Although that way may not be obvious at first unless you're Dutch.
|
||||
Now is better than never.
|
||||
Although never is often better than <span class="bold"><b>right</b></span> now.
|
||||
Although never is often better than <span class="bold"><strong>right</strong></span> now.
|
||||
If the implementation is hard to explain, it's a bad idea.
|
||||
If the implementation is easy to explain, it may be a good idea.
|
||||
Namespaces are one honking great idea -- let's do more of those!
|
||||
@@ -123,19 +120,19 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||
and a pointer to <tt class="literal">z</tt>
|
||||
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code>
|
||||
and a pointer to <code class="literal">z</code>
|
||||
</li>
|
||||
<li>
|
||||
A reference to <tt class="literal">y.x</tt> is returned
|
||||
A reference to <code class="literal">y.x</code> is returned
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference
|
||||
<code class="literal">y</code> is deleted. <code class="literal">x</code> is a dangling reference
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">x.some_method()</tt> is called
|
||||
<code class="literal">x.some_method()</code> is called
|
||||
</li>
|
||||
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||
<li><span class="bold"><strong>BOOM!</strong></span></li>
|
||||
</ol></div>
|
||||
<p>
|
||||
We could copy result into a new object:
|
||||
@@ -165,7 +162,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice that the data member <tt class="literal">z</tt> is held by class Y using
|
||||
Notice that the data member <code class="literal">z</code> is held by class Y using
|
||||
a raw pointer. Now we have a potential dangling pointer problem inside Y:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -174,7 +171,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">>>></span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||
</pre>
|
||||
<p>
|
||||
For reference, here's the implementation of <tt class="literal">f</tt> again:
|
||||
For reference, here's the implementation of <code class="literal">f</code> again:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">X</span><span class="special">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
|
||||
@@ -188,33 +185,33 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||
and a pointer to <tt class="literal">z</tt>
|
||||
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code>
|
||||
and a pointer to <code class="literal">z</code>
|
||||
</li>
|
||||
<li>
|
||||
A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt>
|
||||
A pointer to <code class="literal">z</code> is held by <code class="literal">y</code>
|
||||
</li>
|
||||
<li>
|
||||
A reference to <tt class="literal">y.x</tt> is returned
|
||||
A reference to <code class="literal">y.x</code> is returned
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer
|
||||
<code class="literal">z</code> is deleted. <code class="literal">y.z</code> is a dangling pointer
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">y.z_value()</tt> is called
|
||||
<code class="literal">y.z_value()</code> is called
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">z->value()</tt> is called
|
||||
<code class="literal">z->value()</code> is called
|
||||
</li>
|
||||
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||
<li><span class="bold"><strong>BOOM!</strong></span></li>
|
||||
</ol></div>
|
||||
<a name="call_policies.call_policies"></a><h2>
|
||||
<a name="id455614"></a>
|
||||
<a name="call_policies.call_policies"></a><h3>
|
||||
<a name="id3144432"></a>
|
||||
Call Policies
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Call Policies may be used in situations such as the example detailed above.
|
||||
In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
|
||||
In our example, <code class="literal">return_internal_reference</code> and <code class="literal">with_custodian_and_ward</code>
|
||||
are our friends:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -223,27 +220,27 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span> <span class="special">>());</span>
|
||||
</pre>
|
||||
<p>
|
||||
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
|
||||
What are the <code class="literal">1</code> and <code class="literal">2</code> parameters, you
|
||||
ask?
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">return_internal_reference</span><span class="special"><</span><span class="number">1</span>
|
||||
</pre>
|
||||
<p>
|
||||
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&
|
||||
y</tt>, is the owner of the returned reference: <tt class="literal">X&</tt>.
|
||||
The "<tt class="literal">1</tt>" simply specifies the first argument.
|
||||
In short: "return an internal reference <tt class="literal">X&</tt> owned
|
||||
by the 1st argument <tt class="literal">Y& y</tt>".
|
||||
Informs Boost.Python that the first argument, in our case <code class="literal">Y&
|
||||
y</code>, is the owner of the returned reference: <code class="literal">X&</code>.
|
||||
The "<code class="literal">1</code>" simply specifies the first argument.
|
||||
In short: "return an internal reference <code class="literal">X&</code> owned
|
||||
by the 1st argument <code class="literal">Y& y</code>".
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span>
|
||||
</pre>
|
||||
<p>
|
||||
Informs Boost.Python that the lifetime of the argument indicated by ward
|
||||
(i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
|
||||
of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&
|
||||
y</tt>).
|
||||
(i.e. the 2nd argument: <code class="literal">Z* z</code>) is dependent on the lifetime
|
||||
of the argument indicated by custodian (i.e. the 1st argument: <code class="literal">Y&
|
||||
y</code>).
|
||||
</p>
|
||||
<p>
|
||||
It is also important to note that we have defined two policies above. Two
|
||||
@@ -260,41 +257,43 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
<span class="bold"><b>with_custodian_and_ward</b></span><br> Ties lifetimes
|
||||
<span class="bold"><strong>with_custodian_and_ward</strong></span><br> Ties lifetimes
|
||||
of the arguments
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>with_custodian_and_ward_postcall</b></span><br>
|
||||
<span class="bold"><strong>with_custodian_and_ward_postcall</strong></span><br>
|
||||
Ties lifetimes of the arguments and results
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>return_internal_reference</b></span><br> Ties lifetime
|
||||
<span class="bold"><strong>return_internal_reference</strong></span><br> Ties lifetime
|
||||
of one argument to that of result
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>return_value_policy<T> with T one of:</b></span><br>
|
||||
<span class="bold"><strong>return_value_policy<T> with T one of:</strong></span><br>
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>reference_existing_object</b></span><br> naive
|
||||
<span class="bold"><strong>reference_existing_object</strong></span><br> naive
|
||||
(dangerous) approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>copy_const_reference</b></span><br> Boost.Python
|
||||
<span class="bold"><strong>copy_const_reference</strong></span><br> Boost.Python
|
||||
v1 approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>copy_non_const_reference</b></span><br>
|
||||
<span class="bold"><strong>copy_non_const_reference</strong></span><br>
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>manage_new_object</b></span><br> Adopt a pointer
|
||||
<span class="bold"><strong>manage_new_object</strong></span><br> Adopt a pointer
|
||||
and hold the instance
|
||||
</li>
|
||||
</ul></div>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><b>Remember the Zen, Luke:</b></span><br>
|
||||
<br> "Explicit is better than implicit"<br> "In the face
|
||||
of ambiguity, refuse the temptation to guess"<br>
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><strong>Remember the Zen, Luke:</strong></span><br>
|
||||
<br> "Explicit is better than implicit"<br> "In
|
||||
the face of ambiguity, refuse the temptation to guess"<br>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
@@ -356,21 +355,21 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
|
||||
pointers carry no default argument info. Take a function <tt class="literal">f</tt>
|
||||
pointers carry no default argument info. Take a function <code class="literal">f</code>
|
||||
with default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span> <span class="special">=</span> <span class="number">3.14</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="special">=</span> <span class="string">"hello"</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
But the type of a pointer to the function <tt class="literal">f</tt> has no information
|
||||
But the type of a pointer to the function <code class="literal">f</code> has no information
|
||||
about its default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">int</span><span class="special">(*</span><span class="identifier">g</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*)</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">;</span> <span class="comment">// defaults lost!
|
||||
</span></pre>
|
||||
<p>
|
||||
When we pass this function pointer to the <tt class="literal">def</tt> function,
|
||||
When we pass this function pointer to the <code class="literal">def</code> function,
|
||||
there is no way to retrieve the default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -404,10 +403,10 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
are overloaded with a common sequence of initial arguments
|
||||
</li>
|
||||
</ul></div>
|
||||
<a name="default_arguments.boost_python_function_overloads"></a><h2>
|
||||
<a name="id457647"></a>
|
||||
<a name="default_arguments.boost_python_function_overloads"></a><h3>
|
||||
<a name="id3146300"></a>
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Boost.Python now has a way to make it easier. For instance, given a function:
|
||||
</p>
|
||||
@@ -425,19 +424,19 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</pre>
|
||||
<p>
|
||||
will automatically create the thin wrappers for us. This macro will create
|
||||
a class <tt class="literal">foo_overloads</tt> that can be passed on to <tt class="literal">def(...)</tt>.
|
||||
a class <code class="literal">foo_overloads</code> that can be passed on to <code class="literal">def(...)</code>.
|
||||
The third and fourth macro argument are the minimum arguments and maximum
|
||||
arguments, respectively. In our <tt class="literal">foo</tt> function the minimum
|
||||
number of arguments is 1 and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
|
||||
arguments, respectively. In our <code class="literal">foo</code> function the minimum
|
||||
number of arguments is 1 and the maximum number of arguments is 4. The <code class="literal">def(...)</code>
|
||||
function will automatically add all the foo variants for us:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span>
|
||||
</pre>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
|
||||
<a name="id457963"></a>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h3>
|
||||
<a name="id3146587"></a>
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Objects here, objects there, objects here there everywhere. More frequently
|
||||
than anything else, we need to expose member functions of our classes to
|
||||
@@ -446,7 +445,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
play. Another macro is provided to make this a breeze.
|
||||
</p>
|
||||
<p>
|
||||
Like <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
Like <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>, <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
may be used to automatically create the thin wrappers for wrapping member
|
||||
functions. Let's have an example:
|
||||
</p>
|
||||
@@ -467,11 +466,11 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">george_overloads</span><span class="special">,</span> <span class="identifier">wack_em</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt>
|
||||
will generate a set of thin wrappers for george's <code class="literal">wack_em</code>
|
||||
member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
|
||||
the third and fourth macro argument). The thin wrappers are all enclosed
|
||||
in a class named <tt class="literal">george_overloads</tt> that can then be used
|
||||
as an argument to <tt class="literal">def(...)</tt>:
|
||||
in a class named <code class="literal">george_overloads</code> that can then be used
|
||||
as an argument to <code class="literal">def(...)</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"wack_em"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span>
|
||||
@@ -480,13 +479,13 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads
|
||||
reference</a> for details.
|
||||
</p>
|
||||
<a name="default_arguments.init_and_optional"></a><h2>
|
||||
<a name="id458323"></a>
|
||||
<a name="default_arguments.init_and_optional"></a><h3>
|
||||
<a name="id3146923"></a>
|
||||
init and optional
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
A similar facility is provided for class constructors, again, with default
|
||||
arguments or a sequence of overloads. Remember <tt class="literal">init<...></tt>?
|
||||
arguments or a sequence of overloads. Remember <code class="literal">init<...></code>?
|
||||
For example, given a class X with a constructor:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -503,7 +502,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">></span> <span class="special">>())</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice the use of <tt class="literal">init<...></tt> and <tt class="literal">optional<...></tt>
|
||||
Notice the use of <code class="literal">init<...></code> and <code class="literal">optional<...></code>
|
||||
to signify the default (optional arguments).
|
||||
</p>
|
||||
</div>
|
||||
@@ -511,8 +510,8 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
|
||||
<p>
|
||||
It was mentioned in passing in the previous section that <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>
|
||||
and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> can also be
|
||||
It was mentioned in passing in the previous section that <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>
|
||||
and <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code> can also be
|
||||
used for overloaded functions and member functions with a common sequence
|
||||
of initial arguments. Here is an example:
|
||||
</p>
|
||||
@@ -554,24 +553,24 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
Notice though that we have a situation now where we have a minimum of zero
|
||||
(0) arguments and a maximum of 3 arguments.
|
||||
</p>
|
||||
<a name="auto_overloading.manual_wrapping"></a><h2>
|
||||
<a name="id459095"></a>
|
||||
<a name="auto_overloading.manual_wrapping"></a><h3>
|
||||
<a name="id3147627"></a>
|
||||
Manual Wrapping
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
It is important to emphasize however that <span class="bold"><b>the overloaded
|
||||
functions must have a common sequence of initial arguments</b></span>. Otherwise,
|
||||
It is important to emphasize however that <span class="bold"><strong>the overloaded
|
||||
functions must have a common sequence of initial arguments</strong></span>. Otherwise,
|
||||
our scheme above will not work. If this is not the case, we have to wrap
|
||||
our functions <a href="functions.html#python.overloading" title="Overloading">manually</a>.
|
||||
</p>
|
||||
<p>
|
||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||
automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
and its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following
|
||||
automatic wrapping through <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
and its sister, <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>. Following
|
||||
up on our example presented in the section <a href="functions.html#python.overloading" title="Overloading">on
|
||||
overloading</a>, since the first 4 overload functins have a common sequence
|
||||
of initial arguments, we can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
to automatically wrap the first three of the <tt class="literal">def</tt>s and
|
||||
of initial arguments, we can use <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
to automatically wrap the first three of the <code class="literal">def</code>s and
|
||||
manually wrap just the last. Here's how we'll do this:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Building Hello World</title>
|
||||
<title>Building Hello World</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="exposing.html" title=" Exposing Classes">
|
||||
<link rel="next" href="exposing.html" title="Exposing Classes">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -28,26 +25,27 @@
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
|
||||
<a name="hello.from_start_to_finish"></a><h2>
|
||||
<a name="id377427"></a>
|
||||
<a name="hello.from_start_to_finish"></a><h3>
|
||||
<a name="id3091224"></a>
|
||||
From Start To Finish
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Now the first thing you'd want to do is to build the Hello World module and
|
||||
try it for yourself in Python. In this section, we shall outline the steps
|
||||
necessary to achieve that. We shall use the build tool that comes bundled with
|
||||
every boost distribution: <span class="bold"><b>bjam</b></span>.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Building without bjam</b></span><br>
|
||||
<br> Besides bjam, there are of course other ways to get your module built.
|
||||
What's written here should not be taken as "the one and only way".
|
||||
There are of course other build tools apart from <tt class="literal">bjam</tt>.<br>
|
||||
<br> Take note however that the preferred build tool for Boost.Python is
|
||||
bjam. There are so many ways to set up the build incorrectly. Experience shows
|
||||
that 90% of the "I can't build Boost.Python" problems come from people
|
||||
who had to use a different tool.
|
||||
every boost distribution: <span class="bold"><strong>bjam</strong></span>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>Building without bjam</strong></span><br>
|
||||
<br> Besides bjam, there are of course other ways to get your module
|
||||
built. What's written here should not be taken as "the one and only
|
||||
way". There are of course other build tools apart from <code class="literal">bjam</code>.<br>
|
||||
<br> Take note however that the preferred build tool for Boost.Python
|
||||
is bjam. There are so many ways to set up the build incorrectly. Experience
|
||||
shows that 90% of the "I can't build Boost.Python" problems
|
||||
come from people who had to use a different tool. </td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
We shall skip over the details. Our objective will be to simply create the
|
||||
hello world module and run it in Python. For a complete reference to building
|
||||
@@ -78,7 +76,7 @@
|
||||
if you are on Unix.
|
||||
</p>
|
||||
<p>
|
||||
The tutorial example can be found in the directory: <tt class="literal">libs/python/example/tutorial</tt>.
|
||||
The tutorial example can be found in the directory: <code class="literal">libs/python/example/tutorial</code>.
|
||||
There, you can find:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -90,20 +88,20 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The
|
||||
<tt class="literal">Jamfile</tt> is a minimalist <span class="emphasis"><em>bjam</em></span> script
|
||||
The <code class="literal">hello.cpp</code> file is our C++ hello world example. The
|
||||
<code class="literal">Jamfile</code> is a minimalist <span class="emphasis"><em>bjam</em></span> script
|
||||
that builds the DLLs for us.
|
||||
</p>
|
||||
<p>
|
||||
Before anything else, you should have the bjam executable in your boost directory
|
||||
or somewhere in your path such that <tt class="literal">bjam</tt> can be executed
|
||||
or somewhere in your path such that <code class="literal">bjam</code> can be executed
|
||||
in the command line. Pre-built Boost.Jam executables are available for most
|
||||
platforms. The complete list of Bjam executables can be found <a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.
|
||||
</p>
|
||||
<a name="hello.let_s_jam_"></a><h2>
|
||||
<a name="id377613"></a>
|
||||
<a name="hello.let_s_jam_"></a><h3>
|
||||
<a name="id3091427"></a>
|
||||
Let's Jam!
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/jam.png" alt="jam"></span>
|
||||
</p>
|
||||
@@ -123,13 +121,13 @@ extension hello # Declare a Python extension called hello
|
||||
</pre>
|
||||
<p>
|
||||
First, we need to specify our location. You may place your project anywhere.
|
||||
<tt class="literal">project-root</tt> allows you to do that.
|
||||
<code class="literal">project-root</code> allows you to do that.
|
||||
</p>
|
||||
<pre class="programlisting">project-root ;
|
||||
</pre>
|
||||
<p>
|
||||
By doing so, you'll need a Jamrules file. Simply copy the one in the <a href="../../../../../example/tutorial/Jamrules" target="_top">example/tutorial directory</a>
|
||||
and tweak the <tt class="literal">path-global BOOST_ROOT</tt> to where your boost
|
||||
and tweak the <code class="literal">path-global BOOST_ROOT</code> to where your boost
|
||||
root directory is. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||
instructions</a> you can follow.
|
||||
</p>
|
||||
@@ -139,7 +137,7 @@ extension hello # Declare a Python extension called hello
|
||||
<pre class="programlisting">import python ;
|
||||
</pre>
|
||||
<p>
|
||||
Finally we declare our <tt class="literal">hello</tt> extension:
|
||||
Finally we declare our <code class="literal">hello</code> extension:
|
||||
</p>
|
||||
<pre class="programlisting">extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
@@ -151,10 +149,10 @@ extension hello # Declare a Python extension called hello
|
||||
<p>
|
||||
The last part tells BJam that we are depending on the Boost Python Library.
|
||||
</p>
|
||||
<a name="hello.running_bjam"></a><h2>
|
||||
<a name="id377751"></a>
|
||||
<a name="hello.running_bjam"></a><h3>
|
||||
<a name="id3091556"></a>
|
||||
Running bjam
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
<span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
|
||||
interpreter.
|
||||
@@ -164,7 +162,7 @@ extension hello # Declare a Python extension called hello
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
Make sure that the environment is set so that we can invoke the C++ compiler.
|
||||
With MSVC, that would mean running the <tt class="literal">Vcvars32.bat</tt> batch
|
||||
With MSVC, that would mean running the <code class="literal">Vcvars32.bat</code> batch
|
||||
file. For instance:
|
||||
</p>
|
||||
<pre class="programlisting">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
|
||||
@@ -177,21 +175,22 @@ extension hello # Declare a Python extension called hello
|
||||
set PYTHON_VERSION=2.2
|
||||
</pre>
|
||||
<p>
|
||||
The above assumes that the Python installation is in <tt class="literal">c:/dev/tools/python</tt>
|
||||
The above assumes that the Python installation is in <code class="literal">c:/dev/tools/python</code>
|
||||
and that we are using Python version 2.2. You'll have to tweak these appropriately.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span> "2.2.1", even if that's the version you
|
||||
have.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Be sure not to include a third number, e.g. <span class="bold"><strong>not</strong></span> "2.2.1", even if that's the version
|
||||
you have.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Take note that you may also do that through the Jamrules file we put in our
|
||||
project as detailed above. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||
instructions</a> you can follow.
|
||||
</p>
|
||||
<p>
|
||||
Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt>
|
||||
where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamfile"</tt>
|
||||
Now we are ready... Be sure to <code class="literal">cd</code> to <code class="literal">libs/python/example/tutorial</code>
|
||||
where the tutorial <code class="literal">"hello.cpp"</code> and the <code class="literal">"Jamfile"</code>
|
||||
is situated.
|
||||
</p>
|
||||
<p>
|
||||
@@ -254,8 +253,8 @@ b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
if you are on Unix.
|
||||
</p>
|
||||
<p>
|
||||
<tt class="literal">boost_python.dll</tt> and <tt class="literal">hello.pyd</tt> can be
|
||||
found somewhere in your project's <tt class="literal">bin</tt> directory. After a
|
||||
<code class="literal">boost_python.dll</code> and <code class="literal">hello.pyd</code> can be
|
||||
found somewhere in your project's <code class="literal">bin</code> directory. After a
|
||||
successful build, you make it possible for the system to find boost_python.dll
|
||||
or libboost_python.so (usually done with LD_LIBRARY_PATH, DYLD_LIBRARY_PATH,
|
||||
or some other variable on *nix and with PATH on Windows) and for Python to
|
||||
@@ -274,7 +273,7 @@ b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="bold"><b>There you go... Have fun!</b></span>
|
||||
<span class="bold"><strong>There you go... Have fun!</strong></span>
|
||||
</p></blockquote></div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Iterators</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="embedding.html" title="Embedding">
|
||||
<link rel="next" href="exception.html" title=" Exception Translation">
|
||||
<link rel="next" href="exception.html" title="Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -33,7 +30,7 @@
|
||||
iterators, but these are two very different beasts.
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><b>C++ iterators:</b></span>
|
||||
<span class="bold"><strong>C++ iterators:</strong></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
@@ -48,7 +45,7 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
<span class="bold"><b>Python Iterators:</b></span>
|
||||
<span class="bold"><strong>Python Iterators:</strong></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
@@ -62,8 +59,8 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y
|
||||
in x...</b></span></tt> is as follows:
|
||||
The typical Python iteration protocol: <code class="literal"><span class="bold"><strong>for y
|
||||
in x...</strong></span></code> is as follows:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -77,7 +74,7 @@
|
||||
</span></pre>
|
||||
<p>
|
||||
Boost.Python provides some mechanisms to make C++ iterators play along nicely
|
||||
as Python iterators. What we need to do is to produce appropriate <tt class="computeroutput"><span class="identifier">__iter__</span></tt> function from C++ iterators that
|
||||
as Python iterators. What we need to do is to produce appropriate <code class="computeroutput"><span class="identifier">__iter__</span></code> function from C++ iterators that
|
||||
is compatible with the Python iteration protocol. For example:
|
||||
</p>
|
||||
<p>
|
||||
@@ -94,7 +91,7 @@
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"__iter__"</span><span class="special">,</span> <span class="identifier">iterator</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>())</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><b>range</b></span>
|
||||
<span class="bold"><strong>range</strong></span>
|
||||
</p>
|
||||
<p>
|
||||
We can create a Python savvy iterator using the range function:
|
||||
@@ -122,14 +119,14 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
<span class="bold"><b>iterator</b></span>
|
||||
<span class="bold"><strong>iterator</strong></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc"><li>
|
||||
iterator<T, Policies>()
|
||||
</li></ul></div>
|
||||
<p>
|
||||
Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
|
||||
calls <tt class="literal">range</tt> with &T::begin, &T::end.
|
||||
Given a container <code class="literal">T</code>, iterator is a shortcut that simply
|
||||
calls <code class="literal">range</code> with &T::begin, &T::end.
|
||||
</p>
|
||||
<p>
|
||||
Let's put this into action... Here's an example from some hypothetical bogon
|
||||
@@ -155,14 +152,14 @@
|
||||
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"bogons"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><b>stl_input_iterator</b></span>
|
||||
<span class="bold"><strong>stl_input_iterator</strong></span>
|
||||
</p>
|
||||
<p>
|
||||
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
|
||||
we wish to go the other way, though: we'd like to pass a Python sequence to
|
||||
an STL algorithm or use it to initialize an STL container. We need to make
|
||||
a Python iterator look like an STL iterator. For that, we use <tt class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></tt>.
|
||||
Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
|
||||
a Python iterator look like an STL iterator. For that, we use <code class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></code>.
|
||||
Consider how we might implement a function that exposes <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></code> to Python:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -181,7 +178,7 @@
|
||||
</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now in Python, we can assign any integer sequence to <tt class="computeroutput"><span class="identifier">list_int</span></tt>
|
||||
Now in Python, we can assign any integer sequence to <code class="computeroutput"><span class="identifier">list_int</span></code>
|
||||
objects:
|
||||
</p>
|
||||
<p>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Object Interface</title>
|
||||
<title>Object Interface</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="functions.html" title="Functions">
|
||||
@@ -38,13 +35,13 @@
|
||||
Python is dynamically typed, unlike C++ which is statically typed. Python variables
|
||||
may hold an integer, a float, list, dict, tuple, str, long etc., among other
|
||||
things. In the viewpoint of Boost.Python and C++, these Pythonic variables
|
||||
are just instances of class <tt class="literal">object</tt>. We shall see in this
|
||||
are just instances of class <code class="literal">object</code>. We shall see in this
|
||||
chapter how to deal with Python objects.
|
||||
</p>
|
||||
<p>
|
||||
As mentioned, one of the goals of Boost.Python is to provide a bidirectional
|
||||
mapping between C++ and Python while maintaining the Python feel. Boost.Python
|
||||
C++ <tt class="literal">object</tt>s are as close as possible to Python. This should
|
||||
C++ <code class="literal">object</code>s are as close as possible to Python. This should
|
||||
minimize the learning curve significantly.
|
||||
</p>
|
||||
<p>
|
||||
@@ -54,10 +51,10 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
|
||||
<p>
|
||||
Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the
|
||||
intricacies of dealing with <tt class="literal">PyObject</tt>s such as managing
|
||||
reference counting are handled by the <tt class="literal">object</tt> class. C++
|
||||
object interoperability is seamless. Boost.Python C++ <tt class="literal">object</tt>s
|
||||
Class <code class="literal">object</code> wraps <code class="literal">PyObject*</code>. All the
|
||||
intricacies of dealing with <code class="literal">PyObject</code>s such as managing
|
||||
reference counting are handled by the <code class="literal">object</code> class. C++
|
||||
object interoperability is seamless. Boost.Python C++ <code class="literal">object</code>s
|
||||
can in fact be explicitly constructed from any C++ object.
|
||||
</p>
|
||||
<p>
|
||||
@@ -102,7 +99,7 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python comes with a set of derived <tt class="literal">object</tt> types
|
||||
Boost.Python comes with a set of derived <code class="literal">object</code> types
|
||||
corresponding to that of Python's:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -126,32 +123,32 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
These derived <tt class="literal">object</tt> types act like real Python types.
|
||||
These derived <code class="literal">object</code> types act like real Python types.
|
||||
For instance:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">==></span> <span class="string">"1"</span>
|
||||
</pre>
|
||||
<p>
|
||||
Wherever appropriate, a particular derived <tt class="literal">object</tt> has
|
||||
corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
|
||||
has a <tt class="literal">keys()</tt> method:
|
||||
Wherever appropriate, a particular derived <code class="literal">object</code> has
|
||||
corresponding Python type's methods. For instance, <code class="literal">dict</code>
|
||||
has a <code class="literal">keys()</code> method:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span>
|
||||
</pre>
|
||||
<p>
|
||||
<tt class="literal">make_tuple</tt> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
|
||||
<code class="literal">make_tuple</code> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
|
||||
Example:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">make_tuple</span><span class="special">(</span><span class="number">123</span><span class="special">,</span> <span class="char">'D'</span><span class="special">,</span> <span class="string">"Hello, World"</span><span class="special">,</span> <span class="number">0.0</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments
|
||||
In C++, when Boost.Python <code class="literal">object</code>s are used as arguments
|
||||
to functions, subtype matching is required. For example, when a function
|
||||
<tt class="literal">f</tt>, as declared below, is wrapped, it will only accept
|
||||
instances of Python's <tt class="literal">str</tt> type and subtypes.
|
||||
<code class="literal">f</code>, as declared below, is wrapped, it will only accept
|
||||
instances of Python's <code class="literal">str</code> type and subtypes.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
|
||||
@@ -175,15 +172,16 @@
|
||||
<span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Demonstrates that you can write the C++ equivalent of <tt class="literal">"format"
|
||||
% x,y,z</tt> in Python, which is useful since there's no easy way to
|
||||
Demonstrates that you can write the C++ equivalent of <code class="literal">"format"
|
||||
% x,y,z</code> in Python, which is useful since there's no easy way to
|
||||
do that in std C++.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>Beware</b></span> the common
|
||||
pitfall of forgetting that the constructors of most of Python's mutable types
|
||||
make copies, just as in Python.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>Beware</strong></span> the
|
||||
common pitfall of forgetting that the constructors of most of Python's
|
||||
mutable types make copies, just as in Python. </td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Python:
|
||||
</p>
|
||||
@@ -198,12 +196,12 @@
|
||||
<span class="identifier">dict</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span> <span class="comment">// copies x.__dict__
|
||||
</span><span class="identifier">d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies the copy
|
||||
</span></pre>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
|
||||
<a name="id461067"></a>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h3>
|
||||
<a name="id3149441"></a>
|
||||
class_<T> as objects
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt>
|
||||
Due to the dynamic nature of Boost.Python objects, any <code class="literal">class_<T></code>
|
||||
may also be one of these types! The following code snippet wraps the class
|
||||
(type) object.
|
||||
</p>
|
||||
@@ -225,15 +223,15 @@
|
||||
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
|
||||
<p>
|
||||
At some point, we will need to get C++ values out of object instances. This
|
||||
can be achieved with the <tt class="literal">extract<T></tt> function. Consider
|
||||
can be achieved with the <code class="literal">extract<T></code> function. Consider
|
||||
the following:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">);</span> <span class="comment">// compile error
|
||||
</span></pre>
|
||||
<p>
|
||||
In the code above, we got a compiler error because Boost.Python <tt class="literal">object</tt>
|
||||
can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what
|
||||
In the code above, we got a compiler error because Boost.Python <code class="literal">object</code>
|
||||
can't be implicitly converted to <code class="literal">double</code>s. Instead, what
|
||||
we wanted to do above can be achieved by writing:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -243,14 +241,14 @@
|
||||
</pre>
|
||||
<p>
|
||||
The first line attempts to extract the "length" attribute of the
|
||||
Boost.Python <tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span>
|
||||
the <tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt>.
|
||||
Boost.Python <code class="literal">object</code>. The second line attempts to <span class="emphasis"><em>extract</em></span>
|
||||
the <code class="literal">Vec2</code> object from held by the Boost.Python <code class="literal">object</code>.
|
||||
</p>
|
||||
<p>
|
||||
Take note that we said "attempt to" above. What if the Boost.Python
|
||||
<tt class="literal">object</tt> does not really hold a <tt class="literal">Vec2</tt>
|
||||
<code class="literal">object</code> does not really hold a <code class="literal">Vec2</code>
|
||||
type? This is certainly a possibility considering the dynamic nature of Python
|
||||
<tt class="literal">object</tt>s. To be on the safe side, if the C++ type can't
|
||||
<code class="literal">object</code>s. To be on the safe side, if the C++ type can't
|
||||
be extracted, an appropriate exception is thrown. To avoid an exception,
|
||||
we need to test for extractibility:
|
||||
</p>
|
||||
@@ -260,7 +258,7 @@
|
||||
<span class="identifier">Vec2</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <tt class="literal">extract<T></tt>
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <code class="literal">extract<T></code>
|
||||
facility in fact solves the mutable copying problem:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -273,8 +271,8 @@
|
||||
<a name="python.enums"></a>Enums</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python has a nifty facility to capture and wrap C++ enums. While Python
|
||||
has no <tt class="literal">enum</tt> type, we'll often want to expose our C++ enums
|
||||
to Python as an <tt class="literal">int</tt>. Boost.Python's enum facility makes
|
||||
has no <code class="literal">enum</code> type, we'll often want to expose our C++ enums
|
||||
to Python as an <code class="literal">int</code>. Boost.Python's enum facility makes
|
||||
this easy while taking care of the proper conversions from Python's dynamic
|
||||
typing to C++'s strong static typing (in C++, ints cannot be implicitly converted
|
||||
to enums). To illustrate, given a C++ enum:
|
||||
@@ -293,16 +291,18 @@
|
||||
</pre>
|
||||
<p>
|
||||
can be used to expose to Python. The new enum type is created in the current
|
||||
<tt class="literal">scope()</tt>, which is usually the current module. The snippet
|
||||
above creates a Python class derived from Python's <tt class="literal">int</tt>
|
||||
<code class="literal">scope()</code>, which is usually the current module. The snippet
|
||||
above creates a Python class derived from Python's <code class="literal">int</code>
|
||||
type which is associated with the C++ type passed as its first parameter.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>what is a scope?</b></span><br>
|
||||
<br> The scope is a class that has an associated global Python object which
|
||||
controls the Python namespace in which new extension classes and wrapped
|
||||
functions will be defined as attributes. Details can be found <a href="../../../../v2/scope.html" target="_top">here</a>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>what is a scope?</strong></span><br>
|
||||
<br> The scope is a class that has an associated global Python object
|
||||
which controls the Python namespace in which new extension classes
|
||||
and wrapped functions will be defined as attributes. Details can be
|
||||
found <a href="../../../../v2/scope.html" target="_top">here</a>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
You can access those values in Python as
|
||||
</p>
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> General Techniques</title>
|
||||
<title>General Techniques</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="exception.html" title=" Exception Translation">
|
||||
<link rel="prev" href="exception.html" title="Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -53,7 +50,7 @@
|
||||
<p>
|
||||
We have a C++ library that works with sounds: reading and writing various
|
||||
formats, applying filters to the sound data, etc. It is named (conveniently)
|
||||
<tt class="literal">sounds</tt>. Our library already has a neat C++ namespace hierarchy,
|
||||
<code class="literal">sounds</code>. Our library already has a neat C++ namespace hierarchy,
|
||||
like so:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -96,15 +93,16 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Compiling these files will generate the following Python extensions: <tt class="literal">core.pyd</tt>,
|
||||
<tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> The extension <tt class="literal">.pyd</tt> is used for python
|
||||
extension modules, which are just shared libraries. Using the default for
|
||||
your system, like <tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt>
|
||||
for Windows, works just as well.
|
||||
Compiling these files will generate the following Python extensions: <code class="literal">core.pyd</code>,
|
||||
<code class="literal">io.pyd</code> and <code class="literal">filters.pyd</code>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> The extension <code class="literal">.pyd</code> is used
|
||||
for python extension modules, which are just shared libraries. Using
|
||||
the default for your system, like <code class="literal">.so</code> for Unix and
|
||||
<code class="literal">.dll</code> for Windows, works just as well.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Now, we create this directory structure for our Python package:
|
||||
</p>
|
||||
@@ -115,12 +113,12 @@
|
||||
io.pyd
|
||||
</pre>
|
||||
<p>
|
||||
The file <tt class="literal">__init__.py</tt> is what tells Python that the directory
|
||||
<tt class="literal">sounds/</tt> is actually a Python package. It can be a empty
|
||||
The file <code class="literal">__init__.py</code> is what tells Python that the directory
|
||||
<code class="literal">sounds/</code> is actually a Python package. It can be a empty
|
||||
file, but can also perform some magic, that will be shown later.
|
||||
</p>
|
||||
<p>
|
||||
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt>
|
||||
Now our package is ready. All the user has to do is put <code class="literal">sounds</code>
|
||||
into his <a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
|
||||
and fire up the interpreter:
|
||||
</p>
|
||||
@@ -159,7 +157,7 @@
|
||||
</pre>
|
||||
<p>
|
||||
Note that we added an underscore to the module name. The filename will have
|
||||
to be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same
|
||||
to be changed to <code class="literal">_core.pyd</code> as well, and we do the same
|
||||
to the other extension modules. Now, we change our package hierarchy like
|
||||
so:
|
||||
</p>
|
||||
@@ -187,11 +185,11 @@
|
||||
<span class="special">>>></span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(...)</span>
|
||||
</pre>
|
||||
<p>
|
||||
which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
|
||||
magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
|
||||
which is not what we want. But here enters the <code class="literal">__init__.py</code>
|
||||
magic: everything that is brought to the <code class="literal">__init__.py</code> namespace
|
||||
can be accessed directly by the user. So, all we have to do is bring the
|
||||
entire namespace from <tt class="literal">_core.pyd</tt> to <tt class="literal">core/__init__.py</tt>.
|
||||
So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:
|
||||
entire namespace from <code class="literal">_core.pyd</code> to <code class="literal">core/__init__.py</code>.
|
||||
So add this line of code to <code class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span>
|
||||
@@ -208,10 +206,10 @@
|
||||
with the additional benefit that we can easily add pure Python functions
|
||||
to any module, in a way that the user can't tell the difference between a
|
||||
C++ function and a Python function. Let's add a <span class="emphasis"><em>pure</em></span>
|
||||
Python function, <tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt>
|
||||
package. This function applies both the <tt class="literal">echo</tt> and <tt class="literal">noise</tt>
|
||||
filters in sequence in the given <tt class="literal">sound</tt> object. We create
|
||||
a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our
|
||||
Python function, <code class="literal">echo_noise</code>, to the <code class="literal">filters</code>
|
||||
package. This function applies both the <code class="literal">echo</code> and <code class="literal">noise</code>
|
||||
filters in sequence in the given <code class="literal">sound</code> object. We create
|
||||
a file named <code class="literal">sounds/filters/echo_noise.py</code> and code our
|
||||
function:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -222,14 +220,14 @@
|
||||
<span class="keyword">return</span> <span class="identifier">s</span>
|
||||
</pre>
|
||||
<p>
|
||||
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:
|
||||
Next, we add this line to <code class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">from</span> <span class="identifier">echo_noise</span> <span class="keyword">import</span> <span class="identifier">echo_noise</span>
|
||||
</pre>
|
||||
<p>
|
||||
And that's it. The user now accesses this function like any other function
|
||||
from the <tt class="literal">filters</tt> package:
|
||||
from the <code class="literal">filters</code> package:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
|
||||
@@ -263,7 +261,7 @@
|
||||
</p>
|
||||
<p>
|
||||
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||
we have a class <tt class="literal">point</tt> in C++:
|
||||
we have a class <code class="literal">point</code> in C++:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -277,7 +275,7 @@
|
||||
</pre>
|
||||
<p>
|
||||
If we are using the technique from the previous session, <a href="techniques.html#python.creating_packages" title="Creating Packages">Creating
|
||||
Packages</a>, we can code directly into <tt class="literal">geom/__init__.py</tt>:
|
||||
Packages</a>, we can code directly into <code class="literal">geom/__init__.py</code>:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -292,7 +290,7 @@
|
||||
</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">__str__</span> <span class="special">=</span> <span class="identifier">point_str</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><b>All</b></span> point instances created from C++ will
|
||||
<span class="bold"><strong>All</strong></span> point instances created from C++ will
|
||||
also have this member function! This technique has several advantages:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -391,7 +389,7 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now you create a file <tt class="literal">main.cpp</tt>, which contains the <tt class="literal">BOOST_PYTHON_MODULE</tt>
|
||||
Now you create a file <code class="literal">main.cpp</code>, which contains the <code class="literal">BOOST_PYTHON_MODULE</code>
|
||||
macro, and call the various export functions inside it.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -427,17 +425,19 @@
|
||||
exporting it to Python at the same time: changes in a class will only demand
|
||||
the compilation of a single cpp, instead of the entire wrapper code.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
|
||||
take a look at the <tt class="literal">--multiple</tt> option, that generates the
|
||||
wrappers in various files as demonstrated here.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> This method is useful too if you are getting the error
|
||||
message <span class="emphasis"><em>"fatal error C1204:Compiler limit:internal structure
|
||||
overflow"</em></span> when compiling a large source file, as explained
|
||||
in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
|
||||
take a look at the <code class="literal">--multiple</code> option, that generates
|
||||
the wrappers in various files as demonstrated here.</td></tr></tbody>
|
||||
</table></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> This method is useful too if you are getting the
|
||||
error message <span class="emphasis"><em>"fatal error C1204:Compiler limit:internal
|
||||
structure overflow"</em></span> when compiling a large source file,
|
||||
as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1365,11 +1365,6 @@ create a new scope around a class:
|
||||
|
||||
[def Py_Initialize [@http://www.python.org/doc/current/api/initialization.html#l2h-652 Py_Initialize]]
|
||||
[def Py_Finalize [@http://www.python.org/doc/current/api/initialization.html#l2h-656 Py_Finalize]]
|
||||
[def PyRun_String [@http://www.python.org/doc/current/api/veryhigh.html#l2h-55 PyRun_String]]
|
||||
[def PyRun_File [@http://www.python.org/doc/current/api/veryhigh.html#l2h-56 PyRun_File]]
|
||||
[def Py_eval_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-58 Py_eval_input]]
|
||||
[def Py_file_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-59 Py_file_input]]
|
||||
[def Py_single_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-60 Py_single_input]]
|
||||
[def Py_XINCREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-65 Py_XINCREF]]
|
||||
[def Py_XDECREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-67 Py_XDECREF]]
|
||||
[def PyImport_AppendInittab [@http://www.python.org/doc/current/api/importing.html#l2h-137 PyImport_AppendInittab]]
|
||||
@@ -1396,17 +1391,17 @@ all. So stay tuned... :-)
|
||||
|
||||
[h2 Building embedded programs]
|
||||
|
||||
To be able to use embedding in your programs, they have to be linked to
|
||||
both Boost.Python's and Python's static link library.
|
||||
To be able to embed python into your programs, you have to link to
|
||||
both Boost.Python's as well as Python's own runtime library.
|
||||
|
||||
Boost.Python's static link library comes in two variants. Both are located
|
||||
Boost.Python's library comes in two variants. Both are located
|
||||
in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the
|
||||
variants are called [^boost_python.lib] (for release builds) and
|
||||
[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
|
||||
you probably haven't built Boost.Python yet. See
|
||||
[@../../../building.html Building and Testing] on how to do this.
|
||||
|
||||
Python's static link library can be found in the [^/libs] subdirectory of
|
||||
Python's library can be found in the [^/libs] subdirectory of
|
||||
your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
your major Python version number.
|
||||
|
||||
@@ -1444,7 +1439,11 @@ steps:
|
||||
|
||||
# Call other Python C API routines to use the interpreter.\n\n
|
||||
|
||||
# Call Py_Finalize() to stop the interpreter and release its resources.
|
||||
[/ # Call Py_Finalize() to stop the interpreter and release its resources.]
|
||||
|
||||
[blurb __note__ [*Note that at this time you must not call Py_Finalize() to stop the
|
||||
interpreter. This may be fixed in a future version of boost.python.]
|
||||
]
|
||||
|
||||
(Of course, there can be other C++ code between all of these steps.)
|
||||
|
||||
@@ -1461,171 +1460,76 @@ messy and especially hard to get right in the presence of C++ exceptions.
|
||||
Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
|
||||
[@../../../v2/object.html object] class templates to automate the process.
|
||||
|
||||
[h2 Reference-counting handles and objects]
|
||||
|
||||
There are two ways in which a function in the Python/C API can return a
|
||||
[^PyObject*]: as a ['borrowed reference] or as a ['new reference]. Which of
|
||||
these a function uses, is listed in that function's documentation. The two
|
||||
require slightely different approaches to reference-counting but both can
|
||||
be 'handled' by Boost.Python.
|
||||
|
||||
For a function returning a ['borrowed reference] we'll have to tell the
|
||||
[^handle] that the [^PyObject*] is borrowed with the aptly named
|
||||
[@../../../v2/handle.html#borrowed-spec borrowed] function. Two functions
|
||||
returning borrowed references are PyImport_AddModule and PyModule_GetDict.
|
||||
The former returns a reference to an already imported module, the latter
|
||||
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||
namespace of the [^__main__] module:
|
||||
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
For a function returning a ['new reference] we can just create a [^handle]
|
||||
out of the raw [^PyObject*] without wrapping it in a call to borrowed. One
|
||||
such function that returns a new reference is PyRun_String which we'll
|
||||
discuss in the next section.
|
||||
|
||||
[blurb __note__ [*Handle is a class ['template], so why haven't we been using any template parameters?]\n
|
||||
\n
|
||||
[^handle] has a single template parameter specifying the type of the managed object. This type is [^PyObject] 99% of the time, so the parameter was defaulted to [^PyObject] for convenience. Therefore we can use the shorthand [^handle<>] instead of the longer, but equivalent, [^handle<PyObject>].
|
||||
]
|
||||
|
||||
[h2 Running Python code]
|
||||
|
||||
To run Python code from C++ there is a family of functions in the API
|
||||
starting with the PyRun prefix. You can find the full list of these
|
||||
functions [@http://www.python.org/doc/current/api/veryhigh.html here]. They
|
||||
all work similarly so we will look at only one of them, namely:
|
||||
Boost.python provides three related functions to run Python code from C++.
|
||||
|
||||
PyObject* PyRun_String(char *str, int start, PyObject *globals, PyObject *locals)
|
||||
object eval(str expression, object globals = object(), object locals = object())
|
||||
object exec(str code, object globals = object(), object locals = object())
|
||||
object exec_file(str filename, object globals = object(), object locals = object())
|
||||
|
||||
PyRun_String takes the code to execute as a null-terminated (C-style)
|
||||
string in its [^str] parameter. The function returns a new reference to a
|
||||
Python object. Which object is returned depends on the [^start] paramater.
|
||||
eval evaluates the given expression and returns the resulting value.
|
||||
exec executes the given code (typically a set of statements) returning the result,
|
||||
and exec_file executes the code contained in the given file.
|
||||
|
||||
The [^start] parameter is the start symbol from the Python grammar to use
|
||||
for interpreting the code. The possible values are:
|
||||
|
||||
[table Start symbols
|
||||
|
||||
[[Py_eval_input] [for interpreting isolated expressions]]
|
||||
[[Py_file_input] [for interpreting sequences of statements]]
|
||||
[[Py_single_input] [for interpreting a single statement]]
|
||||
]
|
||||
|
||||
When using Py_eval_input, the input string must contain a single expression
|
||||
and its result is returned. When using Py_file_input, the string can
|
||||
contain an abitrary number of statements and None is returned.
|
||||
Py_single_input works in the same way as Py_file_input but only accepts a
|
||||
single statement.
|
||||
|
||||
Lastly, the [^globals] and [^locals] parameters are Python dictionaries
|
||||
The [^globals] and [^locals] parameters are Python dictionaries
|
||||
containing the globals and locals of the context in which to run the code.
|
||||
For most intents and purposes you can use the namespace dictionary of the
|
||||
[^__main__] module for both parameters.
|
||||
|
||||
We have already seen how to get the [^__main__] module's namespace so let's
|
||||
run some Python code in it:
|
||||
Boost.python provides a function to import a module:
|
||||
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
object import(str name)
|
||||
|
||||
import imports a python module (potentially loading it into the running process
|
||||
first), and returns it.
|
||||
|
||||
Let's import the [^__main__] module and run some Python code in its namespace:
|
||||
|
||||
object main_module = import("__main__");
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
handle<> ignored((PyRun_String(
|
||||
|
||||
"hello = file('hello.txt', 'w')\n"
|
||||
"hello.write('Hello world!')\n"
|
||||
"hello.close()"
|
||||
|
||||
, Py_file_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr())
|
||||
));
|
||||
|
||||
Because the Python/C API doesn't know anything about [^object]s, we used
|
||||
the object's [^ptr] member function to retrieve the [^PyObject*].
|
||||
object ignored = exec("hello = file('hello.txt', 'w')\n"
|
||||
"hello.write('Hello world!')\n"
|
||||
"hello.close()",
|
||||
main_namespace);
|
||||
|
||||
This should create a file called 'hello.txt' in the current directory
|
||||
containing a phrase that is well-known in programming circles.
|
||||
|
||||
[blurb
|
||||
__note__ [*Note] that we wrap the return value of PyRun_String in a
|
||||
(nameless) [^handle] even though we are not interested in it. If we didn't
|
||||
do this, the the returned object would be kept alive unnecessarily. Unless
|
||||
you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
|
||||
]
|
||||
[h2 Manipulating Python objects]
|
||||
|
||||
[h2 Beyond handles]
|
||||
|
||||
It's nice that [^handle] manages the reference counting details for us, but
|
||||
other than that it doesn't do much. Often we'd like to have a more useful
|
||||
class to manipulate Python objects. But we have already seen such a class
|
||||
above, and in the [@python/object.html previous section]: the aptly
|
||||
named [^object] class and it's derivatives. We've already seen that they
|
||||
can be constructed from a [^handle]. The following examples should further
|
||||
illustrate this fact:
|
||||
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
Often we'd like to have a class to manipulate Python objects.
|
||||
But we have already seen such a class above, and in the
|
||||
[@python/object.html previous section]: the aptly named [^object] class
|
||||
and its derivatives. We've already seen that they can be constructed from
|
||||
a [^handle]. The following examples should further illustrate this fact:
|
||||
|
||||
object main_module = import("__main__");
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
handle<> ignored((PyRun_String(
|
||||
|
||||
"result = 5 ** 2"
|
||||
|
||||
, Py_file_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr())
|
||||
));
|
||||
|
||||
object ignored = exec("result = 5 ** 2", main_namespace);
|
||||
int five_squared = extract<int>(main_namespace["result"]);
|
||||
|
||||
Here we create a dictionary object for the [^__main__] module's namespace.
|
||||
Then we assign 5 squared to the result variable and read this variable from
|
||||
the dictionary. Another way to achieve the same result is to let
|
||||
PyRun_String return the result directly with Py_eval_input:
|
||||
|
||||
object result((handle<>(
|
||||
PyRun_String("5 ** 2"
|
||||
, Py_eval_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr()))
|
||||
));
|
||||
the dictionary. Another way to achieve the same result is to use eval instead,
|
||||
which returns the result directly:
|
||||
|
||||
object result = eval("5 ** 2");
|
||||
int five_squared = extract<int>(result);
|
||||
|
||||
[blurb
|
||||
__note__ [*Note] that [^object]'s member function to return the wrapped
|
||||
[^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you
|
||||
take into account the different functions that [^object] and [^handle]
|
||||
perform.
|
||||
]
|
||||
|
||||
[h2 Exception handling]
|
||||
|
||||
If an exception occurs in the execution of some Python code, the PyRun_String
|
||||
function returns a null pointer. Constructing a [^handle] out of this null
|
||||
pointer throws [@../../../v2/errors.html#error_already_set-spec error_already_set],
|
||||
so basically, the Python exception is automatically translated into a
|
||||
C++ exception when using [^handle]:
|
||||
If an exception occurs in the evaluation of the python expression,
|
||||
[@../../../v2/errors.html#error_already_set-spec error_already_set] is thrown:
|
||||
|
||||
try
|
||||
{
|
||||
object result((handle<>(PyRun_String(
|
||||
"5/0"
|
||||
, Py_eval_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr()))
|
||||
));
|
||||
|
||||
object result = eval("5/0");
|
||||
// execution will never get here:
|
||||
int five_divided_by_zero = extract<int>(result);
|
||||
}
|
||||
catch(error_already_set)
|
||||
catch(error_already_set const &)
|
||||
{
|
||||
// handle the exception in some way
|
||||
}
|
||||
@@ -1639,7 +1543,7 @@ print the exception's traceback to the console, or comparing the type of the
|
||||
exception with those of the [@http://www.python.org/doc/api/standardExceptions.html
|
||||
standard exceptions]:
|
||||
|
||||
catch(error_already_set)
|
||||
catch(error_already_set const &)
|
||||
{
|
||||
if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
|
||||
{
|
||||
@@ -1655,21 +1559,6 @@ standard exceptions]:
|
||||
(To retrieve even more information from the exception you can use some of the other
|
||||
exception handling functions listed [@http://www.python.org/doc/api/exceptionHandling.html here].)
|
||||
|
||||
If you'd rather not have [^handle] throw a C++ exception when it is constructed, you
|
||||
can use the [@../../../v2/handle.html#allow_null-spec allow_null] function in the same
|
||||
way you'd use borrowed:
|
||||
|
||||
handle<> result((allow_null(PyRun_String(
|
||||
"5/0"
|
||||
, Py_eval_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr()))));
|
||||
|
||||
if (!result)
|
||||
// Python exception occurred
|
||||
else
|
||||
// everything went okay, it's safe to use the result
|
||||
|
||||
[endsect]
|
||||
[endsect] [/ Embedding]
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, click this
|
||||
<a href="doc/html/index.html">link</a>
|
||||
<a href="doc/html/index.html">link</a> <hr>
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,3 +1,7 @@
|
||||
.. Copyright David Abrahams 2006. Distributed under the Boost
|
||||
.. Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
Here's the plan:
|
||||
|
||||
I aim to provide an interface similar to that of Boost.Python v1's
|
||||
|
||||
@@ -132,4 +132,6 @@ BOOST_PYTHON_MODULE(my_ext)
|
||||
</p>
|
||||
|
||||
|
||||
<p><i>© Copyright Joel de Guzman 2003. </i>
|
||||
<p><i>© Copyright Joel de Guzman 2003. </i> Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -165,6 +165,8 @@ struct return_value_policy : Base
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002.</i> Distributed under the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#eval-spec"><code>eval</code></a></dt>
|
||||
<dt><a href="#exec-spec"><code>exec</code></a></dt>
|
||||
<dt><a href="#exec_file-spec"><code>exec_file</code></a></dt>
|
||||
</dl>
|
||||
@@ -52,6 +53,23 @@
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
|
||||
<h3><a name="eval-spec"></a><code>eval</code></h3>
|
||||
<pre>
|
||||
object eval(str expression,
|
||||
object globals = object(),
|
||||
object locals = object());
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
Evaluate Python expression from <code>expression</code> in the context
|
||||
specified by the dictionaries <code>globals</code> and <code>locals</code>.
|
||||
</dt>
|
||||
<dt><b>Returns:</b>
|
||||
An instance of <a href="object.html#object-spec">object</a>
|
||||
which holds the value of the expression.
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="exec-spec"></a><code>exec</code></h3>
|
||||
<pre>
|
||||
object exec(str code,
|
||||
|
||||
@@ -360,7 +360,8 @@
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
<p class="c3">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002.
|
||||
<p class="c3">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. Distributed
|
||||
under the Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
@@ -104,5 +104,7 @@ RuntimeError: Unidentifiable C++ Exception
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
Abrahams</a> 2002. </i> Distributed
|
||||
under the Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/numeric.hpp></title>
|
||||
</head>
|
||||
<title>Boost.Python - <boost/python/numeric.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||
</td>
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header <boost/python/numeric.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 align="center">Header <boost/python/numeric.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#array-spec">Class <code>array</code></a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#array-spec">Class <code>array</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#array-spec-synopsis">Class <code>array</code>
|
||||
synopsis</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#array-spec-synopsis">Class <code>array</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#array-spec-observers">Class <code>array</code>
|
||||
observer functions</a></dt>
|
||||
<dt><a href="#array-spec-observers">Class <code>array</code>
|
||||
observer functions</a></dt>
|
||||
|
||||
<dt><a href="#array-spec-statics">Class <code>array</code>
|
||||
static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="#array-spec-statics">Class <code>array</code> static
|
||||
functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
<h2><a name="introduction" id="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Exposes a <a href=
|
||||
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> for the Python
|
||||
<a href=
|
||||
"http://www.python.org/dev/doc/devel/lib/typesmapping.html">array</a>
|
||||
type.</p>
|
||||
<p>Exposes a <a href=
|
||||
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> for the Python
|
||||
<a href=
|
||||
"http://www.python.org/dev/doc/devel/lib/typesmapping.html">array</a>
|
||||
type.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
<h2><a name="classes" id="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="array-spec"></a>Class <code>array</code></h3>
|
||||
<h3><a name="array-spec" id="array-spec"></a>Class <code>array</code></h3>
|
||||
|
||||
<p>Provides access to the array types of <a href=
|
||||
"http://www.pfdubois.com/numpy/">Numerical Python</a>'s <a href=
|
||||
"http://www.pfdubois.com/numpy/#Numeric">Numeric</a> and <a href=
|
||||
"http://stsdas.stsci.edu/numarray/index.html">NumArray</a> modules. With
|
||||
the exception of the functions documented <a href=
|
||||
"#array-spec-observers">below</a>, the semantics of the constructors and
|
||||
member functions defined below can be fully understood by reading the <a
|
||||
href="ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
|
||||
definition. Since <code>array</code> is publicly derived from <code><a
|
||||
href="object.html#object-spec">object</a></code>, the public object
|
||||
interface applies to <code>array</code> instances as well.</p>
|
||||
<p>Provides access to the array types of <a href=
|
||||
"http://www.pfdubois.com/numpy/">Numerical Python</a>'s <a href=
|
||||
"http://www.pfdubois.com/numpy/#Numeric">Numeric</a> and <a href=
|
||||
"http://stsdas.stsci.edu/numarray/index.html">NumArray</a> modules. With
|
||||
the exception of the functions documented <a href=
|
||||
"#array-spec-observers">below</a>, the semantics of the constructors and
|
||||
member functions defined below can be fully understood by reading the
|
||||
<a href="ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
|
||||
definition. Since <code>array</code> is publicly derived from
|
||||
<code><a href="object.html#object-spec">object</a></code>, the public
|
||||
object interface applies to <code>array</code> instances as well.</p>
|
||||
|
||||
<p><a name="default_search"></a>The default behavior is to use
|
||||
<code>numarray.NDArray</code> as the associated Python type if the
|
||||
<code>numarray</code> module is installed in the default location.
|
||||
Otherwise it falls back to use <code>Numeric.ArrayType</code>. If neither
|
||||
extension module is installed, conversions to arguments of type
|
||||
<code>numeric::array</code> will cause overload resolution to reject the
|
||||
overload, and other attempted uses of <code>numeric::array</code> will <a
|
||||
href="definitions.html#raise">raise</a> an appropriate Python exception.
|
||||
The associated Python type can be set manually using the <code><a href=
|
||||
"#array-spec-statics">set_module_and_type</a>(...)</code> static
|
||||
function.</p>
|
||||
<p><a name="default_search" id="default_search"></a>The default behavior is
|
||||
to use <code>numarray.NDArray</code> as the associated Python type if the
|
||||
<code>numarray</code> module is installed in the default location.
|
||||
Otherwise it falls back to use <code>Numeric.ArrayType</code>. If neither
|
||||
extension module is installed, overloads of wrapped C++ functions with
|
||||
<code>numeric::array</code> parameters will never be matched, and other
|
||||
attempted uses of <code>numeric::array</code> will <a href=
|
||||
"definitions.html#raise">raise</a> an appropriate Python exception. The
|
||||
associated Python type can be set manually using the <code><a href=
|
||||
"#array-spec-statics">set_module_and_type</a>(...)</code> static
|
||||
function.</p>
|
||||
|
||||
<h4><a name="array-spec-synopsis"></a>Class <code>array</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
<h4><a name="array-spec-synopsis" id="array-spec-synopsis"></a>Class
|
||||
<code>array</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace numeric
|
||||
{
|
||||
class array : public object
|
||||
@@ -110,7 +110,7 @@ namespace boost { namespace python { namespace numeric
|
||||
object astype(Type const& type_);
|
||||
|
||||
template <class Type>
|
||||
object new_(Type const& type_) const;
|
||||
array new_(Type const& type_) const;
|
||||
|
||||
template <class Sequence>
|
||||
void resize(Sequence const& x);
|
||||
@@ -136,14 +136,14 @@ namespace boost { namespace python { namespace numeric
|
||||
void tofile(File const& f) const;
|
||||
|
||||
object factory();
|
||||
template <class Buffer>
|
||||
object factory(Buffer const&);
|
||||
template <class Buffer, class Type>
|
||||
object factory(Buffer const&, Type const&);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy, bool savespace, char typecode);
|
||||
template <class Sequence>
|
||||
object factory(Sequence const&);
|
||||
template <class Sequence, class Typecode>
|
||||
object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
|
||||
template <class Sequence, class Typecode, class Type>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
|
||||
template <class Sequence, class Typecode, class Type, class Shape>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
|
||||
|
||||
template <class T1>
|
||||
explicit array(T1 const& x1);
|
||||
@@ -155,6 +155,7 @@ namespace boost { namespace python { namespace numeric
|
||||
|
||||
static void set_module_and_type();
|
||||
static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
|
||||
static void get_module_name();
|
||||
|
||||
object argmax(long axis=-1);
|
||||
|
||||
@@ -203,54 +204,60 @@ namespace boost { namespace python { namespace numeric
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="array-spec-observers"></a>Class <code>array</code> observer
|
||||
functions</h4>
|
||||
<pre>
|
||||
<h4><a name="array-spec-observers" id="array-spec-observers"></a>Class
|
||||
<code>array</code> observer functions</h4>
|
||||
<pre>
|
||||
object factory();
|
||||
template <class Buffer>
|
||||
object factory(Buffer const&);
|
||||
template <class Buffer, class Type>
|
||||
object factory(Buffer const&, Type const&);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy, bool savespace, char typecode);
|
||||
</pre>
|
||||
These functions map to the underlying array type's <code>array()</code>
|
||||
function family. They are not called "<code>array</code>" because of the
|
||||
C++ limitation that you can't define a member function with the same name
|
||||
as its enclosing class.
|
||||
<pre>
|
||||
template <class Sequence>
|
||||
object factory(Sequence const&);
|
||||
template <class Sequence, class Typecode>
|
||||
object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
|
||||
template <class Sequence, class Typecode, class Type>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
|
||||
template <class Sequence, class Typecode, class Type, class Shape>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
|
||||
</pre>These functions map to the underlying array type's <code>array()</code>
|
||||
function family. They are not called "<code>array</code>" because of the C++
|
||||
limitation that you can't define a member function with the same name as its
|
||||
enclosing class.
|
||||
<pre>
|
||||
template <class Type>
|
||||
object new_(Type const&) const;
|
||||
</pre>
|
||||
This function maps to the underlying array type's <code>new()</code>
|
||||
function. It is not called "<code>new</code>" because that is a keyword
|
||||
in C++.
|
||||
array new_(Type const&) const;
|
||||
</pre>This function maps to the underlying array type's <code>new()</code>
|
||||
function. It is not called "<code>new</code>" because that is a keyword in
|
||||
C++.
|
||||
|
||||
<h4><a name="array-spec-statics"></a>Class <code>array</code> static
|
||||
functions</h4>
|
||||
<pre>
|
||||
<h4><a name="array-spec-statics" id="array-spec-statics"></a>Class
|
||||
<code>array</code> static functions</h4>
|
||||
<pre>
|
||||
static void set_module_and_type(char const* package_path, char const* type_name);
|
||||
static void set_module_and_type();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>package_path</code> and
|
||||
<code>type_name</code>, if supplied, is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>package_path</code> and
|
||||
<code>type_name</code>, if supplied, is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> The first form sets the package path of the module
|
||||
which supplies the type named by <code>type_name</code> to
|
||||
<code>package_path</code>. The second form restores the <a href=
|
||||
"#default_search">default search behavior</a>. The associated Python
|
||||
type will be searched for only the first time it is needed, and
|
||||
thereafter the first time it is needed after an invocation of
|
||||
<code>set_module_and_type</code>.</dt>
|
||||
</dl>
|
||||
<dt><b>Effects:</b> The first form sets the package path of the module
|
||||
that supplies the type named by <code>type_name</code> to
|
||||
<code>package_path</code>. The second form restores the <a href=
|
||||
"#default_search">default search behavior</a>. The associated Python type
|
||||
will be searched for only the first time it is needed, and thereafter the
|
||||
first time it is needed after an invocation of
|
||||
<code>set_module_and_type</code>.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
static std::string get_module_name()
|
||||
</pre>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
<pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Returns the name of the module containing the class
|
||||
that will be held by new <code>numeric::array</code> instances.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples" id="examples"></a>Example</h2>
|
||||
<pre>
|
||||
#include <boost/python/numeric.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
|
||||
@@ -261,10 +268,9 @@ void set_first_element(numeric::array& y, double value)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised 03 October, 2002</p>
|
||||
<p>Revised 07 October, 2006</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2006.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -854,12 +854,12 @@ void del(proxy<T> const& x);
|
||||
</dl>
|
||||
<pre>
|
||||
<a name="comparisons-spec"></a>
|
||||
template<class L,class R> bool operator>(L const&l,R const&r);
|
||||
template<class L,class R> bool operator>=(L const&l,R const&r);
|
||||
template<class L,class R> bool operator<(L const&l,R const&r);
|
||||
template<class L,class R> bool operator<=(L const&l,R const&r);
|
||||
template<class L,class R> bool operator==(L const&l,R const&r);
|
||||
template<class L,class R> bool operator!=(L const&l,R const&r);
|
||||
template<class L,class R> object operator>(L const&l,R const&r);
|
||||
template<class L,class R> object operator>=(L const&l,R const&r);
|
||||
template<class L,class R> object operator<(L const&l,R const&r);
|
||||
template<class L,class R> object operator<=(L const&l,R const&r);
|
||||
template<class L,class R> object operator==(L const&l,R const&r);
|
||||
template<class L,class R> object operator!=(L const&l,R const&r);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
|
||||
138
doc/v2/opaque.html
Normal file
138
doc/v2/opaque.html
Normal file
@@ -0,0 +1,138 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<!-- Copyright 2003..2006 Haufe Mediengruppe. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/opaque_pointer_converter.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/opaque_pointer_converter.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque-spec">Class template
|
||||
<code>opaque<Pointee></code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque-spec-synopsis">Class template
|
||||
<code>opaque</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">Macro
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#see-also">See Also</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="opaque-spec"></a>Class template
|
||||
<code>opaque<P></code></h3>
|
||||
|
||||
<p><code>opaque<></code> registers itself as a converter from
|
||||
Python objects to pointers to undefined types and vice versa.</p>
|
||||
|
||||
<h4><a name="opaque-spec-synopsis"></a>Class template
|
||||
<code>opaque</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template<class Pointee>
|
||||
struct opaque
|
||||
{
|
||||
opaque();
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="opaque-spec-constructor"></a>Class template
|
||||
<code>opaque</code> constructor</h4>
|
||||
<pre>
|
||||
opaque();
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<ul>
|
||||
<li>Registers the instance as a
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec"> <code>lvalue_from_pytype</code></a>
|
||||
converter from Python objects into opaque pointers.</p>
|
||||
<p>The Python Objects created are named after the type pointed to
|
||||
by the opaque pointer being wrapped.</p></li>
|
||||
<li>Registers the instance as a
|
||||
<a href="to_python_converter.html#to_python_converter-spec"> <code>to_python_converter</code></a>
|
||||
from opaque pointers to Python objects.</p></li>
|
||||
</ul>
|
||||
<p>If there is already an instance registered by another module, this
|
||||
instance doesn't try to register again in order to avoid warnings
|
||||
about multiple registrations.</p>
|
||||
|
||||
<h4>Note</h4>
|
||||
<p>Normally only a single instance of this class is created for every
|
||||
Pointee.</p>
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="macros"></a>Macros</h2>
|
||||
|
||||
<h3><a name="BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec"></a>
|
||||
Macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)</h3>
|
||||
<p>This macro must be used to define specializations of the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
which can't be instantiated for incomplete types.</p>
|
||||
<h4>Note</h4>
|
||||
<p>The macro must be invoked in every translation unit which uses the
|
||||
opaque converter.</p>
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="return_opaque_pointer.html">return_opaque_pointer</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
10 September, 2006
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright 2003..2006 Haufe Mediengruppe. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/opaque_pointer_converter.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/opaque_pointer_converter.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque_pointer_converter-spec">Class template
|
||||
<code>opaque_pointer_converter<P></code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque_pointer_converter-spec-synopsis">Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">Macro
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
|
||||
<dt><a href="#see-also">See Also</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="opaque_pointer_converter-spec"></a>Class template
|
||||
<code>opaque_pointer_converter<P></code></h3>
|
||||
|
||||
<p><code>opaque_pointer_converter<></code> is derived from
|
||||
<a href="to_python_converter.html#to_python_converter-spec">
|
||||
<code>to_python_converter</code></a>
|
||||
and registers itself as an
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into pointers to undefined types.
|
||||
Thus it may be used as a converter from opaque pointers into
|
||||
Python objects and vice versa.</p>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-synopsis"></a>Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template<class Pointer>
|
||||
struct opaque_pointer_converter
|
||||
: to_python_converter<
|
||||
Pointer, opaque_pointer_converter<Pointer> >
|
||||
{
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-constructor"></a>Class template
|
||||
<code>opaque_pointer_converter</code> constructor</h4>
|
||||
<pre>
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<p>Registers the instance as a
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into opaque pointers.</p>
|
||||
<p>The name is used for the type of the Python Objects created;
|
||||
it should be printable but needn't be an
|
||||
<a href="definitions.html#ntbs">ntbs</a> because the object type is
|
||||
not supposed to be user constructible within python scripts.</p>
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="macros"></a>Macros</h2>
|
||||
|
||||
<h3><a name="BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec"></a>
|
||||
Macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)</h3>
|
||||
<p>This macro must be used to define specializations of the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
which can't be instantiated for incomplete types.</p>
|
||||
<h4>Note</h4>
|
||||
<p>In order for this to work in a cross-module environment the macro must
|
||||
be invoked in every translation unit which uses the
|
||||
opaque_pointer_converter.</p>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
please see example for <a href="return_opaque_pointer.html#examples">
|
||||
return_opaque_pointer</a>.
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="return_opaque_pointer.html">return_opaque_pointer</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
10 March, 2003
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright 2003 Haufe Mediengruppe. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -320,11 +320,9 @@ See also the
|
||||
|
||||
<hr>
|
||||
|
||||
© Copyright Ralf W. Grosse-Kunstleve 2001-2004. Permission to copy,
|
||||
use, modify, sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided "as
|
||||
is" without express or implied warranty, and with no claim as to its
|
||||
suitability for any purpose.
|
||||
© Copyright Ralf W. Grosse-Kunstleve 2001-2004. Distributed under
|
||||
the Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
<p>
|
||||
Updated: Feb 2004.
|
||||
|
||||
@@ -112,5 +112,8 @@ BOOST_PYTHON_MODULE(pointee_demo)
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
Abrahams</a> 2002. </i> Distributed
|
||||
under the Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
|
||||
@@ -259,5 +259,7 @@ void pass_as_arg(expensive_to_copy* x, PyObject* f)
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
Abrahams</a> 2002. </i> Distributed
|
||||
under the Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
@@ -907,26 +907,26 @@
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html">opaque_pointer_converter.hpp</a></dt>
|
||||
"opaque.html">opaque_pointer_converter.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html#classes">Classes</a></dt>
|
||||
"opaque.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html#opaque_pointer_converter-spec">opaque_pointer_converter</a></dt>
|
||||
"opaque.html#opaque-spec">opaque</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="opaque_pointer_converter.html#macros">Macros</a></dt>
|
||||
<dt><a href="opaque.html#macros">Macros</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
"opaque.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -977,6 +977,7 @@
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="exec.html#eval-spec">eval</a></dt>
|
||||
<dt><a href="exec.html#exec-spec">exec</a></dt>
|
||||
<dt><a href="exec.html#exec_file-spec">exec_file</a></dt>
|
||||
</dl>
|
||||
@@ -1094,6 +1095,16 @@
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="ssize_t.html">ssize_t.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="ssize_t.html#typedefs">Typedefs</a></dt>
|
||||
|
||||
<dt><a href="ssize_t.html#constants">Constants</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2><a name="topics">Topics</a></h2>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
undefined types such that the return value is copied into a
|
||||
new Python object.</p>
|
||||
<p>In addition to specifying the <code>return_opaque_pointer</code>
|
||||
policy the <a href="opaque_pointer_converter.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
policy the <a href="opaque.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a> macro must be
|
||||
used to define specializations for the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
@@ -177,8 +177,8 @@ if __name__ == '__main__':
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="opaque_pointer_converter.html">
|
||||
opaque_pointer_converter</a>
|
||||
<a href="opaque.html">
|
||||
opaque</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
|
||||
96
doc/v2/ssize_t.html
Normal file
96
doc/v2/ssize_t.html
Normal file
@@ -0,0 +1,96 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<!-- Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content=
|
||||
"text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/ssize_t.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%"
|
||||
summary="header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width=
|
||||
"277" alt="C++ Boost" src="../../../../boost.png" border=
|
||||
"0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href=
|
||||
"../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/ssize_t.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#typdefs">Typedef</a></dt>
|
||||
|
||||
<dt><a href="#macros">Constants</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction" id=
|
||||
"introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Python 2.5 introduces a new <tt>Py_ssize_t</tt> typedef and
|
||||
two related macros (<a href=
|
||||
"http://www.python.org/dev/peps/pep-0353/">PEP 353</a>). The
|
||||
<tt><boost/python/ssize_t.hpp></tt> header imports these
|
||||
definitions into the <tt>boost::python</tt> namespace as
|
||||
<tt>ssize_t</tt>, <tt>ssize_t_max</tt>, and <tt>ssize_t_min</tt>.
|
||||
Appropriate definitions are provided for backward compatibility
|
||||
with previous Python versions.</p>
|
||||
|
||||
<h2><a name="typedefs" id="typedefs"></a>Typedefs</h2>Imports
|
||||
<tt>Py_ssize_t</tt> into the <tt>boost::python</tt> namespace if
|
||||
available, or provides an appropriate typedef for backward
|
||||
compatibility:
|
||||
<pre>
|
||||
#if PY_VERSION_HEX >= 0x02050000
|
||||
typedef Py_ssize_t ssize_t;
|
||||
#else
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
</pre>
|
||||
|
||||
<h2><a name="constants" id="constants"></a>Constants</h2>Imports
|
||||
<tt>PY_SSIZE_T_MAX</tt> and <tt>PY_SSIZE_T_MIN</tt> as constants
|
||||
into the <tt>boost::python</tt> namespace if available, or
|
||||
provides appropriate constants for backward compatibility:
|
||||
<pre>
|
||||
#if PY_VERSION_HEX >= 0x02050000
|
||||
ssize_t const ssize_t_max = PY_SSIZE_T_MAX;
|
||||
ssize_t const ssize_t_min = PY_SSIZE_T_MIN;
|
||||
#else
|
||||
ssize_t const ssize_t_max = INT_MAX;
|
||||
ssize_t const ssize_t_min = INT_MIN;
|
||||
#endif
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
25 September, 2006
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/ralf_w_grosse_kunstleve.htm">Ralf W.
|
||||
Grosse-Kunstleve</a> 2006.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -190,5 +190,7 @@ struct reference_existing_object
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
Abrahams</a> 2002. </i> Distributed
|
||||
under the Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
@@ -97,5 +97,7 @@ PyObject* operator()(argument_type x) const;
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. </i>
|
||||
Abrahams</a> 2002. </i> Distributed under the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
@@ -215,7 +215,9 @@ bool is_int(T x)
|
||||
</p>
|
||||
|
||||
<p class="c4">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. Distributed under the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)<
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -232,5 +232,7 @@ BOOST_PYTHON_MODULE_INIT(polymorphism)
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2004</i>
|
||||
Abrahams</a> 2004</i> Distributed under the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)</p>
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,81 +0,0 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# This is the top of our own project tree
|
||||
project-root ;
|
||||
|
||||
# Declares the following targets:
|
||||
#
|
||||
# 1. an extension module called "getting_started1", which is
|
||||
# built from "getting_started1.cpp". Built by default
|
||||
#
|
||||
# 2. A test target called my-test.test which runs
|
||||
# test_getting_started1.py with the extension module above. Built
|
||||
# when out-of date, but only if invoked by name or if the global
|
||||
# "test" target is invoked.
|
||||
#
|
||||
# 3. A test target called my-test.run wihch runs the above test
|
||||
# unconditionally. Built only when invoked by name.
|
||||
#
|
||||
# To see verbose test output, add "-sPYTHON_TEST_ARGS=-v" to the bjam
|
||||
# command-line before the first target.
|
||||
#
|
||||
|
||||
# Include definitions needed for Python modules
|
||||
import python ;
|
||||
|
||||
# ----- getting_started1 -------
|
||||
|
||||
# Declare a Python extension called getting_started1
|
||||
extension getting_started1
|
||||
: # sources
|
||||
getting_started1.cpp
|
||||
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
# Declare a test for the extension module
|
||||
boost-python-runtest test1
|
||||
: # Python test driver
|
||||
test_getting_started1.py
|
||||
# extension modules to use
|
||||
<pyd>getting_started1 ;
|
||||
|
||||
|
||||
|
||||
# ----- getting_started2 -------
|
||||
|
||||
# Declare a Python extension called getting_started2
|
||||
extension getting_started2
|
||||
: # sources
|
||||
getting_started2.cpp
|
||||
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
# Declare a test for the extension module
|
||||
boost-python-runtest test2
|
||||
: # Python test driver
|
||||
test_getting_started2.py
|
||||
# extension modules to use
|
||||
<pyd>getting_started2 ;
|
||||
|
||||
# ----- std_pair -------
|
||||
|
||||
# Declare a Python extension called std_pair
|
||||
extension std_pair_ext
|
||||
: # sources
|
||||
std_pair.cpp
|
||||
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
# Declare a test for the extension module
|
||||
boost-python-runtest test3
|
||||
: # Python test driver
|
||||
test_std_pair.py
|
||||
# extension modules to use
|
||||
<pyd>std_pair_ext ;
|
||||
@@ -1,9 +0,0 @@
|
||||
# This is the Jamfile for Boost.Build v2, which is currently in
|
||||
# prerelease. Ignore this file unless you are a bleading edge sort of
|
||||
# person.
|
||||
|
||||
project : requirements <library>/boost/python//boost_python ;
|
||||
|
||||
python-extension getting_started1 : getting_started1.cpp ;
|
||||
python-extension getting_started2 : getting_started2.cpp ;
|
||||
|
||||
40
example/Jamroot
Executable file
40
example/Jamroot
Executable file
@@ -0,0 +1,40 @@
|
||||
# Copyright David Abrahams 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Specify the path to the Boost project. If you move this project,
|
||||
# adjust this path to refer to the Boost root directory.
|
||||
use-project boost
|
||||
: ../../.. ;
|
||||
|
||||
# Set up the project-wide requirements that everything uses the
|
||||
# boost_python library from the project whose global ID is
|
||||
# /boost/python.
|
||||
project
|
||||
: requirements <library>/boost/python//boost_python ;
|
||||
|
||||
# Declare the three extension modules. You can specify multiple
|
||||
# source files after the colon separated by spaces.
|
||||
python-extension getting_started1 : getting_started1.cpp ;
|
||||
python-extension getting_started2 : getting_started2.cpp ;
|
||||
python-extension std_pair_ext : std_pair.cpp ;
|
||||
|
||||
# A little "rule" (function) to clean up the syntax of declaring tests
|
||||
# of these extension modules.
|
||||
local rule run-test ( test-name : sources + )
|
||||
{
|
||||
import testing ;
|
||||
testing.make-test run-pyd : $(sources) : : $(test-name) ;
|
||||
}
|
||||
|
||||
# Declare test targets
|
||||
run-test test1 : getting_started1 test_getting_started1.py ;
|
||||
run-test test2 : getting_started2 test_getting_started2.py ;
|
||||
run-test test3 : std_pair_ext test_std_pair.py ;
|
||||
|
||||
# A target that runs all the tests
|
||||
alias test : test1 test2 test3 ;
|
||||
|
||||
# Only run tests when explicitly requested
|
||||
explicit test test1 test2 test3 ;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# If you move this example from its place in the Boost tree, edit this
|
||||
# path to point at the root directory of your Boost installation (the
|
||||
# one containing a subdirectory called "boost/" and a sub-subdirectory
|
||||
# "boost/python/" full of .hpp files). Absolute paths work, too.
|
||||
#
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
|
||||
# Boost.Python configuration variables, as described in
|
||||
# http://www.boost.org/libs/python/doc/building.html#configuration.
|
||||
# Usually you don't need to set these; the defaults will work. If you
|
||||
# do set them, try to change as few of them as possible, starting with
|
||||
# the first ones.
|
||||
|
||||
# PYTHON_VERSION = <the two-part Major.Minor version number, e.g. 2.2> ;
|
||||
# PYTHON_ROOT = <root directory of your Python installation, e.g. /usr> ;
|
||||
# PYTHON_INCLUDES = <path to Python #include directories> ;
|
||||
# PYTHON_LIB_PATH = <path to Python library object> ;
|
||||
|
||||
# You may need to configure your compiler toolset, especially if you
|
||||
# want to build with a compiler that is not the "system default" or if
|
||||
# it is installed in a nonstandard place; see
|
||||
# http://www.boost.org/more/getting_started.html#Configuring for
|
||||
# details.
|
||||
|
||||
# Makes a project id for boost so that other Boost.Build projects can
|
||||
# refer to it by name.
|
||||
#
|
||||
project boost : $(BOOST_ROOT) ;
|
||||
|
||||
# Change this setting to have all your built products placed under a
|
||||
# single directory:
|
||||
#
|
||||
# ALL_LOCATE_TARGET = <root directory for all built products>
|
||||
@@ -1,19 +1,16 @@
|
||||
.. Copyright David Abrahams 2006. Distributed under the Boost
|
||||
.. Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
To get started with the Boost Python Library, use the examples
|
||||
getting_started1.cpp and getting_started2.cpp.
|
||||
getting_started1.cpp and getting_started2.cpp. Invoking
|
||||
|
||||
bjam -sTOOLS=your-toolset test
|
||||
bjam --toolset=your-toolset test
|
||||
|
||||
in this directory will build and run the examples.
|
||||
|
||||
Other configuration variables may need to be set as described in
|
||||
http://www.boost.org/libs/python/doc/building.html. These can be
|
||||
supplied by the environment, on the command-line with
|
||||
|
||||
-sVARIABLENAME=value
|
||||
|
||||
or in the local Jamrules file.
|
||||
in this directory will build and run the examples. See
|
||||
http://www.boost.org/more/getting_started.html for details about the
|
||||
--toolset= option.
|
||||
|
||||
If you move this example from its place in the Boost development tree
|
||||
you'll need to edit at least one line in Jamrules and one line in
|
||||
you'll need to edit the two lines indicated in Jamroot and
|
||||
boost-build.jam.
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
# Copyright David Abrahams 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Edit this path to point at the tools/build/v1 subdirectory of your
|
||||
# Edit this path to point at the tools/build/v2 subdirectory of your
|
||||
# Boost installation. Absolute paths work, too.
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
boost-build ../../../tools/build/v2 ;
|
||||
|
||||
Binary file not shown.
43
example/quickstart/Jamroot
Executable file
43
example/quickstart/Jamroot
Executable file
@@ -0,0 +1,43 @@
|
||||
# Copyright David Abrahams 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Specify the path to the Boost project. If you move this project,
|
||||
# adjust the path to refer to the Boost root directory.
|
||||
use-project boost
|
||||
: ../../../.. ;
|
||||
|
||||
# Set up the project-wide requirements that everything uses the
|
||||
# boost_python library defined in the project whose global ID is
|
||||
# /boost/python.
|
||||
project boost-python-quickstart
|
||||
: requirements <library>/boost/python//boost_python
|
||||
;
|
||||
|
||||
# Make the definition of the python-extension rule available
|
||||
import python ;
|
||||
|
||||
# Declare a Python extension called hello.
|
||||
python-extension extending : extending.cpp ;
|
||||
|
||||
# Declare an executable called embedding that embeds Python
|
||||
exe embedding : embedding.cpp /python//python ;
|
||||
|
||||
import testing ;
|
||||
|
||||
# Declare a test of the extension module
|
||||
testing.make-test run-pyd : extending test_extending.py : : test_ext ;
|
||||
|
||||
# Declare a test of the embedding application
|
||||
testing.run embedding
|
||||
: # any ordinary arguments
|
||||
: script.py # any arguments that should be treated as relative paths
|
||||
: # requirements
|
||||
: test_embed ; # name of test
|
||||
|
||||
# Create a "test" target that runs all the tests
|
||||
alias test : test_ext test_embed ;
|
||||
|
||||
# make sure the tests don't run by default
|
||||
explicit test_ext test_embed test ;
|
||||
|
||||
7
example/quickstart/boost-build.jam
Normal file
7
example/quickstart/boost-build.jam
Normal file
@@ -0,0 +1,7 @@
|
||||
# Copyright David Abrahams 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Edit this path to point at the tools/build/v2 subdirectory of your
|
||||
# Boost installation. Absolute paths work, too.
|
||||
boost-build ../../../../tools/build/v2 ;
|
||||
154
example/quickstart/embedding.cpp
Normal file
154
example/quickstart/embedding.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright Stefan Seefeld 2005.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/python.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace python = boost::python;
|
||||
|
||||
// An abstract base class
|
||||
class Base : public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
virtual ~Base() {};
|
||||
virtual std::string hello() = 0;
|
||||
};
|
||||
|
||||
// C++ derived class
|
||||
class CppDerived : public Base
|
||||
{
|
||||
public:
|
||||
virtual ~CppDerived() {}
|
||||
virtual std::string hello() { return "Hello from C++!";}
|
||||
};
|
||||
|
||||
// Familiar Boost.Python wrapper class for Base
|
||||
struct BaseWrap : Base, python::wrapper<Base>
|
||||
{
|
||||
virtual std::string hello()
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
// workaround for VC++ 6.x or 7.0, see
|
||||
// http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions
|
||||
return python::call<std::string>(this->get_override("hello").ptr());
|
||||
#else
|
||||
return this->get_override("hello")();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// Pack the Base class wrapper into a module
|
||||
BOOST_PYTHON_MODULE(embedded_hello)
|
||||
{
|
||||
python::class_<BaseWrap, boost::noncopyable> base("Base");
|
||||
}
|
||||
|
||||
|
||||
void exec_test()
|
||||
{
|
||||
std::cout << "registering extension module embedded_hello..." << std::endl;
|
||||
|
||||
// Register the module with the interpreter
|
||||
if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1)
|
||||
throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
|
||||
"builtin modules");
|
||||
|
||||
std::cout << "defining Python class derived from Base..." << std::endl;
|
||||
|
||||
// Retrieve the main module
|
||||
python::object main = python::import("__main__");
|
||||
|
||||
// Retrieve the main module's namespace
|
||||
python::object global(main.attr("__dict__"));
|
||||
|
||||
// Define the derived class in Python.
|
||||
python::object result = python::exec(
|
||||
"from embedded_hello import * \n"
|
||||
"class PythonDerived(Base): \n"
|
||||
" def hello(self): \n"
|
||||
" return 'Hello from Python!' \n",
|
||||
global, global);
|
||||
|
||||
python::object PythonDerived = global["PythonDerived"];
|
||||
|
||||
// Creating and using instances of the C++ class is as easy as always.
|
||||
CppDerived cpp;
|
||||
BOOST_TEST(cpp.hello() == "Hello from C++!");
|
||||
|
||||
std::cout << "testing derived class from C++..." << std::endl;
|
||||
|
||||
// But now creating and using instances of the Python class is almost
|
||||
// as easy!
|
||||
python::object py_base = PythonDerived();
|
||||
Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND;
|
||||
|
||||
// Make sure the right 'hello' method is called.
|
||||
BOOST_TEST(py.hello() == "Hello from Python!");
|
||||
|
||||
std::cout << "success!" << std::endl;
|
||||
}
|
||||
|
||||
void exec_file_test(std::string const &script)
|
||||
{
|
||||
std::cout << "running file " << script << "..." << std::endl;
|
||||
|
||||
// Run a python script in an empty environment.
|
||||
python::dict global;
|
||||
python::object result = python::exec_file(script.c_str(), global, global);
|
||||
|
||||
// Extract an object the script stored in the global dictionary.
|
||||
BOOST_TEST(python::extract<int>(global["number"]) == 42);
|
||||
|
||||
std::cout << "success!" << std::endl;
|
||||
}
|
||||
|
||||
void exec_test_error()
|
||||
{
|
||||
std::cout << "intentionally causing a python exception..." << std::endl;
|
||||
|
||||
// Execute a statement that raises a python exception.
|
||||
python::dict global;
|
||||
python::object result = python::exec("print unknown \n", global, global);
|
||||
|
||||
std::cout << "Oops! This statement should be skipped due to an exception" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BOOST_TEST(argc == 2);
|
||||
std::string script = argv[1];
|
||||
// Initialize the interpreter
|
||||
Py_Initialize();
|
||||
|
||||
bool error_expected = false;
|
||||
|
||||
if (
|
||||
python::handle_exception(exec_test)
|
||||
|| python::handle_exception(boost::bind(exec_file_test, script))
|
||||
|| (
|
||||
(error_expected = true)
|
||||
&& python::handle_exception(exec_test_error)
|
||||
)
|
||||
|
||||
)
|
||||
{
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
if (!error_expected)
|
||||
BOOST_ERROR("Python Error detected");
|
||||
PyErr_Print();
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ERROR("A C++ exception was thrown for which "
|
||||
"there was no exception translator registered.");
|
||||
}
|
||||
}
|
||||
|
||||
// Boost.Python doesn't support Py_Finalize yet, so don't call it!
|
||||
return boost::report_errors();
|
||||
}
|
||||
41
example/quickstart/extending.cpp
Normal file
41
example/quickstart/extending.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright Ralf W. Grosse-Kunstleve 2002-2004. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#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!";
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(extending)
|
||||
{
|
||||
using namespace boost::python;
|
||||
class_<hello>("hello", init<std::string>())
|
||||
// Add a regular member function.
|
||||
.def("greet", &hello::greet)
|
||||
// Add invite() as a member of hello!
|
||||
.def("invite", invite)
|
||||
;
|
||||
|
||||
// Also add invite() as a regular function to the module.
|
||||
def("invite", invite);
|
||||
}
|
||||
6
example/quickstart/script.py
Normal file
6
example/quickstart/script.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copyright Stefan Seefeld 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
print 'Hello World !'
|
||||
number = 42
|
||||
36
example/quickstart/test_extending.py
Normal file
36
example/quickstart/test_extending.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Using the doctest module here to ensure that the results are as expected.
|
||||
r'''>>> from extending import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
'Hello from California'
|
||||
>>> invite(hi)
|
||||
'Hello from California! Please come soon!'
|
||||
>>> hi.invite()
|
||||
'Hello from California! Please come soon!'
|
||||
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida! Please come soon!'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_extending
|
||||
return doctest.testmod(test_extending, verbose=True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
r'''>>> import getting_started1
|
||||
>>> print getting_started1.greet()
|
||||
hello, world
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
r'''>>> from getting_started2 import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
import std_pair_ext
|
||||
assert std_pair_ext.foo() == (3, 5)
|
||||
print "OK"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# Hello World Example from the tutorial
|
||||
# Copyright Joel de Guzman 2002-2004. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||
# or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
# [Joel de Guzman 10/9/2002]
|
||||
|
||||
# This is the top of our own project tree
|
||||
project-root ;
|
||||
|
||||
# Include definitions needed for Python modules
|
||||
import python ;
|
||||
|
||||
extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
18
example/tutorial/Jamroot
Executable file
18
example/tutorial/Jamroot
Executable file
@@ -0,0 +1,18 @@
|
||||
# Copyright David Abrahams 2006. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Specify the path to the Boost project. If you move this project,
|
||||
# adjust this path to refer to the Boost root directory.
|
||||
use-project boost
|
||||
: ../../../.. ;
|
||||
|
||||
# Set up the project-wide requirements that everything uses the
|
||||
# boost_python library from the project whose global ID is
|
||||
# /boost/python.
|
||||
project
|
||||
: requirements <library>/boost/python//boost_python ;
|
||||
|
||||
# Declare a Python extension called hello.
|
||||
python-extension hello : hello.cpp ;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# If you move this example from its place in the Boost tree, edit this
|
||||
# path to point at the root directory of your Boost installation (the
|
||||
# one containing a subdirectory called "boost/" and a sub-subdirectory
|
||||
# "boost/python/" full of .hpp files). Absolute paths work, too.
|
||||
#
|
||||
path-global BOOST_ROOT : ../../../.. ;
|
||||
|
||||
# Boost.Python configuration variables, as described in
|
||||
# http://www.boost.org/libs/python/doc/building.html#configuration.
|
||||
# Usually you don't need to set these; the defaults will work. If you
|
||||
# do set them, try to change as few of them as possible, starting with
|
||||
# the first ones.
|
||||
|
||||
# PYTHON_VERSION = <the two-part Major.Minor version number, e.g. 2.2> ;
|
||||
# PYTHON_ROOT = <root directory of your Python installation, e.g. /usr> ;
|
||||
# PYTHON_INCLUDES = <path to Python #include directories> ;
|
||||
# PYTHON_LIB_PATH = <path to Python library object> ;
|
||||
|
||||
# You may need to configure your compiler toolset, especially if you
|
||||
# want to build with a compiler that is not the "system default" or if
|
||||
# it is installed in a nonstandard place; see
|
||||
# http://www.boost.org/more/getting_started.html#Configuring for
|
||||
# details.
|
||||
|
||||
# Makes a project id for boost so that other Boost.Build projects can
|
||||
# refer to it by name.
|
||||
#
|
||||
project boost : $(BOOST_ROOT) ;
|
||||
|
||||
# Change this setting to have all your built products placed under a
|
||||
# single directory:
|
||||
#
|
||||
# ALL_LOCATE_TARGET = <root directory for all built products>
|
||||
73
include/boost/python.hpp
Normal file
73
include/boost/python.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/python for documentation.
|
||||
|
||||
#ifndef PYTHON_DWA2002810_HPP
|
||||
# define PYTHON_DWA2002810_HPP
|
||||
|
||||
# include <boost/python/args.hpp>
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
# include <boost/python/back_reference.hpp>
|
||||
# include <boost/python/bases.hpp>
|
||||
# include <boost/python/borrowed.hpp>
|
||||
# include <boost/python/call.hpp>
|
||||
# include <boost/python/call_method.hpp>
|
||||
# include <boost/python/class.hpp>
|
||||
# include <boost/python/copy_const_reference.hpp>
|
||||
# include <boost/python/copy_non_const_reference.hpp>
|
||||
# include <boost/python/data_members.hpp>
|
||||
# include <boost/python/def.hpp>
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/dict.hpp>
|
||||
# include <boost/python/docstring_options.hpp>
|
||||
# include <boost/python/enum.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
# include <boost/python/exception_translator.hpp>
|
||||
# include <boost/python/exec.hpp>
|
||||
# include <boost/python/extract.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/python/has_back_reference.hpp>
|
||||
# include <boost/python/implicit.hpp>
|
||||
# include <boost/python/init.hpp>
|
||||
# include <boost/python/import.hpp>
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/iterator.hpp>
|
||||
# include <boost/python/list.hpp>
|
||||
# include <boost/python/long.hpp>
|
||||
# include <boost/python/lvalue_from_pytype.hpp>
|
||||
# include <boost/python/make_constructor.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
# include <boost/python/manage_new_object.hpp>
|
||||
# include <boost/python/module.hpp>
|
||||
# include <boost/python/numeric.hpp>
|
||||
# include <boost/python/object.hpp>
|
||||
# include <boost/python/object_protocol.hpp>
|
||||
# include <boost/python/object_protocol_core.hpp>
|
||||
# include <boost/python/opaque_pointer_converter.hpp>
|
||||
# include <boost/python/operators.hpp>
|
||||
# include <boost/python/other.hpp>
|
||||
# include <boost/python/overloads.hpp>
|
||||
# include <boost/python/pointee.hpp>
|
||||
# include <boost/python/pure_virtual.hpp>
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/reference_existing_object.hpp>
|
||||
# include <boost/python/register_ptr_to_python.hpp>
|
||||
# include <boost/python/return_arg.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/scope.hpp>
|
||||
# include <boost/python/self.hpp>
|
||||
# include <boost/python/slice_nil.hpp>
|
||||
# include <boost/python/str.hpp>
|
||||
# include <boost/python/to_python_converter.hpp>
|
||||
# include <boost/python/to_python_indirect.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
# include <boost/python/tuple.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/with_custodian_and_ward.hpp>
|
||||
|
||||
#endif // PYTHON_DWA2002810_HPP
|
||||
76
include/boost/python/arg_from_python.hpp
Executable file
76
include/boost/python/arg_from_python.hpp
Executable file
@@ -0,0 +1,76 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
# define ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/arg_from_python.hpp>
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|
||||
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
struct arg_from_python
|
||||
: converter::select_arg_from_python<
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|
||||
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
|
||||
typename boost::remove_cv<T>::type
|
||||
# else
|
||||
T
|
||||
# endif
|
||||
>::type
|
||||
{
|
||||
typedef typename converter::select_arg_from_python<
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|
||||
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
|
||||
typename boost::remove_cv<T>::type
|
||||
# else
|
||||
T
|
||||
# endif
|
||||
>::type base;
|
||||
|
||||
arg_from_python(PyObject*);
|
||||
};
|
||||
|
||||
// specialization for PyObject*
|
||||
template <>
|
||||
struct arg_from_python<PyObject*>
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
|
||||
arg_from_python(PyObject* p) : m_source(p) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject* operator()() const { return m_source; }
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct arg_from_python<PyObject* const&>
|
||||
{
|
||||
typedef PyObject* const& result_type;
|
||||
|
||||
arg_from_python(PyObject* p) : m_source(p) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject*const& operator()() const { return m_source; }
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <class T>
|
||||
inline arg_from_python<T>::arg_from_python(PyObject* source)
|
||||
: base(source)
|
||||
{
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
175
include/boost/python/args.hpp
Normal file
175
include/boost/python/args.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef KEYWORDS_DWA2002323_HPP
|
||||
# define KEYWORDS_DWA2002323_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/type_list.hpp>
|
||||
|
||||
# include <boost/type_traits/is_reference.hpp>
|
||||
# include <boost/type_traits/remove_reference.hpp>
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
|
||||
# include <boost/preprocessor/enum_params.hpp>
|
||||
# include <boost/preprocessor/repeat.hpp>
|
||||
# include <boost/preprocessor/facilities/intercept.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
|
||||
# include <boost/python/detail/mpl_lambda.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
# include <cstddef>
|
||||
# include <algorithm>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
typedef detail::keywords<1> arg;
|
||||
typedef arg arg_; // gcc 2.96 workaround
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <std::size_t nkeywords>
|
||||
struct keywords_base
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, size = nkeywords);
|
||||
|
||||
keyword_range range() const
|
||||
{
|
||||
return keyword_range(elements, elements + nkeywords);
|
||||
}
|
||||
|
||||
keyword elements[nkeywords];
|
||||
|
||||
keywords<nkeywords+1>
|
||||
operator,(python::arg const &k) const;
|
||||
|
||||
keywords<nkeywords + 1>
|
||||
operator,(char const *name) const;
|
||||
};
|
||||
|
||||
template <std::size_t nkeywords>
|
||||
struct keywords : keywords_base<nkeywords>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct keywords<1> : keywords_base<1>
|
||||
{
|
||||
explicit keywords(char const *name)
|
||||
{
|
||||
elements[0].name = name;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
python::arg& operator=(T const& value)
|
||||
{
|
||||
object z(value);
|
||||
elements[0].default_value = handle<>(python::borrowed(object(value).ptr()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator detail::keyword const&() const
|
||||
{
|
||||
return elements[0];
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t nkeywords>
|
||||
inline
|
||||
keywords<nkeywords+1>
|
||||
keywords_base<nkeywords>::operator,(python::arg const &k) const
|
||||
{
|
||||
keywords<nkeywords> const& l = *static_cast<keywords<nkeywords> const*>(this);
|
||||
python::detail::keywords<nkeywords+1> res;
|
||||
std::copy(l.elements, l.elements+nkeywords, res.elements);
|
||||
res.elements[nkeywords] = k.elements[0];
|
||||
return res;
|
||||
}
|
||||
|
||||
template <std::size_t nkeywords>
|
||||
inline
|
||||
keywords<nkeywords + 1>
|
||||
keywords_base<nkeywords>::operator,(char const *name) const
|
||||
{
|
||||
return this->operator,(python::arg(name));
|
||||
}
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template<typename T>
|
||||
struct is_keywords
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template<std::size_t nkeywords>
|
||||
struct is_keywords<keywords<nkeywords> >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
template <class T>
|
||||
struct is_reference_to_keywords
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_ref = is_reference<T>::value);
|
||||
typedef typename remove_reference<T>::type deref;
|
||||
typedef typename remove_cv<deref>::type key_t;
|
||||
BOOST_STATIC_CONSTANT(bool, is_key = is_keywords<key_t>::value);
|
||||
BOOST_STATIC_CONSTANT(bool, value = (is_ref & is_key));
|
||||
|
||||
typedef mpl::bool_<value> type;
|
||||
BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T))
|
||||
};
|
||||
# else
|
||||
typedef char (&yes_keywords_t)[1];
|
||||
typedef char (&no_keywords_t)[2];
|
||||
|
||||
no_keywords_t is_keywords_test(...);
|
||||
|
||||
template<std::size_t nkeywords>
|
||||
yes_keywords_t is_keywords_test(void (*)(keywords<nkeywords>&));
|
||||
|
||||
template<std::size_t nkeywords>
|
||||
yes_keywords_t is_keywords_test(void (*)(keywords<nkeywords> const&));
|
||||
|
||||
template<typename T>
|
||||
class is_reference_to_keywords
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_keywords_test( (void (*)(T))0 ))
|
||||
== sizeof(detail::yes_keywords_t)));
|
||||
|
||||
typedef mpl::bool_<value> type;
|
||||
BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T))
|
||||
};
|
||||
# endif
|
||||
}
|
||||
|
||||
inline detail::keywords<1> args(char const* name)
|
||||
{
|
||||
return detail::keywords<1>(name);
|
||||
}
|
||||
|
||||
# define BOOST_PYTHON_ASSIGN_NAME(z, n, _) result.elements[n].name = name##n;
|
||||
# define BOOST_PP_LOCAL_MACRO(n) \
|
||||
inline detail::keywords<n> args(BOOST_PP_ENUM_PARAMS_Z(1, n, char const* name)) \
|
||||
{ \
|
||||
detail::keywords<n> result; \
|
||||
BOOST_PP_REPEAT_1(n, BOOST_PYTHON_ASSIGN_NAME, _) \
|
||||
return result; \
|
||||
}
|
||||
# define BOOST_PP_LOCAL_LIMITS (2, BOOST_PYTHON_MAX_ARITY)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
|
||||
# endif // KEYWORDS_DWA2002323_HPP
|
||||
52
include/boost/python/args_fwd.hpp
Normal file
52
include/boost/python/args_fwd.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef ARGS_FWD_DWA2002927_HPP
|
||||
# define ARGS_FWD_DWA2002927_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/config.hpp>
|
||||
# include <cstddef>
|
||||
# include <utility>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct keyword
|
||||
{
|
||||
keyword(char const* name_=0)
|
||||
: name(name_)
|
||||
{}
|
||||
|
||||
char const* name;
|
||||
handle<> default_value;
|
||||
};
|
||||
|
||||
template <std::size_t nkeywords = 0> struct keywords;
|
||||
|
||||
typedef std::pair<keyword const*, keyword const*> keyword_range;
|
||||
|
||||
template <>
|
||||
struct keywords<0>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, size = 0);
|
||||
static keyword_range range() { return keyword_range(); }
|
||||
};
|
||||
|
||||
namespace error
|
||||
{
|
||||
template <int keywords, int function_args>
|
||||
struct more_keywords_than_function_arguments
|
||||
{
|
||||
typedef char too_many_keywords[keywords > function_args ? -1 : 1];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // ARGS_FWD_DWA2002927_HPP
|
||||
102
include/boost/python/back_reference.hpp
Normal file
102
include/boost/python/back_reference.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BACK_REFERENCE_DWA2002510_HPP
|
||||
# define BACK_REFERENCE_DWA2002510_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/object_fwd.hpp>
|
||||
# include <boost/python/detail/dependent.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
struct back_reference
|
||||
{
|
||||
private: // types
|
||||
typedef typename detail::dependent<object,T>::type source_t;
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
back_reference(PyObject*, T);
|
||||
source_t const& source() const;
|
||||
T get() const;
|
||||
private:
|
||||
source_t m_source;
|
||||
T m_value;
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template<typename T>
|
||||
class is_back_reference
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_back_reference<back_reference<T> >
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
# else // no partial specialization
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_back_reference_t)[1];
|
||||
typedef char (&no_back_reference_t)[2];
|
||||
|
||||
no_back_reference_t is_back_reference_test(...);
|
||||
|
||||
template<typename T>
|
||||
yes_back_reference_t is_back_reference_test(boost::type< back_reference<T> >);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class is_back_reference
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_back_reference_test(boost::type<T>()))
|
||||
== sizeof(detail::yes_back_reference_t)));
|
||||
};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <class T>
|
||||
back_reference<T>::back_reference(PyObject* p, T x)
|
||||
: m_source(detail::borrowed_reference(p))
|
||||
, m_value(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename back_reference<T>::source_t const& back_reference<T>::source() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T back_reference<T>::get() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BACK_REFERENCE_DWA2002510_HPP
|
||||
43
include/boost/python/base_type_traits.hpp
Executable file
43
include/boost/python/base_type_traits.hpp
Executable file
@@ -0,0 +1,43 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
# define BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct unspecialized {};
|
||||
}
|
||||
|
||||
// Derive from unspecialized so we can detect whether traits are
|
||||
// specialized
|
||||
template <class T> struct base_type_traits
|
||||
: detail::unspecialized
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct base_type_traits<PyObject>
|
||||
{
|
||||
typedef PyObject type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct base_type_traits<PyTypeObject>
|
||||
{
|
||||
typedef PyObject type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct base_type_traits<PyMethodObject>
|
||||
{
|
||||
typedef PyObject type;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
68
include/boost/python/bases.hpp
Normal file
68
include/boost/python/bases.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BASES_DWA2002321_HPP
|
||||
# define BASES_DWA2002321_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/python/detail/type_list.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
# include <boost/preprocessor/enum_params_with_a_default.hpp>
|
||||
# include <boost/preprocessor/enum_params.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
# define BOOST_PYTHON_BASE_PARAMS BOOST_PP_ENUM_PARAMS_Z(1, BOOST_PYTHON_MAX_BASES, Base)
|
||||
|
||||
// A type list for specifying bases
|
||||
template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_MAX_BASES, typename Base, mpl::void_) >
|
||||
struct bases : detail::type_list< BOOST_PYTHON_BASE_PARAMS >::type
|
||||
{};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T> struct specifies_bases
|
||||
: mpl::false_
|
||||
{
|
||||
};
|
||||
|
||||
template < BOOST_PP_ENUM_PARAMS_Z(1, BOOST_PYTHON_MAX_BASES, class Base) >
|
||||
struct specifies_bases< bases< BOOST_PYTHON_BASE_PARAMS > >
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
# else
|
||||
template < BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, class Base) >
|
||||
static char is_bases_helper(bases< BOOST_PYTHON_BASE_PARAMS > const&);
|
||||
|
||||
static char (& is_bases_helper(...) )[256];
|
||||
|
||||
template <class T>
|
||||
struct specifies_bases
|
||||
{
|
||||
private:
|
||||
static typename add_reference<T>::type make();
|
||||
BOOST_STATIC_CONSTANT(bool, non_ref = !is_reference<T>::value);
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = non_ref & (sizeof(is_bases_helper(make())) == 1));
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
# endif
|
||||
template <class T, class Prev = bases<> >
|
||||
struct select_bases
|
||||
: mpl::if_<
|
||||
specifies_bases<T>
|
||||
, T
|
||||
, Prev
|
||||
>
|
||||
{
|
||||
};
|
||||
}
|
||||
# undef BOOST_PYTHON_BASE_PARAMS
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BASES_DWA2002321_HPP
|
||||
21
include/boost/python/borrowed.hpp
Executable file
21
include/boost/python/borrowed.hpp
Executable file
@@ -0,0 +1,21 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BORROWED_DWA2002614_HPP
|
||||
# define BORROWED_DWA2002614_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/borrowed_ptr.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
inline python::detail::borrowed<T>* borrowed(T* p)
|
||||
{
|
||||
return (detail::borrowed<T>*)p;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BORROWED_DWA2002614_HPP
|
||||
79
include/boost/python/call.hpp
Normal file
79
include/boost/python/call.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# ifndef CALL_DWA2002411_HPP
|
||||
# define CALL_DWA2002411_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/converter/arg_to_python.hpp>
|
||||
# include <boost/python/converter/return_from_python.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
|
||||
# include <boost/preprocessor/comma_if.hpp>
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/repeat.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \
|
||||
, converter::arg_to_python<A##n>(a##n).get()
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# endif // CALL_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, call.hpp)
|
||||
# endif
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <
|
||||
class R
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
|
||||
>
|
||||
typename detail::returnable<R>::type
|
||||
call(PyObject* callable
|
||||
BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a)
|
||||
, boost::type<R>* = 0
|
||||
)
|
||||
{
|
||||
PyObject* const result =
|
||||
PyEval_CallFunction(
|
||||
callable
|
||||
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
|
||||
);
|
||||
|
||||
// This conversion *must not* be done in the same expression as
|
||||
// the call, because, in the special case where the result is a
|
||||
// reference a Python object which was created by converting a C++
|
||||
// argument for passing to PyEval_CallFunction, its reference
|
||||
// count will be 2 until the end of the full expression containing
|
||||
// the conversion, and that interferes with dangling
|
||||
// pointer/reference detection.
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(result);
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
#endif
|
||||
79
include/boost/python/call_method.hpp
Normal file
79
include/boost/python/call_method.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
# ifndef CALL_METHOD_DWA2002411_HPP
|
||||
# define CALL_METHOD_DWA2002411_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/converter/arg_to_python.hpp>
|
||||
# include <boost/python/converter/return_from_python.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
|
||||
# include <boost/preprocessor/comma_if.hpp>
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/repeat.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \
|
||||
, converter::arg_to_python<A##n>(a##n).get()
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call_method.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# endif // CALL_METHOD_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
|
||||
# endif
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <
|
||||
class R
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
|
||||
>
|
||||
typename detail::returnable<R>::type
|
||||
call_method(PyObject* self, char const* name
|
||||
BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a)
|
||||
, boost::type<R>* = 0
|
||||
)
|
||||
{
|
||||
PyObject* const result =
|
||||
PyEval_CallMethod(
|
||||
self
|
||||
, const_cast<char*>(name)
|
||||
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
|
||||
);
|
||||
|
||||
// This conversion *must not* be done in the same expression as
|
||||
// the call, because, in the special case where the result is a
|
||||
// reference a Python object which was created by converting a C++
|
||||
// argument for passing to PyEval_CallFunction, its reference
|
||||
// count will be 2 until the end of the full expression containing
|
||||
// the conversion, and that interferes with dangling
|
||||
// pointer/reference detection.
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(result);
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_IS_ITERATING
|
||||
106
include/boost/python/cast.hpp
Executable file
106
include/boost/python/cast.hpp
Executable file
@@ -0,0 +1,106 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef CAST_DWA200269_HPP
|
||||
# define CAST_DWA200269_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/python/base_type_traits.hpp>
|
||||
# include <boost/python/detail/convertible.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Source, class Target> inline Target* upcast_impl(Source*, Target*);
|
||||
|
||||
template <class Source, class Target>
|
||||
inline Target* upcast(Source* p, yes_convertible, no_convertible, Target*)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class Source, class Target>
|
||||
inline Target* upcast(Source* p, no_convertible, no_convertible, Target*)
|
||||
{
|
||||
typedef typename base_type_traits<Source>::type base;
|
||||
|
||||
return detail::upcast_impl((base*)p, (Target*)0);
|
||||
}
|
||||
|
||||
template <bool is_same = true>
|
||||
struct upcaster
|
||||
{
|
||||
template <class T>
|
||||
static inline T* execute(T* x, T*) { return x; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct upcaster<false>
|
||||
{
|
||||
template <class Source, class Target>
|
||||
static inline Target* execute(Source* x, Target*)
|
||||
{
|
||||
return detail::upcast(
|
||||
x, detail::convertible<Target*>::check(x)
|
||||
, detail::convertible<Source*>::check((Target*)0)
|
||||
, (Target*)0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* downcast(Source* p, yes_convertible)
|
||||
{
|
||||
return static_cast<Target*>(p);
|
||||
}
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* downcast(Source* p, no_convertible, boost::type<Target>* = 0)
|
||||
{
|
||||
typedef typename base_type_traits<Source>::type base;
|
||||
return (Target*)detail::downcast<base>(p, convertible<Source*>::check((base*)0));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void assert_castable(boost::type<T>* = 0)
|
||||
{
|
||||
typedef char must_be_a_complete_type[sizeof(T)];
|
||||
}
|
||||
|
||||
template <class Source, class Target>
|
||||
inline Target* upcast_impl(Source* x, Target*)
|
||||
{
|
||||
typedef typename add_cv<Source>::type src_t;
|
||||
typedef typename add_cv<Target>::type target_t;
|
||||
bool const same = is_same<src_t,target_t>::value;
|
||||
|
||||
return detail::upcaster<same>::execute(x, (Target*)0);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* upcast(Source* x, Target* = 0)
|
||||
{
|
||||
detail::assert_castable<Source>();
|
||||
detail::assert_castable<Target>();
|
||||
return detail::upcast_impl(x, (Target*)0);
|
||||
|
||||
}
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* downcast(Source* x, Target* = 0)
|
||||
{
|
||||
detail::assert_castable<Source>();
|
||||
detail::assert_castable<Target>();
|
||||
return detail::downcast<Target>(x, detail::convertible<Source*>::check((Target*)0));
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CAST_DWA200269_HPP
|
||||
654
include/boost/python/class.hpp
Normal file
654
include/boost/python/class.hpp
Normal file
@@ -0,0 +1,654 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef CLASS_DWA200216_HPP
|
||||
# define CLASS_DWA200216_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/noncopyable.hpp>
|
||||
|
||||
# include <boost/python/class_fwd.hpp>
|
||||
# include <boost/python/object/class.hpp>
|
||||
|
||||
# include <boost/python/object.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/data_members.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
# include <boost/python/signature.hpp>
|
||||
# include <boost/python/init.hpp>
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
|
||||
# include <boost/python/object/class_metadata.hpp>
|
||||
# include <boost/python/object/pickle_support.hpp>
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
|
||||
# include <boost/python/detail/overloads_fwd.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
# include <boost/python/detail/unwrap_type_id.hpp>
|
||||
# include <boost/python/detail/unwrap_wrapper.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
# include <boost/type_traits/is_polymorphic.hpp>
|
||||
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/for_each.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
# include <boost/mpl/not.hpp>
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) \
|
||||
/* pro9 reintroduced the bug */ \
|
||||
|| (BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) \
|
||||
|| BOOST_WORKAROUND(__GNUC__, < 3)
|
||||
|
||||
# define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1
|
||||
|
||||
# endif
|
||||
|
||||
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
|
||||
# include <boost/mpl/and.hpp>
|
||||
# include <boost/type_traits/is_member_pointer.hpp>
|
||||
# endif
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class DerivedVisitor> class def_visitor;
|
||||
|
||||
enum no_init_t { no_init };
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// This function object is used with mpl::for_each to write the id
|
||||
// of the type a pointer to which is passed as its 2nd compile-time
|
||||
// argument. into the iterator pointed to by its runtime argument
|
||||
struct write_type_id
|
||||
{
|
||||
write_type_id(type_info**p) : p(p) {}
|
||||
|
||||
// Here's the runtime behavior
|
||||
template <class T>
|
||||
void operator()(T*) const
|
||||
{
|
||||
*(*p)++ = type_id<T>();
|
||||
}
|
||||
|
||||
type_info** p;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_data_member_pointer
|
||||
: mpl::and_<
|
||||
is_member_pointer<T>
|
||||
, mpl::not_<is_member_function_pointer<T> >
|
||||
>
|
||||
{};
|
||||
|
||||
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
|
||||
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
|
||||
# define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
|
||||
# define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
|
||||
# elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
|
||||
# define BOOST_PYTHON_YES_DATA_MEMBER , int
|
||||
# define BOOST_PYTHON_NO_DATA_MEMBER , ...
|
||||
# else
|
||||
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
|
||||
# define BOOST_PYTHON_YES_DATA_MEMBER
|
||||
# define BOOST_PYTHON_NO_DATA_MEMBER
|
||||
# endif
|
||||
|
||||
namespace error
|
||||
{
|
||||
//
|
||||
// A meta-assertion mechanism which prints nice error messages and
|
||||
// backtraces on lots of compilers. Usage:
|
||||
//
|
||||
// assertion<C>::failed
|
||||
//
|
||||
// where C is an MPL metafunction class
|
||||
//
|
||||
|
||||
template <class C> struct assertion_failed { };
|
||||
template <class C> struct assertion_ok { typedef C failed; };
|
||||
|
||||
template <class C>
|
||||
struct assertion
|
||||
: mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type
|
||||
{};
|
||||
|
||||
//
|
||||
// Checks for validity of arguments used to define virtual
|
||||
// functions with default implementations.
|
||||
//
|
||||
|
||||
template <class Default>
|
||||
void not_a_derived_class_member(Default) {}
|
||||
|
||||
template <class T, class Fn>
|
||||
struct virtual_function_default
|
||||
{
|
||||
template <class Default>
|
||||
static void
|
||||
must_be_derived_class_member(Default const&)
|
||||
{
|
||||
typedef typename assertion<mpl::not_<is_same<Default,Fn> > >::failed test0;
|
||||
# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
typedef typename assertion<is_polymorphic<T> >::failed test1;
|
||||
# endif
|
||||
typedef typename assertion<is_member_function_pointer<Fn> >::failed test2;
|
||||
not_a_derived_class_member<Default>(Fn());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// This is the primary mechanism through which users will expose
|
||||
// C++ classes to Python.
|
||||
template <
|
||||
class W // class being wrapped
|
||||
, class X1 // = detail::not_specified
|
||||
, class X2 // = detail::not_specified
|
||||
, class X3 // = detail::not_specified
|
||||
>
|
||||
class class_ : public objects::class_base
|
||||
{
|
||||
public: // types
|
||||
typedef objects::class_base base;
|
||||
typedef class_<W,X1,X2,X3> self;
|
||||
typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
|
||||
typedef W wrapped_type;
|
||||
|
||||
private: // types
|
||||
|
||||
// A helper class which will contain an array of id objects to be
|
||||
// passed to the base class constructor
|
||||
struct id_vector
|
||||
{
|
||||
typedef typename metadata::bases bases;
|
||||
|
||||
id_vector()
|
||||
{
|
||||
// Stick the derived class id into the first element of the array
|
||||
ids[0] = detail::unwrap_type_id((W*)0, (W*)0);
|
||||
|
||||
// Write the rest of the elements into succeeding positions.
|
||||
type_info* p = ids + 1;
|
||||
mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0);
|
||||
}
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
std::size_t, size = mpl::size<bases>::value + 1);
|
||||
type_info ids[size];
|
||||
};
|
||||
friend struct id_vector;
|
||||
|
||||
public: // constructors
|
||||
|
||||
// Construct with the class name, with or without docstring, and default __init__() function
|
||||
class_(char const* name, char const* doc = 0);
|
||||
|
||||
// Construct with class name, no docstring, and an uncallable __init__ function
|
||||
class_(char const* name, no_init_t);
|
||||
|
||||
// Construct with class name, docstring, and an uncallable __init__ function
|
||||
class_(char const* name, char const* doc, no_init_t);
|
||||
|
||||
// Construct with class name and init<> function
|
||||
template <class DerivedT>
|
||||
inline class_(char const* name, init_base<DerivedT> const& i)
|
||||
: base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
this->initialize(i);
|
||||
}
|
||||
|
||||
// Construct with class name, docstring and init<> function
|
||||
template <class DerivedT>
|
||||
inline class_(char const* name, char const* doc, init_base<DerivedT> const& i)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->initialize(i);
|
||||
}
|
||||
|
||||
public: // member functions
|
||||
|
||||
// Generic visitation
|
||||
template <class Derived>
|
||||
self& def(def_visitor<Derived> const& visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Wrap a member function or a non-member function which can take
|
||||
// a T, T cv&, or T cv* as its first parameter, a callable
|
||||
// python object, or a generic visitor.
|
||||
template <class F>
|
||||
self& def(char const* name, F f)
|
||||
{
|
||||
this->def_impl(
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name, f, detail::def_helper<char const*>(0), &f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
self& def(char const* name, A1 a1, A2 const& a2)
|
||||
{
|
||||
this->def_maybe_overloads(name, a1, a2, &a2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Fn, class A1, class A2>
|
||||
self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
|
||||
{
|
||||
// The arguments are definitely:
|
||||
// def(name, function, policy, doc_string)
|
||||
// def(name, function, doc_string, policy)
|
||||
|
||||
this->def_impl(
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name, fn
|
||||
, detail::def_helper<A1,A2>(a1,a2)
|
||||
, &fn);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Fn, class A1, class A2, class A3>
|
||||
self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
|
||||
{
|
||||
this->def_impl(
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name, fn
|
||||
, detail::def_helper<A1,A2,A3>(a1,a2,a3)
|
||||
, &fn);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Data member access
|
||||
//
|
||||
template <class D>
|
||||
self& def_readonly(char const* name, D const& d, char const* doc=0)
|
||||
{
|
||||
return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite(char const* name, D const& d, char const* doc=0)
|
||||
{
|
||||
return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readonly(char const* name, D& d, char const* doc=0)
|
||||
{
|
||||
return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite(char const* name, D& d, char const* doc=0)
|
||||
{
|
||||
return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
// Property creation
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
template <class Get>
|
||||
self& add_property(char const* name, Get fget, char const* docstr = 0)
|
||||
{
|
||||
base::add_property(name, this->make_getter(fget), docstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_property(char const* name, Get fget, Set fset, char const* docstr = 0)
|
||||
{
|
||||
base::add_property(
|
||||
name, this->make_getter(fget), this->make_setter(fset), docstr);
|
||||
return *this;
|
||||
}
|
||||
# else
|
||||
private:
|
||||
template <class Get>
|
||||
self& add_property_impl(char const* name, Get fget, char const* docstr, int)
|
||||
{
|
||||
base::add_property(name, this->make_getter(fget), docstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_property_impl(char const* name, Get fget, Set fset, ...)
|
||||
{
|
||||
base::add_property(
|
||||
name, this->make_getter(fget), this->make_setter(fset), 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
template <class Get>
|
||||
self& add_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_property(name, this->make_getter(fget), 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class DocStrOrSet>
|
||||
self& add_property(char const* name, Get fget, DocStrOrSet docstr_or_set)
|
||||
{
|
||||
this->add_property_impl(name, this->make_getter(fget), docstr_or_set, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self&
|
||||
add_property(char const* name, Get fget, Set fset, char const* docstr)
|
||||
{
|
||||
base::add_property(
|
||||
name, this->make_getter(fget), this->make_setter(fset), docstr);
|
||||
return *this;
|
||||
}
|
||||
# endif
|
||||
|
||||
template <class Get>
|
||||
self& add_static_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_static_property(name, object(fget));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_static_property(char const* name, Get fget, Set fset)
|
||||
{
|
||||
base::add_static_property(name, object(fget), object(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
self& setattr(char const* name, U const& x)
|
||||
{
|
||||
this->base::setattr(name, object(x));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Pickle support
|
||||
template <typename PickleSuiteType>
|
||||
self& def_pickle(PickleSuiteType const& x)
|
||||
{
|
||||
error_messages::must_be_derived_from_pickle_suite(x);
|
||||
detail::pickle_suite_finalize<PickleSuiteType>::register_(
|
||||
*this,
|
||||
&PickleSuiteType::getinitargs,
|
||||
&PickleSuiteType::getstate,
|
||||
&PickleSuiteType::setstate,
|
||||
PickleSuiteType::getstate_manages_dict());
|
||||
return *this;
|
||||
}
|
||||
|
||||
self& enable_pickling()
|
||||
{
|
||||
this->base::enable_pickling_(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
self& staticmethod(char const* name)
|
||||
{
|
||||
this->make_method_static(name);
|
||||
return *this;
|
||||
}
|
||||
private: // helper functions
|
||||
|
||||
// Builds a method for this class around the given [member]
|
||||
// function pointer or object, appropriately adjusting the type of
|
||||
// the first signature argument so that if f is a member of a
|
||||
// (possibly not wrapped) base class of T, an lvalue argument of
|
||||
// type T will be required.
|
||||
//
|
||||
// @group PropertyHelpers {
|
||||
template <class F>
|
||||
object make_getter(F f)
|
||||
{
|
||||
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
|
||||
|
||||
return this->make_fn_impl(
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
object make_setter(F f)
|
||||
{
|
||||
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
|
||||
|
||||
return this->make_fn_impl(
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class T, class F>
|
||||
object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_)
|
||||
{
|
||||
return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
|
||||
}
|
||||
|
||||
template <class T, class D, class B>
|
||||
object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return python::make_getter(pm);
|
||||
}
|
||||
|
||||
template <class T, class D, class B>
|
||||
object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return python::make_setter(pm);
|
||||
}
|
||||
|
||||
template <class T, class F>
|
||||
object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
// }
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readonly_impl(
|
||||
char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
|
||||
{
|
||||
return this->add_property(name, pm_, doc);
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readwrite_impl(
|
||||
char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
|
||||
{
|
||||
return this->add_property(name, pm_, pm_, doc);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readonly_impl(
|
||||
char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
|
||||
{
|
||||
return this->add_static_property(name, python::make_getter(d));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite_impl(
|
||||
char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
|
||||
{
|
||||
return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
|
||||
}
|
||||
|
||||
template <class DefVisitor>
|
||||
inline void initialize(DefVisitor const& i)
|
||||
{
|
||||
metadata::register_(); // set up runtime metadata/conversions
|
||||
|
||||
typedef typename metadata::holder holder;
|
||||
this->set_instance_size( objects::additional_instance_size<holder>::value );
|
||||
|
||||
this->def(i);
|
||||
}
|
||||
|
||||
inline void initialize(no_init_t)
|
||||
{
|
||||
metadata::register_(); // set up runtime metadata/conversions
|
||||
this->def_no_init();
|
||||
}
|
||||
|
||||
//
|
||||
// These two overloads discriminate between def() as applied to a
|
||||
// generic visitor and everything else.
|
||||
//
|
||||
// @group def_impl {
|
||||
template <class T, class Helper, class LeafVisitor, class Visitor>
|
||||
inline void def_impl(
|
||||
T*
|
||||
, char const* name
|
||||
, LeafVisitor
|
||||
, Helper const& helper
|
||||
, def_visitor<Visitor> const* v
|
||||
)
|
||||
{
|
||||
v->visit(*this, name, helper);
|
||||
}
|
||||
|
||||
template <class T, class Fn, class Helper>
|
||||
inline void def_impl(
|
||||
T*
|
||||
, char const* name
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...
|
||||
)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this
|
||||
, name
|
||||
, make_function(
|
||||
fn
|
||||
, helper.policies()
|
||||
, helper.keywords()
|
||||
, detail::get_signature(fn, (T*)0)
|
||||
)
|
||||
, helper.doc()
|
||||
);
|
||||
|
||||
this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
|
||||
}
|
||||
// }
|
||||
|
||||
//
|
||||
// These two overloads handle the definition of default
|
||||
// implementation overloads for virtual functions. The second one
|
||||
// handles the case where no default implementation was specified.
|
||||
//
|
||||
// @group def_default {
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(
|
||||
char const* name
|
||||
, Fn
|
||||
, Helper const& helper
|
||||
, mpl::bool_<true>)
|
||||
{
|
||||
detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
|
||||
helper.default_implementation());
|
||||
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
helper.default_implementation(), helper.policies(), helper.keywords())
|
||||
);
|
||||
}
|
||||
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
|
||||
{ }
|
||||
// }
|
||||
|
||||
//
|
||||
// These two overloads discriminate between def() as applied to
|
||||
// regular functions and def() as applied to the result of
|
||||
// BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
|
||||
// discriminate.
|
||||
//
|
||||
// @group def_maybe_overloads {
|
||||
template <class OverloadsT, class SigT>
|
||||
void def_maybe_overloads(
|
||||
char const* name
|
||||
, SigT sig
|
||||
, OverloadsT const& overloads
|
||||
, detail::overloads_base const*)
|
||||
|
||||
{
|
||||
// convert sig to a type_list (see detail::get_signature in signature.hpp)
|
||||
// before calling detail::define_with_defaults.
|
||||
detail::define_with_defaults(
|
||||
name, overloads, *this, detail::get_signature(sig));
|
||||
}
|
||||
|
||||
template <class Fn, class A1>
|
||||
void def_maybe_overloads(
|
||||
char const* name
|
||||
, Fn fn
|
||||
, A1 const& a1
|
||||
, ...)
|
||||
{
|
||||
this->def_impl(
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name
|
||||
, fn
|
||||
, detail::def_helper<A1>(a1)
|
||||
, &fn
|
||||
);
|
||||
|
||||
}
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <class W, class X1, class X2, class X3>
|
||||
inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->initialize(init<>());
|
||||
// select_holder::assert_default_constructible();
|
||||
}
|
||||
|
||||
template <class W, class X1, class X2, class X3>
|
||||
inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t)
|
||||
: base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
this->initialize(no_init);
|
||||
}
|
||||
|
||||
template <class W, class X1, class X2, class X3>
|
||||
inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->initialize(no_init);
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# undef BOOST_PYTHON_DATA_MEMBER_HELPER
|
||||
# undef BOOST_PYTHON_YES_DATA_MEMBER
|
||||
# undef BOOST_PYTHON_NO_DATA_MEMBER
|
||||
# undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
|
||||
|
||||
#endif // CLASS_DWA200216_HPP
|
||||
24
include/boost/python/class_fwd.hpp
Normal file
24
include/boost/python/class_fwd.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef CLASS_FWD_DWA200222_HPP
|
||||
# define CLASS_FWD_DWA200222_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <
|
||||
class T // class being wrapped
|
||||
// arbitrarily-ordered optional arguments. Full qualification needed for MSVC6
|
||||
, class X1 = ::boost::python::detail::not_specified
|
||||
, class X2 = ::boost::python::detail::not_specified
|
||||
, class X3 = ::boost::python::detail::not_specified
|
||||
>
|
||||
class class_;
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CLASS_FWD_DWA200222_HPP
|
||||
336
include/boost/python/converter/arg_from_python.hpp
Executable file
336
include/boost/python/converter/arg_from_python.hpp
Executable file
@@ -0,0 +1,336 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
# define ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/mpl/eval_if.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
# include <boost/mpl/and.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
# include <boost/mpl/not.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/python/detail/void_ptr.hpp>
|
||||
# include <boost/python/back_reference.hpp>
|
||||
# include <boost/python/detail/referent_storage.hpp>
|
||||
# include <boost/python/converter/obj_mgr_arg_from_python.hpp>
|
||||
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T> struct arg_from_python;
|
||||
}}
|
||||
|
||||
// This header defines Python->C++ function argument converters,
|
||||
// parametrized on the argument type.
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
//
|
||||
// lvalue converters
|
||||
//
|
||||
// These require that an lvalue of the type U is stored somewhere in
|
||||
// the Python object being converted.
|
||||
|
||||
// Used when T == U*const&
|
||||
template <class T>
|
||||
struct pointer_cref_arg_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
pointer_cref_arg_from_python(PyObject*);
|
||||
T operator()() const;
|
||||
bool convertible() const;
|
||||
|
||||
private: // storage for a U*
|
||||
// needed because not all compilers will let us declare U* as the
|
||||
// return type of operator() -- we return U*const& instead
|
||||
typename python::detail::referent_storage<T>::type m_result;
|
||||
};
|
||||
|
||||
// Base class for pointer and reference converters
|
||||
struct arg_lvalue_from_python_base
|
||||
{
|
||||
public: // member functions
|
||||
arg_lvalue_from_python_base(void* result);
|
||||
bool convertible() const;
|
||||
|
||||
protected: // member functions
|
||||
void*const& result() const;
|
||||
|
||||
private: // data members
|
||||
void* m_result;
|
||||
};
|
||||
|
||||
// Used when T == U*
|
||||
template <class T>
|
||||
struct pointer_arg_from_python : arg_lvalue_from_python_base
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
pointer_arg_from_python(PyObject*);
|
||||
T operator()() const;
|
||||
};
|
||||
|
||||
// Used when T == U& and (T != V const& or T == W volatile&)
|
||||
template <class T>
|
||||
struct reference_arg_from_python : arg_lvalue_from_python_base
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
reference_arg_from_python(PyObject*);
|
||||
T operator()() const;
|
||||
};
|
||||
|
||||
// ===================
|
||||
|
||||
//
|
||||
// rvalue converters
|
||||
//
|
||||
// These require only that an object of type T can be created from
|
||||
// the given Python object, but not that the T object exist
|
||||
// somewhere in storage.
|
||||
//
|
||||
|
||||
// Used when T is a plain value (non-pointer, non-reference) type or
|
||||
// a (non-volatile) const reference to a plain value type.
|
||||
template <class T>
|
||||
struct arg_rvalue_from_python
|
||||
{
|
||||
typedef typename boost::add_reference<
|
||||
T
|
||||
// We can't add_const here, or it would be impossible to pass
|
||||
// auto_ptr<U> args from Python to C++
|
||||
>::type result_type;
|
||||
|
||||
arg_rvalue_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
|
||||
# if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196
|
||||
typename arg_rvalue_from_python<T>::
|
||||
# endif
|
||||
result_type operator()();
|
||||
|
||||
private:
|
||||
rvalue_from_python_data<result_type> m_data;
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
|
||||
// ==================
|
||||
|
||||
// Converts to a (PyObject*,T) bundle, for when you need a reference
|
||||
// back to the Python object
|
||||
template <class T>
|
||||
struct back_reference_arg_from_python
|
||||
: boost::python::arg_from_python<typename T::type>
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
back_reference_arg_from_python(PyObject*);
|
||||
T operator()();
|
||||
private:
|
||||
typedef boost::python::arg_from_python<typename T::type> base;
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
|
||||
// ==================
|
||||
|
||||
template <class C, class T, class F>
|
||||
struct if_2
|
||||
{
|
||||
typedef typename mpl::eval_if<C, mpl::identity<T>, F>::type type;
|
||||
};
|
||||
|
||||
// This metafunction selects the appropriate arg_from_python converter
|
||||
// type for an argument of type T.
|
||||
template <class T>
|
||||
struct select_arg_from_python
|
||||
{
|
||||
typedef typename if_2<
|
||||
is_object_manager<T>
|
||||
, object_manager_value_arg_from_python<T>
|
||||
, if_2<
|
||||
is_reference_to_object_manager<T>
|
||||
, object_manager_ref_arg_from_python<T>
|
||||
, if_2<
|
||||
is_pointer<T>
|
||||
, pointer_arg_from_python<T>
|
||||
, if_2<
|
||||
mpl::and_<
|
||||
indirect_traits::is_reference_to_pointer<T>
|
||||
, indirect_traits::is_reference_to_const<T>
|
||||
, mpl::not_<indirect_traits::is_reference_to_volatile<T> >
|
||||
>
|
||||
, pointer_cref_arg_from_python<T>
|
||||
, if_2<
|
||||
mpl::or_<
|
||||
indirect_traits::is_reference_to_non_const<T>
|
||||
, indirect_traits::is_reference_to_volatile<T>
|
||||
>
|
||||
, reference_arg_from_python<T>
|
||||
, mpl::if_<
|
||||
boost::python::is_back_reference<T>
|
||||
, back_reference_arg_from_python<T>
|
||||
, arg_rvalue_from_python<T>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// ==================
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
// arg_lvalue_from_python_base
|
||||
//
|
||||
inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result)
|
||||
: m_result(result)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool arg_lvalue_from_python_base::convertible() const
|
||||
{
|
||||
return m_result != 0;
|
||||
}
|
||||
|
||||
inline void*const& arg_lvalue_from_python_base::result() const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
// pointer_cref_arg_from_python
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
// null_ptr_reference -- a function returning a reference to a null
|
||||
// pointer of type U. Needed so that extractors for T*const& can
|
||||
// convert Python's None.
|
||||
template <class T>
|
||||
struct null_ptr_owner
|
||||
{
|
||||
static T value;
|
||||
};
|
||||
template <class T> T null_ptr_owner<T>::value = 0;
|
||||
|
||||
template <class U>
|
||||
inline U& null_ptr_reference(U&(*)())
|
||||
{
|
||||
return null_ptr_owner<U>::value;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline pointer_cref_arg_from_python<T>::pointer_cref_arg_from_python(PyObject* p)
|
||||
{
|
||||
// T == U*const&: store a U* in the m_result storage. Nonzero
|
||||
// indicates success. If find returns nonzero, it's a pointer to
|
||||
// a U object.
|
||||
python::detail::write_void_ptr_reference(
|
||||
m_result.bytes
|
||||
, p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters)
|
||||
, (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool pointer_cref_arg_from_python<T>::convertible() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0;
|
||||
}
|
||||
template <class T>
|
||||
inline T pointer_cref_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return (*(void**)m_result.bytes == Py_None) // None ==> 0
|
||||
? detail::null_ptr_reference((T(*)())0)
|
||||
// Otherwise, return a U*const& to the m_result storage.
|
||||
: python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0);
|
||||
}
|
||||
|
||||
// pointer_arg_from_python
|
||||
//
|
||||
template <class T>
|
||||
inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p)
|
||||
: arg_lvalue_from_python_base(
|
||||
p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T pointer_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return (result() == Py_None) ? 0 : T(result());
|
||||
}
|
||||
|
||||
// reference_arg_from_python
|
||||
//
|
||||
template <class T>
|
||||
inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p)
|
||||
: arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered<T>::converters))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T reference_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(result(), (T(*)())0);
|
||||
}
|
||||
|
||||
|
||||
// arg_rvalue_from_python
|
||||
//
|
||||
template <class T>
|
||||
inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj)
|
||||
: m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
|
||||
, m_source(obj)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool arg_rvalue_from_python<T>::convertible() const
|
||||
{
|
||||
return m_data.stage1.convertible != 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename arg_rvalue_from_python<T>::result_type
|
||||
arg_rvalue_from_python<T>::operator()()
|
||||
{
|
||||
if (m_data.stage1.construct != 0)
|
||||
m_data.stage1.construct(m_source, &m_data.stage1);
|
||||
|
||||
return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
|
||||
}
|
||||
|
||||
// back_reference_arg_from_python
|
||||
//
|
||||
template <class T>
|
||||
back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x)
|
||||
: base(x), m_source(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
back_reference_arg_from_python<T>::operator()()
|
||||
{
|
||||
return T(m_source, base::operator()());
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
261
include/boost/python/converter/arg_to_python.hpp
Executable file
261
include/boost/python/converter/arg_to_python.hpp
Executable file
@@ -0,0 +1,261 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef ARG_TO_PYTHON_DWA200265_HPP
|
||||
# define ARG_TO_PYTHON_DWA200265_HPP
|
||||
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/tag.hpp>
|
||||
# include <boost/python/to_python_indirect.hpp>
|
||||
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/python/converter/arg_to_python_base.hpp>
|
||||
# include <boost/python/converter/shared_ptr_to_python.hpp>
|
||||
// Bring in specializations
|
||||
# include <boost/python/converter/builtin_converters.hpp>
|
||||
|
||||
# include <boost/python/object/function_handle.hpp>
|
||||
|
||||
# include <boost/python/base_type_traits.hpp>
|
||||
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/python/detail/convertible.hpp>
|
||||
# include <boost/python/detail/string_literal.hpp>
|
||||
# include <boost/python/detail/value_is_shared_ptr.hpp>
|
||||
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
# include <boost/type_traits/function_traits.hpp>
|
||||
|
||||
|
||||
# include <boost/mpl/or.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T> struct is_object_manager;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct function_arg_to_python : handle<>
|
||||
{
|
||||
function_arg_to_python(T const& x);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct reference_arg_to_python : handle<>
|
||||
{
|
||||
reference_arg_to_python(T& x);
|
||||
private:
|
||||
static PyObject* get_object(T& x);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct shared_ptr_arg_to_python : handle<>
|
||||
{
|
||||
shared_ptr_arg_to_python(T const& x);
|
||||
private:
|
||||
static PyObject* get_object(T& x);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct value_arg_to_python : arg_to_python_base
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
value_arg_to_python(T const&);
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_deep_arg_to_python : arg_to_python_base
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
pointer_deep_arg_to_python(Ptr);
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_shallow_arg_to_python : handle<>
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
pointer_shallow_arg_to_python(Ptr);
|
||||
private:
|
||||
static PyObject* get_object(Ptr p);
|
||||
};
|
||||
|
||||
// Convert types that manage a Python object to_python
|
||||
template <class T>
|
||||
struct object_manager_arg_to_python
|
||||
{
|
||||
object_manager_arg_to_python(T const& x) : m_src(x) {}
|
||||
|
||||
PyObject* get() const
|
||||
{
|
||||
return python::upcast<PyObject>(get_managed_object(m_src, tag));
|
||||
}
|
||||
|
||||
private:
|
||||
T const& m_src;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_arg_to_python
|
||||
{
|
||||
typedef typename unwrap_reference<T>::type unwrapped_referent;
|
||||
typedef typename unwrap_pointer<T>::type unwrapped_ptr;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
// Special handling for char const[N]; interpret them as char
|
||||
// const* for the sake of conversion
|
||||
python::detail::is_string_literal<T const>
|
||||
, arg_to_python<char const*>
|
||||
|
||||
, typename mpl::if_<
|
||||
python::detail::value_is_shared_ptr<T>
|
||||
, shared_ptr_arg_to_python<T>
|
||||
|
||||
, typename mpl::if_<
|
||||
mpl::or_<
|
||||
is_function<T>
|
||||
, indirect_traits::is_pointer_to_function<T>
|
||||
, is_member_function_pointer<T>
|
||||
>
|
||||
, function_arg_to_python<T>
|
||||
|
||||
, typename mpl::if_<
|
||||
is_object_manager<T>
|
||||
, object_manager_arg_to_python<T>
|
||||
|
||||
, typename mpl::if_<
|
||||
is_pointer<T>
|
||||
, pointer_deep_arg_to_python<T>
|
||||
|
||||
, typename mpl::if_<
|
||||
is_pointer_wrapper<T>
|
||||
, pointer_shallow_arg_to_python<unwrapped_ptr>
|
||||
|
||||
, typename mpl::if_<
|
||||
is_reference_wrapper<T>
|
||||
, reference_arg_to_python<unwrapped_referent>
|
||||
, value_arg_to_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
|
||||
type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct arg_to_python
|
||||
: detail::select_arg_to_python<T>::type
|
||||
{
|
||||
typedef typename detail::select_arg_to_python<T>::type base;
|
||||
public: // member functions
|
||||
// Throw an exception if the conversion can't succeed
|
||||
arg_to_python(T const& x);
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
// reject_raw_object_ptr -- cause a compile-time error if the user
|
||||
// should pass a raw Python object pointer
|
||||
using python::detail::yes_convertible;
|
||||
using python::detail::no_convertible;
|
||||
using python::detail::unspecialized;
|
||||
|
||||
template <class T> struct cannot_convert_raw_PyObject;
|
||||
|
||||
template <class T, class Convertibility>
|
||||
struct reject_raw_object_helper
|
||||
{
|
||||
static void error(Convertibility)
|
||||
{
|
||||
cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead();
|
||||
}
|
||||
static void error(...) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline void reject_raw_object_ptr(T*)
|
||||
{
|
||||
reject_raw_object_helper<T,yes_convertible>::error(
|
||||
python::detail::convertible<PyObject const volatile*>::check((T*)0));
|
||||
|
||||
typedef typename remove_cv<T>::type value_type;
|
||||
|
||||
reject_raw_object_helper<T,no_convertible>::error(
|
||||
python::detail::convertible<unspecialized*>::check(
|
||||
(base_type_traits<value_type>*)0
|
||||
));
|
||||
}
|
||||
// ---------
|
||||
|
||||
template <class T>
|
||||
inline function_arg_to_python<T>::function_arg_to_python(T const& x)
|
||||
: handle<>(python::objects::make_function_handle(x))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline value_arg_to_python<T>::value_arg_to_python(T const& x)
|
||||
: arg_to_python_base(&x, registered<T>::converters)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr x)
|
||||
: arg_to_python_base(x, registered_pointee<Ptr>::converters)
|
||||
{
|
||||
detail::reject_raw_object_ptr((Ptr)0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline PyObject* reference_arg_to_python<T>::get_object(T& x)
|
||||
{
|
||||
to_python_indirect<T&,python::detail::make_reference_holder> convert;
|
||||
return convert(x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline reference_arg_to_python<T>::reference_arg_to_python(T& x)
|
||||
: handle<>(reference_arg_to_python<T>::get_object(x))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline shared_ptr_arg_to_python<T>::shared_ptr_arg_to_python(T const& x)
|
||||
: handle<>(shared_ptr_to_python(x))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline pointer_shallow_arg_to_python<Ptr>::pointer_shallow_arg_to_python(Ptr x)
|
||||
: handle<>(pointer_shallow_arg_to_python<Ptr>::get_object(x))
|
||||
{
|
||||
detail::reject_raw_object_ptr((Ptr)0);
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline PyObject* pointer_shallow_arg_to_python<Ptr>::get_object(Ptr x)
|
||||
{
|
||||
to_python_indirect<Ptr,python::detail::make_reference_holder> convert;
|
||||
return convert(x);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline arg_to_python<T>::arg_to_python(T const& x)
|
||||
: base(x)
|
||||
{}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // ARG_TO_PYTHON_DWA200265_HPP
|
||||
32
include/boost/python/converter/arg_to_python_base.hpp
Executable file
32
include/boost/python/converter/arg_to_python_base.hpp
Executable file
@@ -0,0 +1,32 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# define ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct BOOST_PYTHON_DECL arg_to_python_base
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC <= 1300 || _MSC_FULL_VER > 13102179
|
||||
: handle<>
|
||||
# endif
|
||||
{
|
||||
arg_to_python_base(void const volatile* source, registration const&);
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC > 1300 && _MSC_FULL_VER <= 13102179
|
||||
PyObject* get() const { return m_ptr.get(); }
|
||||
PyObject* release() { return m_ptr.release(); }
|
||||
private:
|
||||
handle<> m_ptr;
|
||||
# endif
|
||||
};
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
46
include/boost/python/converter/as_to_python_function.hpp
Normal file
46
include/boost/python/converter/as_to_python_function.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef AS_TO_PYTHON_FUNCTION_DWA2002121_HPP
|
||||
# define AS_TO_PYTHON_FUNCTION_DWA2002121_HPP
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Given a typesafe to_python conversion function, produces a
|
||||
// to_python_function_t which can be registered in the usual way.
|
||||
template <class T, class ToPython>
|
||||
struct as_to_python_function
|
||||
{
|
||||
// Assertion functions used to prevent wrapping of converters
|
||||
// which take non-const reference parameters. The T* argument in
|
||||
// the first overload ensures it isn't used in case T is a
|
||||
// reference.
|
||||
template <class U>
|
||||
static void convert_function_must_take_value_or_const_reference(U(*)(T), int, T* = 0) {}
|
||||
template <class U>
|
||||
static void convert_function_must_take_value_or_const_reference(U(*)(T const&), long ...) {}
|
||||
|
||||
static PyObject* convert(void const* x)
|
||||
{
|
||||
convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L);
|
||||
|
||||
// Yes, the const_cast below opens a hole in const-correctness,
|
||||
// but it's needed to convert auto_ptr<U> to python.
|
||||
//
|
||||
// How big a hole is it? It allows ToPython::convert() to be
|
||||
// a function which modifies its argument. The upshot is that
|
||||
// client converters applied to const objects may invoke
|
||||
// undefined behavior. The damage, however, is limited by the
|
||||
// use of the assertion function. Thus, the only way this can
|
||||
// modify its argument is if T is an auto_ptr-like type. There
|
||||
// is still a const-correctness hole w.r.t. auto_ptr<U> const,
|
||||
// but c'est la vie.
|
||||
return ToPython::convert(*const_cast<T*>(static_cast<T const*>(x)));
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // AS_TO_PYTHON_FUNCTION_DWA2002121_HPP
|
||||
145
include/boost/python/converter/builtin_converters.hpp
Normal file
145
include/boost/python/converter/builtin_converters.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
# define BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/python/ssize_t.hpp>
|
||||
# include <boost/implicit_cast.hpp>
|
||||
# include <string>
|
||||
# include <complex>
|
||||
# include <boost/limits.hpp>
|
||||
|
||||
// Since all we can use to decide how to convert an object to_python
|
||||
// is its C++ type, there can be only one such converter for each
|
||||
// type. Therefore, for built-in conversions we can bypass registry
|
||||
// lookups using explicit specializations of arg_to_python and
|
||||
// result_to_python.
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace converter
|
||||
{
|
||||
template <class T> struct arg_to_python;
|
||||
BOOST_PYTHON_DECL PyObject* do_return_to_python(char);
|
||||
BOOST_PYTHON_DECL PyObject* do_return_to_python(char const*);
|
||||
BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject*);
|
||||
BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject*);
|
||||
}
|
||||
|
||||
// Provide specializations of to_python_value
|
||||
template <class T> struct to_python_value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Since there's no registry lookup, always report the existence of
|
||||
// a converter.
|
||||
struct builtin_to_python
|
||||
{
|
||||
// This information helps make_getter() decide whether to try to
|
||||
// return an internal reference or not. I don't like it much,
|
||||
// but it will have to serve for now.
|
||||
BOOST_STATIC_CONSTANT(bool, uses_registry = false);
|
||||
};
|
||||
}
|
||||
|
||||
// Use expr to create the PyObject corresponding to x
|
||||
# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
template <> struct to_python_value<T&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
inline PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
}; \
|
||||
template <> struct to_python_value<T const&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
inline PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
};
|
||||
|
||||
# define BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
namespace converter \
|
||||
{ \
|
||||
template <> struct arg_to_python< T > \
|
||||
: handle<> \
|
||||
{ \
|
||||
arg_to_python(T const& x) \
|
||||
: python::handle<>(expr) {} \
|
||||
}; \
|
||||
}
|
||||
|
||||
// Specialize argument and return value converters for T using expr
|
||||
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr) \
|
||||
BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr)
|
||||
|
||||
// Specialize converters for signed and unsigned T to Python Int
|
||||
# define BOOST_PYTHON_TO_INT(T) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x)) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE( \
|
||||
unsigned T \
|
||||
, static_cast<unsigned long>(x) > static_cast<unsigned long>( \
|
||||
(std::numeric_limits<long>::max)()) \
|
||||
? ::PyLong_FromUnsignedLong(x) \
|
||||
: ::PyInt_FromLong(x))
|
||||
|
||||
// Bool is not signed.
|
||||
#if PY_VERSION_HEX >= 0x02030000
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyBool_FromLong(x))
|
||||
#else
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x))
|
||||
#endif
|
||||
|
||||
// note: handles signed char and unsigned char, but not char (see below)
|
||||
BOOST_PYTHON_TO_INT(char)
|
||||
|
||||
BOOST_PYTHON_TO_INT(short)
|
||||
BOOST_PYTHON_TO_INT(int)
|
||||
BOOST_PYTHON_TO_INT(long)
|
||||
|
||||
// using Python's macro instead of Boost's - we don't seem to get the
|
||||
// config right all the time.
|
||||
# ifdef HAVE_LONG_LONG
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x))
|
||||
# endif
|
||||
|
||||
# undef BOOST_TO_PYTHON_INT
|
||||
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())))
|
||||
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())))
|
||||
# endif
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
|
||||
# undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_TO_INT
|
||||
|
||||
namespace converter
|
||||
{
|
||||
|
||||
void initialize_builtin_converters();
|
||||
|
||||
}
|
||||
|
||||
}} // namespace boost::python::converter
|
||||
|
||||
#endif // BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
17
include/boost/python/converter/constructor_function.hpp
Normal file
17
include/boost/python/converter/constructor_function.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef CONSTRUCTOR_FUNCTION_DWA200278_HPP
|
||||
# define CONSTRUCTOR_FUNCTION_DWA200278_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Declares the type of functions used to construct C++ objects for
|
||||
// rvalue from_python conversions.
|
||||
struct rvalue_from_python_stage1_data;
|
||||
typedef void (*constructor_function)(PyObject* source, rvalue_from_python_stage1_data*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CONSTRUCTOR_FUNCTION_DWA200278_HPP
|
||||
17
include/boost/python/converter/context_result_converter.hpp
Executable file
17
include/boost/python/converter/context_result_converter.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// Copyright David Abrahams 2003.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
# define CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// A ResultConverter base class used to indicate that this result
|
||||
// converter should be constructed with the original Python argument
|
||||
// list.
|
||||
struct context_result_converter {};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
14
include/boost/python/converter/convertible_function.hpp
Normal file
14
include/boost/python/converter/convertible_function.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef CONVERTIBLE_FUNCTION_DWA200278_HPP
|
||||
# define CONVERTIBLE_FUNCTION_DWA200278_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
typedef void* (*convertible_function)(PyObject*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CONVERTIBLE_FUNCTION_DWA200278_HPP
|
||||
41
include/boost/python/converter/from_python.hpp
Normal file
41
include/boost/python/converter/from_python.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
# define FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
|
||||
BOOST_PYTHON_DECL void* get_lvalue_from_python(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL bool implicit_rvalue_convertible_from_python(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL void* rvalue_from_python_stage2(
|
||||
PyObject* source, rvalue_from_python_stage1_data&, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL void* rvalue_result_from_python(
|
||||
PyObject*, rvalue_from_python_stage1_data&);
|
||||
|
||||
BOOST_PYTHON_DECL void* reference_result_from_python(PyObject*, registration const&);
|
||||
BOOST_PYTHON_DECL void* pointer_result_from_python(PyObject*, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL void void_result_from_python(PyObject*);
|
||||
|
||||
BOOST_PYTHON_DECL void throw_no_pointer_from_python(PyObject*, registration const&);
|
||||
BOOST_PYTHON_DECL void throw_no_reference_from_python(PyObject*, registration const&);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
46
include/boost/python/converter/implicit.hpp
Normal file
46
include/boost/python/converter/implicit.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef IMPLICIT_DWA2002326_HPP
|
||||
# define IMPLICIT_DWA2002326_HPP
|
||||
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registrations.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
|
||||
# include <boost/python/extract.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class Source, class Target>
|
||||
struct implicit
|
||||
{
|
||||
static void* convertible(PyObject* obj)
|
||||
{
|
||||
// Find a converter which can produce a Source instance from
|
||||
// obj. The user has told us that Source can be converted to
|
||||
// Target, and instantiating construct() below, ensures that
|
||||
// at compile-time.
|
||||
return implicit_rvalue_convertible_from_python(obj, registered<Source>::converters)
|
||||
? obj : 0;
|
||||
}
|
||||
|
||||
static void construct(PyObject* obj, rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
void* storage = ((rvalue_from_python_storage<Target>*)data)->storage.bytes;
|
||||
|
||||
arg_from_python<Source> get_source(obj);
|
||||
bool convertible = get_source.convertible();
|
||||
BOOST_ASSERT(convertible);
|
||||
|
||||
new (storage) Target(get_source());
|
||||
|
||||
// record successful construction
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // IMPLICIT_DWA2002326_HPP
|
||||
121
include/boost/python/converter/obj_mgr_arg_from_python.hpp
Normal file
121
include/boost/python/converter/obj_mgr_arg_from_python.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
# define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/referent_storage.hpp>
|
||||
# include <boost/python/detail/destroy.hpp>
|
||||
# include <boost/python/detail/construct.hpp>
|
||||
# include <boost/python/converter/object_manager.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
# include <boost/python/tag.hpp>
|
||||
|
||||
//
|
||||
// arg_from_python converters for Python type wrappers, to be used as
|
||||
// base classes for specializations.
|
||||
//
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T>
|
||||
struct object_manager_value_arg_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
object_manager_value_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
T operator()() const;
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
// Used for converting reference-to-object-manager arguments from
|
||||
// python. The process used here is a little bit odd. Upon
|
||||
// construction, we build the object manager object in the m_result
|
||||
// object, *forcing* it to accept the source Python object by casting
|
||||
// its pointer to detail::borrowed_reference. This is supposed to
|
||||
// bypass any type checking of the source object. The convertible
|
||||
// check then extracts the owned object and checks it. If the check
|
||||
// fails, nothing else in the program ever gets to touch this strange
|
||||
// "forced" object.
|
||||
template <class Ref>
|
||||
struct object_manager_ref_arg_from_python
|
||||
{
|
||||
typedef Ref result_type;
|
||||
|
||||
object_manager_ref_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
Ref operator()() const;
|
||||
~object_manager_ref_arg_from_python();
|
||||
private:
|
||||
typename python::detail::referent_storage<Ref>::type m_result;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <class T>
|
||||
inline object_manager_value_arg_from_python<T>::object_manager_value_arg_from_python(PyObject* x)
|
||||
: m_source(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool object_manager_value_arg_from_python<T>::convertible() const
|
||||
{
|
||||
return object_manager_traits<T>::check(m_source);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T object_manager_value_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return T(python::detail::borrowed_reference(m_source));
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline object_manager_ref_arg_from_python<Ref>::object_manager_ref_arg_from_python(PyObject* x)
|
||||
{
|
||||
# if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243
|
||||
// needed for warning suppression
|
||||
python::detail::borrowed_reference x_ = python::detail::borrowed_reference(x);
|
||||
python::detail::construct_referent<Ref>(&m_result.bytes, x_);
|
||||
# else
|
||||
python::detail::construct_referent<Ref>(&m_result.bytes, (python::detail::borrowed_reference)x);
|
||||
# endif
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline object_manager_ref_arg_from_python<Ref>::~object_manager_ref_arg_from_python()
|
||||
{
|
||||
python::detail::destroy_referent<Ref>(this->m_result.bytes);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
inline bool object_manager_ref_check(T const& x)
|
||||
{
|
||||
return object_manager_traits<T>::check(get_managed_object(x, tag));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline bool object_manager_ref_arg_from_python<Ref>::convertible() const
|
||||
{
|
||||
return detail::object_manager_ref_check(
|
||||
python::detail::void_ptr_to_reference(this->m_result.bytes, (Ref(*)())0));
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline Ref object_manager_ref_arg_from_python<Ref>::operator()() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(
|
||||
this->m_result.bytes, (Ref(*)())0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
230
include/boost/python/converter/object_manager.hpp
Executable file
230
include/boost/python/converter/object_manager.hpp
Executable file
@@ -0,0 +1,230 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef OBJECT_MANAGER_DWA2002614_HPP
|
||||
# define OBJECT_MANAGER_DWA2002614_HPP
|
||||
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/python/cast.hpp>
|
||||
# include <boost/python/converter/pyobject_traits.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
// Facilities for dealing with types which always manage Python
|
||||
// objects. Some examples are object, list, str, et. al. Different
|
||||
// to_python/from_python conversion rules apply here because in
|
||||
// contrast to other types which are typically embedded inside a
|
||||
// Python object, these are wrapped around a Python object. For most
|
||||
// object managers T, a C++ non-const T reference argument does not
|
||||
// imply the existence of a T lvalue embedded in the corresponding
|
||||
// Python argument, since mutating member functions on T actually only
|
||||
// modify the held Python object.
|
||||
//
|
||||
// handle<T> is an object manager, though strictly speaking it should
|
||||
// not be. In other words, even though mutating member functions of
|
||||
// hanlde<T> actually modify the handle<T> and not the T object,
|
||||
// handle<T>& arguments of wrapped functions will bind to "rvalues"
|
||||
// wrapping the actual Python argument, just as with other object
|
||||
// manager classes. Making an exception for handle<T> is simply not
|
||||
// worth the trouble.
|
||||
//
|
||||
// borrowed<T> cv* is an object manager so that we can use the general
|
||||
// to_python mechanisms to convert raw Python object pointers to
|
||||
// python, without the usual semantic problems of using raw pointers.
|
||||
|
||||
|
||||
// Object Manager Concept requirements:
|
||||
//
|
||||
// T is an Object Manager
|
||||
// p is a PyObject*
|
||||
// x is a T
|
||||
//
|
||||
// * object_manager_traits<T>::is_specialized == true
|
||||
//
|
||||
// * T(detail::borrowed_reference(p))
|
||||
// Manages p without checking its type
|
||||
//
|
||||
// * get_managed_object(x, boost::python::tag)
|
||||
// Convertible to PyObject*
|
||||
//
|
||||
// Additional requirements if T can be converted from_python:
|
||||
//
|
||||
// * T(object_manager_traits<T>::adopt(p))
|
||||
// steals a reference to p, or throws a TypeError exception if
|
||||
// p doesn't have an appropriate type. May assume p is non-null
|
||||
//
|
||||
// * X::check(p)
|
||||
// convertible to bool. True iff T(X::construct(p)) will not
|
||||
// throw.
|
||||
|
||||
// Forward declarations
|
||||
//
|
||||
namespace boost { namespace python
|
||||
{
|
||||
namespace api
|
||||
{
|
||||
class object;
|
||||
}
|
||||
}}
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
|
||||
// Specializations for handle<T>
|
||||
template <class T>
|
||||
struct handle_object_manager_traits
|
||||
: pyobject_traits<typename T::element_type>
|
||||
{
|
||||
private:
|
||||
typedef pyobject_traits<typename T::element_type> base;
|
||||
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
|
||||
|
||||
// Initialize with a null_ok pointer for efficiency, bypassing the
|
||||
// null check since the source is always non-null.
|
||||
static null_ok<typename T::element_type>* adopt(PyObject* p)
|
||||
{
|
||||
return python::allow_null(base::checked_downcast(p));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct default_object_manager_traits
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, is_specialized = python::detail::is_borrowed_ptr<T>::value
|
||||
);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct object_manager_traits
|
||||
: mpl::if_c<
|
||||
is_handle<T>::value
|
||||
, handle_object_manager_traits<T>
|
||||
, default_object_manager_traits<T>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
// Traits for detecting whether a type is an object manager or a
|
||||
// (cv-qualified) reference to an object manager.
|
||||
//
|
||||
|
||||
template <class T>
|
||||
struct is_object_manager
|
||||
: mpl::bool_<object_manager_traits<T>::is_specialized>
|
||||
{
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager
|
||||
: mpl::false_
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T const&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T volatile&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T const volatile&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
# else
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_reference_to_object_manager)[1];
|
||||
typedef char (&no_reference_to_object_manager)[2];
|
||||
|
||||
// A number of nastinesses go on here in order to work around MSVC6
|
||||
// bugs.
|
||||
template <class T>
|
||||
struct is_object_manager_help
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
is_object_manager<T>
|
||||
, yes_reference_to_object_manager
|
||||
, no_reference_to_object_manager
|
||||
>::type type;
|
||||
|
||||
// If we just use the type instead of the result of calling this
|
||||
// function, VC6 will ICE.
|
||||
static type call();
|
||||
};
|
||||
|
||||
// A set of overloads for each cv-qualification. The same argument
|
||||
// is passed twice: the first one is used to unwind the cv*, and the
|
||||
// second one is used to avoid relying on partial ordering for
|
||||
// overload resolution.
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U*, void*);
|
||||
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U const*, void const*);
|
||||
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U volatile*, void volatile*);
|
||||
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U const volatile*, void const volatile*);
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager_nonref
|
||||
: mpl::false_
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager_ref
|
||||
{
|
||||
static T sample_object;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value
|
||||
= (sizeof(is_object_manager_helper(&sample_object, &sample_object).call())
|
||||
== sizeof(detail::yes_reference_to_object_manager)
|
||||
)
|
||||
);
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager
|
||||
: mpl::if_<
|
||||
is_reference<T>
|
||||
, detail::is_reference_to_object_manager_ref<T>
|
||||
, detail::is_reference_to_object_manager_nonref<T>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
# endif
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // OBJECT_MANAGER_DWA2002614_HPP
|
||||
68
include/boost/python/converter/pointer_type_id.hpp
Normal file
68
include/boost/python/converter/pointer_type_id.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef POINTER_TYPE_ID_DWA2002222_HPP
|
||||
# define POINTER_TYPE_ID_DWA2002222_HPP
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool is_ref = false>
|
||||
struct pointer_typeid_select
|
||||
{
|
||||
template <class T>
|
||||
static inline type_info execute(T*(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pointer_typeid_select<true>
|
||||
{
|
||||
template <class T>
|
||||
static inline type_info execute(T* const volatile&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline type_info execute(T*volatile&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline type_info execute(T*const&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline type_info execute(T*&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Usage: pointer_type_id<T>()
|
||||
//
|
||||
// Returns a type_info associated with the type pointed
|
||||
// to by T, which may be a pointer or a reference to a pointer.
|
||||
template <class T>
|
||||
type_info pointer_type_id(T(*)() = 0)
|
||||
{
|
||||
return detail::pointer_typeid_select<
|
||||
is_reference<T>::value
|
||||
>::execute((T(*)())0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // POINTER_TYPE_ID_DWA2002222_HPP
|
||||
41
include/boost/python/converter/pyobject_traits.hpp
Normal file
41
include/boost/python/converter/pyobject_traits.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
# define PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/pyobject_type.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class> struct pyobject_traits;
|
||||
|
||||
template <>
|
||||
struct pyobject_traits<PyObject>
|
||||
{
|
||||
// All objects are convertible to PyObject
|
||||
static bool check(PyObject*) { return true; }
|
||||
static PyObject* checked_downcast(PyObject* x) { return x; }
|
||||
};
|
||||
|
||||
//
|
||||
// Specializations
|
||||
//
|
||||
|
||||
# define BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(T) \
|
||||
template <> struct pyobject_traits<Py##T##Object> \
|
||||
: pyobject_type<Py##T##Object, &Py##T##_Type> {}
|
||||
|
||||
// This is not an exhaustive list; should be expanded.
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Type);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(List);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Int);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Long);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Dict);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Tuple);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
34
include/boost/python/converter/pyobject_type.hpp
Normal file
34
include/boost/python/converter/pyobject_type.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef PYOBJECT_TYPE_DWA2002720_HPP
|
||||
# define PYOBJECT_TYPE_DWA2002720_HPP
|
||||
|
||||
# include <boost/python/cast.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*);
|
||||
|
||||
// Used as a base class for specializations which need to provide
|
||||
// Python type checking capability.
|
||||
template <class Object, PyTypeObject* pytype>
|
||||
struct pyobject_type
|
||||
{
|
||||
static bool check(PyObject* x)
|
||||
{
|
||||
return ::PyObject_IsInstance(x, (PyObject*)pytype);
|
||||
}
|
||||
|
||||
static Object* checked_downcast(PyObject* x)
|
||||
{
|
||||
return python::downcast<Object>(
|
||||
(checked_downcast_impl)(x, pytype)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYOBJECT_TYPE_DWA2002720_HPP
|
||||
42
include/boost/python/converter/pytype_object_mgr_traits.hpp
Normal file
42
include/boost/python/converter/pytype_object_mgr_traits.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
# define PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
# include <boost/python/cast.hpp>
|
||||
# include <boost/python/converter/pyobject_type.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Provide a forward declaration as a convenience for clients, who all
|
||||
// need it.
|
||||
template <class T> struct object_manager_traits;
|
||||
|
||||
// Derive specializations of object_manager_traits from this class
|
||||
// when T is an object manager for a particular Python type hierarchy.
|
||||
//
|
||||
template <PyTypeObject* pytype, class T>
|
||||
struct pytype_object_manager_traits
|
||||
: pyobject_type<T, pytype> // provides check()
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
|
||||
static inline python::detail::new_reference adopt(PyObject*);
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <PyTypeObject* pytype, class T>
|
||||
inline python::detail::new_reference pytype_object_manager_traits<pytype,T>::adopt(PyObject* x)
|
||||
{
|
||||
return python::detail::new_reference(python::pytype_check(pytype, x));
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
111
include/boost/python/converter/registered.hpp
Normal file
111
include/boost/python/converter/registered.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef REGISTERED_DWA2002710_HPP
|
||||
# define REGISTERED_DWA2002710_HPP
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/registrations.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/is_void.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/type.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// You'll see shared_ptr mentioned in this header because we need to
|
||||
// note which types are shared_ptrs in their registrations, to
|
||||
// implement special shared_ptr handling for rvalue conversions.
|
||||
template <class T> class shared_ptr;
|
||||
|
||||
namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct registered_base
|
||||
{
|
||||
static registration const& converters;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct registered
|
||||
: detail::registered_base<
|
||||
typename add_reference<
|
||||
typename add_cv<T>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|
||||
&& !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
|
||||
// collapses a few more types to the same static instance. MSVC7.1
|
||||
// fails to strip cv-qualification from array types in typeid. For
|
||||
// some reason we can't use this collapse there or array converters
|
||||
// will not be found.
|
||||
template <class T>
|
||||
struct registered<T&>
|
||||
: registered<T> {};
|
||||
# endif
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
inline void
|
||||
register_shared_ptr0(...)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
register_shared_ptr0(shared_ptr<T>*)
|
||||
{
|
||||
registry::lookup_shared_ptr(type_id<shared_ptr<T> >());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
register_shared_ptr1(T const volatile*)
|
||||
{
|
||||
detail::register_shared_ptr0((T*)0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline registration const&
|
||||
registry_lookup2(T&(*)())
|
||||
{
|
||||
detail::register_shared_ptr1((T*)0);
|
||||
return registry::lookup(type_id<T&>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline registration const&
|
||||
registry_lookup1(type<T>)
|
||||
{
|
||||
return registry_lookup2((T(*)())0);
|
||||
}
|
||||
|
||||
inline registration const&
|
||||
registry_lookup1(type<const volatile void>)
|
||||
{
|
||||
detail::register_shared_ptr1((void*)0);
|
||||
return registry::lookup(type_id<void>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
registration const& registered_base<T>::converters = detail::registry_lookup1(type<T>());
|
||||
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTERED_DWA2002710_HPP
|
||||
62
include/boost/python/converter/registered_pointee.hpp
Normal file
62
include/boost/python/converter/registered_pointee.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef REGISTERED_POINTEE_DWA2002710_HPP
|
||||
# define REGISTERED_POINTEE_DWA2002710_HPP
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/pointer_type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct registered_pointee
|
||||
: registered<
|
||||
typename remove_pointer<
|
||||
typename remove_cv<
|
||||
typename remove_reference<T>::type
|
||||
>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
# else
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct registered_pointee_base
|
||||
{
|
||||
static registration const& converters;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct registered_pointee
|
||||
: detail::registered_pointee_base<
|
||||
typename add_reference<
|
||||
typename add_cv<T>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
registration const& registered_pointee_base<T>::converters
|
||||
= registry::lookup(pointer_type_id<T>());
|
||||
}
|
||||
|
||||
# endif
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTERED_POINTEE_DWA2002710_HPP
|
||||
89
include/boost/python/converter/registrations.hpp
Normal file
89
include/boost/python/converter/registrations.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef REGISTRATIONS_DWA2002223_HPP
|
||||
# define REGISTRATIONS_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/converter/convertible_function.hpp>
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct lvalue_from_python_chain
|
||||
{
|
||||
convertible_function convert;
|
||||
lvalue_from_python_chain* next;
|
||||
};
|
||||
|
||||
struct rvalue_from_python_chain
|
||||
{
|
||||
convertible_function convertible;
|
||||
constructor_function construct;
|
||||
rvalue_from_python_chain* next;
|
||||
};
|
||||
|
||||
struct BOOST_PYTHON_DECL registration
|
||||
{
|
||||
public: // member functions
|
||||
explicit registration(type_info target, bool is_shared_ptr = false);
|
||||
|
||||
// Convert the appropriately-typed data to Python
|
||||
PyObject* to_python(void const volatile*) const;
|
||||
|
||||
// Return the class object, or raise an appropriate Python
|
||||
// exception if no class has been registered.
|
||||
PyTypeObject* get_class_object() const;
|
||||
|
||||
public: // data members. So sue me.
|
||||
const python::type_info target_type;
|
||||
|
||||
// The chain of eligible from_python converters when an lvalue is required
|
||||
lvalue_from_python_chain* lvalue_chain;
|
||||
|
||||
// The chain of eligible from_python converters when an rvalue is acceptable
|
||||
rvalue_from_python_chain* rvalue_chain;
|
||||
|
||||
// The class object associated with this type
|
||||
PyTypeObject* m_class_object;
|
||||
|
||||
// The unique to_python converter for the associated C++ type.
|
||||
to_python_function_t m_to_python;
|
||||
|
||||
// True iff this type is a shared_ptr. Needed for special rvalue
|
||||
// from_python handling.
|
||||
const bool is_shared_ptr;
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
private:
|
||||
void operator=(registration); // This is not defined, and just keeps MWCW happy.
|
||||
# endif
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
inline registration::registration(type_info target_type, bool is_shared_ptr)
|
||||
: target_type(target_type)
|
||||
, lvalue_chain(0)
|
||||
, rvalue_chain(0)
|
||||
, m_class_object(0)
|
||||
, m_to_python(0)
|
||||
, is_shared_ptr(is_shared_ptr)
|
||||
{}
|
||||
|
||||
inline bool operator<(registration const& lhs, registration const& rhs)
|
||||
{
|
||||
return lhs.target_type < rhs.target_type;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTRATIONS_DWA2002223_HPP
|
||||
53
include/boost/python/converter/registry.hpp
Normal file
53
include/boost/python/converter/registry.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright David Abrahams 2001.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef REGISTRY_DWA20011127_HPP
|
||||
# define REGISTRY_DWA20011127_HPP
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/converter/convertible_function.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
// This namespace acts as a sort of singleton
|
||||
namespace registry
|
||||
{
|
||||
// Get the registration corresponding to the type, creating it if necessary
|
||||
BOOST_PYTHON_DECL registration const& lookup(type_info);
|
||||
|
||||
// Get the registration corresponding to the type, creating it if
|
||||
// necessary. Use this first when the type is a shared_ptr.
|
||||
BOOST_PYTHON_DECL registration const& lookup_shared_ptr(type_info);
|
||||
|
||||
// Return a pointer to the corresponding registration, if one exists
|
||||
BOOST_PYTHON_DECL registration const* query(type_info);
|
||||
|
||||
BOOST_PYTHON_DECL void insert(to_python_function_t, type_info);
|
||||
|
||||
// Insert an lvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info);
|
||||
|
||||
// Insert an rvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(
|
||||
convertible_function
|
||||
, constructor_function
|
||||
, type_info
|
||||
);
|
||||
|
||||
// Insert an rvalue from_python converter at the tail of the
|
||||
// chain. Used for implicit conversions
|
||||
BOOST_PYTHON_DECL void push_back(
|
||||
convertible_function
|
||||
, constructor_function
|
||||
, type_info
|
||||
);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTRY_DWA20011127_HPP
|
||||
162
include/boost/python/converter/return_from_python.hpp
Executable file
162
include/boost/python/converter/return_from_python.hpp
Executable file
@@ -0,0 +1,162 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef RETURN_FROM_PYTHON_DWA200265_HPP
|
||||
# define RETURN_FROM_PYTHON_DWA200265_HPP
|
||||
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/python/converter/object_manager.hpp>
|
||||
# include <boost/python/detail/void_ptr.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/type_traits/has_trivial_copy.hpp>
|
||||
# include <boost/mpl/and.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T> struct is_object_manager;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct return_pointer_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct return_reference_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct return_rvalue_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
return_rvalue_from_python();
|
||||
result_type operator()(PyObject*);
|
||||
private:
|
||||
rvalue_from_python_data<T> m_data;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct return_object_manager_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
result_type operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_return_from_python
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, obj_mgr = is_object_manager<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr = is_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ref = is_reference<T>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
obj_mgr
|
||||
, return_object_manager_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
ptr
|
||||
, return_pointer_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
ref
|
||||
, return_reference_from_python<T>
|
||||
, return_rvalue_from_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct return_from_python
|
||||
: detail::select_return_from_python<T>::type
|
||||
{
|
||||
};
|
||||
|
||||
// Specialization as a convenience for call and call_method
|
||||
template <>
|
||||
struct return_from_python<void>
|
||||
{
|
||||
typedef python::detail::returnable<void>::type result_type;
|
||||
|
||||
result_type operator()(PyObject* x) const
|
||||
{
|
||||
(void_result_from_python)(x);
|
||||
# ifdef BOOST_NO_VOID_RETURNS
|
||||
return result_type();
|
||||
# endif
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
inline return_rvalue_from_python<T>::return_rvalue_from_python()
|
||||
: m_data(
|
||||
const_cast<registration*>(®istered<T>::converters)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename return_rvalue_from_python<T>::result_type
|
||||
return_rvalue_from_python<T>::operator()(PyObject* obj)
|
||||
{
|
||||
// Take possession of the source object here. If the result is in
|
||||
// fact going to be a copy of an lvalue embedded in the object,
|
||||
// and we take possession inside rvalue_result_from_python, it
|
||||
// will be destroyed too early.
|
||||
handle<> holder(obj);
|
||||
|
||||
return *(T*)
|
||||
(rvalue_result_from_python)(obj, m_data.stage1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T return_reference_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(
|
||||
(reference_result_from_python)(obj, registered<T>::converters)
|
||||
, (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T return_pointer_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return T(
|
||||
(pointer_result_from_python)(obj, registered_pointee<T>::converters)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T return_object_manager_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return T(
|
||||
object_manager_traits<T>::adopt(expect_non_null(obj))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // RETURN_FROM_PYTHON_DWA200265_HPP
|
||||
140
include/boost/python/converter/rvalue_from_python_data.hpp
Normal file
140
include/boost/python/converter/rvalue_from_python_data.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/detail/referent_storage.hpp>
|
||||
# include <boost/python/detail/destroy.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/add_cv.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
// Data management for potential rvalue conversions from Python to C++
|
||||
// types. When a client requests a conversion to T* or T&, we
|
||||
// generally require that an object of type T exists in the source
|
||||
// Python object, and the code here does not apply**. This implements
|
||||
// conversions which may create new temporaries of type T. The classic
|
||||
// example is a conversion which converts a Python tuple to a
|
||||
// std::vector. Since no std::vector lvalue exists in the Python
|
||||
// object -- it must be created "on-the-fly" by the converter, and
|
||||
// which must manage the lifetime of the created object.
|
||||
//
|
||||
// Note that the client is not precluded from using a registered
|
||||
// lvalue conversion to T in this case. In other words, we will
|
||||
// happily accept a Python object which /does/ contain a std::vector
|
||||
// lvalue, provided an appropriate converter is registered. So, while
|
||||
// this is an rvalue conversion from the client's point-of-view, the
|
||||
// converter registry may serve up lvalue or rvalue conversions for
|
||||
// the target type.
|
||||
//
|
||||
// ** C++ argument from_python conversions to T const& are an
|
||||
// exception to the rule for references: since in C++, const
|
||||
// references can bind to temporary rvalues, we allow rvalue
|
||||
// converters to be chosen when the target type is T const& for some
|
||||
// T.
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Conversions begin by filling in and returning a copy of this
|
||||
// structure. The process looks up a converter in the rvalue converter
|
||||
// registry for the target type. It calls the convertible() function
|
||||
// of each registered converter, passing the source PyObject* as an
|
||||
// argument, until a non-null result is returned. This result goes in
|
||||
// the convertible field, and the converter's construct() function is
|
||||
// stored in the construct field.
|
||||
//
|
||||
// If no appropriate converter is found, conversion fails and the
|
||||
// convertible field is null. When used in argument conversion for
|
||||
// wrapped C++ functions, it causes overload resolution to reject the
|
||||
// current function but not to fail completely. If an exception is
|
||||
// thrown, overload resolution stops and the exception propagates back
|
||||
// through the caller.
|
||||
//
|
||||
// If an lvalue converter is matched, its convertible() function is
|
||||
// expected to return a pointer to the stored T object; its
|
||||
// construct() function will be NULL. The convertible() function of
|
||||
// rvalue converters may return any non-singular pointer; the actual
|
||||
// target object will only be available once the converter's
|
||||
// construct() function is called.
|
||||
struct rvalue_from_python_stage1_data
|
||||
{
|
||||
void* convertible;
|
||||
constructor_function construct;
|
||||
};
|
||||
|
||||
// Augments rvalue_from_python_stage1_data by adding storage for
|
||||
// constructing an object of remove_reference<T>::type. The
|
||||
// construct() function of rvalue converters (stored in m_construct
|
||||
// above) will cast the rvalue_from_python_stage1_data to an
|
||||
// appropriate instantiation of this template in order to access that
|
||||
// storage.
|
||||
template <class T>
|
||||
struct rvalue_from_python_storage
|
||||
{
|
||||
rvalue_from_python_stage1_data stage1;
|
||||
|
||||
// Storage for the result, in case an rvalue must be constructed
|
||||
typename python::detail::referent_storage<
|
||||
typename add_reference<T>::type
|
||||
>::type storage;
|
||||
};
|
||||
|
||||
// Augments rvalue_from_python_storage<T> with a destructor. If
|
||||
// stage1.convertible == storage.bytes, it indicates that an object of
|
||||
// remove_reference<T>::type has been constructed in storage and
|
||||
// should will be destroyed in ~rvalue_from_python_data(). It is
|
||||
// crucial that successful rvalue conversions establish this equality
|
||||
// and that unsuccessful ones do not.
|
||||
template <class T>
|
||||
struct rvalue_from_python_data : rvalue_from_python_storage<T>
|
||||
{
|
||||
# if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \
|
||||
&& (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \
|
||||
&& (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) \
|
||||
&& !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing this */
|
||||
// This must always be a POD struct with m_data its first member.
|
||||
BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage<T>,stage1) == 0);
|
||||
# endif
|
||||
|
||||
// The usual constructor
|
||||
rvalue_from_python_data(rvalue_from_python_stage1_data const&);
|
||||
|
||||
// This constructor just sets m_convertible -- used by
|
||||
// implicitly_convertible<> to perform the final step of the
|
||||
// conversion, where the construct() function is already known.
|
||||
rvalue_from_python_data(void* convertible);
|
||||
|
||||
// Destroys any object constructed in the storage.
|
||||
~rvalue_from_python_data();
|
||||
private:
|
||||
typedef typename add_reference<typename add_cv<T>::type>::type ref_type;
|
||||
};
|
||||
|
||||
//
|
||||
// Implementataions
|
||||
//
|
||||
template <class T>
|
||||
inline rvalue_from_python_data<T>::rvalue_from_python_data(rvalue_from_python_stage1_data const& stage1)
|
||||
{
|
||||
this->stage1 = stage1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline rvalue_from_python_data<T>::rvalue_from_python_data(void* convertible)
|
||||
{
|
||||
this->stage1.convertible = convertible;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline rvalue_from_python_data<T>::~rvalue_from_python_data()
|
||||
{
|
||||
if (this->stage1.convertible == this->storage.bytes)
|
||||
python::detail::destroy_referent<ref_type>(this->storage.bytes);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
22
include/boost/python/converter/shared_ptr_deleter.hpp
Normal file
22
include/boost/python/converter/shared_ptr_deleter.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef SHARED_PTR_DELETER_DWA2002121_HPP
|
||||
# define SHARED_PTR_DELETER_DWA2002121_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct BOOST_PYTHON_DECL shared_ptr_deleter
|
||||
{
|
||||
shared_ptr_deleter(handle<> owner);
|
||||
~shared_ptr_deleter();
|
||||
|
||||
void operator()(void const*);
|
||||
|
||||
handle<> owner;
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // SHARED_PTR_DELETER_DWA2002121_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user