+ "HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
@@ -75,6 +75,12 @@ void def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
+
If Fn is [derived from] object, it will be added to
+ the current scope as a single overload. To be useful,
+ fn should be callable.
+
If a1 is the result of an overload-dispatch-expression,
@@ -104,67 +110,52 @@ void def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
-
- Otherwise, a single function overload built around fn (which must
- not be null) is added to the current
- scope:
-
-
-
If fn is a function or member function pointer,
- a1-a3 (if supplied) may be selected
- in any order from the table below.
-
-
Otherwise, Fn must be [derived from] object, and
- a1-a2 (if supplied) may be selcted in any order
- from the first two rows of the table below. To be useful,
- fn should be
- callable.
A copy will be used as the call policies of the resulting
- method overload.
-
-
-
+
Otherwise, fn must be a non-null function or member function
+ pointer, and a single function overload built around fn is added to
+ the current scope. If any of
+ a1-a3 are supplied, they may be selected
+ in any order from the table below.
+ReferenceError: Attempt to return dangling reference to object of type:
+class period
+
+
+
In this case, the Python method invoked by call_method
+ constructs a new Python object. You're trying to return a reference to a
+ C++ object (an instance of class period) contained within
+ and owned by that Python object. Because the called method handed back a
+ brand new object, the only reference to it is held for the duration of
+ get_floating_frequency() above. When the function returns,
+ the Python object will be destroyed, destroying the instance of
+ class period, and leaving the returned reference dangling.
+ That's already undefined behavior, and if you try to do anything with
+ that reference you're likely to cause a crash. Boost.Python detects this
+ situation at runtime and helpfully throws an exception instead of letting
+ you do that.
+
+
+
+
Is return_internal_reference efficient?
+
Q:I have an object composed of 12 doubles. A const& to
this object is returned by a member function of another class. From the
@@ -74,126 +99,129 @@
return_internal_reference. Are there considerations that would lead me
to prefer one over the other, such as size of generated code or memory
overhead?
-
- A: copy_const_reference will make an instance with storage for
- one of your objects, size = base_size + 12 * sizeof(double).
- return_internal_reference will make an instance with storage for a
- pointer to one of your objects, size = base_size + sizeof(void*).
- However, it will also create a weak reference object which goes in
- the source object's weakreflist and a special callback object to
- manage the lifetime of the internally-referenced object. My guess?
- copy_const_reference is your friend here, resulting in less overall
- memory use and less fragmentation, also probably fewer total cycles.
-
+
+
A: copy_const_reference will make an instance with storage
+ for one of your objects, size = base_size + 12 * sizeof(double).
+ return_internal_reference will make an instance with storage for a
+ pointer to one of your objects, size = base_size + sizeof(void*).
+ However, it will also create a weak reference object which goes in the
+ source object's weakreflist and a special callback object to manage the
+ lifetime of the internally-referenced object. My guess?
+ copy_const_reference is your friend here, resulting in less overall
+ memory use and less fragmentation, also probably fewer total
+ cycles.
-
- How can I wrap functions which take C++
- containers as arguments?
-
-
- Ralf W. Grosse-Kunstleve provides these notes:
-
+
+
How can I wrap functions which take C++
+ containers as arguments?
This can be moved to a template so that several types (double, int,
-long, etc.) can be wrapped with the same code. This technique is used in the
-file
+
+ This can be moved to a template so that several types (double, int,
+ long, etc.) can be wrapped with the same code. This technique is used
+ in the file
+
This code can be used to convert from C++ container
- types such as std::vector<> or std::list<> to Python
- tuples and vice versa. A few simple examples can be found in the file
-
+
+ This code can be used to convert from C++ container types such as
+ std::vector<> or std::list<> to Python tuples and vice
+ versa. A few simple examples can be found in the file
+
Automatic C++ container <-> Python tuple
- conversions are most suitable for containers of moderate size. These
- converters generate significantly less object code compared to
- alternative 1 above.
+
+ Automatic C++ container <-> Python tuple conversions are most
+ suitable for containers of moderate size. These converters generate
+ significantly less object code compared to alternative 1 above.
- A disadvantage of using alternative 2 is that operators such as
+
+ A disadvantage of using alternative 2 is that operators such as
arithmetic +,-,*,/,% are not available. It would be useful to have custom
rvalue converters that convert to a "math_array" type instead of tuples.
This is currently not implemented but is possible within the framework of
Boost.Python V2 as it will be released in the next couple of weeks. [ed.:
this was posted on 2002/03/10]
-
- It would also be useful to also have "custom lvalue converters" such as
- std::vector<> <-> Python list. These converters would
- support the modification of the Python list from C++. For example:
-
-
- C++:
-
-
+
+
It would also be useful to also have "custom lvalue converters" such
+ as std::vector<> <-> Python list. These converters would
+ support the modification of the Python list from C++. For example:
If you find that a class_<...> declaration can't fit
-in a single source file without triggering the error, you can always pass a
-reference to the class_ object to a function in another source
-file, and call some of its member functions (e.g. .def(...)) in
-the auxilliary source file:
-
- more_of_my_class.cpp:
-
-
+
+ If you find that a class_<...> declaration
+ can't fit in a single source file without triggering the error, you
+ can always pass a reference to the class_ object to a
+ function in another source file, and call some of its member
+ functions (e.g. .def(...)) in the auxilliary source
+ file:
+
+
- Greg Burley gives the following answer for Unix GCC users:
-
+
+
How do I debug my Python extensions?
+
+
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
@@ -249,13 +278,12 @@ void more_of_my_class(class<my_class>& x)
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.
-
-
+
+
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
>>> from my_ext import *
@@ -269,44 +297,43 @@ Current language: auto; currently c++
(gdb) do debugging stuff
-
- 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.
-
-
- 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.
-
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?
-
+
+
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*=
@@ -314,60 +341,57 @@ which may be needed by your debugger in order to get things to work right.
type". If I use p1.__imul__(p2)instead ofp1 *= 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).
-
-
+
+
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):
... print 'imul'
...
>>> 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?
-
+
+
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.
-
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.
"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:
-
+
+ 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
@@ -393,44 +417,43 @@ 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.
-
+ 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 you to change your C++ code a bit;
+ if that's an option for you it might be a better way to go. work we've
+ been meaning to get to anyway. When a shared_ptr<X> is
+ converted from Python, the shared_ptr actually manages a reference to the
+ containing Python object. 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. So you could
+ just write object(p) to get the Python object back. 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.
Part of an API that I'm wrapping goes something like this:
-
+
struct A {}; struct B { void add( A* ); }
where B::add() takes ownership of the pointer passed to it.
-
- However:
-
-
+
+
However:
+
a = mod.A()
b = mod.B()
b.add( a )
@@ -439,41 +462,43 @@ del b
# python interpreter crashes
# later due to memory corruption.
-
- Even binding the lifetime of a to b via
- with_custodian_and_ward doesn't prevent the python object a from
- ultimately trying to delete the object it's pointing to. Is there a
- way to accomplish a 'transfer-of-ownership' of a wrapped C++ object?
-
-
- --Bruce Lowery
-
-
Yes: Make sure the C++ object is held by auto_ptr:
-
+
+
Even binding the lifetime of a to b via
+ with_custodian_and_ward doesn't prevent the python object a from
+ ultimately trying to delete the object it's pointing to. Is there a way
+ to accomplish a 'transfer-of-ownership' of a wrapped C++ object?
+
+
--Bruce Lowery
+
+ Yes: Make sure the C++ object is held by auto_ptr:
+
class_<A, std::auto_ptr<A> >("A")
...
;
-
Then make a thin wrapper function which takes an auto_ptr parameter:
-
+
+ Then make a thin wrapper function which takes an auto_ptr parameter:
+
void b_insert(B& b, std::auto_ptr<A> a)
{
b.insert(a.get());
a.release();
}
-
Wrap that as B.add. Note that pointers returned via
- manage_new_object
- will also be held by auto_ptr, so this
- transfer-of-ownership will also work correctly.
+
+ Wrap that as B.add. Note that pointers returned via manage_new_object
+ will also be held by auto_ptr, so this transfer-of-ownership
+ will also work correctly.
-