SlideShare a Scribd company logo
Interface Oxidation
Razvan Rotari
FFI
● Rust FFI uses C ABI
● Rust ABI is not standardized
● C++ ABI is not standardized
C -> Rust
C
int oxidize(int i);
int ret = oxidize(42);
Rust
#[no_mangle]
pub extern "C" fn oxidize(i: i32) -> i32 {
println!("Oxidize {}", i);
i+1
}
How to automate this?
How crates work
● Package manager concept (cargo)
● A crate is the way to package a module
● Can generate executable and libraries
● Can contain subfolders
● Handles the dependencies using cargo
● Compile-time scripting
ROOT
src
lib.rs # entry point for libs
main.rs # entry point for exe
Cargo.toml
Build.rs - run at compile-time
CBindgen
● Generates C or C++ headers that wraps the Rust code
● Functions need to be annotated with #[no_mangle]
● Types need to be annotated with #[repr(C)]
● Does not handle all cases
● Can be run standalone or at compile time
CBindgen
C
typedef struct TestStruct {
int32_t age;
} TestStruct;
typedef enum TestEnum_Tag{
TestEnum_First,
TestEnum_Second,
TestEnum_Empty,
} TestEnum_Tag;
typedef struct TestEnum{
TestEnum_Tag tag;
union {
struct{
int32_t first;
};
struct { float second; }; };
} TestEnum;
Rust
#[repr(C)]
pub struct TestStruct{
age: i32,
}
#[repr(C)]
pub enum TestEnum{
First(i32),
Second(f32),
Empty,
}
Rust -> C
C
int call_me(int i);
Rust
extern “C” {
fn call_me(i:i32) -> i32;
}
fn main() {
let ret = call_me(42);
}
Bindgen
● Parses the C headers and generates Rust wrappers.
● Run at compile time or as standalone application.
● Convention is to make a new crate with the suffix -sys for each lib. Ex. openssl-sys
● Recommended to create a C header in the crate as the starting point.
● Can handle C++ to some extent.
● Define macros are converted in constants
● Function macros are ignored
● Templates are ignored
Bindgen
lib.rs
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!("bindings.rs");
build.rs
let bindings = bindgen::Builder::default()
.header("wrapper.hpp")
.clang_arg("-I../../src")
.generate();
bindings.write_to_file("bindings.rs");
println!("cargo:rerun-if-changed=wrapper.hpp");
Error handling
● Safe Rust does not have NULL, instead uses Optional<T>.
● Rust has pointers, but operation needs to be done in unsafe code.
● For error handling Rust uses Result<T,E>, where E is the error type.
● Rust has something similar to exceptions called panic. Are used only in
specific cases for fatal errors.
● C++ uses exceptions and return codes.
● Panics and exceptions are not compatible.
● Exceptions MUST NOT cross the FFI boundary
● Use a common logging system. Most rust logging crates provide a way to
write custom adaptors.
Error handling - Exceptions to Result
1. Parse C++ headers using `clang -Xclang -fsyntax-only –ast-dump=json`
2. For each possible return type create a variant that contains the return type
and the exception in C
3. In Rust for each variant write conversion functions to Result<T,E>
4. For each function generate a wrapper that catches the exception and
converts it to the variant in C
5. Generate Rust bindings only for the wrappers
Error handling - Result to Exceptions
1. Parse Rust code using `syn` crate
2. For each possible Result used generate in Rust a variant that can be created
from a Result
3. For each function generate in Rust a wrapper that calls the functions and
converts the result to the variant.
4. For each wrapper generate in C++ another wrapper that converts the variant
to an exception
Callbacks
● Hard to wrap.
● Easy to throw exceptions in the middle of that code.
● Either write them with care or create a wrapper that handles all the error
handling.
● Thread safety
● Use the ‘user data’ pattern when posibile.
Issues
● Different C/C++ compilers use different underlying types for common types.
● char might be signed or unsigned, 1 byte or 4 bytes.
● Use fixed sized type when possible.
● Calling convention might be different.
● Make sure the generated code uses the same compiler flags as the normal
one
● Rust might use different allocator then C code, so freeing needs to be
handled in the same code base.
● Rust strings are UTF-8 and are not NULL terminated. Conversions need to be
done using the CString/&cstr classes.
Good news
● Gdb and rr can works with both languages at the same time.
● Backtraces will make sense.
● ‘Go-to definition’ feature will work in your IDE.
Questions?
● https://doc.rust-lang.org/nomicon/ffi.html
● https://docs.rs/syn/latest/syn/
● https://github.com/eqrion/cbindgen/tree/master
● https://rust-lang.github.io/rust-bindgen/
● https://nrc.github.io/error-docs

More Related Content

PPTX
A Slice Of Rust - A quick look at the Rust programming language
PDF
Embedded Rust
PDF
Writing Rust Command Line Applications
PDF
Intro to Rust 2019
PPTX
Introduction to Ruby Native Extensions and Foreign Function Interface
PDF
Short intro to the Rust language
PPTX
Rust vs C++
PDF
OS_Compilation_Makefile_kt4jerb34834343553
A Slice Of Rust - A quick look at the Rust programming language
Embedded Rust
Writing Rust Command Line Applications
Intro to Rust 2019
Introduction to Ruby Native Extensions and Foreign Function Interface
Short intro to the Rust language
Rust vs C++
OS_Compilation_Makefile_kt4jerb34834343553

Similar to Interface Oxidation (20)

PPTX
Auto-Generating Language-Specific Wrappers for Rust Libraries
PDF
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
PDF
Intro to introducing rust to ruby
PDF
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016
PDF
Rust and Eclipse
PDF
Rust Type Layout - Binary Compatibility 2023-02-23
PPTX
Pyconke2018
PDF
Rusted Ruby
PPTX
Introduction to Rust (Presentation).pptx
PPTX
MozillaPH Rust Hack & Learn Session 1
PDF
Rust All Hands Winter 2011
PDF
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
PDF
Building a Cross-Platform Mobile SDK in Rust.pdf
PDF
Compiler design notes phases of compiler
PDF
Embedded Systems: Lecture 13: Introduction to GNU Toolchain (Build Tools)
PDF
C言語静的解析ツールと Ruby 1.9 trunk
PDF
How to write rust instead of c and get away with it
PDF
Rust + python: lessons learnt from building a toy filesystem
PDF
Rust LDN 24 7 19 Oxidising the Command Line
Auto-Generating Language-Specific Wrappers for Rust Libraries
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Intro to introducing rust to ruby
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016
Rust and Eclipse
Rust Type Layout - Binary Compatibility 2023-02-23
Pyconke2018
Rusted Ruby
Introduction to Rust (Presentation).pptx
MozillaPH Rust Hack & Learn Session 1
Rust All Hands Winter 2011
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
Building a Cross-Platform Mobile SDK in Rust.pdf
Compiler design notes phases of compiler
Embedded Systems: Lecture 13: Introduction to GNU Toolchain (Build Tools)
C言語静的解析ツールと Ruby 1.9 trunk
How to write rust instead of c and get away with it
Rust + python: lessons learnt from building a toy filesystem
Rust LDN 24 7 19 Oxidising the Command Line
Ad

More from Ovidiu Farauanu (13)

PDF
SIMD with C++ 26 by Alexandru Pentilescu
PDF
Introduction to C++20 Coroutines by Alex P
PDF
Interfacing C++ with Python to boost your legacy apps with Python interfaces
PDF
Back in Business with C++
PDF
Optimization of the build times using Conan
PDF
Bind me if you can
PDF
Distributed Cache, bridging C++ to new technologies (Hazelcast)
PPTX
Monadic Computations in C++14
PDF
Domain Specific Languages and C++ Code Generation
PDF
Florentin Picioroaga - C++ by choice
PDF
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
PDF
High Order Function Computations in c++14 (C++ Dev Meetup Iasi)
PDF
Cap'n Proto (C++ Developer Meetup Iasi)
SIMD with C++ 26 by Alexandru Pentilescu
Introduction to C++20 Coroutines by Alex P
Interfacing C++ with Python to boost your legacy apps with Python interfaces
Back in Business with C++
Optimization of the build times using Conan
Bind me if you can
Distributed Cache, bridging C++ to new technologies (Hazelcast)
Monadic Computations in C++14
Domain Specific Languages and C++ Code Generation
Florentin Picioroaga - C++ by choice
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
High Order Function Computations in c++14 (C++ Dev Meetup Iasi)
Cap'n Proto (C++ Developer Meetup Iasi)
Ad

Recently uploaded (20)

PDF
STL Containers in C++ : Sequence Container : Vector
PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PDF
Cost to Outsource Software Development in 2025
PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
PPTX
Introduction to Windows Operating System
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
Time Tracking Features That Teams and Organizations Actually Need
PPTX
Trending Python Topics for Data Visualization in 2025
PPTX
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PDF
Types of Token_ From Utility to Security.pdf
PDF
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
How Tridens DevSecOps Ensures Compliance, Security, and Agility
PDF
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
PPTX
Computer Software and OS of computer science of grade 11.pptx
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
STL Containers in C++ : Sequence Container : Vector
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
Oracle Fusion HCM Cloud Demo for Beginners
Why Generative AI is the Future of Content, Code & Creativity?
Cost to Outsource Software Development in 2025
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
Introduction to Windows Operating System
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Time Tracking Features That Teams and Organizations Actually Need
Trending Python Topics for Data Visualization in 2025
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
wealthsignaloriginal-com-DS-text-... (1).pdf
Monitoring Stack: Grafana, Loki & Promtail
Types of Token_ From Utility to Security.pdf
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
How Tridens DevSecOps Ensures Compliance, Security, and Agility
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
Computer Software and OS of computer science of grade 11.pptx
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf

