Search code examples
javacgraalvm-native-image

How to pass byte array from C to GraalVM native-image Java entrypoint using a void pointer?


I create this entrypoint on the Java side:

    @CEntryPoint(name = "printStruct")
    public static void printStruct(IsolateThread thread, VoidPointer message, int size) {
        System.out.println(message.isNull());
        ByteBuffer buf = CTypeConversion.asByteBuffer(message, size);

        System.out.println(new String(buf.array()));
    }

It's compiled by the GraalVM native-image compiler and libexample.h is generated with:

    void printStruct(graal_isolatethread_t* thread, void* message, int size);

Then I build and run C code:

   int main() {
     graal_isolatethread_t *thread;


     int i = graal_create_isolate(NULL, NULL, &thread);
     if (i != 0) {
       printf("Error creating isolate %d", i);
       return -1;
     }
     printStruct(thread, "heh", 3);
     i = graal_tear_down_isolate(thread);
     if (i != 0) {
       printf("Error tearing down isolate %d", i);
     }

     return 0;
   }

It builds fine but being executed outputs:

  false
  java.lang.UnsupportedOperationException: null
     at java.nio.ByteBuffer.array(ByteBuffer.java:1471)
     at examples.App.printStruct(App.java:26)

I couldn't find any explanation of that. The documentation of asByteArray says:

Creates a ByteBuffer that refers to the native memory at the specified address.

So the message is not a null pointer but I cannot access byte array I passed.


Solution

  • you need to transfer the bytes from the buffer to destination array:

        var buf = CTypeConversion.asByteBuffer(message, size);
        byte[] arr = new byte[buf.remaining()];
        buf.get(arr);