I need to create a dll file from a quarkus application. I have tried several approaches that didn't work (IKVM, IKVM, JNI,...) My current approach is by using GraalVM. I'm able to compile the Java classes using the command:
javac *.java
and I'm able to generate the dll using the command:
native-image --shared -H:Name=dbexample -H:-CheckToolchain --enable-native-access=ALL-UNNAMED --no-fallback
and when looking inside the generated dlls I can see that the java methods are there, inside the dll, using the command:
dumpbin /EXPORTS dbexample.dll
But when calling the method I get an error. A kind of a generic error, probably accessing the memory. Something like "Exited Thread 44280"
This is my Java application
import .graalvm.nativeimage.IsolateThread;
import .graalvm.nativeimage.c.function.CEntryPoint;
import .graalvm.nativeimage.Isolates;
import .graalvm.nativeimage.Isolates.CreateIsolateParameters;
public final class LogicConnectionImpl implements LogicConnection {
@CEntryPoint(name = "IsolateCreate")
public static IsolateThread createIsolate(@SuppressWarnings("unused") IsolateThread thread) {
var context = Isolates.createIsolate(CreateIsolateParameters.getDefault());
return context;
}
@CEntryPoint(name = "doSomething")
public static void doSomething(@SuppressWarnings("unused") IsolateThread thread) {
System.out.println("Hello, World from inside JAVA!");
}
@CEntryPoint(name = "test")
public static int test(@SuppressWarnings("unused") IsolateThread thread) {
return 23;
}
@CEntryPoint(name = "test2")
public static void test2(@SuppressWarnings("unused") IsolateThread thread, int value) {
int value2 = value + 1;
System.out.println("Hello, World from inside JAVA!");
}
public void test3(String thisTest) {
System.out.println("Hello, World from inside JAVA! " + thisTest);
}
}
And this is my C# application:
using System;
using System.Runtime.InteropServices;
class Program
{
// Define the P/Invoke signatures
[DllImport("dbexample.dll", EntryPoint = "doSomething")]
public static extern void DoSomething(IntPtr thread);
[DllImport("dbexample.dll", EntryPoint = "test")]
public static extern int Test(IntPtr thread);
[DllImport("dbexample.dll", EntryPoint = "test2")]
public static extern void Test2(IntPtr thread, int value);
[DllImport("dbexample.dll", EntryPoint = "IsolateCreate")]
public static extern IntPtr IsolateCreate(IntPtr thread);
static void Main(string[] args)
{
try
{
IntPtr isolateThread = IsolateCreate(IntPtr.Zero);
if (isolateThread == IntPtr.Zero)
{
Console.WriteLine("Failed to create IsolateThread.");
return;
}
// Call the methods from the DLL
DoSomething(isolateThread);
int result = Test(isolateThread);
Console.WriteLine("Result from test: " + result);
Test2(isolateThread, 42);
}
catch (Exception ex)
{
Console.WriteLine("An error occurred: " + ex.Message);
}
}
}
The error happens on the following line:
IntPtr isolateThread = IsolateCreate(IntPtr.Zero);
I believe that it happens due to the method parameter (IntPtr.Zero). From what I saw, I need to have the "IsolateCreate" comming from the Java application. Meaning that I cannot call the following methods like for instance DoSomething with IntPtr.Zero, like this:
DoSomething(IntPtr.Zero);
Because if I do it that way, then the error will be in that line of code For that same reason I should call DoSomething with the "IsolateThread" coming from the Java application (method createIsolate), as it is from the examples I show above. However, by doing so, the method "createIsolate" that also must have the decorator "@CEntryPoint", so that it is exported to the dll, must also have a parameter of type "IsolateThread", which in turn in C# I need to pass a parameter "IsolateThread" and I'm calling it with "IntPtr.Zero".
I feel I'm close to importing the Java dll in C# but there is some tweak here that I'm missing. Can you please help?