Saturday, December 4, 2010

Getting Started with JNI

Java Native Interface (JNI) allows Java code to call native applications, e.g. applications written in C or C++. In this example, I will show you how to call C and C++ application from Java using JNI on Linux.

* JNI for C application *

CHelloWorld.java
public class CHelloWorld {
    
    static {
        System.loadLibrary("chello");
    }
    
    private native void print();

    public static void main(String[] args) {
        new CHelloWorld().print();
    }
}
1. Create a header file for CHelloWorld.
javah -jni CHelloWorld

2. Implement CHelloWorld.c
#include <jni.h>
#include <stdio.h>
#include "CHelloWorld.h"

JNIEXPORT void JNICALL
Java_CHelloWorld_print(JNIEnv *env, jobject obj)
{
    printf("Hello World from C\n");
    return;
}

3. Compile the CHelloWorld.c
gcc -Wall -fPIC -c CHelloWorld.c -I$HOME/jdk1.6.0_22/include \
-I$HOME/jdk1.6.0_22/include/linux
This will produce the CHelloWorld.o

4. Create a shared library (.so on Linux or .dll on Windows).
gcc -shared -o libchello.so CHelloWorld.o

5. Execute CHelloWorld in Java.
java -Djava.library.path=. CHelloWorld
The -Djava.library.path is required to tell where to load the library from. Alternatively, LD_LIBRARY_PATH (on Linux) or PATH (on Windows) can also be used.

* JNI for C++ application *
public class CppHelloWorld {

    static {
        System.loadLibrary("cpphello");
    }
    
    private native void print();

    public static void main(String[] args) {
        new CppHelloWorld().print();
    }
}
1. Create a header file for CppHelloWorld
javah -jni CppHelloWorld

2. Implement CppHelloWorld.cpp
#include <jni.h>
#include "CppHelloWorld.h"
#include <iostream>
using namespace std;

JNIEXPORT void JNICALL
Java_CppHelloWorld_print(JNIEnv *env, jobject obj)
{
    cout << "Hello World from C++" << endl;
    return;
}

3. Compile CppHelloWorld
g++ -Wall -fPIC -c CppHelloWorld.cpp -I$HOME/jdk1.6.0_22/include \
-I$HOME/jdk1.6.0_22/include/linux
This will produce the CppHelloWorld.o

4. Create a shared library (.so on Linux or .dll on Windows)
g++ -shared -o libcpphello.so CppHelloWorld.o

5. Execute CppHelloWorld in Java.
java -Djava.library.path=. CppHelloWorld
The -Djava.library.path is required to tell where to load the library from. Alternatively, LD_LIBRARY_PATH (on Linux) or PATH (on Windows) can also be used.

To call native library in Java using similar concept like Python's ctypes or C#'s P/Invoke, JNA is a good alternative.

No comments:

Post a Comment