• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[chapter Frequently Asked Questions (FAQs)
2    [quickbook 1.7]
3    [id faq]
4]
5
6[section How can I wrap a function which takes a function pointer as an argument?]
7
8If what you're trying to do is something like this:
9``
10  typedef boost::function<void (string s) > funcptr;
11
12  void foo(funcptr fp)
13  {
14    fp("hello,world!");
15  }
16
17  BOOST_PYTHON_MODULE(test)
18  {
19    def("foo",foo);
20  }
21``
22
23And then:
24
25``
26>>> def hello(s):
27...    print s
28...
29>>> foo(hello)
30hello, world!
31``
32The short answer is: "you can't".  This is not a
33Boost.Python limitation so much as a limitation of C++.  The
34problem is that a Python function is actually data, and the only
35way of associating data with a C++ function pointer is to store it
36in a static variable of the function.  The problem with that is
37that you can only associate one piece of data with every C++
38function, and we have no way of compiling a new C++ function
39on-the-fly for every Python function you decide to pass
40to `foo`.  In other words, this could work if the C++
41function is always going to invoke the /same/ Python
42function, but you probably don't want that.
43
44If you have the luxury of changing the C++ code you're
45wrapping, pass it an `object` instead and call that;
46the overloaded function call operator will invoke the Python
47function you pass it behind the `object`.
48
49[endsect]
50[section I'm getting the "attempt to return dangling reference" error.
51 What am I doing wrong?]
52
53That exception is protecting you from causing a nasty crash. It usually
54happens in response to some code like this:
55``
56  period const &get_floating_frequency() const
57  {
58    return boost::python::call_method<period const &>(
59      m_self,"get_floating_frequency");
60  }
61``
62And you get:
63``
64  ReferenceError: Attempt to return dangling reference to object of type:
65  class period
66``
67
68In this case, the Python method invoked by `call_method`
69constructs a new Python object. You're trying to return a reference to a
70C++ object (an instance of `class period`) contained within
71and owned by that Python object. Because the called method handed back a
72brand new object, the only reference to it is held for the duration of
73`get_floating_frequency()` above. When the function returns,
74the Python object will be destroyed, destroying the instance of
75`class period`, and leaving the returned reference dangling.
76That's already undefined behavior, and if you try to do anything with
77that reference you're likely to cause a crash. Boost.Python detects this
78situation at runtime and helpfully throws an exception instead of letting
79you do that.
80
81[endsect]
82[section Is `return_internal_reference` efficient?]
83
84[*Q:] /I have an object composed of 12 doubles. A `const&` to
85this object is returned by a member function of another class. From the
86viewpoint of using the returned object in Python I do not care if I get
87a copy or a reference to the returned object. In Boost.Python I have the
88choice of using `copy_const_reference` or `return_internal_reference`.
89Are there considerations that would lead me to prefer one over the other,
90such as size of generated code or memory overhead?/
91
92[*A:] `copy_const_reference` will make an instance with storage
93for one of your objects, `size = base_size + 12 * sizeof(double)`.
94`return_internal_reference` will make an instance with storage for a
95pointer to one of your objects, `size = base_size + sizeof(void*)`.
96However, it will also create a weak reference object which goes in the
97source object's weakreflist and a special callback object to manage the
98lifetime of the internally-referenced object. My guess?
99`copy_const_reference` is your friend here, resulting in less overall
100memory use and less fragmentation, also probably fewer total
101cycles.
102
103[endsect]
104[section How can I wrap functions which take C++ containers as arguments?]
105
106Ralf W. Grosse-Kunstleve provides these notes:
107
108# Using the regular `class_<>` wrapper:
109  ``
110    class_<std::vector<double> >("std_vector_double")
111      .def(...)
112      ...
113    ;
114  ``
115  This can be moved to a template so that several types (`double`, `int`,
116  `long`, etc.) can be wrapped with the same code. This technique is used
117  in the file `scitbx/include/scitbx/array_family/boost_python/flex_wrapper.h`
118  in the "scitbx" package. The file could easily be modified for
119  wrapping `std::vector<>` instantiations.
120  This type of C++/Python binding is most suitable for containers
121  that may contain a large number of elements (>10000).
122
123# Using custom rvalue converters. Boost.Python "rvalue converters"
124  match function signatures such as:
125  ``
126    void foo(std::vector<double> const &array); // pass by const-reference
127    void foo(std::vector<double> array); // pass by value
128  ``
129  Some custom rvalue converters are implemented in the file
130  `scitbx/include/scitbx/boost_python/container_conversions.h`
131  This code can be used to convert from C++ container types such as
132  `std::vector<>` or `std::list<>` to Python tuples and vice
133  versa. A few simple examples can be found in the file
134  `scitbx/array_family/boost_python/regression_test_module.cpp`
135  Automatic C++ container <-> Python tuple conversions are most
136  suitable for containers of moderate size. These converters generate
137  significantly less object code compared to alternative 1 above.
138
139A disadvantage of using alternative 2 is that operators such as
140arithmetic +,-,*,/,% are not available. It would be useful to have custom
141rvalue converters that convert to a "math_array" type instead of tuples.
142This is currently not implemented but is possible within the framework of
143Boost.Python V2 as it will be released in the next couple of weeks. [ed.:
144this was posted on 2002/03/10]
145
146It would also be useful to also have "custom lvalue converters" such
147as `std::vector<>` <-> Python list. These converters would
148support the modification of the Python list from C++. For example:
149
150C++:
151``
152  void foo(std::vector<double> &array)
153  {
154    for(std::size_t i=0;i&lt;array.size();i++) {
155      array[i] *= 2;
156    }
157  }
158``
159Python: [python]
160``
161  >>> l = [1, 2, 3]
162  >>> foo(l)
163  >>> print l
164  [2, 4, 6]
165``
166Custom lvalue converters require changes to the Boost.Python core library
167and are currently not available.
168
169P.S.:
170
171The "scitbx" files referenced above are available via anonymous
172CVS:
173``
174  cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx login
175  cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
176``
177
178[endsect]
179[section fatal error C1204:Compiler limit:internal structure overflow]
180
181[*Q:] /I get this error message when compiling a large source file. What can I do?/
182
183[*A:] You have two choices:
184
185# Upgrade your compiler (preferred)
186
187# Break your source file up into multiple translation units.
188
189  `my_module.cpp`: [c++]
190
191  ``
192    ...
193    void more_of_my_module();
194    BOOST_PYTHON_MODULE(my_module)
195    {
196      def("foo", foo);
197      def("bar", bar);
198      ...
199      more_of_my_module();
200    }
201  ``
202  `more_of_my_module.cpp`:
203  ``
204    void more_of_my_module()
205    {
206      def("baz", baz);
207      ...
208    }
209  ``
210  If you find that a `class_<...>` declaration
211  can't fit in a single source file without triggering the error, you
212  can always pass a reference to the `class_` object to a
213  function in another source file, and call some of its member
214  functions (e.g. `.def(...)`) in the auxilliary source
215  file:
216
217  `more_of_my_class.cpp`:
218  ``
219    void more_of_my_class(class&lt;my_class&gt;&amp; x)
220    {
221      x
222       .def("baz", baz)
223       .add_property("xx", &my_class::get_xx, &my_class::set_xx)
224       ;
225      ...
226    }
227  ``
228
229[endsect]
230[section How do I debug my Python extensions?]
231
232Greg Burley gives the following answer for Unix GCC users:
233
234[:Once you have created a boost python extension for your c++ library or
235  class, you may need to debug the code. Afterall this is one of the
236  reasons for wrapping the library in python. An expected side-effect or
237  benefit of using BPL is that debugging should be isolated to the c++
238  library that is under test, given that python code is minimal and
239  boost::python either works or it doesn't. (ie. While errors can occur
240  when the wrapping method is invalid, most errors are caught by the
241  compiler ;-).
242
243  The basic steps required to initiate a gdb session to debug a c++
244  library via python are shown here. Note, however that you should start
245  the gdb session in the directory that contains your BPL my_ext.so
246  module.
247
248  ``
249    (gdb) target exec python
250    (gdb) run
251    >>> from my_ext import *
252    >>> [C-c]
253    (gdb) break MyClass::MyBuggyFunction
254    (gdb) cont
255    >>> pyobj = MyClass()
256    >>> pyobj.MyBuggyFunction()
257    Breakpoint 1, MyClass::MyBuggyFunction ...
258    Current language:  auto; currently c++
259    (gdb) do debugging stuff
260  ``
261]
262
263Greg's approach works even better using Emacs' "gdb"
264command, since it will show you each line of source as you step through it.
265
266On *Windows*, my favorite debugging solution is the debugger that
267comes with Microsoft Visual C++ 7. This debugger seems to work with code
268generated by all versions of Microsoft and Metrowerks toolsets; it's rock
269solid and "just works" without requiring any special tricks from the
270user.
271
272Raoul Gough has provided the following for gdb on Windows:
273
274[:gdb support for Windows DLLs has improved lately, so it is
275  now possible to debug Python extensions using a few
276  tricks. Firstly, you will need an up-to-date gdb with support
277  for minimal symbol extraction from a DLL. Any gdb from version 6
278  onwards, or Cygwin gdb-20030214-1 and onwards should do. A
279  suitable release will have a section in the gdb.info file under
280  Configuration - Native - Cygwin Native -
281  Non-debug DLL symbols. Refer to that info section for more
282  details of the procedures outlined here.
283
284  Secondly, it seems necessary to set a breakpoint in the
285  Python interpreter, rather than using ^C to break execution. A
286  good place to set this breakpoint is PyOS_Readline, which will
287  stop execution immediately before reading each interactive
288  Python command. You have to let Python start once under the
289  debugger, so that it loads its own DLL, before you can set the
290  breakpoint:
291
292  ``
293    $ gdb python
294    GNU gdb 2003-09-02-cvs (cygwin-special)
295    [...]
296
297    (gdb) run
298    Starting program: /cygdrive/c/Python22/python.exe
299    Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
300    Type "help", "copyright", "credits" or "license" for more information.
301    >>> ^Z
302
303
304    Program exited normally.
305    (gdb) break *&PyOS_Readline
306    Breakpoint 1 at 0x1e04eff0
307    (gdb) run
308    Starting program: /cygdrive/c/Python22/python.exe
309    Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
310    Type "help", "copyright", "credits" or "license" for more information.
311
312    Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
313       from /cygdrive/c/WINNT/system32/python22.dll
314    (gdb) cont
315    Continuing.
316    >>> from my_ext import *
317
318    Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
319       from /cygdrive/c/WINNT/system32/python22.dll
320    (gdb) # my_ext now loaded (with any debugging symbols it contains)
321  ``
322]
323
324[h2 Debugging extensions through Boost.Build]
325
326If you are launching your extension module tests with _bb_ using the
327`boost-python-runtest` rule, you can ask it to launch your
328debugger for you by adding "--debugger=/debugger/" to your bjam
329command-line:
330``
331  bjam -sTOOLS=vc7.1 "--debugger=devenv /debugexe" test
332  bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
333``
334It can also be extremely useful to add the `-d+2` option when
335you run your test, because Boost.Build will then show you the exact
336commands it uses to invoke it. This will invariably involve setting up
337PYTHONPATH and other important environment variables such as
338LD_LIBRARY_PATH which may be needed by your debugger in order to get
339things to work right.
340
341[endsect]
342[section Why doesn't my `*=` operator work?]
343
344[*Q:] ['I have exported my class to python, with many overloaded
345operators. it works fine for me except the `*=`
346operator. It always tells me "can't multiply sequence with non int
347type". If I use `p1.__imul__(p2)` instead of
348`p1 *= p2`, it successfully executes my code. What's
349wrong with me?]
350
351[*A:] There's nothing wrong with you. This is a bug in Python
352      2.2. You can see the same effect in Pure Python (you can learn a lot
353      about what's happening in Boost.Python by playing with new-style
354      classes in Pure Python).
355``
356>>> class X(object):
357...     def __imul__(self, x):
358...         print 'imul'
359...
360>>> x = X()
361>>> x *= 1
362``
363To cure this problem, all you need to do is upgrade your Python to
364version 2.2.1 or later.
365
366[endsect]
367[section Does Boost.Python work with Mac OS X?]
368
369It is known to work under 10.2.8 and 10.3 using
370Apple's gcc 3.3 compiler:
371``gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1493)``
372Under 10.2.8 get the August 2003 gcc update (free at [@http://connect.apple.com]).
373Under 10.3 get the Xcode Tools v1.0 (also free).
374
375Python 2.3 is required. The Python that ships with 10.3 is
376fine. Under 10.2.8 use these commands to install Python
377as a framework:
378``./configure --enable-framework
379make
380make frameworkinstall``
381
382The last command requires root privileges because the target
383directory is `/Library/Frameworks/Python.framework/Versions/2.3`.
384However, the installation does not interfere with the Python
385version that ships with 10.2.8.
386
387It is also crucial to increase the `stacksize` before
388starting compilations, e.g.:
389``limit stacksize 8192k``
390If the `stacksize` is too small the build might crash with
391internal compiler errors.
392
393Sometimes Apple's compiler exhibits a bug by printing an error
394like the following while compiling a
395`boost::python::class_<your_type>`
396template instantiation:
397``
398  .../inheritance.hpp:44: error: cannot
399    dynamic_cast `p' (of type `struct cctbx::boost_python::<unnamed>::add_pair*
400    ') to type `void*' (source type is not polymorphic)
401``
402
403We do not know a general workaround, but if the definition of
404`your_type` can be modified the following was found
405to work in all cases encountered so far:
406``
407  struct your_type
408  {
409    // before defining any member data
410  #if defined(__MACH__) &amp;&amp; defined(__APPLE_CC__) &amp;&amp; __APPLE_CC__ == 1493
411    bool dummy_;
412  #endif
413    // now your member data, e.g.
414    double x;
415    int j;
416    // etc.
417  };
418``
419[endsect]
420[section How can I find the existing PyObject that holds a C++ object?]
421
422[: "I am wrapping a function that always returns a pointer to an
423      already-held C++ object."]
424
425One way to do that is to hijack the mechanisms used for wrapping a class
426with virtual functions. If you make a wrapper class with an initial
427PyObject* constructor argument and store that PyObject* as "self", you
428can get back to it by casting down to that wrapper type in a thin wrapper
429function. For example:
430``
431  class X { X(int); virtual ~X(); ... };
432  X* f();  // known to return Xs that are managed by Python objects
433
434
435  // wrapping code
436
437  struct X_wrap : X
438  {
439    X_wrap(PyObject* self, int v) : self(self), X(v) {}
440    PyObject* self;
441  };
442
443  handle<> f_wrap()
444  {
445    X_wrap* xw = dynamic_cast<X_wrap*>(f());
446    assert(xw != 0);
447    return handle<>(borrowed(xw->self));
448  }
449
450  ...
451
452  def("f", f_wrap());
453  class_<X,X_wrap,boost::noncopyable>("X", init<int>())
454   ...
455   ;
456``
457
458Of course, if X has no virtual functions you'll have to use
459`static_cast` instead of `dynamic_cast` with no
460runtime check that it's valid. This approach also only works if the
461`X` object was constructed from Python, because
462`X`\ s constructed from C++ are of course never
463`X_wrap` objects.
464
465Another approach to this requires you to change your C++ code a bit;
466if that's an option for you it might be a better way to go. work we've
467been meaning to get to anyway. When a `shared_ptr<X>` is
468converted from Python, the shared_ptr actually manages a reference to the
469containing Python object. When a shared_ptr<X> is converted back to
470Python, the library checks to see if it's one of those "Python object
471managers" and if so just returns the original Python object. So you could
472just write `object(p)` to get the Python object back. To
473exploit this you'd have to be able to change the C++ code you're wrapping
474so that it deals with shared_ptr instead of raw pointers.
475
476There are other approaches too. The functions that receive the Python
477object that you eventually want to return could be wrapped with a thin
478wrapper that records the correspondence between the object address and
479its containing Python object, and you could have your f_wrap function
480look in that mapping to get the Python object out.
481
482[endsect]
483[section How can I wrap a function which needs to take ownership of a raw pointer?]
484
485[*Q:] Part of an API that I'm wrapping goes something like this:
486
487``
488  struct A {}; struct B { void add( A* ); }
489  where B::add() takes ownership of the pointer passed to it.
490``
491
492However:
493
494``
495  a = mod.A()
496  b = mod.B()
497  b.add( a )
498  del a
499  del b
500  # python interpreter crashes
501  # later due to memory corruption.
502``
503
504Even binding the lifetime of a to b via `with_custodian_and_ward` doesn't prevent
505the python object a from ultimately trying to delete the object it's pointing to.
506Is there a way to accomplish a 'transfer-of-ownership' of a wrapped C++ object?
507
508--Bruce Lowery
509
510Yes: Make sure the C++ object is held by auto_ptr:
511``
512  class_<A, std::auto_ptr<A> >("A")
513    ...
514    ;
515``
516Then make a thin wrapper function which takes an auto_ptr parameter:
517``
518  void b_insert(B &b, std::auto_ptr<A> a)
519  {
520    b.insert(a.get());
521    a.release();
522  }
523``
524Wrap that as B.add. Note that pointers returned via `manage_new_object`
525will also be held by `auto_ptr`, so this transfer-of-ownership
526will also work correctly.
527
528[endsect]
529[section Compilation takes too much time and eats too much memory!
530 What can I do to make it faster?]
531
532Please refer to the `Reducing Compiling Time` section in the _tutorial_.
533
534[endsect]
535[section How do I create sub-packages using Boost.Python?]
536
537Please refer to the `Creating Packages` section in the _tutorial_.
538
539[endsect]
540[section error C2064: term does not evaluate to a function taking 2 arguments]
541
542/Niall Douglas provides these notes:/
543
544If you see Microsoft Visual C++ 7.1 (MS Visual Studio .NET 2003) issue
545an error message like the following it is most likely due to a bug
546in the compiler:
547``
548  boost\boost\python\detail\invoke.hpp(76):
549  error C2064: term does not evaluate to a function taking 2 arguments"
550``
551This message is triggered by code like the following:
552``
553  #include <boost/python.hpp>
554
555  using namespace boost::python;
556
557  class FXThread
558  {
559  public:
560    bool setAutoDelete(bool doso) throw();
561  };
562
563  void Export_FXThread()
564  {
565    class_< FXThread >("FXThread")
566        .def("setAutoDelete", &amp;FXThread::setAutoDelete)
567    ;
568  }
569``
570The bug is related to the `throw()` modifier.
571As a workaround cast off the modifier. E.g.:
572``
573   .def("setAutoDelete", (bool (FXThread::*)(bool)) &FXThread::setAutoDelete)
574``
575(The bug has been reported to Microsoft.)
576
577[endsect]
578[section How can I automatically convert my custom string type to and from a Python string?]
579
580/Ralf W. Grosse-Kunstleve provides these notes:/
581
582Below is a small, self-contained demo extension module that shows
583how to do this. Here is the corresponding trivial test:
584``
585  import custom_string
586  assert custom_string.hello() == "Hello world."
587  assert custom_string.size("california") == 10
588``
589If you look at the code you will find:
590
591* A custom `to_python` converter (easy):
592        `custom_string_to_python_str`
593
594*A custom lvalue converter (needs more code):
595        `custom_string_from_python_str`
596
597The custom converters are registered in the global Boost.Python
598registry near the top of the module initialization function. Once
599flow control has passed through the registration code the automatic
600conversions from and to Python strings will work in any module
601imported in the same process.
602
603``
604  #include <boost/python/module.hpp>
605  #include <boost/python/def.hpp>
606  #include <boost/python/to_python_converter.hpp>
607
608  namespace sandbox { namespace {
609
610  class custom_string
611  {
612    public:
613      custom_string() {}
614      custom_string(std::string const &value) : value_(value) {}
615      std::string const &value() const { return value_; }
616    private:
617      std::string value_;
618  };
619
620  struct custom_string_to_python_str
621  {
622    static PyObject* convert(custom_string const &s)
623    {
624      return boost::python::incref(boost::python::object(s.value()).ptr());
625    }
626  };
627
628  struct custom_string_from_python_str
629  {
630    custom_string_from_python_str()
631    {
632      boost::python::converter::registry::push_back(
633        &convertible,
634        &construct,
635        boost::python::type_id<custom_string>());
636    }
637
638    static void* convertible(PyObject* obj_ptr)
639    {
640      if (!PyString_Check(obj_ptr)) return 0;
641      return obj_ptr;
642    }
643
644    static void construct(
645      PyObject* obj_ptr,
646      boost::python::converter::rvalue_from_python_stage1_data* data)
647    {
648      const char* value = PyString_AsString(obj_ptr);
649      if (value == 0) boost::python::throw_error_already_set();
650      void* storage = (
651        (boost::python::converter::rvalue_from_python_storage<custom_string>*)
652          data)->storage.bytes;
653      new (storage) custom_string(value);
654      data->convertible = storage;
655    }
656  };
657
658  custom_string hello() { return custom_string("Hello world."); }
659
660  std::size_t size(custom_string const &s) { return s.value().size(); }
661
662  void init_module()
663  {
664    using namespace boost::python;
665
666    boost::python::to_python_converter<
667      custom_string,
668      custom_string_to_python_str>();
669
670    custom_string_from_python_str();
671
672    def("hello", hello);
673    def("size", size);
674  }
675
676  }} // namespace sandbox::<anonymous>
677
678  BOOST_PYTHON_MODULE(custom_string)
679  {
680    sandbox::init_module();
681  }
682``
683[endsect]
684[section Why is my automatic to-python conversion not being found?]
685
686/Niall Douglas provides these notes:/
687
688If you define custom converters similar to the ones
689shown above the `def_readonly()` and `def_readwrite()`
690member functions provided by `boost::python::class_` for
691direct access to your member data will not work as expected.
692This is because `def_readonly("bar",&foo::bar)` is
693equivalent to:
694
695``
696  .add_property("bar", make_getter(&foo::bar, return_internal_reference()))
697``
698Similarly, `def_readwrite("bar",&foo::bar)` is
699equivalent to:
700
701``
702  .add_property("bar", make_getter(&foo::bar, return_internal_reference()),
703                     make_setter(&foo::bar, return_internal_reference())
704``
705In order to define return value policies compatible with the
706custom conversions replace `def_readonly()` and
707`def_readwrite()` by `add_property()`. E.g.:
708
709``
710  .add_property("bar", make_getter(&foo::bar, return_value_policy<return_by_value>()),
711                     make_setter(&foo::bar, return_value_policy<return_by_value>()))
712``
713
714[endsect]
715[section Is Boost.Python thread-aware/compatible with multiple interpreters?]
716
717/Niall Douglas provides these notes:/
718
719The quick answer to this is: no.
720
721The longer answer is that it can be patched to be so, but it's
722complex. You will need to add custom lock/unlock wrapping of every
723time your code enters Boost.Python (particularly every virtual
724function override) plus heavily modify
725`boost/python/detail/invoke.hpp` with custom unlock/lock
726wrapping of every time Boost.Python enters your code. You must
727furthermore take care to /not/ unlock/lock when Boost.Python
728is invoking iterator changes via `invoke.hpp`.
729
730There is a patched `invoke.hpp` posted on the C++-SIG
731mailing list archives and you can find a real implementation of all
732the machinery necessary to fully implement this in the TnFOX
733project at [@http://sourceforge.net/projects/tnfox/ this]
734SourceForge project location.
735
736[endsect]