mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-08 13:48:26 +00:00
test+doc(c-api) Add a complete test for errors + improve the documentation.
This commit is contained in:
@@ -1,4 +1,51 @@
|
||||
//! Read runtime errors.
|
||||
//! Utilities to read errors.
|
||||
//!
|
||||
//! Only one error can be registered at a time. Error are registered
|
||||
//! by Rust only, and are usually read by C or C++.
|
||||
//!
|
||||
//! Reading an error from C or C++ happens in 2 steps: Getting the
|
||||
//! error's length with [`wasmer_last_error_length`], and then reading
|
||||
//! the actual error with [`wasmer_last_error_message`].
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use inline_c::assert_c;
|
||||
//! # fn main() {
|
||||
//! # (assert_c! {
|
||||
//! # #include "tests/wasmer_wasm.h"
|
||||
//! #
|
||||
//! int main() {
|
||||
//! // Create an invalid WebAssembly module from a WAT definition,
|
||||
//! // it will generate an error!
|
||||
//! wasm_byte_vec_t wat;
|
||||
//! wasmer_byte_vec_new_from_string(&wat, "(foobar)");
|
||||
//! wasm_byte_vec_t wasm;
|
||||
//! wat2wasm(&wat, &wasm);
|
||||
//!
|
||||
//! int error_length = wasmer_last_error_length();
|
||||
//!
|
||||
//! // There is an error!
|
||||
//! assert(error_length > 0);
|
||||
//!
|
||||
//! char *error_message = malloc(error_length);
|
||||
//! wasmer_last_error_message(error_message, error_length);
|
||||
//! printf("Error message: %s\n", error_message);
|
||||
//!
|
||||
//! // Side note: The error has now been cleared on the Rust side!
|
||||
//! assert(wasmer_last_error_length() == 0);
|
||||
//!
|
||||
//! // Free everything.
|
||||
//! free(error_message);
|
||||
//! wasm_byte_vec_delete(&wasm);
|
||||
//! wasm_byte_vec_delete(&wat);
|
||||
//!
|
||||
//! return 0;
|
||||
//! }
|
||||
//! # })
|
||||
//! # .success();
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
use libc::{c_char, c_int};
|
||||
use std::cell::RefCell;
|
||||
@@ -11,6 +58,17 @@ thread_local! {
|
||||
static LAST_ERROR: RefCell<Option<Box<dyn Error>>> = RefCell::new(None);
|
||||
}
|
||||
|
||||
/// Rust function to register a new error.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use wasmer_c_api::error::{update_last_error, CApiError};
|
||||
///
|
||||
/// update_last_error(CApiError {
|
||||
/// msg: "Hello, World!".to_string(),
|
||||
/// });
|
||||
/// ```
|
||||
pub fn update_last_error<E: Error + 'static>(err: E) {
|
||||
LAST_ERROR.with(|prev| {
|
||||
*prev.borrow_mut() = Some(Box::new(err));
|
||||
@@ -22,12 +80,14 @@ pub(crate) fn take_last_error() -> Option<Box<dyn Error>> {
|
||||
LAST_ERROR.with(|prev| prev.borrow_mut().take())
|
||||
}
|
||||
|
||||
/// Gets the length in bytes of the last error if any.
|
||||
/// Gets the length in bytes of the last error if any, zero otherwise.
|
||||
///
|
||||
/// This can be used to dynamically allocate a buffer with the correct number of
|
||||
/// bytes needed to store a message.
|
||||
///
|
||||
/// See `wasmer_last_error_message()` to get a full example.
|
||||
/// # Example
|
||||
///
|
||||
/// See this module's documentation to get a complete example.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_last_error_length() -> c_int {
|
||||
LAST_ERROR.with(|prev| match *prev.borrow() {
|
||||
@@ -41,29 +101,23 @@ pub extern "C" fn wasmer_last_error_length() -> c_int {
|
||||
///
|
||||
/// The `length` parameter must be large enough to store the last
|
||||
/// error message. Ideally, the value should come from
|
||||
/// `wasmer_last_error_length()`.
|
||||
/// [`wasmer_last_error_length`].
|
||||
///
|
||||
/// The function returns the length of the string in bytes, `-1` if an
|
||||
/// error occurs. Potential errors are:
|
||||
///
|
||||
/// * The buffer is a null pointer,
|
||||
/// * The buffer is too small to hold the error message.
|
||||
/// * The `buffer` is a null pointer,
|
||||
/// * The `buffer` is too small to hold the error message.
|
||||
///
|
||||
/// Note: The error message always has a trailing NUL character.
|
||||
///
|
||||
/// Example:
|
||||
/// Important note: If the provided `buffer` is non-null, once this
|
||||
/// function has been called, regardless whether it fails or succeeds,
|
||||
/// the error is cleared.
|
||||
///
|
||||
/// ```c
|
||||
/// int error_length = wasmer_last_error_length();
|
||||
/// # Example
|
||||
///
|
||||
/// if (error_length > 0) {
|
||||
/// char *error_message = malloc(error_length);
|
||||
/// wasmer_last_error_message(error_message, error_length);
|
||||
/// printf("Error message: `%s`\n", error_message);
|
||||
/// } else {
|
||||
/// printf("No error message\n");
|
||||
/// }
|
||||
/// ```
|
||||
/// See this module's documentation to get a complete example.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_last_error_message(
|
||||
buffer: Option<NonNull<c_char>>,
|
||||
@@ -103,8 +157,10 @@ pub unsafe extern "C" fn wasmer_last_error_message(
|
||||
error_message.len() as c_int + 1
|
||||
}
|
||||
|
||||
/// Rust type to represent a C API error.
|
||||
#[derive(Debug)]
|
||||
pub struct CApiError {
|
||||
/// The error message.
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user