Correct docs and examples to call SWIG_fail after setting a Python error
Although 'return NULL' works, it may miss out on some cleanup and NULL is the wrong value to return in generated code for overloaded functions.
This commit is contained in:
parent
e9e6a99f0f
commit
129ef8ea8f
7 changed files with 74 additions and 66 deletions
|
|
@ -3717,7 +3717,7 @@ or a NULL pointer perhaps). Here is a simple example of how you might handle th
|
|||
$action
|
||||
if (!result) {
|
||||
PyErr_SetString(PyExc_MemoryError,"Not enough memory");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
void *malloc(size_t nbytes);
|
||||
|
|
@ -3749,7 +3749,7 @@ that. For example:
|
|||
$action
|
||||
if (err_occurred()) {
|
||||
PyErr_SetString(PyExc_RuntimeError, err_message());
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
|
@ -3770,7 +3770,7 @@ C++ exceptions are also easy to handle. For example, you can write code like th
|
|||
$action
|
||||
} catch (std::out_of_range &e) {
|
||||
PyErr_SetString(PyExc_IndexError, const_cast<char*>(e.what()));
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3784,7 +3784,8 @@ public:
|
|||
|
||||
<p>
|
||||
When raising a Python exception from C, use the <tt>PyErr_SetString()</tt>
|
||||
function as shown above. The following exception types can be used as the first argument.
|
||||
function as shown above followed by <tt>SWIG_fail</tt>.
|
||||
The following exception types can be used as the first argument.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -3818,6 +3819,13 @@ PyExc_ZeroDivisionError
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<tt>SWIG_fail</tt> is a C macro which when called within the context of SWIG wrapper function,
|
||||
will jump to the error handler code. This will call any cleanup code (freeing any temp variables)
|
||||
and then return from the wrapper function so that the Python interpreter can raise the Python exception.
|
||||
This macro should always be called after setting a Python error in code snippets, such as typemaps and <tt>%exception</tt>, that are ultimately generated into the wrapper function.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The language-independent <tt>exception.i</tt> library file can also be used
|
||||
to raise exceptions. See the <a href="Library.html#Library">SWIG Library</a> chapter.
|
||||
|
|
@ -4417,7 +4425,7 @@ You can refine this by supplying an optional parameter name. For example:
|
|||
$1 = (int) PyLong_AsLong($input);
|
||||
if ($1 < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a nonnegative value.");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
%inline %{
|
||||
|
|
@ -4750,18 +4758,18 @@ object to be used as a <tt>char **</tt> object.
|
|||
$1 = (char **) malloc((size+1)*sizeof(char *));
|
||||
for (i = 0; i < size; i++) {
|
||||
PyObject *o = PyList_GetItem($input,i);
|
||||
if (PyString_Check(o))
|
||||
if (PyString_Check(o)) {
|
||||
$1[i] = PyString_AsString(PyList_GetItem($input,i));
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError,"list must contain strings");
|
||||
} else {
|
||||
free($1);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_TypeError,"list must contain strings");
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
$1[i] = 0;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError,"not a list");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4849,18 +4857,18 @@ previous example:
|
|||
$2 = (char **) malloc(($1+1)*sizeof(char *));
|
||||
for (i = 0; i < $1; i++) {
|
||||
PyObject *o = PyList_GetItem($input,i);
|
||||
if (PyString_Check(o))
|
||||
if (PyString_Check(o)) {
|
||||
$2[i] = PyString_AsString(PyList_GetItem($input,i));
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError,"list must contain strings");
|
||||
} else {
|
||||
free($2);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_TypeError,"list must contain strings");
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
$2[i] = 0;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError,"not a list");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5038,12 +5046,12 @@ This too, can be handled used typemaps as follows :
|
|||
if (PyTuple_Check($input)) {
|
||||
if (!PyArg_ParseTuple($input,"dddd",temp,temp+1,temp+2,temp+3)) {
|
||||
PyErr_SetString(PyExc_TypeError,"tuple must have 4 elements");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$1 = &temp[0];
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError,"expected a tuple.");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5078,18 +5086,18 @@ arrays of different sizes. To do this, you might write a typemap as follows:
|
|||
int i;
|
||||
if (!PySequence_Check($input)) {
|
||||
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
if (PyObject_Length($input) != $1_dim0) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expecting a sequence with $1_dim0 elements");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
for (i =0; i < $1_dim0; i++) {
|
||||
PyObject *o = PySequence_GetItem($input,i);
|
||||
if (!PyFloat_Check(o)) {
|
||||
Py_XDECREF(o);
|
||||
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of floats");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
temp[i] = PyFloat_AsDouble(o);
|
||||
Py_DECREF(o);
|
||||
|
|
@ -5146,7 +5154,7 @@ static int convert_darray(PyObject *input, double *ptr, int size) {
|
|||
|
||||
%typemap(in) double [ANY](double temp[$1_dim0]) {
|
||||
if (!convert_darray($input,temp,$1_dim0)) {
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$1 = &temp[0];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -373,11 +373,11 @@ example, you could write a typemap like this:
|
|||
<div class="code">
|
||||
<pre>
|
||||
%typemap(in) <b>double nonnegative</b> {
|
||||
$1 = PyFloat_AsDouble($input);
|
||||
if ($1 < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,"argument must be nonnegative.");
|
||||
return NULL;
|
||||
}
|
||||
$1 = PyFloat_AsDouble($input);
|
||||
if ($1 < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,"argument must be nonnegative.");
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
|
|
@ -2964,11 +2964,11 @@ similar to this:
|
|||
int i;
|
||||
if (!PySequence_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
if (PySequence_Length($input) != 4) {
|
||||
PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected 4 elements");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
PyObject *o = PySequence_GetItem($input,i);
|
||||
|
|
@ -2976,7 +2976,7 @@ similar to this:
|
|||
temp[i] = (float) PyFloat_AsDouble(o);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
$1 = temp;
|
||||
|
|
@ -3009,11 +3009,11 @@ If you wanted to generalize the typemap to apply to arrays of all dimensions you
|
|||
int i;
|
||||
if (!PySequence_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
if (PySequence_Length($input) != $1_dim0) {
|
||||
PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
for (i = 0; i < $1_dim0; i++) {
|
||||
PyObject *o = PySequence_GetItem($input,i);
|
||||
|
|
@ -3021,7 +3021,7 @@ If you wanted to generalize the typemap to apply to arrays of all dimensions you
|
|||
temp[i] = (float) PyFloat_AsDouble(o);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
$1 = temp;
|
||||
|
|
@ -3053,11 +3053,11 @@ as shown. To work with heap allocated data, the following technique can be use
|
|||
int i;
|
||||
if (!PySequence_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
if (PySequence_Length($input) != $1_dim0) {
|
||||
PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$1 = (float *) malloc($1_dim0*sizeof(float));
|
||||
for (i = 0; i < $1_dim0; i++) {
|
||||
|
|
@ -3065,9 +3065,9 @@ as shown. To work with heap allocated data, the following technique can be use
|
|||
if (PyNumber_Check(o)) {
|
||||
$1[i] = (float) PyFloat_AsDouble(o);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
||||
free($1);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3229,7 +3229,7 @@ pointers. For example:</p>
|
|||
%typemap(check) Vector * {
|
||||
if ($1 == 0) {
|
||||
PyErr_SetString(PyExc_TypeError,"NULL Pointer not allowed");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3508,7 +3508,7 @@ maps perform the conversion described for the above example:
|
|||
int i;
|
||||
if (!PyList_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expecting a list");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$1 = PyList_Size($input);
|
||||
$2 = (char **) malloc(($1+1)*sizeof(char *));
|
||||
|
|
@ -3517,7 +3517,7 @@ maps perform the conversion described for the above example:
|
|||
if (!PyString_Check(s)) {
|
||||
free($2);
|
||||
PyErr_SetString(PyExc_ValueError, "List items must be strings");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$2[i] = PyString_AsString(s);
|
||||
}
|
||||
|
|
@ -3633,7 +3633,7 @@ might write typemaps like this:
|
|||
%typemap(in) (void *wbuffer, size_t len) {
|
||||
if (!PyString_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expecting a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$1 = (void *) PyString_AsString($input);
|
||||
$2 = PyString_Size($input);
|
||||
|
|
@ -3643,12 +3643,12 @@ might write typemaps like this:
|
|||
%typemap(in) (void *rbuffer, size_t len) {
|
||||
if (!PyInt_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expecting an integer");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$2 = PyInt_AsLong($input);
|
||||
if ($2 < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "Positive integer expected");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$1 = (void *) malloc($2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -517,7 +517,7 @@ like this:
|
|||
argc = PyTuple_Size(varargs);
|
||||
if (argc > 10) {
|
||||
PyErr_SetString(PyExc_ValueError, "Too many arguments");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
PyObject *pyobj = PyTuple_GetItem(varargs, i);
|
||||
|
|
@ -526,7 +526,7 @@ like this:
|
|||
PyObject *pystr;
|
||||
if (!PyUnicode_Check(pyobj)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expected a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
pystr = PyUnicode_AsUTF8String(pyobj);
|
||||
str = strdup(PyBytes_AsString(pystr));
|
||||
|
|
@ -534,7 +534,7 @@ like this:
|
|||
%#else
|
||||
if (!PyString_Check(pyobj)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expected a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
str = PyString_AsString(pyobj);
|
||||
%#endif
|
||||
|
|
@ -635,9 +635,9 @@ example. For example:
|
|||
for (i = 0; i < argc; i++) {
|
||||
PyObject *o = PyTuple_GetItem(varargs,i);
|
||||
if (!PyString_Check(o)) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a string");
|
||||
free(argv);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a string");
|
||||
SWIG_fail;
|
||||
}
|
||||
argv[i] = PyString_AsString(o);
|
||||
}
|
||||
|
|
@ -676,11 +676,11 @@ example. For example:
|
|||
&ffi_type_uint, types) == FFI_OK) {
|
||||
ffi_call(&cif, (void (*)()) execlp, &result, values);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
free(types);
|
||||
free(values);
|
||||
free(arg3);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
SWIG_fail;
|
||||
}
|
||||
free(types);
|
||||
free(values);
|
||||
|
|
@ -744,8 +744,8 @@ As a more extreme example of libffi, here is some code that attempts to wrap <tt
|
|||
argv[i].type = VT_POINTER;
|
||||
argv[i].val.pvalue = (void *) PyString_AsString(o);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
|
||||
free(argv);
|
||||
PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -793,11 +793,11 @@ As a more extreme example of libffi, here is some code that attempts to wrap <tt
|
|||
&ffi_type_uint, types) == FFI_OK) {
|
||||
ffi_call(&cif, (void (*)()) printf, &result, values);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
free(types);
|
||||
free(values);
|
||||
free(args);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
SWIG_fail;
|
||||
}
|
||||
free(types);
|
||||
free(values);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
PyObject *o = PyTuple_GetItem(varargs,i);
|
||||
if (!PyString_Check(o)) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
argv[i] = PyString_AsString(o);
|
||||
}
|
||||
|
|
@ -58,11 +58,11 @@
|
|||
&ffi_type_uint, types) == FFI_OK) {
|
||||
ffi_call(&cif, (void (*)()) execlp, &result, values);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
free(types);
|
||||
free(values);
|
||||
free(arg3);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
SWIG_fail;
|
||||
}
|
||||
free(types);
|
||||
free(values);
|
||||
|
|
@ -107,9 +107,9 @@ int execlp(const char *path, const char *arg1, ...);
|
|||
argv[i].type = VT_POINTER;
|
||||
argv[i].val.pvalue = (void *) PyString_AsString(o);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
|
||||
free(argv);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,11 +157,11 @@ int execlp(const char *path, const char *arg1, ...);
|
|||
&ffi_type_uint, types) == FFI_OK) {
|
||||
ffi_call(&cif, (void (*)()) printf, &result, values);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
free(types);
|
||||
free(values);
|
||||
free(args);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
|
||||
SWIG_fail;
|
||||
}
|
||||
free(types);
|
||||
free(values);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ extern int gcdmain(int argc, char *argv[]);
|
|||
PyObject *utf8str;
|
||||
if (!PyUnicode_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
utf8str = PyUnicode_AsUTF8String($input);
|
||||
PyBytes_AsStringAndSize(utf8str, &cstr, &len);
|
||||
|
|
@ -79,7 +79,7 @@ extern int gcdmain(int argc, char *argv[]);
|
|||
%#else
|
||||
if (!PyString_Check($input)) {
|
||||
PyErr_SetString(PyExc_ValueError,"Expected a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
$1 = PyString_AsString($input);
|
||||
$2 = (int)PyString_Size($input);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace test {
|
|||
PyComplex_ImagAsDouble($input));
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError,"Expected test_complex.\n");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
%typemap(freearg) test::test_complex * {
|
||||
|
|
@ -242,7 +242,7 @@ namespace Split {
|
|||
$1 = PyInt_AsLong($input);
|
||||
if ($1 < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,"domain error\n");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
argc = PyTuple_Size(varargs);
|
||||
if (argc > 10) {
|
||||
PyErr_SetString(PyExc_ValueError, "Too many arguments");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
PyObject *pyobj = PyTuple_GetItem(varargs, i);
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
PyObject *pystr;
|
||||
if (!PyUnicode_Check(pyobj)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expected a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
pystr = PyUnicode_AsUTF8String(pyobj);
|
||||
str = strdup(PyBytes_AsString(pystr));
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
%#else
|
||||
if (!PyString_Check(pyobj)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Expected a string");
|
||||
return NULL;
|
||||
SWIG_fail;
|
||||
}
|
||||
str = PyString_AsString(pyobj);
|
||||
%#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue