graalvm / graalvm-website

GraalVM: Run Programs Faster Anywhere 🚀
https://www.graalvm.org
8 stars 9 forks source link

Add example using native image C API #12

Open nirvdrum opened 2 years ago

nirvdrum commented 2 years ago

The Native Image C API doc introduce the set of functions for managing GraalVM Isolates, but does not provide any sample code for how those functions should be used. I couldn't find anything in the docs for embedding languages either. Additionally, there are no examples in the GraalVM Demos repository.

christianwimmer commented 2 years ago

The C API has functions to managing isolates, but we want to discourage people from using it. Instead, people should use the JNI invocation API https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html to manage isolates. That is fully supported in Native Image, and it is well specified.

nirvdrum commented 2 years ago

I'm sorry, I don't entirely follow what's being suggested here. Is @CEntryPoint supposed to be replaced by CallStaticVoidMethod? Is there a public example of using this invocation API?

christianwimmer commented 2 years ago

Of course you can use JNI also to invoke functions, instead of using @CEntryPoint. But we need to wait for OpenJDK project Panama to be finished before we can deprecate @CEntryPoint because JNI has inherently higher overheads than the current low-level SVM C interface.

But your issue was not about that part - you are talking about the functions to create isolates and attach threads to the isolate. For that part, there is actually no good reason to use the low-level SVM API, as the JNI invocation API functions like JNI_CreateJavaVM and AttachCurrentThread do exactly that. Now that we fully support JNI, I want to guide people towards that so that eventually we could even deprecate the SVM counterparts (graal_create_isolate for JNI_CreateJavaVM and graal_attach_thread for AttachCurrentThread).

nirvdrum commented 2 years ago

I think there may be a misunderstanding here. Whether it's through the native image C API or JNI, I have not found an example using a native image as a shared library anywhere in the docs or in the demo repository. There are docs about building a shared library in the Native Image reference manual and those docs show the generated function declarations require a graal_isolatethread_t* as the first argument. The page then linkes back to the the native C API, very much implying those functions are how you're going to create the graal_isolatethread_t* that the @CEntryPoint function requires. But, the docs stop there. They don't actually show how to use this API or call that function.

I ended up asking for help in the #native-image channel on the GraalVM Slack and several people shared open source projects they have where the figured out how to call into these functions. Each one was slightly different in the way it initialized and cleaned up these resources. None of them used JNI.

I also went through all of the GraalVM Demos and none of them have any C code that I could find.

Regardless of whether libpolyglot, the Graal isolate API, or JNI should be used, the purpose of this issue is that there isn't an example of using any of them through C or through an FFI. Without such documentation, developers will use whatever 3rd party source they can find and that very likely will cause bad patterns to propagate.

nirvdrum commented 2 years ago

As a follow-up, I was using GraalVM 21.3.0 when I opened this issue. With 22.0.0, the generated header files now include JNI-based function declarations creating isolates. That's a nice usability improvement.

olyagpl commented 2 years ago

That's great! The lack of examples for JNI functions invocation remains. We created a task for that.

serefarikan commented 5 months ago

@olyagpl @christianwimmer a very late follow up but this issue is relevant to what I've been trying to understand for the last few evenings. As far as I can see, the Native C API is much more convenieent for calling shared libraries built with Java from C. The Panama based APIs, in their current form in JDK 22 make the Arena the entry point (conceptually) for MemorySegment use and all the examples are using try-with-resources syntax, apparently aiming for memory-leak-safe approach for calling native code from Java. I cannot see the convenience offered by the C api in Panama based examples. I have no clue how I'm supposed to allocate some off-heap byte array and return a pointer to it for example: I have to use an Arena, and it would free the allocated memory segment when the java function returns, so calls form C would end up with dangling pointers. Am I missing something here? In other words, which part of Panama is supposed to replace the current native C Api? For example, the section titled "creating C libraries from Java programs" here: https://medium.com/graalvm/3-ways-to-polyglot-with-graalvm-fb28c1542b45 What's the Panama equivalent of that? Especially with Arena apparently making call-native-code-from-Java the primary, if not the only scenario. Am I missing something here? It feels like I am!