64bit (g)fortran JNI

Hans Horn hannes@2horns.com
Wed Apr 13 22:18:00 GMT 2011


On 4/12/2011 7:25 PM, Jerry DeLisle wrote:
> On 04/12/2011 07:38 AM, Hans Horn wrote:
>> Folks,
>>
>> has anybody got any experience interfacing (g)fortran routines with
>> Java via JNI?
>>
>> I'm on 64bit Windows7 using cygwin
>> x86_64-w64-mingw32-gcc and x86_64-w64-mingw32-gfortran, both v4.5.2
>>
>> Java: jdk-6u24-windows-x64
>>
>> Even though I can statically link the JNI code successfully (using
>> gfortran as
>> linker), calling any native method from Java crashes the JVM - even
>> when no
>> fortran code is called at all.
>>
> What do you mean by native method? Are you trying to call Fortran
> procedures from Java?
>
> In what way does it crash? Can you get a back trace from a debugger?
>
> Jerry
>
> PS I have no experience with this, just asking some questions to glean
> additional information. Fortran calling conventions are no exactly the
> same as C.

Ok,

 > What do you mean by native method? Are you trying to call Fortran
 > procedures from Java?
Nope, via a C wrapper.

I condensed things to the simplest possible testcase that still does not 
function.
In the process I figured that I needed to link with '-shared'. Without 
that I get said crash of the JVM in both cases, with or without calling 
fortran.



here's my fortran routine:
------------------------------------------------
       subroutine f77sub(string)
       character*(*) string

       write(*,*) 'string is ',string
       call fflush(6)

       end


here's the JNI C wrapper that calls the fortran routine:
------------------------------------------------
#include "JNItest.h"

#ifdef F77SUB
   void f77sub(char*, int);
#endif

JNIEXPORT void JNICALL Java_JNItest_java2C2f77
(JNIEnv* env, jclass obj) {
#ifdef F77SUB
   printf("calling fortran\n"); fflush(stdout);
   f77sub("here is fortran", 15);
   printf("back from fortran\n"); fflush(stdout);
#else
   printf("not calling fortran at all\n"); fflush(stdout);
#endif
}


here's my Java class calling the JNI C wrapper:
------------------------------------------------
class JNItest {
   private native void java2C2f77 ();
   static {
     System.loadLibrary("jnitest");
   }
   public static void main (String[] args) {
     new JNItest().java2C2f77();
   }
}


here's the makefile used to compile the jnitest.dll:
------------------------------------------------
gcc_opt = -O3 -std=c99 -DCYGWIN -Wl,--kill-at \
-fno-omit-frame-pointer -I${JAVA_HOME}/include/win32 \ 
-I${JAVA_HOME}/include -Wall -D_JNI_IMPLEMENTATION_
gcc = gcc
gfc = gfortran
gfc_opt = -O3 -fno-underscoring -fno-f2c -W -Wunused \
-Wuninitialized -fno-omit-frame-pointer
ld_opt = -luuid -lole32 -fno-omit-frame-pointer -shared
ifeq ($(PROCESSOR_ARCHITEW6432), AMD64) #use mingw 64bit cross compilers
   gcc_opt += -m64
   gcc = x86_64-w64-mingw32-gcc
   gfc = x86_64-w64-mingw32-gfortran
   gfc_opt += -m64
   ld_opt += -m64
endif

########################################################################

allnof: jnitest_h jnitestnof;

jnitest_h: JNItest.class; javah -classpath ./ JNItest

jnitestnof: JNItest.c JNItest.h; \
${gcc} ${gcc_opt} JNItest.c ${ld_opt} -o jnitest.dll

########################################################################

# attempt to call fortran from JNI code; must link with gfortran else
# we're mssing fortran runtime libs, eg. _gfortran_st_write

allf: f77o jnitest_h jnitestf;

f77o: f77sub.o; ${gfc} ${gfc_opt} -c f77sub.f -o f77sub.o

jnitestf: JNItest.c JNItest.h; \
${gcc} -DF77SUB ${gcc_opt} -c JNItest.c -o JNItest.o; \
${gfc} ${ld_opt} JNItest.o f77sub.o -o jnitest.dll



--------------------------------------------------------------------------
the dll built w/o calling fortran (-DF77SUB not set; make jnitestnof) 
prints (as it should):
"not calling fortran at all"

---------------------------------------------------------------------------
the dll built with calling fortran (-DF77SUB set; make jnitestf, 
gfortran as linker) is expected to print:
calling fortran
here is fortran
back from fortran

however, it produces an unsatisfied link error such as:

java.lang.UnsatisfiedLinkError: D:\native\jnitest.dll: %1 is not a valid 
Win32 application
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1728)
	at java.lang.Runtime.loadLibrary0(Runtime.java:823)
	at java.lang.System.loadLibrary(System.java:1028)
	at JNItest.<clinit>(JNItest.java:4)

Note that the path to the gfortran runtime is included in the Windows 
PATH variable:
PATH=D:\native;C:\CygWin\usr\i686-w64-mingw32\sys-root\mingw\bin;...


Thx.,
H.


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple



More information about the Cygwin mailing list