Skip to content

GreetingSet should not include explicit size on Rust side #4

@mintern

Description

@mintern

First of all, thank you very much for this example project! It really helped me get started on using Rust from Java.

As for the problem, greetings.rs defines GreetingSet as follows:

pub struct GreetingSet {
    // A pointer to an array of Greetings. This is converted to a Greeting.ByReference by JNA.
    greetings: Box<[Greeting]>,
    // The size of the array. We need to pass it back to Java so that we know how long the array
    // is (JNA can't guess the size). We need to do this with all arrays created in Java and read
    // in Rust (or vise-versa). This c_int is converted to a Java int by JNA.
    number_of_greetings: c_int
}

This is actually incorrect. It won't crop up if you have a single GreetingSet, but if you had a contiguous array of them, you would run into problems.

The issue is apparent when you check mem::size_of::<GreetingSet>(). On a 64-bit platform, you probably expect it to be 16: 8 for the pointer, 4 for the int, and another 4 for alignment. If you test it out, though, it will actually be 24!

It turns out that the Box<[Greeting]> is basically a struct, itself: it contains the 8-byte pointer, and an 8-byte usize size field. Then, GreetingSet (as it's currently defined) tacks on a redundant 4-byte size and 4 bytes for alignment. JNA is already reading the size as provided by the Box<[]>, not your number_of_greetings field (you can test it out by putting a junk value in there).

To sum it up, GreetingSet on the Rust side should look like this:

pub struct GreetingSet {
    // A struct that includes a pointer to an array of Greetings and a size. JNA will convert this
    // to two fields: a Greeting.ByReference and an int.
    greetings: Box<[Greeting]>,
}

As the updated comment indicates, the Java code remains the same. You could optionally use a size-dependent type (com.sun.jna.IntegerType?), but Java will break on arrays longer than Integer.MAX_VALUE, anyway.

Without this change, JNA expects GreetingSetto be 16 bytes in length, but as indicated above, it's actually 24 bytes, and this leads to improper alignment if you have a GreetingSet[].

In case it's relevant, I tested this behavior on Rust nightly (1.4).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions