From: Hans H. <ha...@2h...> - 2011-04-15 15:47:01
|
On 4/15/2011 7:50 AM, Kai Tietz wrote: > 2011/4/15 Hans Horn<ha...@2h...>: >> On 4/14/2011 11:25 PM, Kai Tietz wrote: >>> 2011/4/14 Hans Horn<ha...@2h...>: >>>> 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. >>> >>> Hmm, for me the error message indicates that you either try to load >>> jnitest.dll under foreign bitness of JVM. Are you using here 32-bit >>> JVM and 64-bit DLL, or 64-bit JVM and 32-bit DLL? >>> As this would describe what the error-message of java is showing. >>> >>> Regards, >>> Kai >> >> >> Kai, >> >> it's all 64bit! >> Unless linking with x86_64-w64-mingw32-gfortran produces something >> 32bit'ish. >> >> java -version >> java version "1.6.0_24" >> Java(TM) SE Runtime Environment (build 1.6.0_24-b07) >> Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode) >> >> x86_64-w64-mingw32-gfortran --version >> GNU Fortran (GCC) 4.5.2 >> >> x86_64-w64-mingw32-gcc --version >> x86_64-w64-mingw32-gcc (GCC) 4.5.2 >> >> >> Is there any means to inspect the dll wrt its "bitness"? >> >> Greets, >> H. > > Yes, you can use the objdump tool with option -f for this. > > Btw are the functions in your DLL exported? You can check this via > x86_64-w64-mingw32-objdump tool, too. Use here -x option and see the > dump about export table. > > Regards, > Kai Kai, I've attached the outputs of 'x86_64-w64-mingw32-objdump -x' for the dlls built with and without fortran. Unfortunately, as I'm a mere mortal, I cannot comprehend what these outputs tell me. Thx., Hans |