From: Kai T. <kti...@go...> - 2011-04-15 14:50:44
|
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 |