mirror of
https://github.com/boostorg/python.git
synced 2026-01-27 07:02:15 +00:00
Added a FAQ
[SVN r17010]
This commit is contained in:
247
doc/v2/faq.html
247
doc/v2/faq.html
@@ -29,10 +29,10 @@
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#question1">Is return_internal reference
|
||||
<dt><a href="#question1">Is return_internal_reference
|
||||
efficient?</a></dt>
|
||||
|
||||
<dt><a href="#question2">How can I wrap containers which take C++
|
||||
<dt><a href="#question2">How can I wrap functions which take C++
|
||||
containers as arguments?</a></dt>
|
||||
|
||||
<dt><a href="#c1204">fatal error C1204:Compiler limit:internal
|
||||
@@ -40,13 +40,18 @@
|
||||
|
||||
<dt><a href="#debugging">How do I debug my Python extensions?</a></dt>
|
||||
|
||||
<dt><a href="#imul">Why doesn't my <code>*=</code> operator work?</a></dt>
|
||||
<dt><a href="#imul">Why doesn't my <code>*=</code> operator
|
||||
work?</a></dt>
|
||||
|
||||
<dt><a href="#macosx">Does Boost.Python work with Mac OS X?</a></dt>
|
||||
|
||||
<dt><a href="#xref">How can I find the existing PyObject that holds a
|
||||
C++ object?</a></dt>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="question1"></a>Is return_internal reference efficient?</h2>
|
||||
<h2><a name="question1"></a>Is return_internal_reference efficient?</h2>
|
||||
|
||||
<blockquote>
|
||||
<b>Q:</b> <i>I have an object composed of 12 doubles. A const& to
|
||||
@@ -70,6 +75,7 @@
|
||||
cycles.</p>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
<h2><a name="question2"></a>How can I wrap functions which take C++
|
||||
containers as arguments?</h2>
|
||||
|
||||
@@ -161,7 +167,7 @@ cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx login
|
||||
cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
|
||||
</pre>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="c1204"></a>fatal error C1204:Compiler limit:internal
|
||||
structure overflow</h2>
|
||||
|
||||
@@ -203,9 +209,9 @@ void more_of_my_module()
|
||||
can always pass a reference to the <code>class_</code> object to a
|
||||
function in another source file, and call some of its member
|
||||
functions (e.g. <code>.def(...)</code>) in the auxilliary source
|
||||
file: <code>
|
||||
file:
|
||||
|
||||
<p><b>more_of_my_class.cpp</b></code>:
|
||||
<p><code><b>more_of_my_class.cpp</b></code>:</p>
|
||||
<pre>
|
||||
void more_of_my_class(class<my_class>& x)
|
||||
{
|
||||
@@ -221,28 +227,25 @@ void more_of_my_class(class<my_class>& x)
|
||||
</ol>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
<h2><a name="debugging"></a>How do I debug my Python extensions?</h2>
|
||||
|
||||
<p>Greg Burley gives the following answer for Unix GCC users:
|
||||
<p>Greg Burley gives the following answer for Unix GCC users:</p>
|
||||
|
||||
<blockquote>
|
||||
Once you have created a boost python extension for your c++ library or
|
||||
class, you may need to debug the code. Afterall this is one of the
|
||||
reasons for wrapping the library in python. An expected side-effect or
|
||||
benefit of using BPL is that debugging should be isolated to the c++
|
||||
library that is under test, given that python code is minimal and
|
||||
boost::python either works or it doesn't. (ie. While errors can occur
|
||||
when the wrapping method is invalid, most errors are caught by the
|
||||
compiler ;-).
|
||||
|
||||
<p>
|
||||
|
||||
The basic steps required to initiate a gdb session to debug a c++
|
||||
library via python are shown here. Note, however that you should start
|
||||
the gdb session in the directory that contains your BPL my_ext.so
|
||||
module.
|
||||
|
||||
Once you have created a boost python extension for your c++ library or
|
||||
class, you may need to debug the code. Afterall this is one of the
|
||||
reasons for wrapping the library in python. An expected side-effect or
|
||||
benefit of using BPL is that debugging should be isolated to the c++
|
||||
library that is under test, given that python code is minimal and
|
||||
boost::python either works or it doesn't. (ie. While errors can occur
|
||||
when the wrapping method is invalid, most errors are caught by the
|
||||
compiler ;-).
|
||||
|
||||
<p>The basic steps required to initiate a gdb session to debug a c++
|
||||
library via python are shown here. Note, however that you should start
|
||||
the gdb session in the directory that contains your BPL my_ext.so
|
||||
module.</p>
|
||||
<pre>
|
||||
(gdb) target exec python
|
||||
(gdb) run
|
||||
@@ -258,63 +261,54 @@ Current language: auto; currently c++
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
<p>Greg's approach works even better using Emacs' "<code>gdb</code>"
|
||||
command, since it will show you each line of source as you step through
|
||||
it.</p>
|
||||
|
||||
Greg's approach works even better using Emacs'
|
||||
"<code>gdb</code>" command, since it will show you each line
|
||||
of source as you step through it.
|
||||
<p>On <b>Windows</b>, my favorite debugging solution is the debugger that
|
||||
comes with Microsoft Visual C++ 7. This debugger seems to work with code
|
||||
generated by all versions of Microsoft and Metrowerks toolsets; it's rock
|
||||
solid and "just works" without requiring any special tricks from the
|
||||
user.</p>
|
||||
|
||||
<p>
|
||||
|
||||
On Windows, my favorite debugging solution is the debugger that comes
|
||||
with Microsoft Visual C++ 7. This debugger seems to work with code
|
||||
generated by all versions of Microsoft and Metrowerks toolsets; it's
|
||||
rock solid and "just works" without requiring any special
|
||||
tricks from the user.
|
||||
|
||||
<p>
|
||||
|
||||
Unfortunately for Cygwin and MinGW users, as of this writing gdb on
|
||||
Windows has a very hard time dealing with shared libraries, which
|
||||
could make Greg's approach next to useless for you. My best advice for
|
||||
you is to use Metrowerks C++ for compiler conformance and Microsoft
|
||||
Visual Studio as a debugger when you need one.
|
||||
|
||||
<h3>Debugging extensions through Boost.Build</h3>
|
||||
|
||||
If you are launching your extension module tests with <a
|
||||
href="../../../tools/build">Boost.Build</a> using the
|
||||
<code>boost-python-runtest</code> rule, you can ask it to launch your
|
||||
debugger for you by adding "-sPYTHON_LAUNCH=<i>debugger</i>"
|
||||
to your bjam command-line:
|
||||
<p>Unfortunately for Cygwin and MinGW users, as of this writing gdb on
|
||||
Windows has a very hard time dealing with shared libraries, which could
|
||||
make Greg's approach next to useless for you. My best advice for you is
|
||||
to use Metrowerks C++ for compiler conformance and Microsoft Visual
|
||||
Studio as a debugger when you need one.</p>
|
||||
|
||||
<h3>Debugging extensions through Boost.Build</h3>
|
||||
If you are launching your extension module tests with <a href=
|
||||
"../../../tools/build">Boost.Build</a> using the
|
||||
<code>boost-python-runtest</code> rule, you can ask it to launch your
|
||||
debugger for you by adding "-sPYTHON_LAUNCH=<i>debugger</i>" to your bjam
|
||||
command-line:
|
||||
<pre>
|
||||
bjam -sTOOLS=metrowerks "-sPYTHON_LAUNCH=devenv /debugexe" test
|
||||
bjam -sTOOLS=metrowerks "-sPYTHON_LAUNCH=devenv /debugexe" test
|
||||
bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
|
||||
</pre>
|
||||
It can also be extremely useful to add the <code>-d+2</code> option when
|
||||
you run your test, because Boost.Build will then show you the exact
|
||||
commands it uses to invoke it. This will invariably involve setting up
|
||||
PYTHONPATH and other important environment variables such as
|
||||
LD_LIBRARY_PATH which may be needed by your debugger in order to get
|
||||
things to work right.
|
||||
|
||||
It can also be extremely useful to add the <code>-d+2</code> option
|
||||
when you run your test, because Boost.Build will then show you the
|
||||
exact commands it uses to invoke it. This will invariably involve
|
||||
setting up PYTHONPATH and other important environment variables such
|
||||
as LD_LIBRARY_PATH which may be needed by your debugger in order to
|
||||
get things to work right.
|
||||
|
||||
<hr>
|
||||
<h2><a name="imul"></a>Why doesn't my <code>*=</code> operator work?</h2>
|
||||
|
||||
<blockquote>
|
||||
<b>Q:</b> <i>I have exported my class to python, with many overloaded operators. it
|
||||
works fine for me except the </i><code>*=</code><i> operator. It always tells
|
||||
me "can't multiply sequence with non int type". If I use
|
||||
</i><code>p1.__imul__(p2)</code><i> instead of </i><code>p1 *=
|
||||
p2</code><i>, it successfully executes my code. What's wrong with
|
||||
me?</i>
|
||||
|
||||
<p><b>A:</b> There's nothing wrong with you. This is a bug in Python
|
||||
2.2. You can see the same effect in Pure Python (you can learn a lot
|
||||
about what's happening in Boost.Python by playing with new-style
|
||||
classes in Pure Python).
|
||||
<blockquote>
|
||||
<b>Q:</b> <i>I have exported my class to python, with many overloaded
|
||||
operators. it works fine for me except the</i> <code>*=</code>
|
||||
<i>operator. It always tells me "can't multiply sequence with non int
|
||||
type". If I use</i> <code>p1.__imul__(p2)</code> <i>instead of</i>
|
||||
<code>p1 *= p2</code><i>, it successfully executes my code. What's
|
||||
wrong with me?</i>
|
||||
|
||||
<p><b>A:</b> There's nothing wrong with you. This is a bug in Python
|
||||
2.2. You can see the same effect in Pure Python (you can learn a lot
|
||||
about what's happening in Boost.Python by playing with new-style
|
||||
classes in Pure Python).</p>
|
||||
<pre>
|
||||
>>> class X(object):
|
||||
... def __imul__(self, x):
|
||||
@@ -323,44 +317,103 @@ classes in Pure Python).
|
||||
>>> x = X()
|
||||
>>> x *= 1
|
||||
</pre>
|
||||
To cure this problem, all you need to do is upgrade your Python to
|
||||
version 2.2.1 or later.
|
||||
</blockquote>
|
||||
|
||||
To cure this problem, all you need to do is upgrade your Python to
|
||||
version 2.2.1 or later.
|
||||
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
<h2><a name="macosx"></a>Does Boost.Python work with Mac OS X?</h2>
|
||||
|
||||
<blockquote>
|
||||
<p>The short answer: as of January 2003, unfortunately not.
|
||||
<p>
|
||||
The longer answer: using Mac OS 10.2.3 with the December Developer's Kit,
|
||||
Python 2.3a1, and bjam's darwin-tools.jam, Boost.Python compiles fine,
|
||||
including the examples. However, there are problems at runtime
|
||||
(see <a
|
||||
href="http://mail.python.org/pipermail/c++-sig/2003-January/003267.html"
|
||||
>http://mail.python.org/pipermail/c++-sig/2003-January/003267.html</a>).
|
||||
Solutions are currently unknown.
|
||||
<p>
|
||||
It is known that under certain circumstances objects are double-destructed.
|
||||
See <a
|
||||
href="http://mail.python.org/pipermail/c++-sig/2003-January/003278.html"
|
||||
>http://mail.python.org/pipermail/c++-sig/2003-January/003278.html"</a>
|
||||
for details. It is not clear however if this problem is related to
|
||||
the Boost.Python runtime issues.
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>The short answer: as of January 2003, unfortunately not.</p>
|
||||
|
||||
<p>The longer answer: using Mac OS 10.2.3 with the December Developer's
|
||||
Kit, Python 2.3a1, and bjam's darwin-tools.jam, Boost.Python compiles
|
||||
fine, including the examples. However, there are problems at runtime
|
||||
(see <a href=
|
||||
"http://mail.python.org/pipermail/c++-sig/2003-January/003267.html">http://mail.python.org/pipermail/c++-sig/2003-January/003267.html</a>).
|
||||
Solutions are currently unknown.</p>
|
||||
|
||||
<p>It is known that under certain circumstances objects are
|
||||
double-destructed. See <a href=
|
||||
"http://mail.python.org/pipermail/c++-sig/2003-January/003278.html">http://mail.python.org/pipermail/c++-sig/2003-January/003278.html"</a>
|
||||
for details. It is not clear however if this problem is related to the
|
||||
Boost.Python runtime issues.</p>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
<h2><a name="xref">How can I find the existing PyObject that holds a C++
|
||||
object?</a></h2>
|
||||
|
||||
<blockquote>
|
||||
"I am wrapping a function that always returns a pointer to an
|
||||
already-held C++ object."
|
||||
</blockquote>
|
||||
One way to do that is to hijack the mechanisms used for wrapping a class
|
||||
with virtual functions. If you make a wrapper class with an initial
|
||||
PyObject* constructor argument and store that PyObject* as "self", you
|
||||
can get back to it by casting down to that wrapper type in a thin wrapper
|
||||
function. For example:
|
||||
<pre>
|
||||
class X { X(int); virtual ~X(); ... };
|
||||
X* f(); // known to return Xs that are managed by Python objects
|
||||
|
||||
|
||||
// wrapping code
|
||||
|
||||
struct X_wrap : X
|
||||
{
|
||||
X_wrap(PyObject* self, int v) : self(self), X(v) {}
|
||||
PyObject* self;
|
||||
};
|
||||
|
||||
handle<> f_wrap()
|
||||
{
|
||||
X_wrap* xw = dynamic_cast<X_wrap*>(f());
|
||||
assert(xw != 0);
|
||||
return handle<>(borrowed(xw->self));
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
def("f", f_wrap());
|
||||
class_<X,X_wrap>("X", init<int>())
|
||||
...
|
||||
;
|
||||
</pre>
|
||||
Of course, if X has no virtual functions you'll have to use
|
||||
<code>static_cast</code> instead of <code>dynamic_cast</code> with no
|
||||
runtime check that it's valid. This approach also only works if the
|
||||
<code>X</code> object was constructed from Python, because
|
||||
<code>X</code>s constructed from C++ are of course never
|
||||
<code>X_wrap</code> objects.
|
||||
|
||||
<p>Another approach to this requires some work on Boost.Python, but it's
|
||||
work we've been meaning to get to anyway. Currently, when a
|
||||
<code>shared_ptr<X></code> is converted from Python, the shared_ptr
|
||||
actually manages a reference to the containing Python object. I plan to
|
||||
make it so that when a shared_ptr<X> is converted back to Python,
|
||||
the library checks to see if it's one of those "Python object managers"
|
||||
and if so just returns the original Python object. To exploit this you'd
|
||||
have to be able to change the C++ code you're wrapping so that it deals
|
||||
with shared_ptr instead of raw pointers.</p>
|
||||
|
||||
<p>There are other approaches too. The functions that receive the Python
|
||||
object that you eventually want to return could be wrapped with a thin
|
||||
wrapper that records the correspondence between the object address and
|
||||
its containing Python object, and you could have your f_wrap function
|
||||
look in that mapping to get the Python object out.</p>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
14 January, 2003
|
||||
23 January, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All
|
||||
Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user