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