Skip to content
← All Rust tracks

Macros, FFI and Type-Driven Design

Rust

Generate code with declarative macros, call C interfaces, and use types to express API constraints. Learn the limits and responsibilities of each approach.

This track uses Rust. You can make it your practice mode to browse related content across the site.

20 exercises

8 articles

Explore freely. Sign in to keep your progress.

Your learning sequence

  1. 1 Why macros exist: code that writes code Read
  2. 2 Not solved yet. Your first macro_rules!: matchers and transcribers Practice · Easy
  3. 3 Not solved yet. Classify syntax with macro fragment specifiers Practice · Medium
  4. 4 Not solved yet. Preserve expression grouping in a macro Practice · Medium
  5. 5 Not solved yet. Macro repetition: lists and repeated values Practice · Easy
  6. 6 Not solved yet. Nested repetition and zipping metavariables Practice · Hard
  7. 7 Not solved yet. Count macro arguments with stable Rust Practice · Medium
  8. 8 Not solved yet. Macro recursion and incremental TT munchers Practice · Hard
  9. 9 Not solved yet. Accumulate enum variants in a recursive macro Practice · Hard
  10. 10 Not solved yet. Macro callbacks and token-tree bundles Practice · Hard
  11. 11 Not solved yet. Macro hygiene: why your variable didn't leak Practice · Medium
  12. 12 Not solved yet. Follow-set rules: why the compiler rejects your matcher Practice · Hard
  13. 13 Debugging macros when expansion goes wrong Read
  14. 14 Not solved yet. Build vector, pattern-matching and map macros Practice · Medium
  15. 15 Not solved yet. A mini DSL: compile-time expression evaluation Practice · Hard
  16. 16 The real limits of macro_rules! Read
  17. 17 Procedural macros: the three kinds Read
  18. 18 Read the code behind derives and attribute macros Read
  19. 19 Function-like proc macros and proc-macro hygiene Read
  20. 20 Choosing between generics and macros Read
  21. 21 What an ABI is, and why FFI exists Read
  22. 22 Not solved yet. Calling C functions through safe Rust wrappers Practice · Medium
  23. 23 Not solved yet. Edition 2024: unsafe extern blocks and safe declarations Practice · Medium
  24. 24 Not solved yet. Export Rust functions with C-compatible names and signatures Practice · Hard
  25. 25 Not solved yet. C strings and ownership across FFI Practice · Medium
  26. 26 Not solved yet. Nullable pointer optimization, callbacks and qsort Practice · Hard
  27. 27 Not solved yet. Opaque handles and bounded C formatting Practice · Hard
  28. 28 Not solved yet. Type-driven design: newtypes, smart constructors, builders, typestate Practice · Hard

Check yourself

4 questions · not saved while you're signed out

Use these questions to check your understanding and compare explanations. Your score does not affect track completion.

0 / 4 correct

What does repr(C) provide for Point when matching the C struct shown in the comment?

Choose one answer to reveal the explanations. Answers are kept only while this page is open.

// C counterpart: struct Point { int32_t x; int32_t y; };
#[repr(C)]
pub struct Point {
    pub x: i32,
    pub y: i32,
}

unsafe extern "C" {
    pub fn takes(point: Point);
}

fn main() {
    println!("size: {}", std::mem::size_of::<Point>());
    println!("y offset: {}", std::mem::offset_of!(Point, y));
}
Question 1 of 4