Friday, November 2, 2012

Calling C function from Java through JNI

This example shows how to call a C function from Java program

First, we implement a simple Java program "MainClass.java"

package com.giri.jni;

public class MainClass {

 public native String nativeFoo();
 
 static {
  System.loadLibrary("foo");
 }
 
 public void print() {
  String str = nativeFoo();
  System.out.println("str = " + str);
 }
 /**
  * @param args
  */
 public static void main(String[] args) {
  System.out.println("test program");
  
  (new MainClass()).print();
  return;
 }

}

Now, we go ahead and compile the above program

# javac MainClass.java

Next step would be to generate the header file

# javah -v com.giri.jni.MainClass

The above command will generate "com_giri_jni_MainClass.h"

Contents of "com_giri_jni_MainClass.h"


/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_giri_jni_MainClass */

#ifndef _Included_com_giri_jni_MainClass
#define _Included_com_giri_jni_MainClass
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_giri_jni_MainClass
 * Method:    nativeFoo
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_giri_jni_MainClass_nativeFoo
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Next we implement our actual C-program "foo.c"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include "com_giri_jni_MainClass.h"

JNIEXPORT jstring JNICALL Java_com_giri_jni_MainClass_nativeFoo(JNIEnv *env, jobject obj)
{
    int i;
    int ds_ret;

    char *newstring;

    jstring ret = 0;

    newstring = (char *) malloc(30);

    if(newstring == NULL)
    {
        return ret;
    }

    memset(newstring, 0, 30);

    char *tmpstring = "foo: Test program of JNI\n";
    strcpy( newstring, tmpstring );

    ret = (*env)->NewStringUTF(env,newstring);

    free(newstring);

    return ret;
}

Now we compile the C Program "foo.c"

gcc -dynamiclib -o libfoo.jnilib -I /System/Library/Frameworks/JavaVM.framework/Headers foo.c -framework JavaVM

Now we have the following files:

[src]$ ls -l
total 40
drwxr-xr-x  3 apple  staff   102 Oct 31 22:46 com
-rw-r--r--  1 apple  staff   465 Nov  1 19:13 com_giri_jni_MainClass.h
-rw-r--r--  1 apple  staff   538 Nov  1 00:37 foo.c
-rwxr-xr-x  1 apple  staff  8664 Nov  1 19:15 libfoo.jnilib

And the following

com
com/giri
com/giri/jni
com/giri/jni/MainClass.class
com/giri/jni/MainClass.java

Now we run the Java program which calls the C function !

java -Djava.library.path=/Users/apple/Documents/workspace/JniTest/src com.giri.jni.MainClass

Output:

test program
str = foo: Test program of JNI

1 comment :