- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have been following the examples in "FORTRAN 90/95 and Java interoperability using JNA", successfully inserting and testing the Fortran subroutines shown in the webpage one by one, each time generating a DLL using it in NetBeans Java. The Java code has no problem loading and using the DLL. The source code for the DLL contains the following 4 subroutines, as per the examples:
FUNCTION mult(a, b)
!DEC$ ATTRIBUTES ALIAS:'foomult', DLLEXPORT :: mult
INTEGER,VALUE :: a,b
INTEGER :: mult
mult = a * b
END FUNCTION
SUBROUTINE ffunc(a, b)
!DEC$ ATTRIBUTES ALIAS:'reffunc', DLLEXPORT :: ffunc
INTEGER :: a,b
a = 3
b = 5
END SUBROUTINE
SUBROUTINE inc(arr, len)
!DEC$ ATTRIBUTES ALIAS:'fooinc', DLLEXPORT :: inc
INTEGER,DIMENSION(len) :: arr
INTEGER,VALUE :: len
INTEGER :: i
DO i = 1, len
arr(i) = arr(i) + 30
END DO
END SUBROUTINE
SUBROUTINE arr2d(arr, m, n)
!DEC$ ATTRIBUTES ALIAS:'arr2d', DLLEXPORT :: arr2d
INTEGER,DIMENSION(m,n) :: arr
INTEGER,VALUE :: m
INTEGER,VALUE :: n
INTEGER :: i,j
DO i = 1, m
DO j = 1, n
arr(i,j) = arr(i,j) + 1
END DO
END DO
END SUBROUTINE
When I add the piece of code below, suddenly Java cannot load the DLL at all, even though the compile/link steps in Fortran show no errors or warnings, and dumpbin /exports correctly indicates that the appropriate modules have been exported.
FUNCTION strpass(line, b)
!DEC$ ATTRIBUTES ALIAS:'foostr', DLLEXPORT :: strpass
INTEGER :: b
CHARACTER(len=b) :: line
LOGICAL :: strpass
strpass = (line == 'str_test') .AND. (b == 8)
END FUNCTION
The text of the error message in Java is as follows:
run:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'libf90str': The specified module could not be found.
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:163)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:236)
at com.sun.jna.Library$Handler.
at com.sun.jna.Native.loadLibrary(Native.java:379)
at com.sun.jna.Native.loadLibrary(Native.java:364)
at jna_test.Main$F95Test.
at jna_test.Main.main(Main.java:84)
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)
!DEC$ ATTRIBUTES ALIAS:'foostr', DLLEXPORT :: strpass
INTEGER :: b
CHARACTER(len=b) :: line
LOGICAL :: strpass
strpass = (line == 'str_test') .AND. (b == 8)
END FUNCTION
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Moreover, it seems that you forget to add :BIND(C, name='foostr')to the declaration of the function as mentioned in the article you refer to.
[fortran]FUNCTION strpass(line, b) BIND(C, name='foostr') CHARACTER(len=b) :: line INTEGER, VALUE :: b LOGICAL :: strpass strpass = (line == 'str_test') .AND. (b == 8) END FUNCTION[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the suggestion. I will make sure the declaration for the string length is as you indicate and as it appears in the article. I purposefully removed the BIND declaration, as I am using the !DEC$ in all the functions (not just this one), where the ALIAS declaration is used in it's stead. However, I now think that the "C" portion of the BIND declaration may have something to do with the problem.
I have had to make minor allowances and changes from what's posted in the article, as there are minor typos and reversals of instructions; problems occur if we use the examples verbatim.
Also, it is a little baffling that the addition of the 'foostr' subroutine apparently causes the entire DLL to be "not found" by Java, intead of giving a less definitive error. It apparently loses the definitions for the other subroutines.
Bruno
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can use the depends utility that comes with visual studio (and is available as a free download) to see whether all the DLLs needed to load your DLL can be found. Note that you need to run it in the same environment (same PATH) as Java uses to see the same results that Java would see.
As an aside (more of a response to a previous post of yours) - my personal preference is to avoid compiler directives whenever I can - because they are inherently compiler specific. In this case (Fortran to another language) nstead of DLLEXPORT I would supply a separate DEF file to the linker to nominate the DLL's exported entry points. Your code then just looks like...
[fortran]MODULE MyJavaUtils IMPLICIT NONE CONTAINS FUNCTION mult(a, b) BIND(C, NAME='foomult') USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT INTEGER(C_INT), VALUE :: a,b INTEGER(C_INT) :: mult mult = a * b END FUNCTION END MODULE MyJavaUtils [/fortran](C_INT kind corresponds to C's int type)
and then you would have a DEF file that contained...
[plain]EXPORTS foomult[/plain]Within Visual Studio you supply the name of the DEF file via the property Linker > Input > Module Definition File, if you are using the command line you can just supply the filename directly as an argument to the ifort driver. See the help for the linker for more information on DEF files.
Note with a separate DEF file I think you lose magic DLLEXPORT to DLLIMPORT handling with module procedures that are USE'd elsewhere, plus some people find that having a separate file is opaque/inconvenient and/or a maintenance problem, so they are not everyone's cup of tea.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I hate cryptic error messaging.
Thanks to all who helped!
Bruno Repetto, PhD
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I am having the same problem you were experiencing. I used Intel's Fortran compiler. What is the compiler you used? Also can you provide the compiler settings if they are different than the default ones. I used the dependency tool and it is showing that the following dll libraries are missing.
msvcr110d.dll
kernel32.dll
libifcoremdd.dll
Although I copied these libraries into the path where the library is called this did not resolve the error message. The message is:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'echoOutput_': The specified procedure could not be found.
at com.sun.jna.Function.<init>(Function.java:179)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:345)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:325)
at com.sun.jna.Library$Handler.invoke(Library.java:203)
at NB3Eqs.$Proxy0.echoOutput_(Unknown Source)
at NB3Eqs.NB3Eqs_Solution.unitTest(NB3Eqs_Solution.java:110)
at NB3Eqs.NB3Eqs_Solution.main(NB3Eqs_Solution.java:148)
Thanks for your help,
Mohammad
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mohammed,
I managed to solve this problem a while back, so much so that I don't remember all the details... but we can collaborate here and make sure things will work with you, so let me give it a shot:
- The compiler I used back then identified itself as "Intel(R) Visual Fortran Composer XE 2011 Update 9 Integration for Microsoft Visual Studio* 2008, 12.1.3526.2008".
- Make sure that your Java package knows where the support DLLs are. I used Eclipse. In Eclipse, you point to the necessary folders by entering the paths to anything you want to include in Java Build Path / Libraries entry of your Java project properties.
- I put the JNA.jar file in the folder where I have the DLL.
- Point to your DLL using a VM argument. In Eclipse, I followed this path of menus and tabs:
Run / Run Configurations... / "Main" entry under "Java Application" on the left-side panel / "(x)= Arguments" tab
In the VM arguments sub-window, enter these: -Xmx768m -Djna.library.path="<full path to the folder where your DLL is>".
You may have to tweak the 768 number.
- These are the DLLs that I had to include, in addition to mine (myDLL.dll) to support Fortran access by Java:
libifcoremd.dll libifportmd.dll libmmd.dll
I defined my Fortran project in two ways: One, where the subroutine would be tested using a fortran "driver" routine, so I could debug it, and another where the DLL would be created and tested using the Java code. The only difference between the project modes was that the DLL-generating one would include the compiler-directive in the subroutine that read:
!DEC$ ATTRIBUTES ALIAS:'myDLL', DLLEXPORT :: myDLL
The presence or absence of this compiler directive was controlled by the presence or absence of "DLL", a compiler symbol that I defined.
Hope this helps!!
Bruno W. Repetto, PhD
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bruno,
Thanks for your quick and detailed reply. After generating the DLL from Intel Fortran compiler is there a way to check that the functions are accessible to JAVA. For gfortran I can write nm filename.dll and all the functions in the dll are shown in command prompt. But for the Intel compiler the nm functions indicates there are no symbols in the dll.
Thanks for your help,
Mohammad
Mohammad
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, there is a way, but unfortunately I must confess I don't remember how I did it. My apologies. Perhaps you may want to ask this question elsewhere in this forum.
Bruno W. Repetto, PhD
Bruno Repetto.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The depends.exe (Depenency Walker) utility shows you the exports from a particular DLL (in addition to checking that all the other DLL prerequisites are available).
(A modern Windows system that can't find kernel32.dll is rather broken!)

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page