Skip to content

Commit

Permalink
Added the uniffi_forward_scaffolding macro
Browse files Browse the repository at this point in the history
This can be used to work around
[rust-lang#50007](rust-lang/rust#50007), which
is getting to be more and more of an issue on the desktop JS project.
  • Loading branch information
bendk committed Mar 28, 2022
1 parent 12fb0cd commit 156a347
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
33 changes: 33 additions & 0 deletions docs/manual/src/tutorial/Rust_scaffolding.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,36 @@ uniffi_build = { path = "path/to/uniffi-rs/uniffi_build, features=["builtin-bind
Note that `path/to/uniffi-rs` should be the path to the root of the `uniffi`
source tree - ie, the 2 path specs above point to different sub-directories
under the `uniffi` root.

### Libraries that depend on UniFFI components

Suppose you want to create a shared library that includes one or more
components using UniFFI. The typical way to achieve this is to create a new
crate that depends on the component crates. However, this can run into
[rust-lang#50007](https://github.com/rust-lang/rust/issues/50007). Under
certain circumstances, the scaffolding functions that the component crates
export do not get re-exported by the dependent crate.

Use the `uniffi_forward_scaffolding!` macro to work around this issue. If your
library depends on `foo_component`, then add
`foo_component::uniffi_forward_scaffolding!();` to your `lib.rs` file. This
will generate new exported functions that forward to the scaffolding functions
in the dependent crate. The generated code will look something like this:

```rust
#[doc(hidden)]
#[no_mangle]
pub extern "C" fn foo_component_eb69_some_function(
arg1: i64,
arg2: uniffi::RustBuffer,
call_status: &mut uniffi::RustCallStatus
) -> f64 {
foo_component::foo_component_eb69_some_function(arg1, arg2)
}

// ... repeat for each scaffolding function
```

Note that each scaffolding function contains a hash that's derived from the UDL
file. This avoids name collisions when combining multiple UniFFI components
into one library.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Create a macro that can be used by a dependent create to forward all of the scaffolding
// functions defined here. This is used in 2 ways:
//
// - Building libraries that contain multiple UniFFI components (megazord, libxul). The combined
// library can depend on each component then call uniffi_forward_scaffolding!() for each one.
// - Test fixtures. Each binding generator needs to test against the test fixtures. To allow
// this, they call uniffi_forward_scaffolding!() for the test fixture in their test module.
#[macro_export]
macro_rules! uniffi_forward_scaffolding {
() => {
{%- for ffi_func in ci.iter_ffi_function_definitions() %}
pub extern "C" fn {{ ffi_func.name() }}(
{%- call rs::arg_list_ffi_decl(ffi_func) %}
) {% call rs::return_signature_ffi(ffi_func) %} {
$crate::{{ ffi_func.name() }}({% for arg in ffi_func.arguments() %}{{ arg.name() }}, {% endfor %}callStatus)
}
{% endfor -%}
};
}
4 changes: 2 additions & 2 deletions uniffi_bindgen/src/scaffolding/templates/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@
{%- endif %}
{%- endmacro -%}

{% macro return_signature(func) %}{% match func.ffi_func().return_type() %}{% when Some with (return_type) %} -> {% call return_type_func(func) %}{%- else -%}{%- endmatch -%}{%- endmacro -%}
{% macro return_signature(func) %}{% call return_signature_ffi(func.ffi_func()) %}{% endmacro %}

{% macro return_type_func(func) %}{% match func.ffi_func().return_type() %}{% when Some with (return_type) %}{{ return_type|type_ffi }}{%- else -%}(){%- endmatch -%}{%- endmacro -%}
{% macro return_signature_ffi(ffi_func) %}{% match ffi_func.return_type() %}{% when Some with (return_type) %} -> {{ return_type|type_ffi }}{%- else -%}{%- endmatch -%}{%- endmacro -%}

{% macro ret(func) %}{% match func.return_type() %}{% when Some with (return_type) %}{{ return_type|ffi_converter }}::lower(_retval){% else %}_retval{% endmatch %}{% endmacro %}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,7 @@ uniffi::assert_compatible_version!("{{ uniffi_version }}"); // Please check that
// External and Wrapped types
{% include "ExternalTypesTemplate.rs" %}

// The `forward_uniffi_scaffolding` macro
{% include "ForwardUniFFIScaffolding.rs" %}

{%- import "macros.rs" as rs -%}

0 comments on commit 156a347

Please sign in to comment.