Handling Rust Structs in Java

Rust Side

In Rust, a struct is a user-defined type that groups related values. Structs use specific memory layouts, which must match on the Java side. The layout of structs is especially crucial for cross-language bindings because memory misalignment can lead to undefined behavior.

Example Rust Struct:

#![allow(unused)]
fn main() {
#[repr(C)]  // Ensures compatibility with C-style memory layout
struct Point {
    x: i32,
    y: i32,
}
}

Explanation: The #[repr(C)] attribute ensures that the struct is laid out in memory according to the C ABI, which is compatible with Java's FFM API.

Java Side

To use this struct in Java, we need to:

  • Define a StructLayout that matches the Rust struct layout.
  • Use VarHandles to access each struct field.

Example Java Code:

StructLayout pointLayout = MemoryLayout.structLayout(
    ValueLayout.JAVA_INT.withName("x"),  // Maps to Rust's i32 `x`
    ValueLayout.JAVA_INT.withName("y")   // Maps to Rust's i32 `y`
);

VarHandle xHandle = pointLayout.varHandle(PathElement.groupElement("x"));
VarHandle yHandle = pointLayout.varHandle(PathElement.groupElement("y"));

Explanation:

  • ValueLayout.JAVA_INT: This matches Rust’s i32 type.
  • withName("x") and withName("y"): Naming each field lets us retrieve a VarHandle to read and write to specific fields of the MemorySegment that represents the Rust struct.

Allocating and Using the Struct

Allocate Memory: Use an arena to manage the memory allocation.

Access Fields: Access x and y using VarHandles.

var arena = Arena.ofConfined();
MemorySegment pointSegment = arena.allocate(pointLayout);

xHandle.set(pointSegment, 0, 10);  // Set x = 10
yHandle.set(pointSegment, 0, 20);  // Set y = 20

int x = (int) xHandle.get(pointSegment);  // Get x value
int y = (int) yHandle.get(pointSegment);  // Get y value

Explanation:

Arena Allocation: Using an arena (e.g., Arena.ofConfined()) ensures the struct’s memory is safely managed.

Set and Get Values: VarHandle operations allow us to interact with Rust struct fields directly, facilitating cross-language data manipulation.