graal icon indicating copy to clipboard operation
graal copied to clipboard

[GR-64789] [Native Image] FFI Bug

Open akashKarmakar02 opened this issue 7 months ago • 4 comments

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.

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

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

akashKarmakar02 avatar Apr 30 '25 16:04 akashKarmakar02

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.

selhagani avatar May 02 '25 12:05 selhagani

https://github.com/akashKarmakar02/graalnative

just run sh build.sh and LD_LIBRARY_PATH=. ./Main

akashKarmakar02 avatar May 02 '25 14:05 akashKarmakar02

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 avatar May 06 '25 14:05 selhagani

@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.

akashKarmakar02 avatar May 09 '25 15:05 akashKarmakar02

@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.

christianhaeubl avatar Jul 09 '25 15:07 christianhaeubl