14 August 2011

Java Native Access (JNA) by Example..

Java Native Access is a mean by which you can call native code (C/CPP) from your java programs.

It is intend is to remove the plumbing code when using JNI..

Let's write a simple example together..

First, let's write the Native (CPP) library:
#include <iostream>

extern "C" __declspec(dllexport) 
int add (int x, int y)
{
    return x + y;
}

(Don't ask me what this line "extern "C" __declspec(dllexport)
" means, you can read in wikipedia about each term, but what you need to know, it is required to be included in our code to be able to export it to a DLL library)

Let's generate the DLL from the above source code:
g++ -c add.cc
dir add.o
g++ -shared -o add.dll add.o
dir add.dll

Now we have the file "add.dll", we need to export its contents to see whether the our "add" function is being exported or not.

There's a yet simple but powerful tool called dependencywalker
.. download it and open the dll file using it. (as shown below)

Now Let's write the Java program that will call this native function ..

You will need to download the jar file of jna library..
Download it from here.

Open Eclipse and create a new Java Project and name it as "AddJNAExample".
put the file "jna.jar" and put it in the project build path in eclipse.. and come to write the source code for the program.


package com.daz;

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface Add extends Library
{
    Add INSTANCE = (Add) Native.loadLibrary("add", Add.class);
    int add(int x, int y);
}

And Here's the Driver:

package com.daz;

public class Test {
    public static void main(String[] args) {
        Add lib = Add.INSTANCE;
        System.out.println(lib.add(10, 20));
    }
}

Note, If you run it now, the following exception will be thrown:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'add': The specified module could not be found.

This is because, you will need to specify the dll library to the jvm as follows:

java -Djna.library.path="D:\dlls\add.dll" com.daz.Test

The result will be:
30

JNA involves more complex type-mappings ...

References:
http://www.cygwin.com/cygwin-ug-net/dll.html
http://today.java.net/pub/a/today/2009/05/19/protect-your-legacy-code-jna.html
http://www.dependencywalker.com/

6 comments:

Anonymous said...

muchas gracias por tu post, fue de gran ayuda.

Anonymous said...

Thanks a lot for good article.I just want to learn how we can access classes in dll file.For instance;
If we assume,we have codes like that in dll ;
Class1 class1=new Class1();
class1.doSomeStaff();

How can we access that class1 object and its method?
Thanks in advance

mhewedy said...

The syntax you wrote is not C or C++ syntax. It might be C#, so I am not sure how to access C# code as native.

Anonymous said...

Can you tell me how to implement this code in Javascript using engines such as Rhino that can access the libraries of Java? I am confused about the syntax.

mhewedy said...

About accessing it with javascirpt, I did't tried before.

Nitin Singh said...

Any idea about this :

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.sun.jna.Pointer.pointerSize()I
at com.sun.jna.Pointer.pointerSize(Native Method)
at com.sun.jna.Pointer.(Pointer.java:57)
at com.sun.jna.NativeLibrary.(NativeLibrary.java:52)
at com.sun.jna.Library$Handler.(Library.java:105)
at com.sun.jna.Native.loadLibrary(Native.java:164)
at com.sun.jna.Native.loadLibrary(Native.java:147)
at com.compdev.jautoit.autoitx.autoitx.(autoitx.java:14)
at checkonautoitxjar.Main.main(Main.java:19)