faq.qbk 23 KB

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