|
214 | 214 | #undef SetPort |
215 | 215 | %} |
216 | 216 |
|
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 |
218 | 230 | %exception { |
219 | 231 | try { |
220 | | - $action; |
221 | | - } catch (std::exception &e) { |
| 232 | + $action |
| 233 | + } catch (const std::exception &e) { |
222 | 234 | _swig_gopanic(e.what()); |
| 235 | + } catch (...) { |
| 236 | + _swig_gopanic("unknown exception occurred"); |
223 | 237 | } |
224 | 238 | } |
225 | 239 |
|
| 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 |
226 | 294 | %typemap(goout) pdftron::SDF::Obj |
227 | 295 | %{ |
228 | 296 | // Without the brackets, swig attempts to turn $1 into a c++ dereference.. seems like a bug |
229 | 297 | if ($1).GetMp_obj().Swigcptr() != 0 { |
230 | | - $result = $1 |
231 | | - return $result |
| 298 | + return $1, swig_err |
232 | 299 | } |
233 | 300 |
|
234 | | - $result = nil |
| 301 | + return nil, swig_err |
235 | 302 | %} |
236 | 303 |
|
| 304 | +// ================== |
| 305 | +// END ERROR HANDLING |
| 306 | +// ================== |
| 307 | + |
237 | 308 | /** |
238 | 309 | * Provides mapping for C++ vectors. |
239 | 310 | * For example, vector<double> will be called as VectorDouble in GoLang. |
|
0 commit comments