Make it possible to customize swig_check() definition

Move this function definition to cexcept.swg from the code and only
define it if SWIG_swig_check_DEFINED is not defined yet, which both
simplifies the code in C.cxx and makes exception handling code more
flexible, as it's now possible to predefine SWIG_swig_check_DEFINED
in the code injected into the "cxxheader" section to replace the default
implementation. Show an example of doing this in the documentation and
document handling exceptions with C API too.

The changes above required adding a new "cxxcode" section, corresponding
to the "implementation" part of C++ wrappers and defining a new
SWIG_CXX_WRAPPERS preprocessor symbol to allow only adding C++-specific
code when C++ wrappers are actually generated. Also improve the
documentation of the C-specific sections in the manual.
This commit is contained in:
Vadim Zeitlin 2021-12-09 00:18:05 +01:00
commit f06bba320a
3 changed files with 86 additions and 22 deletions

View file

@ -683,6 +683,10 @@ void SomeIntTemplateClass_delete(SomeIntTemplateClass * carg1);
<H2><a name="C_exceptions"></a>36.5 Exception handling</H2>
<p>
Any call to a C++ function may throw an exception, which cannot be caught by C code. Instead, the special <tt>SWIG_CException_get_pending()</tt> function must be called to check for this. If it returns a non-null pointer, <tt>SWIG_CException_msg_get()</tt> can be called to retrieve the error message associated with the exception. Finally, <tt>SWIG_CException_reset_pending()</tt> must be called to free the exception object and reset the current pending exception. Note that exception handling is much simpler when using C++, rather than C, wrappers, see sections 36.6.2.
</p>
<H2><a name="C_cxx_wrappers"></a>36.6 C++ Wrappers</H2>
<p>
@ -702,8 +706,52 @@ Other ones are due to things that could be supported but haven't been implemente
</ul>
</p>
Note that <tt>cxxheader</tt> section can be used to output additional
declarations to the C++-only part of the generated header.
<H3>36.6.1 Additional sections</H3>
Generated C++ code can be customized by inserting custom code in the following sections:
<ul>
<li><tt>cxxheader</tt> for including additional headers and other declarations in the global scope.</li>
<li><tt>cxxcode</tt> for additional code to appear after the declarations of all wrapper classes, inside the module-specific namespace.</li>
</ul>
<H3>36.6.2 Exception handling</H3>
<p>
Exception handling in C++ is more natural, as the exceptions are re-thrown when using C++ wrappers and so can be caught, as objects of the special <tt>SWIG_CException</tt> type, using the usual <tt>try/catch</tt> statement. The objects of <tt>SWIG_CException</tt> class have <tt>code()</tt> and <tt>msg()</tt> methods, with the latter returning the error message associated with the exception.
</p>
<p>
If necessary, a custom exception type may be used instead of <tt>SWIG_CException</tt>. To do this, a custom implementation of <tt>swig_check()</tt> function, called to check for the pending exception and throw the corresponding C++ exception if necessary, must be provided and <tt>SWIG_swig_check_DEFINED</tt> preprocessor symbol must be defined to prevent the default implementation of this function from being compiled:
</p>
<div class="code"><pre>
%insert(cxxheader) %{
#ifndef SWIG_swig_check_DEFINED
#define SWIG_swig_check_DEFINED 1
#include <stdexcept>
class Exception : public std::runtime_error {
public:
explicit Exception(const char* msg) : std::runtime_error{msg} {}
};
inline void swig_check() {
if (auto* swig_ex = SWIG_CException_get_pending()) {
Exception const e{SWIG_CException_msg_get(swig_ex)};
SWIG_CException_reset_pending();
throw e;
}
}
template <typename T> T swig_check(T x) {
swig_check();
return x;
}
#endif // SWIG_swig_check_DEFINED
%}
</pre></div>
</body>
</html>