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<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<my_class>& 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__) && defined(__APPLE_CC__) && __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", &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]