-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Always use
uniffi_macros
to generate callback interface scaffolding
This makes it so the scaffolding templates use `export_for_udl` rather than generating their own code.
- Loading branch information
Showing
5 changed files
with
23 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 14 additions & 79 deletions
93
uniffi_bindgen/src/scaffolding/templates/CallbackInterfaceTemplate.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,17 @@ | ||
{# | ||
// For each Callback Interface definition, we assume that there is a corresponding trait defined in Rust client code. | ||
// If the UDL callback interface and Rust trait's methods don't match, the Rust compiler will complain. | ||
// We generate: | ||
// * an init function to accept that `ForeignCallback` from the foreign language, and stores it. | ||
// * a holder for a `ForeignCallback`, of type `uniffi::ForeignCallbackInternals`. | ||
// * a proxy `struct` which implements the `trait` that the Callback Interface corresponds to. This | ||
// is the object that client code interacts with. | ||
// - for each method, arguments will be packed into a `RustBuffer` and sent over the `ForeignCallback` to be | ||
// unpacked and called. The return value is packed into another `RustBuffer` and sent back to Rust. | ||
// - a `Drop` `impl`, which tells the foreign language to forget about the real callback object. | ||
#} | ||
{% let trait_name = cbi.name() -%} | ||
{% let trait_impl = format!("UniFFICallbackHandler{}", trait_name) %} | ||
{% let foreign_callback_internals = format!("foreign_callback_{}_internals", trait_name)|upper -%} | ||
|
||
// Register a foreign callback for getting across the FFI. | ||
#[doc(hidden)] | ||
static {{ foreign_callback_internals }}: uniffi::ForeignCallbackInternals = uniffi::ForeignCallbackInternals::new(); | ||
|
||
#[doc(hidden)] | ||
#[no_mangle] | ||
pub extern "C" fn {{ cbi.ffi_init_callback().name() }}(callback: uniffi::ForeignCallback, _: &mut uniffi::RustCallStatus) { | ||
{{ foreign_callback_internals }}.set_callback(callback); | ||
// The call status should be initialized to CALL_SUCCESS, so no need to modify it. | ||
} | ||
|
||
// Make an implementation which will shell out to the foreign language. | ||
#[doc(hidden)] | ||
#[derive(Debug)] | ||
struct {{ trait_impl }} { | ||
handle: u64 | ||
} | ||
|
||
impl {{ trait_impl }} { | ||
fn new(handle: u64) -> Self { | ||
Self { handle } | ||
} | ||
} | ||
|
||
impl Drop for {{ trait_impl }} { | ||
fn drop(&mut self) { | ||
{{ foreign_callback_internals }}.invoke_callback::<(), crate::UniFfiTag>( | ||
self.handle, uniffi::IDX_CALLBACK_FREE, Default::default() | ||
) | ||
} | ||
} | ||
|
||
uniffi::deps::static_assertions::assert_impl_all!({{ trait_impl }}: ::core::marker::Send); | ||
|
||
impl r#{{ trait_name }} for {{ trait_impl }} { | ||
#[::uniffi::export_for_udl(callback_interface)] | ||
pub trait r#{{ cbi.name() }} { | ||
{%- for meth in cbi.methods() %} | ||
|
||
{#- Method declaration #} | ||
fn r#{{ meth.name() -}} | ||
({% call rs::arg_list_decl_with_prefix("&self", meth) %}) | ||
{%- match (meth.return_type(), meth.throws_type()) %} | ||
{%- when (Some(return_type), None) %} -> {{ return_type.borrow()|type_rs }} | ||
{%- when (Some(return_type), Some(err)) %} -> ::std::result::Result<{{ return_type.borrow()|type_rs }}, {{ err|type_rs }}> | ||
{%- when (None, Some(err)) %} -> ::std::result::Result<(), {{ err|type_rs }}> | ||
{% else -%} | ||
{%- endmatch -%} { | ||
{#- Method body #} | ||
|
||
{#- Packing args into a RustBuffer #} | ||
{% if meth.arguments().len() == 0 -%} | ||
let args_buf = Vec::new(); | ||
{% else -%} | ||
let mut args_buf = Vec::new(); | ||
{% endif -%} | ||
fn r#{{ meth.name() }}( | ||
{% if meth.takes_self_by_arc()%}self: Arc<Self>{% else %}&self{% endif %}, | ||
{%- for arg in meth.arguments() %} | ||
{{ arg.as_type().borrow()|ffi_trait("Lower") }}::write(r#{{ arg.name() }}, &mut args_buf); | ||
{%- endfor -%} | ||
let args_rbuf = uniffi::RustBuffer::from_vec(args_buf); | ||
|
||
{#- Calling into foreign code. #} | ||
{{ foreign_callback_internals }}.invoke_callback::<{{ meth|return_type }}, crate::UniFfiTag>(self.handle, {{ loop.index }}, args_rbuf) | ||
} | ||
{%- endfor %} | ||
r#{{ arg.name() }}: {% if arg.by_ref() %}&{% endif %}{{ arg.as_type().borrow()|type_rs }}, | ||
{%- endfor %} | ||
) | ||
{%- match (meth.return_type(), meth.throws_type()) %} | ||
{%- when (Some(return_type), None) %} -> {{ return_type|type_rs }}; | ||
{%- when (Some(return_type), Some(error_type)) %} -> ::std::result::Result::<{{ return_type|type_rs }}, {{ error_type|type_rs }}>; | ||
{%- when (None, Some(error_type)) %} -> ::std::result::Result::<(), {{ error_type|type_rs }}>; | ||
{%- when (None, None) %}; | ||
{%- endmatch %} | ||
{% endfor %} | ||
} | ||
|
||
::uniffi::scaffolding_ffi_converter_callback_interface!(r#{{ trait_name }}, {{ trait_impl }}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters