Attribute Macro interoptopus::ffi_service_method

source ·
#[ffi_service_method]
Available on crate feature derive only.
Expand description

Inside a #[ffi_service] block, configure the generated FFI helper.

This is an optional attribute that can be applied to some methods.

By default service methods must return a Result<(), Error> return type that will be mapped to an FFIError and transparently checked in languages supporting the pattern. However, sometimes you might want to return an actual value. Using this attribute and specifying an on_panic behavior allows you to opt out of error mapping, and instead return values as-is.

See the service module for an introduction into services.

§Parameters

The following attributes can be provided:

ParameterExplanation
on_panicDetermines what will happen on a panic (ffi_error, return_default, undefined_behavior) and, as a side effect, also determine how return values will be handled. See below.

§Wrapping Behavior

Details what on_panic means:

ModeExplanation
ffi_errorMethod must return Result<(), Error> and maps that to an FFIError. Default behavior.
return_defaultMethod can return any T: Default. If a panic occurs T::default() will be returned, see below.
undefined_behaviorMethod can return any T. If a panic occurs undefined behavior happens. Slightly faster (nanoseconds) and mostly an escape hatch when running into lifetime issues in autogenerated code, e.g., when returning an AsciiPointer from a service. In the long term our proc macro code gen should be fixed to handle this situation.

§Panic Behavior

⚠️ Generated methods add panic guards when used with ffi_error and return_default. However, since return_default methods have no other way to signal errors they will return [Default::default()] instead if a panic is encountered. If you compiled Interoptopus with the log feature a message will be emitted in that case.

§Safety

⚠️ You must ensure that methods marked with on_panic = "undefined_behavior" will never panic. Failure to do so will lead to undefined behavior.

§Example

use interoptopus::{ffi_type, ffi_service, ffi_service_ctor, ffi_service_method};

#[ffi_type(opaque)]
pub struct SimpleService { }

#[ffi_service(error = "MyFFIError", prefix = "simple_service_")]
impl SimpleService {

    #[ffi_service_ctor]
    pub fn new_with(some_value: u32) -> Result<Self, Error> {
        Ok(Self { })
    }

    #[ffi_service_method(on_panic = "return_default")]
    #[allow(unconditional_panic)]
    pub fn oops(&self, x: u32) -> u32 {
        let array = [0, 1, 2];

        // This will panic. The method will return 0 instead.
        array[5]
    }


    #[ffi_service_method(on_panic = "undefined_behavior")]
    pub fn return_value(&self) -> u32 {
        // If this method ever panicked the entire application calling
        // you (not just your library) will crash or worse.
        123
    }

}