Calling C# or other .NET code from Clojure

As part of our efforts to alleviate developer fatigue, we’re showcasing the ways that JNBridgePro can support interoperability when using alternative and emerging languages based on the JVM or CLR. So far, we’ve demonstrated interoperability with Groovy, Jython, and Iron Python. In this post, we’re going to look at Clojure, a LISP variant that runs in a JVM and includes the ability to call Java. (There’s also a .NET-based version of Clojure.)

We’ll put JNBridgePro through its paces by reworking our earlier Jython example, where Jython code called a .NET library.  Here’s the .NET library we’ll be using, written in C# (although things will work just as well with a library written in VB.NET or any other .NET-based language):

namespace DotNetLibrary
{
   public class HelloWorldFromDotNet
   {
      private string theString = "";

      public HelloWorldFromDotNet()
      {
         theString = "Hello World from .NET!";
      }

      public HelloWorldFromDotNet(string s)
      {
         theString = s;
      }

      public string returnString()
      {
         return theString;
      }
   }
}

Once we build the library and proxy DotNetLibrary.HelloWorldFromDotNet and supporting classes into a proxy jar file, we can easily call the classes from a Closure REPL (read-eval-print loop).

Assuming you’ve already downloaded and installed Clojure (go here to download it), and you’ve collected the Clojure jar along with the proxies and jnbcore.jar and bcel-5.1-jnbridge.jar into a single directory, start up Clojure as follows, with all of the above jar files in the classpath:

java -cp "clojure-1.6.0.jar;jnbcore.jar;bcel-5.1-jnbridge.jar;proxies.jar" clojure.main

Once Clojure starts, and you get a user prompt, enter your commands to configure and initialize JNBridgePro, and then to call the proxies.  Since the proxies are Java classes like any other, call them in the same way as you would call other Java classes.

Clojure 1.6.0
user=> (def props (new java.util.Properties))
#'user/props
user=> (.setProperty props "dotNetSide.serverType", "sharedMem")
nil
user=> (.setProperty props "dotNetSide.assemblyList.1", "C:/Clojure Example/DotNetLibrary.dll")
nil
user=> (.setProperty props "dotNetSide.javaEntry", "C:/Program Files (x86)/JNBridge/JNBridgePro v7.2/4.0-targeted")
nil
user=> (.setProperty props "dotNetSide.appBase", "C:/Program Files (x86)/JNBridge/JNBridgePro v7.2/4.0-targeted")
nil
user=> (com.jnbridge.jnbcore.DotNetSide/init props)
nil
user=> (def h1 (new DotNetLibrary.HelloWorldFromDotNet))
#'user/h1
user=> (.returnString h1)
"Hello World from .NET!"
user=> (def h2 (new DotNetLibrary.HelloWorldFromDotNet "Test String from DotNet"))
#'user/h2
user=> (.returnString h2)
"Test String from DotNet"
user=>

While the form of the calls to Properties, DotNetSide, and the proxy class may look strange if you’re not familiar with Clojure, but only familiar with Java, a close examination of each line above should allow you to translate it into the equivalent Java or Jython code.

Note that, while we use a REPL above, we can also pre-compile the Clojure code and it should run equally well.  Also, we can clean up the above code a bit by importing namespaces, but in the code above we wanted to be as transparent as possible. Finally, if we want, we can dispense with the references to java.util.Properties and instead use the variant of DotNetSide.init() that takes a string representing a path to a properties file containing the JNBridgePro configuration.

As you can see, using JNBridgePro to call .NET code from Clojure is as easy as calling it from Java or any other JVM-based language.

Are you currently using or planning to use Clojure? Do you have any scenarios where you need to call .NET assemblies from your Clojure code? If so, let us know!