Interface Oxidation

  • 2. FFI ● Rust FFI uses C ABI ● Rust ABI is not standardized ● C++ ABI is not standardized
  • 3. C -> Rust C int oxidize(int i); int ret = oxidize(42); Rust #[no_mangle] pub extern "C" fn oxidize(i: i32) -> i32 { println!("Oxidize {}", i); i+1 }
  • 5. How crates work ● Package manager concept (cargo) ● A crate is the way to package a module ● Can generate executable and libraries ● Can contain subfolders ● Handles the dependencies using cargo ● Compile-time scripting ROOT src lib.rs # entry point for libs main.rs # entry point for exe Cargo.toml Build.rs - run at compile-time
  • 6. CBindgen ● Generates C or C++ headers that wraps the Rust code ● Functions need to be annotated with #[no_mangle] ● Types need to be annotated with #[repr(C)] ● Does not handle all cases ● Can be run standalone or at compile time
  • 7. CBindgen C typedef struct TestStruct { int32_t age; } TestStruct; typedef enum TestEnum_Tag{ TestEnum_First, TestEnum_Second, TestEnum_Empty, } TestEnum_Tag; typedef struct TestEnum{ TestEnum_Tag tag; union { struct{ int32_t first; }; struct { float second; }; }; } TestEnum; Rust #[repr(C)] pub struct TestStruct{ age: i32, } #[repr(C)] pub enum TestEnum{ First(i32), Second(f32), Empty, }
  • 8. Rust -> C C int call_me(int i); Rust extern “C” { fn call_me(i:i32) -> i32; } fn main() { let ret = call_me(42); }
  • 9. Bindgen ● Parses the C headers and generates Rust wrappers. ● Run at compile time or as standalone application. ● Convention is to make a new crate with the suffix -sys for each lib. Ex. openssl-sys ● Recommended to create a C header in the crate as the starting point. ● Can handle C++ to some extent. ● Define macros are converted in constants ● Function macros are ignored ● Templates are ignored
  • 10. Bindgen lib.rs #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] include!("bindings.rs"); build.rs let bindings = bindgen::Builder::default() .header("wrapper.hpp") .clang_arg("-I../../src") .generate(); bindings.write_to_file("bindings.rs"); println!("cargo:rerun-if-changed=wrapper.hpp");
  • 11. Error handling ● Safe Rust does not have NULL, instead uses Optional<T>. ● Rust has pointers, but operation needs to be done in unsafe code. ● For error handling Rust uses Result<T,E>, where E is the error type. ● Rust has something similar to exceptions called panic. Are used only in specific cases for fatal errors. ● C++ uses exceptions and return codes. ● Panics and exceptions are not compatible. ● Exceptions MUST NOT cross the FFI boundary ● Use a common logging system. Most rust logging crates provide a way to write custom adaptors.
  • 12. Error handling - Exceptions to Result 1. Parse C++ headers using `clang -Xclang -fsyntax-only –ast-dump=json` 2. For each possible return type create a variant that contains the return type and the exception in C 3. In Rust for each variant write conversion functions to Result<T,E> 4. For each function generate a wrapper that catches the exception and converts it to the variant in C 5. Generate Rust bindings only for the wrappers
  • 13. Error handling - Result to Exceptions 1. Parse Rust code using `syn` crate 2. For each possible Result used generate in Rust a variant that can be created from a Result 3. For each function generate in Rust a wrapper that calls the functions and converts the result to the variant. 4. For each wrapper generate in C++ another wrapper that converts the variant to an exception
  • 14. Callbacks ● Hard to wrap. ● Easy to throw exceptions in the middle of that code. ● Either write them with care or create a wrapper that handles all the error handling. ● Thread safety ● Use the ‘user data’ pattern when posibile.
  • 15. Issues ● Different C/C++ compilers use different underlying types for common types. ● char might be signed or unsigned, 1 byte or 4 bytes. ● Use fixed sized type when possible. ● Calling convention might be different. ● Make sure the generated code uses the same compiler flags as the normal one ● Rust might use different allocator then C code, so freeing needs to be handled in the same code base. ● Rust strings are UTF-8 and are not NULL terminated. Conversions need to be done using the CString/&cstr classes.
  • 16. Good news ● Gdb and rr can works with both languages at the same time. ● Backtraces will make sense. ● ‘Go-to definition’ feature will work in your IDE.
  • 18. ● https://doc.rust-lang.org/nomicon/ffi.html ● https://docs.rs/syn/latest/syn/ ● https://github.com/eqrion/cbindgen/tree/master ● https://rust-lang.github.io/rust-bindgen/ ● https://nrc.github.io/error-docs