GSoC Rust UNO API Weekly Update

Mohmed Ali mohmedali1462005 at gmail.com
Thu Jun 12 12:19:40 UTC 2025


Hi all,

I’ll outline our chosen strategy for the Rust–UNO binding project, explain
why we’ve settled on raw FFI against the C UNO API, and show our
implementation plan—starting with the very first tasks we’ll tackle.

*Why We Chose Raw FFI*
We have chosen to build our Rust–UNO bindings by using the C UNO API
directly through raw FFI instead of using cxx.rs or other interop tools.
Working with the stable C interface makes our build process easier— avoids
the MSVC build errors we saw with recent cxx versions. While this method
means writing more manual code to wrap C structs and manage lifetimes, it
gives us full control over memory safety and future updates, making
maintenance easier down the road.


*Evaluation of cxx.rs <http://cxx.rs>*
During our review, we found three main problems with cxx.rs. First, mapping
UNO’s complicated inheritance structures and heavy use of templates (like
Reference<T> and container types) was awkward in Rust’s trait system and cxx’s
setup. Second, important C++ features—many types don’t translate cleanly
into Rust, leading to fragile wrappers or extra layers. In contrast, Rust’s
FFI tools (like bindgen) are well known and reliable.

*Implementation Plan*


   1. *Bindgen Generation*
   Our very first task is to run bindgen against the primary UNO C headers
   (e.g., core API headers). This will automatically generate Rust functions,
   structs, and enum definitions matching the C signatures. We’ll review the
   generated code, prune any unnecessary items, and ensure the bindings
   compile cleanly on all target platforms. This gives us a complete low-level
   foundation—every UNO function and type we need will already exist in Rust,
   albeit in an unsafe form.

   2. *Safe Wrapper Layer*
   UNO’s C API relies on manual reference counting via functions like
   uno_Reference_addRef and uno_Reference_release. We’ll encapsulate that
   in Rust smart-pointer types—perhaps UnoRef<T>—that call the appropriate
   add/release functions in their Clone and Drop implementations. This
   mimics UNO’s Reference<T> semantics and ensures that Rust’s ownership
   rules align with UNO’s lifetime model, all while preserving zero-cost
   performance.

   3.
*Incremental Testing *Testing happens at every stage. Right after bindgen,
   we’ll write small build-only tests to check that each raw binding compiles
   and links. After the safe wrapper layer is in place, we’ll call our
   embindtest FFI service to verify primitive types (integers, floats,
   strings) and container types (arrays, sequences) behave correctly. Finally,
   once smart pointers and ergonomic APIs are ready, we’ll write integration
   tests against a real UNO service—ensuring end-to-end functionality. This
   step-by-step validation ensures we catch issues early and keep confidence
   high as the project grows.

Best,
Mohamed Ali
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/libreoffice/attachments/20250612/c87480fd/attachment.htm>


More information about the LibreOffice mailing list