Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
2852bd59
Commit
2852bd59
authored
Oct 04, 2020
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clarify the section on exception return values.
parent
e1ce5480
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
46 additions
and
31 deletions
+46
-31
docs/src/userguide/language_basics.rst
docs/src/userguide/language_basics.rst
+46
-31
No files found.
docs/src/userguide/language_basics.rst
View file @
2852bd59
...
...
@@ -355,27 +355,40 @@ of :ref:`error_return_values`.
Error return values
-------------------
If you don't do anything special, a function declared with :keyword:`cdef` that
does not return a Python object has no way of reporting Python exceptions to
its caller. If an exception is detected in such a function, a warning message
is printed and the exception is ignored.
If you want a C function that does not return a Python object to be able to
propagate exceptions to its caller, you need to declare an exception value for
it. Here is an example::
In Python (more specifically, in the CPython runtime), exceptions that occur
inside of a function are signaled to the caller and propagated up the call stack
through defined error return values. For functions that return Python object
(and thus, a pointer to such an object), the error return value is simply the
``NULL`` pointer, so any function returning a Python object has a well-defined
error return value.
While this is always the case for :keyword:`def` functions, functions
defined as :keyword`cdef` or :keyword:`cpdef` can return arbitrary C types,
which do not have such a well-defined error return value. Thus, if an
exception is detected in such a function, a warning message is printed,
the exception is ignored, and the function returns without propagating it
to its caller.
If you want such a C function to be able to propagate exceptions, you need
to declare an exception return value for it as a contract with the caller.
Here is an example::
cdef int spam() except -1:
...
With this declaration, whenever an exception occurs inside
spam
, it will
immediately return with the value ``-1``.
Furthermore, whenever a call to spam
returns ``-1``, an exception will be assumed to have occurred and will be
propagated
.
With this declaration, whenever an exception occurs inside
``spam``
, it will
immediately return with the value ``-1``.
From the caller's side, whenever
a call to spam returns ``-1``, the claler will assume that an exception has
occurred and can now process or propagate it
.
When you declare an exception value for a function, you should never
explicitly or implicitly return that value. In particular, if the exceptional return value
is a ``False`` value, then you should ensure the function will never terminate via an implicit
or empty return.
When you declare an exception value for a function, you should never explicitly
or implicitly return that value. This includes empty :keyword:`return`
statements, without a return value, for which Cython inserts the default return
value (e.g. ``0`` for C number types). In general, exception return values
are best chosen from invalid or very unlikely return values of the function,
such as a negative value for functions that return only non-negative results,
or a very large value like ``INT_MAX`` for a function that "usually" only
returns small results.
If all possible return values are legal and you
can't reserve one entirely for signalling errors, you can use an alternative
...
...
@@ -384,9 +397,10 @@ form of exception value declaration::
cdef int spam() except? -1:
...
The "?" indicates that the value ``-1`` only indicates a possible error. In this
case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value is
returned, to make sure it really is an error.
The "?" indicates that the value ``-1`` only signals a possible error. In this
case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value
is returned, to make sure it really received an exception and not just a normal
result.
There is also a third form of exception value declaration::
...
...
@@ -394,10 +408,11 @@ There is also a third form of exception value declaration::
...
This form causes Cython to generate a call to :c:func:`PyErr_Occurred` after
every call to spam, regardless of what value it returns. If you have a
function returning void that needs to propagate errors, you will have to use
this form, since there isn't any return value to test.
Otherwise there is little use for this form.
*every* call to spam, regardless of what value it returns. If you have a
function returning ``void`` that needs to propagate errors, you will have to
use this form, since there isn't any error return value to test.
Otherwise, an explicit error return value allows the C compiler to generate
more efficient code and is thus generally preferable.
An external C++ function that may raise an exception can be declared with::
...
...
@@ -407,22 +422,22 @@ See :ref:`wrapping-cplusplus` for more details.
Some things to note:
* Exception values can only declared for functions returning an integer, enum,
float or pointer type, and the value must be a constant expression.
Void functions can only use the ``except *`` form.
* Exception values can only be declared for functions returning an integer,
enum, float or pointer type, and the value must be a constant expression.
Functions that return ``void``, or a struct/union by value, can only use
the ``except *`` form.
* The exception value specification is part of the signature of the function.
If you're passing a pointer to a function as a parameter or assigning it
to a variable, the declared type of the parameter or variable must have
the same exception value specification (or lack thereof). Here is an
example of a pointer-to-function declaration with an exception
value::
example of a pointer-to-function declaration with an exception value::
int (*grail)(int, char*) except -1
* You don't need to (and shouldn't) declare exception values for functions
which return Python objects. Remember that a function with no declared
return type implicitly returns a Python object. (Exceptions on such
functions
are implicitly propagated by returning NULL
.)
return type implicitly returns a Python object. (Exceptions on such
functions are implicitly propagated by returning ``NULL``
.)
.. _checking_return_values_of_non_cython_functions:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment