6

I've written a lot of code in a C# library, which I now need to call from Java.

I saw it recommended on SO to use JNA, but I'm having trouble even getting out of the starting blocks; the documentation there is very sketchy.

Firstly, it only appears to show you how to connect to the Native C library, which is no good to me; I want to connect to my own library. The code sample there shows:

// This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types.
public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary)
        Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
                           CLibrary.class);

    void printf(String format, Object... args);
}

I want to connect to my library (MyLibrary.dll), and call a static method on MyNamespace.MyClass whose C# signature is:

public static string HelloWorld(string p)

So what parameters to I give to Native.loadLibrary()?

That's just for "Hello World". What if I want to return an object? Let's say MyClass also has a static method

public static MyClass GetInstance()

How would I call that using JNA? I guess I would have to define an interface in Java that matches the C# MyClass interface... but would it have to be exhaustive, i.e. for every public member of MyClass I would have to declare a method in an IMyClass interface in Java? Or can I just leave out the interfaces I don't care about?

Any sample code would be gratefully welcomed!

Shaul Behr
  • 36,951
  • 69
  • 249
  • 387

3 Answers3

11

You won't be able to call directly into your C# code from Java. JNA will only be able to access a native library (C or C++). However you could enable COM Interop in your library and link the 2 together with a native wrapper. I.e. it would look some thing like:

Java --(JNA)--> C/C++ --(COM Interop)--> C#

There are a couple of alternatives:

  • Make the C# a stand alone command line app and have the Java code send/receive data from it using stdin/stdout (ProcessBuilder can help you here).
  • Run the C# as a stand alone app with some form of platform neutral messaging protocol to communicate between the 2 of them, e.g. HTTP, AMQP.
Michael Barker
  • 14,153
  • 4
  • 48
  • 55
  • this sounds like a lot of pain to track – mbx May 15 '11 at 15:30
  • 4
    @mbx: it is what it is, but Michael Barker does a good job of succinctly describing the options. +1 to him. – Hovercraft Full Of Eels May 15 '11 at 16:37
  • @Hovercraft - Agreed. It's not the answer I *wanted*, but it is an answer, and I'll accept it. In practice though I'll probably have to buy some other solution like JNBridge. – Shaul Behr May 16 '11 at 07:25
  • actually, while not 1:1 related with your question, it might help to know that there are open-source cross-compilers that allow you to compile the C/C++ "middleware" on platforms like Linux to run C# stuff on WIndows. – user1050755 Dec 08 '16 at 02:38
1

This Nugget is super easy to use and works perfectly. https://www.nuget.org/packages/UnmanagedExports

You need Visual Studio 2012 (Express works fine). Once installed, just add [RGiesecke.DllExport.DllExport] before any static function you want to export. That's it!

Example:

C#

[RGiesecke.DllExport.DllExport]
public static int YourFunction(string data)
{
     /*Your code here*/
     return 1;
}

Java

Add the import at the top:

   import com.sun.jna.Native;

Add the interface in your class. Its your C# function name preceded by the letter "I":

  public interface IYourFunction extends com.sun.jna.Library
    {
       public int YourFunction(String tStr);
    };

Call your DLL where you need it in your class:

IYourFunction iYourFunction = (IYourFunction )Native.loadLibrary("full or relative path to DLL withouth the .dll extention", IYourFunction.class);//call JNA
        System.out.println("Returned: " + IYourFunction.YourFunction("some parameter"));
John
  • 1,011
  • 11
  • 18
0

You can use Caffeine for this http://caffeine.berlios.de/site/documentation/

Daniel Voina
  • 3,185
  • 1
  • 27
  • 32