Introduction
In my last assignment I was asked to write a Java code that makes use of .Net DLLs. There are a lot of tools/libraries available on the web that will do this for you (JNI4Net actually works bi-directionally; you can call Java code from .Net code). But I wanted greater control over things so I decided to do it from scratch.
Assumption: I am assuming reader has basic knowledge of JNI programming. Like native methods in java code, generated header files and implementing the headers in native code.

Solutions
Most common way to solve this problem is to write a native code which invokes .Net code and uses this native wrapper in Java using JNI (This tutorial explains Native to .net part http://support.microsoft.com/kb/828736 ).For this thing to work, you should register your .Net assemblies using regasm.exe (tool that comes with Visual Studio). 

But, there can be situations where you can’t use regasm.exe, in such case you can use registration free activation of .Net assemblies. (http://msdn.microsoft.com/en-us/library/ms973915.aspx). This procedure involves embedding registry information (that would have been written to registry by regasm.exe otherwise) in the DLLs. But I personally feel this approach is very complex and somehow didn’t work for me from JNI.

And when I thought I’m completely out of options, I met C++/CLI :)
C++/CLI is an entirely new language which is intended to supersede Managed Extensions for C++, you can find out more about this language at http://msdn.microsoft.com/en-us/magazine/cc163852.aspx

Why this is interesting because when you compile your C++/CLI code, generated code is a hybrid of native and managed code. And since you can code in C, C++/CLI and reuse managed library code in the same source file this becomes a lucrative option for our Java-Net connectivity bridge.


Tutorial 
 There are 3 different projects in this tutorial, You can download all these projects HERE.
  1.  A simple C# class library: Single class with one method that add two integers.
  2. Java code which loads DLL created in project 3 to invoke functions implemented in C++/CLI code. 
  3.  A C++/CLI library which uses C# library created in project 1 and implements JNI headers generated from Java native methods.
        
Part1:  Simple C# library
Here, you can use any existing .Net library (.Net DLL) that you want to call from Java. I have included one for better understanding.
  1. Create a C# project of type “Class library”.
  2. My sample project includes single class which has a method that adds given two integers.
namespace MyCSharpMathsLib
{
    public class Adder
    {
        public int addTwoNumberes(int a, int b)
        {
            return a + b;
        }
    }
}

Part2:  Java code with native method.

This code is a simple Java class plus some native methods. You can directly import this project in Eclipse IDE and run CsharpConsumer.java once you have completed compiling and adding Proejct 3 DLLs  to %PATH%

CsharpConsumer.java
public class CsharpConsumer {
       static{
              System.loadLibrary(“JNICsharpBridge");
//Load Project3 generated DLL, DLL’s parent folder should be in your libpath. [%PATH% variable], This will be executed at time of loading class CsharpConsumer
       }
       public static void main(String[] args) {
              CsharpConsumer csc = new CsharpConsumer();
              csc.reigsterAssemblyHandler("c:\\mydlls\\");
//Tell native code where to look for .net DLLs.
              System.out.println("Result of adding = "+ csc.addTwoNos(1, 5));
       }
       native int addTwoNos(int a,int b);
       native int reigsterAssemblyHandler(String str);
}

  1.  addTwoNos and reigsterAssemblyHandler are declarations of two native methods that we will implement in C++/CLI code.
  2.  “javah” tool generates C/C++ header files using compiled CsharpConsumer.java.
  3. In order to use native code we must load native binaries into JVM process that’s done using System.loadLibrary call
  4.   In order to use .Net assemblies you must register corresponding DLLs to GAC (Global assembly cache) or the DLLs should be present in the same folder as that of your executables. But since our bridge DLL runs under JVM, these dlls should be copied to JRE\bin, and from deployment perspective this is an awkward situation. To overcome this problem we can load .Net assemblies that our code depends upon(MyCSharpMathsLib.dll in this case) dynamically from C++/CLI code
  5.  Native mothod “reigsterAssemblyHandler” does this job, and tells C++/CLI code where to look for dependencies (implemented in native code)


Part3:  A C++/CLI library that acts as a bridge

This code acts as bridge between Java and C# (and managed code written in any language) code.  C++/CLI has entirely new language syntax and I personally find it bit complex. But one major advantage of using C++/CLI is that here is that you can directly use managed objects and still your compiled binaries and accessible through native interfaces (e.g. JNI).

  1.  Create new CLR Console application.
  2.  From build settings make this project’s output type a DLL instead of exe, select /clr switch.
  3.  Include the files generated using “javah” in this project. Following snippet shows how to implement.
  4.  Add Project1 or its DLL as dependency / reference.
  5.  Implemented header file generated by javah utility.
  6. Compile your code as a DLL and with “/clr” switch.
  7.  Put generated DLL in a directory that is listed in %PATH%, or put that directory in %PATH% variable, either ways possible, see what suits you.

Links:
AssemblyResolve Event handler: 
Calling managed code from native
Registration free .net assemblies.
C++/CLI introduction


©2012 Abhijeet Apsunde LinkedIn
4

View comments

Loading