IKVM C# to Java Interop with Callback using IKVM

前端 未结 2 1516
梦毁少年i
梦毁少年i 2021-02-06 18:10

I\'ve started using IKVM to translate Java libs into .NET CIL. I can successfully write a C# program that pulls in (inproc) a translated Java assembly as a reference and make ca

相关标签:
2条回答
  • 2021-02-06 18:19

    JaapM, I think CSharpLibrary in mj_'s solution is a transient class from third C# DLL project (cshardassembly.dll), that he compiles first and then shares between actual java and C# code. It doesn't matter what's in it, the idea is that both sides have a piece of code (class) known in advance. This is overkill, if I'm correct.

    I know, it's a long time passed but I would like to post a short solution here that works for me, cuz I wasted too much time on it and IKVM documentation is very poor:

    Java:

    package what.ever.package;
    import cli.System.Delegate;
    import cli.System.Int32;
    public class SomeJavaClass
    {
        public static void setCallback(Delegate callback)
        {
            // I call delegate in static setter to keep example short, 
            // but you may save it and call later...
            Int32 result = (Int32)callback.DynamicInvoke("hello", "world");
            System.out.println("Callback returned [" + result + "]");
        }
    }
    

    Don't forget to convert mscorlib.dll into jar and attach it to your java project to support cli imports. build it and run ikvmc.exe on jar with -target:library parameter and add resulting DLL into C# project.

    C#:

    using what.ever.package
    class Program
    {
        // signature of delegate must match target function.
        public delegate Int32 TheDelegateItself(String a, String b);
    
        // callback that we pass into java.
        public static Int32 DelegateTarget(String a, String b)
        {
            Console.WriteLine("DelegateTarget Executed: [" + a + ", " + b + "]!");
            return 42;
        }
    
        static void Main(string[] args)
        {
            // again, static call to keep it short
            // but you may want a class instance in most cases.
            SomeJavaClass.setCallback(new TheDelegateItself(DelegateTarget));
        }
    }
    

    output:

    DelegateTarget Executed: [hello, world]!
    Callback returned [42]

    0 讨论(0)
  • 2021-02-06 18:29

    Ladies and Gentlemen, I figured out my own question. Code first followed by steps.

    Java Class

    public class TestClass {
    private cli.CSharpLibrary.Library m_lib = null;
    
    public void AddDelegate( cli.CSharpLibrary.Library lib )
    {
        m_lib = lib;
    }
    
    public void FireDelegate()
    {
        if( m_lib != null )
        {
            m_lib.ExecuteRunnableDelegate();
        }
    }
    
    public void PrintInt()
    {
        System.out.print(23);
    }
    }
    

    C# Class

    using ikvm.runtime;
    using CSharpLibrary;
    
    namespace CSharp
    {
      class Program
      {
    public static void DelegateTarget()
    {
      Console.WriteLine("DelegateTarget Executed!");
    }
    
    static void Main(string[] args)
    {
      Library lib = new Library();
      lib.m_runnableDelegate = new Delegates.RunnableDelegate(DelegateTarget);
    
      TestClass tc = new TestClass();
      tc.AddDelegate(lib);
      tc.FireDelegate();
    
    }
    }
    }
    

    1) Write your Java app

    2) Convert your *.class files into a jar file (jar -cf myjar.jar *.class)

    3) Convert the jar file into a .NET assembly (ikvmc -reference:csharpassembly.dll myjar.jar)

    Should work at this point. You can run your C# program, have it call the converted Java program and vice versa. Watch out for the "-reference" flag on the ikvmc call. This tells IKVM when it's converting the Java code that csharpassembly.dll has some class definitions that it needs to watch out for.

    0 讨论(0)
提交回复
热议问题