[GR-64789] [Native Image] FFI Bug
Describe the Issue
When i pass a struct to c function @CStruct annotated interface it's values are garbage
Using the latest version of GraalVM can resolve many issues.
- [x] I tried with the latest version of GraalVM.
GraalVM Version
java version "24" 2025-03-18 Java(TM) SE Runtime Environment Oracle GraalVM 24+36.1 (build 24+36-jvmci-b01) Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 24+36.1 (build 24+36-jvmci-b01, mixed mode, sharing)
Operating System and Version
Linux fedora 6.14.3-300.fc42.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Apr 20 16:08:39 UTC 2025 x86_64 GNU/Linux
Troubleshooting Confirmation
- [x] I tried the suggestions in the troubleshooting guide.
Run Command
native-image -cp . -H:CLibraryPath=$(pwd) -H:IncludeResources=add.h --native-compiler-options="-I$(pwd)" -Ob -jar Main.jar
Expected Behavior
5 Age: 5
Actual Behavior
5 Age: -678812048
Steps to Reproduce
1.create a c function which takes a struct as param 2. pass the struct obj from java 3. print the properties in c and java
Additional Context
java code:
import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.struct.CField;
import org.graalvm.nativeimage.c.struct.CStruct;
import org.graalvm.word.PointerBase;
@CStruct("User")
@CContext(Main.Directives.class)
public interface User extends PointerBase {
@CField("age")
int age();
@CField("age")
void age(int age);
}
User u = StackValue.get(User.class);
u.age(5);
System.out.println(u.age());
print_user(u);
C code:
void print_user(User u) {
printf("Age: %d", u.age);
}
Run-Time Log Output and Error Messages
No response
Hi @akashKarmakar02,
Thank you for reaching out to us.
To be able to reproduce this reliably on my end, could you please provide a more complete reproducer with all the code you used? You could also share all the code in a github repository alongside the steps/commands needed to reproduce the issue you're encountering.
This will help speed up the process on our end. Thank you.
https://github.com/akashKarmakar02/graalnative
just run sh build.sh and LD_LIBRARY_PATH=. ./Main
Thank you for sharing the reproducer. I was able to reproduce the issue on my end. We will take a closer look into this and I'll make sure to keep you updated.
@selhagani Hey, i made some progress if a receive User *user in c then it works. but how can i send normal structs from java.
@CStruct and @CFunction are primarily intended for VM-internal code, so its support is a bit limited. At the moment, there is no way to pass a struct by value. You can work around this limitation, by adding a method to your C code that:
- receives a pointer to the struct
- copies the struct
- and then forwards the copy to C methods that need "struct by value"-semantics
Another option would be to use the Foreign Function & Memory (FFM) API.