2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
nobody
7fb1d0e8e5 This commit was manufactured by cvs2svn to create tag
'Version_1_34_1_RC3'.

[SVN r38225]
2007-07-16 13:13:26 +00:00
Thomas Witt
2851325748 Doc and build fixes by Dave Abrahams.
[SVN r38154]
2007-07-06 19:47:17 +00:00
Thomas Witt
bd606e5017 Fix #583.
[SVN r37947]
2007-06-08 18:30:46 +00:00
Thomas Witt
a5706ec3b0 Fixes for #583.
[SVN r37929]
2007-06-07 18:08:54 +00:00
Rene Rivera
a346c577cf Fix the abolute reference to the Boost sources inserted by Dave.
[SVN r37837]
2007-05-31 22:03:06 +00:00
Dave Abrahams
217e4ca8f8 Repair auto-configuration and allow this project to work with --build-dir
[SVN r37829]
2007-05-31 13:49:45 +00:00
Stefan Seefeld
f2f47f85c0 Enhance embedding python docs.
[SVN r37710]
2007-05-18 15:54:25 +00:00
Stefan Seefeld
b130c93af6 Backport new eval() function from HEAD.
[SVN r37693]
2007-05-15 13:43:52 +00:00
Dave Abrahams
13432b504f Jamfile had extra bogus tst executable target
Build/test instructions were outdated somehow; a checkin must've failed.


[SVN r37620]
2007-05-07 19:00:01 +00:00
Dave Abrahams
0739bb7df8 Added reference to Py++
[SVN r37586]
2007-05-04 01:08:54 +00:00
Dave Abrahams
c253c5cc9c Updated build-and-test howto
[SVN r37585]
2007-05-04 00:56:22 +00:00
Dave Abrahams
8f263e1fdb Progress on the build docs
[SVN r37551]
2007-05-01 16:14:39 +00:00
Ralf W. Grosse-Kunstleve
a6125a3632 merged from trunk
[SVN r37520]
2007-04-27 22:16:47 +00:00
35 changed files with 1805 additions and 1526 deletions

View File

@@ -38,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

View File

@@ -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

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
|(logo)|__ Boost.Python Build and Test HOWTO
==============================================
.. |(logo)| image:: ../boost.png
.. |(logo)| image:: ../../../boost.png
:alt: Boost C++ Libraries:
:class: boost-logo
@@ -31,36 +31,6 @@ Boost.Python requires `Python 2.2`_ [#2.2]_ *or* |newer|__.
.. _Python 2.2: http://www.python.org/2.2
__ http://www.python.org
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.
.. 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**.
If you want to use another system anyway, we suggest that you
follow these instructions, and then invoke ``bjam`` with the
``-a -o``\ *filename* option to dump the build commands it executes
to a file, so you can see what your build system needs to do.
1. Get Boost; see sections 1 and 2 of the Boost `Getting Started Guide`_.
2. Get the ``bjam`` build driver. See sections 5.2.1-5.2.3 of the
Boost `Getting Started Guide`_.
3. cd into the ``libs/python/test/example`` directory.
.. _Getting Started Guide: ../../../more/getting_started/index.html
Background
==========
@@ -81,7 +51,7 @@ There are two basic models for combining C++ and Python:
.. _embedding: http://www.python.org/doc/current/ext/embedding.html
The key distinction between extending and embedding is the location
of C++' ``main()`` function: in the Python interpreter executable,
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
@@ -95,8 +65,254 @@ 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()``.
Getting Boost.Python Binaries
=============================
.. _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
@@ -104,25 +320,24 @@ Boost.Python library binary.
.. _header-only: ../../../more/getting_started/windows.html#header-only-libraries
Installing Boost.Python on your System
--------------------------------------
If you need a regular, installation of the Boost.Python library
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 installing one. If building binaries
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
describe the build resources available to the build system. You'll
need to tell it about your Python installation.
``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
@@ -135,66 +350,58 @@ __ http://www.boost.orgdoc/html/bbv2/advanced.html#bbv2.advanced.configuration
were built, your ``user-config.jam`` file is probably already
correct.
If you have a fairly “standard” python installation for your
platform, there's very little you need to do to describe it.
Simply having ::
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 ;
in a ``user-config.jam`` file in your home directory [#home-dir]_
should be enough. [#user-config.jam]_ For more complicated setups,
see `Advanced Configuration`_.
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.
.. Note:: 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 passing some of
the optional `Python configuration parameters`_ detailed below.
Building an Extension Module
============================
Testing
=======
Advanced Configuration
======================
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``.
Python Configuration Parameters
-------------------------------
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
additional argument required.
configuration argument required.
cmd-or-prefix
preferably, a command that invokes a Python
interpreter. Alternatively, the installation prefix for Python
libraries and header files. Use the alternative formulation if
there is no appropriate Python executable available.
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`` path for Python headers.
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.
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.
Boost.Build selects a Python configuration to use. See examples
below for details.
extension-suffix
A string to append to the name of extension
@@ -202,10 +409,12 @@ extension-suffix
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
|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
@@ -247,6 +456,17 @@ significant.
: <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
@@ -290,7 +510,7 @@ __ http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection
Choosing a Boost.Python Library Binary
======================================
If—instead of letting Boost.Build construct and link withthe right
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
@@ -332,6 +552,64 @@ any of the following cases:
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
=======================================================
@@ -365,13 +643,9 @@ __ http://www.python.org/doc/current/inst/index.html
__ ../../../more/getting_started/windows.html#library-naming
__ ../../../more/getting_started/unix-variants.html#library-naming
Be sure to read this section even if your compiler supports
auto-linking, as Boost.Python does not yet take advantage of
that feature.
.. [#toolset-specific] Because of the way most \*nix platforms
share symbols among dynamically-loaded objects, I'm not
certainextension modules built with different compiler toolsets
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
@@ -391,14 +665,17 @@ __ http://www.python.org/doc/current/inst/index.html
toolset, and you might need handle both explicitly if you also
have a MinGW GCC installed.
.. [#user-config.jam] Create the ``user-config.jam`` file if you don't
already have one.
.. [#home-dir] Windows users, your home directory can be
found by typing::
ECHO %HOMEDRIVE%%HOMEPATH%
into a `Windows command prompt`__
into a `command prompt`_ window.
__ ../../../more/getting_started/windows.html#or-build-from-the-command-prompt
.. [#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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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
&lt;library-path&gt;$(PYTHON_LIB_PATH)
&lt;find-library&gt;$(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">&lt;boost/python.hpp&gt;</tt><br><br>
#include
 <code class="literal">&lt;boost/python.hpp&gt;</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">&lt;&gt;(</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&lt;&gt;</tt>
instead of the longer, but equivalent, <tt class="literal">handle&lt;PyObject&gt;</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">&lt;&gt;(</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">&lt;&gt;</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">&lt;&gt;(</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">&lt;&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
</pre>
<p>
Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
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">&lt;&gt;(</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">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</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">&lt;&gt;(</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">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&amp;)</span>
<span class="special">{</span>
<span class="comment">// handle the exception in some way
</span><span class="special">}</span>
</pre>
<p>
The <tt class="literal">error_already_set</tt> exception class doesn't carry any
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">&amp;)</span>
<span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">PyErr_ExceptionMatches</span><span class="special">(</span><span class="identifier">PyExc_ZeroDivisionError</span><span class="special">))</span>
<span class="special">{</span>
@@ -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">&lt;&gt;</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>

View File

@@ -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%">

View File

@@ -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_&lt;World&gt;</tt> about the constructor
We have to tell <code class="literal">class_&lt;World&gt;</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&lt;std::string&gt;()</tt> exposes the constructor taking
in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").
<code class="literal">init&lt;std::string&gt;()</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&lt;...&gt;</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&lt;...&gt;</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">&lt;</span><span class="identifier">Abstract</span><span class="special">&gt;(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
</pre>
<p>
This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
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">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">'e'</span> <span class="comment"># can't change name
@@ -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">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!
</span></pre>
<p>
Take note that the class property <tt class="literal">rovalue</tt> is exposed as
<span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
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">&lt;</span><span class="identifier">Base</span><span class="special">&gt;(</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">&lt;</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"Derived"</span><span class="special">)</span>
@@ -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&lt;manage_new_object&gt;</tt> to instruct
Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
in a new Python <tt class="literal">Base</tt> object until the the Python object
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&lt;manage_new_object&gt;</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">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
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">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
<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">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></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">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
@@ -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">&lt;</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*&gt;(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
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">&lt;</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*&gt;(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></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">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
to its default implementation <tt class="literal">default_f</tt>. There's a special
<tt class="literal">def</tt> function for this purpose.
Take note that we expose both <code class="computeroutput"><span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></code> and <code class="computeroutput"><span class="special">&amp;</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">&gt;&gt;&gt;</span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
</pre>
<p>
Calling <tt class="literal">base.f()</tt>:
Calling <code class="literal">base.f()</code>:
</p>
<pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
<span class="number">0</span>
</pre>
<p>
Calling <tt class="literal">derived.f()</tt>:
Calling <code class="literal">derived.f()</code>:
</p>
<pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
@@ -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&lt;T&gt;()</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&lt;T&gt;()</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">&lt;&lt;</span></tt>? Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt>
requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt>
to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt> is used by the method defined by
<tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.
</p>
<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">&lt;&lt;</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">&lt;&lt;</span></code> to do its work (i.e. <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</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>

View File

@@ -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">&gt;&gt;&gt; import this</tt>.
<code class="literal">&gt;&gt;&gt; import this</code>.
</p>
<pre class="programlisting">&gt;&gt;&gt; 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">&gt;&gt;&gt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> # <span class="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">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
@@ -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-&gt;value()</tt> is called
<code class="literal">z-&gt;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">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="special">&gt;());</span>
</pre>
<p>
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
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">&lt;</span><span class="number">1</span>
</pre>
<p>
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&amp;
y</tt>, is the owner of the returned reference: <tt class="literal">X&amp;</tt>.
The "<tt class="literal">1</tt>" simply specifies the first argument.
In short: "return an internal reference <tt class="literal">X&amp;</tt> owned
by the 1st argument <tt class="literal">Y&amp; y</tt>".
Informs Boost.Python that the first argument, in our case <code class="literal">Y&amp;
y</code>, is the owner of the returned reference: <code class="literal">X&amp;</code>.
The "<code class="literal">1</code>" simply specifies the first argument.
In short: "return an internal reference <code class="literal">X&amp;</code> owned
by the 1st argument <code class="literal">Y&amp; y</code>".
</p>
<pre class="programlisting">
<span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span>
</pre>
<p>
Informs Boost.Python that the lifetime of the argument indicated by ward
(i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&amp;
y</tt>).
(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&amp;
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&lt;T&gt; with T one of:</b></span><br>
<span class="bold"><strong>return_value_policy&lt;T&gt; 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">&amp;</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span>
@@ -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&lt;...&gt;</tt>?
arguments or a sequence of overloads. Remember <code class="literal">init&lt;...&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
</pre>
<p>
Notice the use of <tt class="literal">init&lt;...&gt;</tt> and <tt class="literal">optional&lt;...&gt;</tt>
Notice the use of <code class="literal">init&lt;...&gt;</code> and <code class="literal">optional&lt;...&gt;</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">

View File

@@ -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>

View File

@@ -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">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
</pre>
<p>
<span class="bold"><b>range</b></span>
<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&lt;T, Policies&gt;()
</li></ul></div>
<p>
Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
calls <tt class="literal">range</tt> with &amp;T::begin, &amp;T::end.
Given a container <code class="literal">T</code>, iterator is a shortcut that simply
calls <code class="literal">range</code> with &amp;T::begin, &amp;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">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
</pre>
<p>
<span class="bold"><b>stl_input_iterator</b></span>
<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">&lt;&gt;</span></tt>.
Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
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">&lt;&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</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>

View File

@@ -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">==&gt;</span> <span class="string">"1"</span>
</pre>
<p>
Wherever appropriate, a particular derived <tt class="literal">object</tt> has
corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
has a <tt class="literal">keys()</tt> method:
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_&lt;T&gt; as objects
</h2>
</h3>
<p>
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_&lt;T&gt;</tt>
Due to the dynamic nature of Boost.Python objects, any <code class="literal">class_&lt;T&gt;</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&lt;T&gt;</tt> function. Consider
can be achieved with the <code class="literal">extract&lt;T&gt;</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">&amp;</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
</pre>
<p>
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <tt class="literal">extract&lt;T&gt;</tt>
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <code class="literal">extract&lt;T&gt;</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>

View File

@@ -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">&gt;&gt;&gt;</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(...)</span>
</pre>
<p>
which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
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">&gt;&gt;&gt;</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>

View File

@@ -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]

View File

@@ -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,

View File

@@ -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>

Binary file not shown.

View File

@@ -1,36 +0,0 @@
# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
project : requirements <library>/boost/python//boost_python ;
python-extension getting_started1 : getting_started1.cpp ;
bpl-test test1
: # Python test driver
test_getting_started1.py
# extension modules to use
getting_started1 ;
python-extension getting_started2 : getting_started2.cpp ;
bpl-test test2
: # Python test driver
test_getting_started2.py
# extension modules to use
getting_started2 ;
python-extension std_pair : std_pair.cpp ;
bpl-test test3
: # Python test driver
test_std_pair.py
# extension modules to use
std_pair_ext ;
# Don't run tests by default
explicit test1 test2 test3 ;
alias test : test1 test2 test3 ;
explicit test ;

View File

@@ -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>

Binary file not shown.

43
example/quickstart/Jamroot Executable file
View 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 ;

View 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 ;

View 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();
}

View 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);
}

View 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

View 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])

View File

@@ -51,6 +51,7 @@
# if defined(_SGI_COMPILER_VERSION) && _SGI_COMPILER_VERSION >= 740
# undef _POSIX_C_SOURCE
# undef _XOPEN_SOURCE
# undef HAVE_STDINT_H // undo Python 2.5.1 define
# endif
//

View File

@@ -13,18 +13,25 @@ namespace boost
namespace python
{
// Evaluate python expression from str.
// global and local are the global and local scopes respectively,
// used during evaluation.
object
BOOST_PYTHON_DECL
eval(str string, object global = object(), object local = object());
// Execute python source code from str.
// global and local are the global and local scopes respectively,
// used during execution.
object
BOOST_PYTHON_DECL
BOOST_PYTHON_DECL
exec(str string, object global = object(), object local = object());
// Execute python source code from file filename.
// global and local are the global and local scopes respectively,
// used during execution.
object
BOOST_PYTHON_DECL
BOOST_PYTHON_DECL
exec_file(str filename, object global = object(), object local = object());
}

View File

@@ -26,23 +26,7 @@ extern "C" __declspec(dllexport) void init##name() \
} \
void init_module_##name()
# elif defined(_AIX) && !defined(BOOST_PYTHON_STATIC_MODULE)
# include <boost/python/detail/aix_init_module.hpp>
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
extern "C" \
{ \
extern PyObject* _PyImport_LoadDynamicModule(char*, char*, FILE *); \
void init##name() \
{ \
boost::python::detail::aix_init_module( \
_PyImport_LoadDynamicModule, #name, &init_module_##name); \
} \
} \
void init_module_##name()
# elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
# elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
@@ -52,7 +36,7 @@ extern "C" __attribute__ ((visibility("default"))) void init##name() \
} \
void init_module_##name()
# else
# else
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \

View File

@@ -1,141 +0,0 @@
// 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)
#ifdef _AIX
#include <cstdio>
#include <cstdlib>
extern "C"
{
#include <sys/stat.h>
#include <unistd.h>
}
# include <string>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/detail/aix_init_module.hpp>
# include <boost/python/module.hpp>
namespace boost { namespace python { namespace detail {
namespace
{
static PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } };
extern "C" void initlibboost_python()
{
Py_InitModule("libboost_python", initial_methods);
}
struct find_and_open_file
{
FILE* fp;
std::string libpath; // -- search path
std::string filename; // -- filename to look for
std::string fullpath; // -- full path to file
find_and_open_file(
const std::string& libpath_env
, const std::string& file);
};
find_and_open_file::find_and_open_file(
const std::string& libpath_env
, const std::string& file)
: fp(0)
{
char* value = std::getenv(libpath_env.c_str());
if(value == 0)
return;
libpath = value;
if (libpath == "")
return;
std::string::size_type pos = 0, prev_pos = 0;
// -- loop through all search paths looking for file
while((pos = libpath.find_first_of(":",pos)) != std::string::npos)
{
fullpath = libpath.substr(prev_pos,pos - prev_pos) + "/" + file;
if (::access(fullpath.c_str(), R_OK) == 0)
{
struct stat filestat;
::stat(fullpath.c_str(), &filestat);
if (!S_ISDIR(filestat.st_mode))
{
fp = std::fopen(fullpath.c_str(), "r");
if (fp)
{
filename = file;
}
return;
}
}
prev_pos = ++pos;
}
// -- mop up odd path
if (libpath.find_first_of(":", prev_pos) == std::string::npos)
{
fullpath = libpath.substr(prev_pos, libpath.size() - prev_pos) + "/" + file;
if (::access(fullpath.c_str(), R_OK) == 0)
{
struct stat filestat;
::stat(fullpath.c_str(),&filestat);
if (!S_ISDIR(filestat.st_mode))
{
fp = std::fopen(fullpath.c_str(), "r");
filename = file;
}
}
}
}
}
void aix_init_module(
so_load_function load_dynamic_module
, char const* module_name
, void (*init_module)())
{
static bool initialized;
if (!initialized)
{
char const* const name = "libboost_python.so";
find_and_open_file dynlib("LIBPATH", name);
if (dynlib.fp == 0)
{
fprintf(stderr, " Error: could not find %s\n", name);
return;
}
std::string::size_type pos = pos = dynlib.filename.rfind(".so");
if (pos != dynlib.filename.size() - 3)
{
fprintf(stderr, "dynamic library %s must end with .so\n", dynlib.filename.c_str());
return;
}
PyObject* m =
load_dynamic_module(
const_cast<char*>(dynlib.filename.substr(0,pos).c_str()),
const_cast<char*>(dynlib.fullpath.c_str()),
dynlib.fp);
if (m == 0)
{
fprintf(stderr, "failed to load library %s\n", name);
return;
}
Py_DECREF(m);
initialized = true;
}
python::detail::init_module(module_name, init_module);
}
}}} // namespace boost::python
#endif

