Stach Jankowski
Stach Jankowski

Reputation: 53

Integration of Fortran code with Java by JNI

I have a problem with the integration of Fortran code with Java by JNI. The problem probably occurs when I link the C object with the Fortran object.

File: HelloWorld.java

public class HelloWorld {
    native void foo();
    static {
        System.loadLibrary("test");
    }
    static public void main(String argv[]) {
        new HelloWorld().foo();
    }
}

File: ctest.c

#include <jni.h>
#include <stdio.h>

extern void bar_();

JNIEXPORT void JNICALL Java_HelloWorld_foo
  (JNIEnv * env, jobject jobj)
{
    printf("Hello World!\n");
}

Compilation:

$ gcc -fPIC -shared -lc \
    -I/usr/lib/jvm/java-7-oracle/include \
    -I/usr/lib/jvm/java-7-oracle/include/linux \
    -o libtest.so ctest.c
$ javac HelloWorld.java
$ java HelloWorld
Hello World!

Excellent, Hello World! works properly. But when I add Fortran code, Java throws an exception.

File: ftest.f95

subroutine bar()
    return
end

Compilation:

$ gcc -fPIC -shared -lc \
    -I/usr/lib/jvm/java-7-oracle/include \
    -I/usr/lib/jvm/java-7-oracle/include/linux \
    -o ctest.o ctest.c
$ gfortran -c ftest.f95
$ gcc -shared ftest.o ctest.o -o libtest.so
$ javac HelloWorld.java
$ java HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld.foo()V
        at HelloWorld.foo(Native Method)
        at HelloWorld.main(HelloWorld.java:7)

What am I doing wrong?

Upvotes: 5

Views: 848

Answers (2)

Alexander Vogt
Alexander Vogt

Reputation: 18118

A couple of things:

  • For the build of the C object, you should not specify -shared. You are not generating an independent library. Instead, use -c to compile the object:
gcc -fPIC -lc \
    -I/usr/lib/jvm/java-7-oracle/include \
    -I/usr/lib/jvm/java-7-oracle/include/linux \
    -o ctest.o -c ctest.c
  • If you want to link together the C and Fortran objects, you need to specify -fPIC in both cases and when linking the library. Furthermore, you need to link against libgfortran:
gfortran -fPIC -c ftest.f95
gcc -fPIC -shared ftest.o ctest.o -o libtest.so -lgfortran
  • You need to extend the java.library.path such that the JVM can find the library:
javac HelloWorld.java
java -Djava.library.path="$PWD" HelloWorld

With these commands, your code runs fine on my machine.

Upvotes: 3

Stach Jankowski
Stach Jankowski

Reputation: 53

I found, the solution is ld.

gcc -fPIC -shared -lc \
    -I/usr/lib/jvm/java-7-oracle/include \
    -I/usr/lib/jvm/java-7-oracle/include/linux \
    -o ctest.o ctest.c
gfortran -c ftest.f95
ld -shared ftest.o ctest.o -o libtest.so -lc

Upvotes: 0

Related Questions