1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - <boost/python/errors.hpp></title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header <boost/python/errors.hpp></h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#error_already_set-spec">Class
<code>error_already_set</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#error_already_set-spec-synopsis">Class
<code>error_already_set</code> synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#functions">Functions</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#handle_exception-spec">handle_exception</a></dt>
<dt><a href="#expect_non_null-spec">expect_non_null</a></dt>
<dt><a href=
"#throw_error_already_set-spec">throw_error_already_set</a></dt>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p><code><boost/python/errors.hpp></code> provides types and
functions for managing and translating between Python and C++ exceptions.
This is relatively low-level functionality that is mostly used internally
by Boost.Python. Users should seldom need it.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="error_already_set-spec"></a>Class
<code>error_already_set</code></h3>
<p><code>error_already_set</code> is an exception type which can be
thrown to indicate that a Python error has occurred. If thrown, the
precondition is that <a href=
"http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71">PyErr_Occurred()</a>
returns a value convertible to <code>true</code>. Portable code shouldn't
throw this exception type directly, but should instead use <code><a href=
"#throw_error_already_set-spec">throw_error_already_set</a>()</code>,
below.</p>
<h4><a name="error_already_set-spec-synopsis"></a>Class error_already_set
synopsis</h4>
<pre>
namespace boost { namespace python
{
class error_already_set {};
}}
</pre>
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name=
"handle_exception-spec">template <class T> bool handle_exception</a>(T f) throw();
void handle_exception() throw();
</pre>
<dl class="handle_exception-semantics">
<dt><b>Requires:</b> The first form requires that the expression
<code><a href=
"../../../../doc/html/functionN.html">function0</a><void>(f)</code>
is valid. The second form requires that a C++ exception is currently
being handled (see section 15.1 in the C++ standard).</dt>
<dt><b>Effects:</b> The first form calls <code>f()</code> inside a
<code>try</code> block which first attempts to use all registered <a
href="exception_translator.html">exception translators</a>. If none of
those translates the exception, the <code>catch</code> clauses then set
an appropriate Python exception for the C++ exception caught, returning
<code>true</code> if an exception was thrown, <code>false</code>
otherwise. The second form passes a function which rethrows the
exception currently being handled to the first form.</dt>
<dt><b>Postconditions:</b> No exception is being handled</dt>
<dt><b>Throws:</b> nothing</dt>
<dt><b>Rationale:</b> At inter-language boundaries it is important to
ensure that no C++ exceptions escape, since the calling language
usually doesn't have the equipment necessary to properly unwind the
stack. Use <code>handle_exception</code> to manage exception
translation whenever your C++ code is called directly from the Python
API. This is done for you automatically by the usual function wrapping
facilities: <code><a href=
"make_function.html#make_function-spec">make_function</a>()</code>,
<code><a href=
"make_function.html#make_constructor-spec">make_constructor</a>()</code>,
<code><a href="def.html#class_-spec-modifiers">def</a>()</code> and <code><a href=
"class.html#def-spec">class_::def</a>()</code>. The second form can be
more convenient to use (see the <a href="#examples">example</a> below),
but various compilers have problems when exceptions are rethrown from
within an enclosing <code>try</code> block.</dt>
</dl>
<pre>
<a name=
"expect_non_null-spec">template <class T> T* expect_non_null(T* x);</a>
</pre>
<dl class="expect_non_null-semantics">
<dt><b>Returns:</b> <code>x</code></dt>
<dt><b>Throws:</b> <code><a href=
"#error_already_set-spec">error_already_set</a>()</code> iff <code>x ==
0</code>.</dt>
<dt><b>Rationale:</b> Simplifies error-handling when calling functions
in the <a href="http://www.python.org/doc/2.2/api/api.html">Python/C
API</a> which return 0 on error.</dt>
</dl>
<pre>
<a name="throw_error_already_set-spec">void throw_error_already_set();</a>
</pre>
<dl class="throw_error_already_set-semantics">
<dt><b>Effects:</b> <code>throw <a href=
"#error_already_set-spec">error_already_set</a>();</code></dt>
</dl>
<dl>
<dt><b>Rationale:</b> Many platforms and compilers are not able to
consistently catch exceptions thrown across shared library boundaries.
Using this function from the Boost.Python library ensures that the
appropriate <code>catch</code> block in <code><a href=
"#handle_exception-spec">handle_exception</a>()</code> can catch the
exception.</dt>
</dl>
<h2><a name="examples"></a>Examples</h2>
<pre>
#include <string>
#include <boost/python/errors.hpp>
#include <boost/python/object.hpp>
#include <boost/python/handle.hpp>
// Returns a std::string which has the same value as obj's "__name__"
// attribute.
std::string get_name(boost::python::object obj)
{
// throws if there's no __name__ attribute
PyObject* p = boost::python::expect_non_null(
PyObject_GetAttrString(obj.ptr(), "__name__"));
char const* s = PyString_AsString(p);
if (s != 0)
Py_DECREF(p);
// throws if it's not a Python string
std::string result(
boost::python::expect_non_null(
PyString_AsString(p)));
Py_DECREF(p); // Done with p
return result;
}
//
// Demonstrate form 1 of handle_exception
//
// Place into result a Python Int object whose value is 1 if a and b have
// identical "__name__" attributes, 0 otherwise.
void same_name_impl(PyObject*& result, boost::python::object a, boost::python::object b)
{
result = PyInt_FromLong(
get_name(a) == get_name(a2));
}
object borrowed_object(PyObject* p)
{
return boost::python::object(
boost::python::handle<>(
boost::python::borrowed(a1)));
}
// This is an example Python 'C' API interface function
extern "C" PyObject*
same_name(PyObject* args, PyObject* keywords)
{
PyObject* a1;
PyObject* a2;
PyObject* result = 0;
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
return 0;
// Use boost::bind to make an object compatible with
// boost::Function0<void>
if (boost::python::handle_exception(
boost::bind<void>(same_name_impl, boost::ref(result), borrowed_object(a1), borrowed_object(a2))))
{
// an exception was thrown; the Python error was set by
// handle_exception()
return 0;
}
return result;
}
//
// Demonstrate form 2 of handle_exception. Not well-supported by all
// compilers.
//
extern "C" PyObject*
same_name2(PyObject* args, PyObject* keywords)
{
PyObject* a1;
PyObject* a2;
PyObject* result = 0;
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
return 0;
try {
return PyInt_FromLong(
get_name(borrowed_object(a1)) == get_name(borrowed_object(a2)));
}
catch(...)
{
// If an exception was thrown, translate it to Python
boost::python::handle_exception();
return 0;
}
}
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>© Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
</html>
|