Friday, November 2, 2012

Calling C function from Java through SWIG framework

This example shows how to use SWIG framework so that our Java program can call C functions - without going through the painful process of creating our own JNI code from scratch

What is SWIG ?

From SWIG web page:


SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different types of target languages including common scripting languages such as Perl, PHP, Python, Tcl and Ruby. The list of supported languages also includes non-scripting languages such as C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), D, Go language, Java including Android, Lua, Modula-3, OCAML, Octave and R. Also several interpreted and compiled Scheme implementations (Guile, MzScheme/Racket, Chicken) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG is typically used to parse C/C++ interfaces and generate the 'glue code' required for the above target languages to call into the C/C++ code. SWIG can also export its parse tree in the form of XML and Lisp s-expressions. SWIG is free software and the code that SWIG generates is compatible with both commercial and non-commercial projects.

Let us go ahead and write those programs

Here is our header file "example.h"
#include 
#include 
extern float MY_VARIABLE;
extern int square_num(int num);
extern int do_addition(int first, int second);
extern char* get_time();

Here is our C implementation "example.c"

#include 
#include 
#include 

Now just to make sure, we create a test program "main_program.c" and execute it to make sure things are okay !

#include 
#include 
#include "example.h"

int main(int argc, char **argv)
{
    int x = 5;
    int first = 50;
    int second = 150;
    char *currenttime = NULL;
    printf("\n square_num(%d) = %d", x, square_num(x));
    printf("\n do_addition(%d, %d) = %d", first,second,do_addition(first,second));
    printf("\n get_time() = %s",get_time());
    printf("\n MY_VARIABLE = %f \n\n", MY_VARIABLE);
}

To Compile:

gcc main_program.c -o MAIN example.c

Output:

giri@giri-vm:~/Java/Swig$ ./MAIN 

 square_num(5) = 25
 do_addition(50, 150) = 200
 get_time() = Fri Nov  2 00:20:42 2012

 MY_VARIABLE = 3.141593 

Things look okay ! Now, we go ahead and write the Java program which calls the C program

Before that, we need to create the interface file - which is used by SWIG to generate the JNI code automatically for us

We now create the interface file (example.i)
%module example
%{
/* put the header files or function declarations like below */
extern double MY_VARIABLE;
extern int square_num(int num);
extern int do_addition(int first, int second);
extern char* get_time();
%}

extern double MY_VARIABLE;
extern int square_num(int num);
extern int do_addition(int first, int second);
extern char* get_time();

Now we generate the code through "swig" command !

# swig -java example.i

The above command generates the following files:

1. example_wrap.c
2. exampleJNI.java

Next we compile our (*.c) code !

# gcc -fpic -c example.c example_wrap.c -I/usr/lib/jvm/java-7-openjdk-amd64/include

The above command generates the following files:

1. example.o
2. example_wrap.o

Next, we generate the shared object file - which java program will invoke !

# gcc -shared example.o example_wrap.o -o libexample.so

The above command will generate:

"libexample.so"

Now, we go ahead and implement out Java program (which will eventually call the C functions) - "MainClass.java"

public class MainClass
{
    public static void main(String[] args)
    {
        System.loadLibrary("example");
        System.out.println("Java: square_num(25) : " + example.square_num((int) 25));
        System.out.println("Java: do_addition(5,41) : " + example.do_addition(5,41));
        System.out.println("Java: get_time() : " + example.get_time());
    }
}

Next we complie and execute !

# javac MainClass.java
# java MainClass

Output:

giri@giri-vm:~/Java/Swig$ java MainClass 
Java: square_num(25) : 625
Java: do_addition(5,41) : 46
Java: get_time() : Fri Nov  2 00:31:38 2012

No comments :

Post a Comment