View File

@@ -13,6 +13,15 @@ namespace boost
namespace python
{
object BOOST_PYTHON_DECL eval(str string, object global, object local)
{
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = python::extract<char *>(string);
PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
object BOOST_PYTHON_DECL exec(str string, object global, object local)
{
// should be 'char const *' but older python versions don't use 'const' yet.

View File

@@ -49,6 +49,13 @@ BOOST_PYTHON_MODULE(embedded_hello)
}
void eval_test()
{
python::object result = python::eval("'abcdefg'.upper()");
std::string value = python::extract<std::string>(result) BOOST_EXTRACT_WORKAROUND;
BOOST_TEST(value == "ABCDEFG");
}
void exec_test()
{
// Register the module with the interpreter
@@ -108,7 +115,8 @@ int main(int argc, char **argv)
// Initialize the interpreter
Py_Initialize();
if (python::handle_exception(exec_test) ||
if (python::handle_exception(eval_test) ||
python::handle_exception(exec_test) ||
python::handle_exception(boost::bind(exec_file_test, script)))
{
if (PyErr_Occurred())

View File

@@ -5,9 +5,10 @@
#include <boost/python/type_id.hpp>
#include <iostream>
// gcc 2.95.x and MIPSpro 7.3.1.3 linker seem to demand this definition
#if ((defined(__GNUC__) && __GNUC__ < 3)) \
|| (defined(__sgi) && defined(__EDG_VERSION__) && (__EDG_VERSION__ == 238))
// gcc 2.95.x, MIPSpro 7.3.1.3 and IBM XL for Linux linker seem to demand this definition
#if (defined(__GNUC__) && (__GNUC__ < 3)) \
|| (defined(__sgi) && defined(__EDG_VERSION__) && (__EDG_VERSION__ == 238)) \
|| (defined(__IBMCPP__) && defined(__linux__))
namespace boost { namespace python {
BOOST_PYTHON_DECL bool handle_exception_impl(function0<void>)
{