]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/python/doc/reference/errors.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / python / doc / reference / errors.qbk
1 [section boost/python/errors.hpp]
2 [section Introduction]
3 <boost/python/errors.hpp> 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.
4 [endsect]
5 [section Class `error_already_set`]
6 error_already_set is an exception type which can be thrown to indicate that a Python error has occurred. If thrown, the precondition is that [@http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71 PyErr_Occurred()] returns a value convertible to `true`. Portable code shouldn't throw this exception type directly, but should instead use [link high_level_components.boost_python_errors_hpp.functions throw_error_already_set()], below.
7 ``
8 namespace boost { namespace python
9 {
10 class error_already_set {};
11 }}
12 ``
13 [endsect]
14 [section Functions]
15 ``
16 template <class T> bool handle_exception(T f) throw();
17 void handle_exception() throw();
18 ``
19 [variablelist
20 [[Requires][The first form requires that the expression function0<void>(f) is valid. The second form requires that a C++ exception is currently being handled (see section 15.1 in the C++ standard).]]
21 [[Effects][The first form calls f() inside a try block which first attempts to use all registered [link high_level_components.boost_python_exception_translato exception translators]. If none of those translates the exception, the catch clauses then set an appropriate Python exception for the C++ exception caught, returning true if an exception was thrown, false otherwise. The second form passes a function which rethrows the exception currently being handled to the first form.]]
22 [[Postconditions][No exception is being handled]]
23 [[Throws][nothing]]
24 [[Rationale][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 handle_exception 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: [link function_invocation_and_creation.boost_python_make_function_hpp.functions make_function()], [link function_invocation_and_creation.boost_python_make_function_hpp.functions make_constructor()], [link high_level_components.boost_python_def_hpp.functions def()] and [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu class_::def()]. The second form can be more convenient to use (see the example below), but various compilers have problems when exceptions are rethrown from within an enclosing try block.]]
25 ]
26 ``template <class T> T* expect_non_null(T* x);``
27 [variablelist
28 [[Returns][x]]
29 [[Throws][error_already_set() iff x == 0.]]
30 [[Rationale][Simplifies error-handling when calling functions in the Python/C API which return 0 on error.]]
31 ]
32 ``void throw_error_already_set();``
33 [variablelist
34 [[Effects][throw error_already_set();]]
35 [[Rationale][Simplifies error-handling when calling functions in the Python/C API which return 0 on error.]]
36 ]
37 ``void throw_error_already_set();``
38 [variablelist
39 [[Effects][throw error_already_set();]]
40 [[Rationale][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 catch block in handle_exception() can catch the exception.]]
41 ]
42 [endsect]
43 [section Example]
44 ``
45 #include <string>
46 #include <boost/python/errors.hpp>
47 #include <boost/python/object.hpp>
48 #include <boost/python/handle.hpp>
49
50 // Returns a std::string which has the same value as obj's "__name__"
51 // attribute.
52 std::string get_name(boost::python::object obj)
53 {
54 // throws if there's no __name__ attribute
55 PyObject* p = boost::python::expect_non_null(
56 PyObject_GetAttrString(obj.ptr(), "__name__"));
57
58 char const* s = PyString_AsString(p);
59 if (s != 0)
60 Py_DECREF(p);
61
62 // throws if it's not a Python string
63 std::string result(
64 boost::python::expect_non_null(
65 PyString_AsString(p)));
66
67 Py_DECREF(p); // Done with p
68
69 return result;
70 }
71
72 //
73 // Demonstrate form 1 of handle_exception
74 //
75
76 // Place into result a Python Int object whose value is 1 if a and b have
77 // identical "__name__" attributes, 0 otherwise.
78 void same_name_impl(PyObject*& result, boost::python::object a, boost::python::object b)
79 {
80 result = PyInt_FromLong(
81 get_name(a) == get_name(a2));
82 }
83
84 object borrowed_object(PyObject* p)
85 {
86 return boost::python::object(
87 boost::python::handle<>(
88 boost::python::borrowed(a1)));
89 }
90
91 // This is an example Python 'C' API interface function
92 extern "C" PyObject*
93 same_name(PyObject* args, PyObject* keywords)
94 {
95 PyObject* a1;
96 PyObject* a2;
97 PyObject* result = 0;
98
99 if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
100 return 0;
101
102 // Use boost::bind to make an object compatible with
103 // boost::Function0<void>
104 if (boost::python::handle_exception(
105 boost::bind<void>(same_name_impl, boost::ref(result), borrowed_object(a1), borrowed_object(a2))))
106 {
107 // an exception was thrown; the Python error was set by
108 // handle_exception()
109 return 0;
110 }
111
112 return result;
113 }
114
115 //
116 // Demonstrate form 2 of handle_exception. Not well-supported by all
117 // compilers.
118 //
119 extern "C" PyObject*
120 same_name2(PyObject* args, PyObject* keywords)
121 {
122 PyObject* a1;
123 PyObject* a2;
124 PyObject* result = 0;
125
126 if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
127 return 0;
128
129 try {
130 return PyInt_FromLong(
131 get_name(borrowed_object(a1)) == get_name(borrowed_object(a2)));
132 }
133 catch(...)
134 {
135 // If an exception was thrown, translate it to Python
136 boost::python::handle_exception();
137 return 0;
138 }
139 }
140 ``
141 [endsect]
142 [endsect]