Skip to content

Commit 8884539

Browse files
Adding better error handling in Go through panic/recovery method with error returns
1 parent a1f6c78 commit 8884539

File tree

1 file changed

+77
-6
lines changed

1 file changed

+77
-6
lines changed

PDFTronGo/pdftron.i

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,26 +214,97 @@
214214
#undef SetPort
215215
%}
216216

217-
%include "exception.i"
217+
// ==============
218+
// ERROR HANDLING
219+
// ==============
220+
// Converts C++ exceptions to Go errors using panic/recovery mechanism.
221+
// All functions now return an error in addition to their return type instead of panicking on exceptions.
222+
223+
// Ensure necessary imports for error handling code
224+
%insert(go_imports) %{
225+
import "errors"
226+
import "fmt"
227+
%}
228+
229+
// Handle exceptions by triggering recoverable panic containing the exception message
218230
%exception {
219231
try {
220-
$action;
221-
} catch (std::exception &e) {
232+
$action
233+
} catch (const std::exception &e) {
222234
_swig_gopanic(e.what());
235+
} catch (...) {
236+
_swig_gopanic("unknown exception occurred");
223237
}
224238
}
225239

240+
// Macro for generating gotype (adding error to return) and cgoout (adding panic recovery to return errors) typemaps
241+
%define ERROR_HANDLING_TYPEMAPS(TYPE)
242+
%typemap(gotype) TYPE "$gotype, error"
243+
%typemap(cgoout) TYPE %{
244+
var swig_r $gotypes
245+
var swig_err error
246+
247+
func() {
248+
defer func() {
249+
if r := recover(); r != nil {
250+
swig_err = errors.New(fmt.Sprintf("%v", r))
251+
}
252+
}()
253+
swig_r = $cgocall
254+
}()
255+
256+
return swig_r, swig_err
257+
%}
258+
%enddef
259+
260+
// Apply gotype and cgoout typemaps to functions that return:
261+
262+
// Value types
263+
ERROR_HANDLING_TYPEMAPS(SWIGTYPE)
264+
// Pointers
265+
ERROR_HANDLING_TYPEMAPS(SWIGTYPE *)
266+
// References
267+
ERROR_HANDLING_TYPEMAPS(SWIGTYPE &)
268+
// Primitives
269+
ERROR_HANDLING_TYPEMAPS(bool)
270+
ERROR_HANDLING_TYPEMAPS(char)
271+
ERROR_HANDLING_TYPEMAPS(double)
272+
ERROR_HANDLING_TYPEMAPS(int)
273+
ERROR_HANDLING_TYPEMAPS(ptrdiff_t)
274+
ERROR_HANDLING_TYPEMAPS(size_t)
275+
276+
// Generate gotype and cgoout typemaps for void separately
277+
%typemap(gotype) void "error"
278+
%typemap(cgoout) void %{
279+
var swig_err error
280+
281+
func() {
282+
defer func() {
283+
if r := recover(); r != nil {
284+
swig_err = errors.New(fmt.Sprintf("%v", r))
285+
}
286+
}()
287+
$cgocall
288+
}()
289+
290+
return swig_err
291+
%}
292+
293+
// Handle edge case: SDF::Obj returns nil when internal pointer is invalid
226294
%typemap(goout) pdftron::SDF::Obj
227295
%{
228296
// Without the brackets, swig attempts to turn $1 into a c++ dereference.. seems like a bug
229297
if ($1).GetMp_obj().Swigcptr() != 0 {
230-
$result = $1
231-
return $result
298+
return $1, swig_err
232299
}
233300

234-
$result = nil
301+
return nil, swig_err
235302
%}
236303

304+
// ==================
305+
// END ERROR HANDLING
306+
// ==================
307+
237308
/**
238309
* Provides mapping for C++ vectors.
239310
* For example, vector<double> will be called as VectorDouble in GoLang.

0 commit comments

Comments
 (0)