Callback/Delegate to Java for handling some C# event

821 views Asked by At

I am using C# assembly in a Java application via JNA & Unmanaged Exports. Now I would need to implement a Callback/Delegate in order to inform Java that some Event in the C# .dll has occured.

How can this be accomplished? or is there any reading reference you could suggest?


What I tried so far: I am using Java Native Access (JNA) & unmanaged exports by Robert Giesecke in order to call C# methods from Java. - works fine so far.

I pass the Callback-method as a void* pointer from Java to C#. I would like to call this Method somehow.

For verification I added the code I use:

  1. Defining JNA Interface (incl. Callback) in Java:

    import com.sun.jna.Callback;
    import com.sun.jna.Library;
        public interface Ijna extends Library {
            interface sig_t extends Callback {
                boolean invoke(int signal);
            }
            String TestCallback(sig_t callbackparam);
        }
    
  2. unsafe C# Method exported to unmanaged code, receiving a "any pointer" (void*) as parameter which should be the adress of the method

    [DllExport]
    public unsafe static String TestCallback(void* someMethod) {
        //use someMethod here
        if(someMethod != null)
            return "not null"; // someMethod is not null when running the app
        else
            return "null";
    }
    
  3. Load .dll, define Callback function and call it in Java.

    public static void main(String[] args) {
        //load unmanaged .dll
        Ijna.sig_t referenceToFunction = new Ijna.sig_t() {
            @Override
                public boolean invoke(int sig) {
                System.out.println("signal " + sig + " was raised");
                return true;
            }
        };
        String test = INSTANCE.TestCallback(referenceToFunction);//returns "not null"
        System.out.println(test); 
    }
    
1

There are 1 answers

0
Haphil On BEST ANSWER

I could solve it. Using Marshal.GetDelegateForFunctionPointer(IntPtr, Type) it was possible to convert the void* (any pointer) to a C# delegate.

So the C# code is adapted to the following:

    delegate void Del(int someInt);
    Del csharpfuncptr; //save the Delegate, but not the void* (the void* is not preventing the GB from deleting the method, and could therefore get invalid)
    [DllExport]
    public unsafe static String TestCallback(void* someMethod)
    {
        IntPtr method = new IntPtr(someMethod);
        csharpfuncptr = (Del)Marshal.GetDelegateForFunctionPointer(method, typeof(Del));
        csharpfuncptr(5);
    }