From 6f687ee402ff640b2360318b53f46f846789286a Mon Sep 17 00:00:00 2001
From: Dave Abrahams
-
+*= operator work?*= operator
+ work?
- Is return_internal reference efficient?
+ Is return_internal_reference efficient?
Q: I have an object composed of 12 doubles. A const& to
@@ -70,6 +75,7 @@
cycles.
class_ object to a
function in another source file, and call some of its member
functions (e.g. .def(...)) in the auxilliary source
- file:
+ file:
- more_of_my_class.cpp
:
+ more_of_my_class.cpp:
void more_of_my_class(class<my_class>& x)
{
@@ -221,28 +227,25 @@ void more_of_my_class(class<my_class>& x)
+
How do I debug my Python extensions?
- Greg Burley gives the following answer for Unix GCC users:
+
Greg Burley gives the following answer for Unix GCC users:
-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 ;-).
-
-
-
-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 ;-).
+
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.
(gdb) target exec python
(gdb) run
@@ -258,63 +261,54 @@ Current language: auto; currently c++
-
+
Greg's approach works even better using Emacs' "gdb"
+ command, since it will show you each line of source as you step through
+ it.
-Greg's approach works even better using Emacs'
-"gdb" command, since it will show you each line
-of source as you step through it.
+ 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.
-
-
-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.
-
-
-
-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.
-
-
Debugging extensions through Boost.Build
-
-If you are launching your extension module tests with Boost.Build using the
-boost-python-runtest rule, you can ask it to launch your
-debugger for you by adding "-sPYTHON_LAUNCH=debugger"
-to your bjam command-line:
+ 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.
+ Debugging extensions through Boost.Build
+ If you are launching your extension module tests with Boost.Build using the
+ boost-python-runtest rule, you can ask it to launch your
+ debugger for you by adding "-sPYTHON_LAUNCH=debugger" to your bjam
+ command-line:
-bjam -sTOOLS=metrowerks "-sPYTHON_LAUNCH=devenv /debugexe" test
+bjam -sTOOLS=metrowerks "-sPYTHON_LAUNCH=devenv /debugexe" test
bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
+ It can also be extremely useful to add the -d+2 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 -d+2 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.
-
+
Why doesn't my *= operator work?
-
-Q: I have exported my class to python, with many overloaded operators. it
-works fine for me except the *= operator. It always tells
-me "can't multiply sequence with non int type". If I use
-p1.__imul__(p2) instead of p1 *=
-p2, it successfully executes my code. What's wrong with
-me?
-
-A: 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).
+
+ Q: I have exported my class to python, with many overloaded
+ operators. it works fine for me except the *=
+ operator. It always tells me "can't multiply sequence with non int
+ type". If I use p1.__imul__(p2) instead of
+ p1 *= p2, it successfully executes my code. What's
+ wrong with me?
+ A: 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).
>>> class X(object):
... def __imul__(self, x):
@@ -323,44 +317,103 @@ classes in Pure Python).
>>> x = X()
>>> x *= 1
+ To cure this problem, all you need to do is upgrade your Python to
+ version 2.2.1 or later.
+
-To cure this problem, all you need to do is upgrade your Python to
-version 2.2.1 or later.
-
-
-
+
Does Boost.Python work with Mac OS X?
-
-The short answer: as of January 2003, unfortunately not.
-
-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 http://mail.python.org/pipermail/c++-sig/2003-January/003267.html).
-Solutions are currently unknown.
-
-It is known that under certain circumstances objects are double-destructed.
-See http://mail.python.org/pipermail/c++-sig/2003-January/003278.html"
-for details. It is not clear however if this problem is related to
-the Boost.Python runtime issues.
-
+
+ The short answer: as of January 2003, unfortunately not.
+ 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 http://mail.python.org/pipermail/c++-sig/2003-January/003267.html).
+ Solutions are currently unknown.
+
+ It is known that under certain circumstances objects are
+ double-destructed. See http://mail.python.org/pipermail/c++-sig/2003-January/003278.html"
+ for details. It is not clear however if this problem is related to the
+ Boost.Python runtime issues.
+
+
+
+ How can I find the existing PyObject that holds a C++
+ object?
+
+
+ "I am wrapping a function that always returns a pointer to an
+ already-held C++ object."
+
+ 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:
+
+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>())
+ ...
+ ;
+
+ Of course, if X has no virtual functions you'll have to use
+ static_cast instead of dynamic_cast with no
+ runtime check that it's valid. This approach also only works if the
+ X object was constructed from Python, because
+ Xs constructed from C++ are of course never
+ X_wrap objects.
+
+ 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
+ shared_ptr<X> 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.
+
+ 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.
Revised
- 14 January, 2003
+ 23 January, 2003
© Copyright Dave Abrahams 2002-2003. All Rights
- Reserved.
+ "../../../../people/dave_abrahams.htm">Dave Abrahams 2002-2003. All
+ Rights Reserved.