<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Athena&#x27;s Parthenon - UniFFI</title>
    <subtitle>Athena&#x27;s Parthenon</subtitle>
    <link rel="self" type="application/atom+xml" href="https://parthen.online/topics/uniffi/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://parthen.online"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-04-26T00:00:00+00:00</updated>
    <id>https://parthen.online/topics/uniffi/atom.xml</id>
    <entry xml:lang="en">
        <title>Java&#x27;s Functional Interfaces for Rust&#x2F;UniFFI</title>
        <published>2026-04-26T00:00:00+00:00</published>
        <updated>2026-04-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Athena
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://parthen.online/notes/rust-uniffi-functional-interface/"/>
        <id>https://parthen.online/notes/rust-uniffi-functional-interface/</id>
        
        <content type="html" xml:base="https://parthen.online/notes/rust-uniffi-functional-interface/">&lt;h2 id=&quot;functional-interfaces&quot;&gt;Functional Interfaces&lt;&#x2F;h2&gt;
&lt;p&gt;UniFFI has good support for callback interfaces, allowing calling code to supply its own logic
to be called from Rust. How to make this work on the other-language side was relatively obvious
to me: you just implement the interface. However, how to make this smooth in Rust took a moment to
figure out, so I figured I&#x27;d make a note.&lt;&#x2F;p&gt;
&lt;p&gt;A UniFFI callback interface looks (using the proc macros) like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #EBDBB2); background-color: light-dark(#FFFFFF, #1D2021);&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;uniffi&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;callback_interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FE8019);&quot;&gt; trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; MyCallback&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; Sync&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; consume&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #83A598);&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #83A598);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; MyValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(where &lt;code&gt;MyValue&lt;&#x2F;code&gt; has &lt;code&gt;#[uniffi::export]&lt;&#x2F;code&gt; as well)&lt;&#x2F;p&gt;
&lt;p&gt;and some function which takes it (boxed, because we can&#x27;t know the implementing type at compile
time, so it&#x27;s gotta be a &lt;code&gt;dyn&lt;&#x2F;code&gt; rather than being able to use a generic&#x2F;&lt;code&gt;impl Trait&lt;&#x2F;code&gt;) like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #EBDBB2); background-color: light-dark(#FFFFFF, #1D2021);&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;uniffi&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; do_it&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #83A598);&quot;&gt;doer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; MyCallback&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #83A598);&quot;&gt;  doer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt;consume&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #83A598);&quot;&gt;some_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which is all well and good. But using this from Rust is a bit of a pain - there&#x27;s just one method,
so it should be possible to just yunk in a closure. But if you wanna do that you gotta tell Rust
that&#x27;s okay, it doesn&#x27;t infer it like Java&#x27;s functional interfaces. Here&#x27;s how you do that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #EBDBB2); background-color: light-dark(#FFFFFF, #1D2021);&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; MyCallback&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; Fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt;MyValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; Sync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;  fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; consume&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #83A598);&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #83A598);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt; MyValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #83A598);&quot;&gt;    self&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #83A598);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Getting the syntax right on this took a sec but it&#x27;s fairly self-explanatory if you&#x27;re used to Rust.
I also went down a road of trying to use &lt;code&gt;impl From&lt;&#x2F;code&gt;, which doesn&#x27;t really work out (try it
yourself if you want to know why). Anyway, now you can call &lt;code&gt;do_it&lt;&#x2F;code&gt; from Rust and give it a boxed,
but otherwise plain, closure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #EBDBB2); background-color: light-dark(#FFFFFF, #1D2021);&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt;do_it&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #8EC07C);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #FABD2F);&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #83A598);&quot;&gt;_it&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #FB4934);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #A89984);&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
</feed>
