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
Hide 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`.
...
@@ -355,27 +355,40 @@ of :ref:`error_return_values`.
Error return values
Error return values
-------------------
-------------------
If you don't do anything special, a function declared with :keyword:`cdef` that
In Python (more specifically, in the CPython runtime), exceptions that occur
does not return a Python object has no way of reporting Python exceptions to
inside of a function are signaled to the caller and propagated up the call stack
its caller. If an exception is detected in such a function, a warning message
through defined error return values. For functions that return Python object
is printed and the exception is ignored.
(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
If you want a C function that does not return a Python object to be able to
error return value.
propagate exceptions to its caller, you need to declare an exception value for
it. Here is an example::
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:
cdef int spam() except -1:
...
...
With this declaration, whenever an exception occurs inside
spam
, it will
With this declaration, whenever an exception occurs inside
``spam``
, it will
immediately return with the value ``-1``.
Furthermore, whenever a call to spam
immediately return with the value ``-1``.
From the caller's side, whenever
returns ``-1``, an exception will be assumed to have occurred and will be
a call to spam returns ``-1``, the claler will assume that an exception has
propagated
.
occurred and can now process or propagate it
.
When you declare an exception value for a function, you should never
When you declare an exception value for a function, you should never explicitly
explicitly or implicitly return that value. In particular, if the exceptional return value
or implicitly return that value. This includes empty :keyword:`return`
is a ``False`` value, then you should ensure the function will never terminate via an implicit
statements, without a return value, for which Cython inserts the default return
or empty 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
If all possible return values are legal and you
can't reserve one entirely for signalling errors, you can use an alternative
can't reserve one entirely for signalling errors, you can use an alternative
...
@@ -384,9 +397,10 @@ form of exception value declaration::
...
@@ -384,9 +397,10 @@ form of exception value declaration::
cdef int spam() except? -1:
cdef int spam() except? -1:
...
...
The "?" indicates that the value ``-1`` only indicates a possible error. In this
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
case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value
returned, to make sure it really is an error.
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::
There is also a third form of exception value declaration::
...
@@ -394,10 +408,11 @@ 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
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
*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
function returning ``void`` that needs to propagate errors, you will have to
this form, since there isn't any return value to test.
use this form, since there isn't any error return value to test.
Otherwise there is little use for this form.
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::
An external C++ function that may raise an exception can be declared with::
...
@@ -407,22 +422,22 @@ See :ref:`wrapping-cplusplus` for more details.
...
@@ -407,22 +422,22 @@ See :ref:`wrapping-cplusplus` for more details.
Some things to note:
Some things to note:
* Exception values can only declared for functions returning an integer, enum,
* Exception values can only be declared for functions returning an integer,
float or pointer type, and the value must be a constant expression.
enum, float or pointer type, and the value must be a constant expression.
Void functions can only use the ``except *`` form.
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.
* 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
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
to a variable, the declared type of the parameter or variable must have
the same exception value specification (or lack thereof). Here is an
the same exception value specification (or lack thereof). Here is an
example of a pointer-to-function declaration with an exception
example of a pointer-to-function declaration with an exception value::
value::
int (*grail)(int, char*) except -1
int (*grail)(int, char*) except -1
* You don't need to (and shouldn't) declare exception values for functions
* You don't need to (and shouldn't) declare exception values for functions
which return Python objects. Remember that a function with no declared
which return Python objects. Remember that a function with no declared
return type implicitly returns a Python object. (Exceptions on such
functions
return type implicitly returns a Python object. (Exceptions on such
are implicitly propagated by returning NULL
.)
functions are implicitly propagated by returning ``NULL``
.)
.. _checking_return_values_of_non_cython_functions:
.. _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