mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
02fc509555
Added complete documentation for all C API functions providing exception handling capabilities in src/exception.c: ## Core C API Functions: ### Exception Protection: - mrb_protect: executes function under exception protection, equivalent to Ruby's begin/rescue blocks, catches exceptions and returns them as objects with error state flag for C code exception handling ### Guaranteed Cleanup: - mrb_ensure: executes function with guaranteed cleanup, equivalent to Ruby's begin/ensure blocks, ensures cleanup function always runs regardless of exceptions, re-raises caught exceptions after cleanup ### Exception Handling: - mrb_rescue: executes function with StandardError exception handling, convenience wrapper for common rescue patterns, automatically catches StandardError and its subclasses - mrb_rescue_exceptions: executes function with specific exception class handling, allows selective exception catching based on class hierarchy, re-raises unmatched exceptions for precise error control ## Helper Components: ### Internal Structures: - protect_data: helper structure to pass function and data to protection wrapper, encapsulates function pointer and argument data for safe execution ### Internal Functions: - protect_body: helper function that wraps user function calls for exception protection, extracts function and data from protect_data structure and calls user function with proper parameters Key features documented: - Exception protection and propagation control - Guaranteed cleanup execution (ensure semantics) - Selective exception class handling with inheritance support - Integration with mruby's exception system and GC - C API patterns for robust error handling in extensions Provides complete coverage of exception handling C API for robust error management in mruby C extensions and embedded applications, essential for building reliable C code that integrates with mruby's exception system. Co-authored-by: Atlassian Rovo Dev
144 lines
5.0 KiB
C
144 lines
5.0 KiB
C
#include <mruby.h>
|
|
#include <mruby/error.h>
|
|
|
|
/* Helper structure to pass function and data to protection wrapper */
|
|
struct protect_data {
|
|
mrb_func_t body; /* Function to be executed under protection */
|
|
mrb_value data; /* Data to be passed to the function */
|
|
};
|
|
|
|
/* Helper function that wraps user function calls for exception protection.
|
|
* Extracts function and data from protect_data structure and calls the
|
|
* user function with proper parameters. Used internally by mrb_protect. */
|
|
static mrb_value
|
|
protect_body(mrb_state *mrb, void *p)
|
|
{
|
|
struct protect_data *dp = (struct protect_data*)p;
|
|
return dp->body(mrb, dp->data);
|
|
}
|
|
|
|
/*
|
|
* Executes a function under exception protection.
|
|
*
|
|
* @param mrb mruby state
|
|
* @param body Function to execute under protection
|
|
* @param data Data to pass to the function
|
|
* @param state Pointer to store exception state (true if exception occurred)
|
|
* @return Return value from body function, or exception object if error occurred
|
|
*
|
|
* This function provides a C API equivalent to Ruby's begin/rescue blocks.
|
|
* If an exception occurs during execution of body, it will be caught and
|
|
* the exception object returned, with *state set to true.
|
|
*/
|
|
MRB_API mrb_value
|
|
mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state)
|
|
{
|
|
struct protect_data protect_data = { body, data };
|
|
return mrb_protect_error(mrb, protect_body, &protect_data, state);
|
|
}
|
|
|
|
/*
|
|
* Executes a function with guaranteed cleanup (ensure block).
|
|
*
|
|
* @param mrb mruby state
|
|
* @param body Main function to execute
|
|
* @param b_data Data to pass to body function
|
|
* @param ensure Cleanup function that always executes
|
|
* @param e_data Data to pass to ensure function
|
|
* @return Return value from body function
|
|
*
|
|
* This function provides a C API equivalent to Ruby's begin/ensure blocks.
|
|
* The ensure function is guaranteed to execute regardless of whether the
|
|
* body function completes normally or raises an exception. If an exception
|
|
* occurs in the body, it will be re-raised after the ensure block executes.
|
|
*/
|
|
MRB_API mrb_value
|
|
mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data)
|
|
{
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
struct protect_data protect_data = { body, b_data };
|
|
mrb_bool error;
|
|
mrb_value result = mrb_protect_error(mrb, protect_body, &protect_data, &error);
|
|
ensure(mrb, e_data);
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
mrb_gc_protect(mrb, result);
|
|
if (error) {
|
|
mrb_exc_raise(mrb, result); /* rethrow caught exceptions */
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* Executes a function with exception handling for StandardError and its subclasses.
|
|
*
|
|
* @param mrb mruby state
|
|
* @param body Main function to execute
|
|
* @param b_data Data to pass to body function
|
|
* @param rescue Exception handler function
|
|
* @param r_data Data to pass to rescue function
|
|
* @return Return value from body function, or rescue function if StandardError occurred
|
|
*
|
|
* This function provides a C API equivalent to Ruby's begin/rescue blocks that
|
|
* catch StandardError. It's a convenience wrapper around mrb_rescue_exceptions
|
|
* that automatically handles StandardError and its subclasses.
|
|
*/
|
|
MRB_API mrb_value
|
|
mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
|
|
mrb_func_t rescue, mrb_value r_data)
|
|
{
|
|
return mrb_rescue_exceptions(mrb, body, b_data, rescue, r_data, 1, &mrb->eStandardError_class);
|
|
}
|
|
|
|
/*
|
|
* Executes a function with exception handling for specific exception classes.
|
|
*
|
|
* @param mrb mruby state
|
|
* @param body Main function to execute
|
|
* @param b_data Data to pass to body function
|
|
* @param rescue Exception handler function
|
|
* @param r_data Data to pass to rescue function
|
|
* @param len Number of exception classes to handle
|
|
* @param classes Array of exception classes to catch
|
|
* @return Return value from body function, or rescue function if matching exception occurred
|
|
*
|
|
* This function provides a C API equivalent to Ruby's begin/rescue blocks with
|
|
* specific exception class handling. Only exceptions that are instances of the
|
|
* specified classes will be caught; others will be re-raised.
|
|
*/
|
|
MRB_API mrb_value
|
|
mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data,
|
|
mrb_int len, struct RClass **classes)
|
|
{
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
struct protect_data protect_data = { body, b_data };
|
|
mrb_bool error;
|
|
mrb_value result = mrb_protect_error(mrb, protect_body, &protect_data, &error);
|
|
if (error) {
|
|
mrb_bool error_matched = FALSE;
|
|
for (mrb_int i = 0; i < len; i++) {
|
|
if (mrb_obj_is_kind_of(mrb, result, classes[i])) {
|
|
error_matched = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!error_matched) { mrb_exc_raise(mrb, result); }
|
|
|
|
mrb->exc = NULL;
|
|
result = rescue(mrb, r_data);
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
mrb_gc_protect(mrb, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void
|
|
mrb_mruby_error_gem_init(mrb_state *mrb)
|
|
{
|
|
}
|
|
|
|
void
|
|
mrb_mruby_error_gem_final(mrb_state *mrb)
|
|
{
|
|
}
|