Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

JNI for using fortran dll

Samantha_G_
Beginner
6,489 Views

I'm new to this forum and was not sure where to post this question.  I've got some questions regarding setting up a JNI to access a Fortran dll.

I've built a Fortran dll from f77 from UNIX for the PC using the Intel compiler.  Now I need to access it from my Java code via C++ wrapper code.  I've searched online and most examples show you how to take a simple piece of Fortran code and nothing as complex as I really need.  My basic issue is that the Fortran code I used to make the dll is maintained by someone else.  So I am not really authorized to make any changes to it.  I'd like to be able to do everything I need inside the wrapper C++ code and simply call the dll to perform the necessary calculations.

That being said here are my questions:

1.  Is there some kind of table so I can match up the datatypes between the Java/C/Fortran codes?  The Fortran code is expecting reals, real arrays, int, int arrays, character*1, and character*(*).  I'm not sure how to specify these in the extern line in the C++ code.  Do I pass by reference or by value?

extern "C" void WIND(float*,float[],float[][],const char*....) ??

Java is of course passing floats, 2d float arrays, and strings.  I can't find an example that explains how to declare variables for the function prototype for the Fortran subroutine.

I know the conversion from Java to C++ code has items such as jstring, jobjectArray, and jfloatArrays which make sense and works fine for me.

2.  Assuming I can correctly call my Fortran subroutine from the dll, how to I get values back.  The subroutine accepts several input variables and returns several output variables.  I understand that I have to convert the java arrays into native arrays to pass to Fortan and vice versa, once the Fortan code has returned the output values, I must convert those arrays back into something I can pass back to Java.

I have Fortran subroutines and not Fortran functions so will I still be able to get back a bunch of ouptut variables the same way such as this?

WIND(inX,inY,inZ,outA,outB,outC)

3.  Assuming I can get back outA, outB, and outC does this mean I have to write getter/setter methods inside the C++ code so my java code can get back all of my data since Java limits me to one object for returning?  What's the best way to do this?  Should I just make global variables in the C++ code that get set once I get my data back from the Fortran dll call?  Then I could tell Java to call the getter methods after the initial run of the calculations have been completed?

Any suggestions any one can give me with be very much appreciated.  I have gotten a JNI working for some other C++ code so I just need help on how to extend this to work for a Fortran dll that I'm not allowed to alter.

0 Kudos
31 Replies
mecej4
Honored Contributor III
1,970 Views

From your last CPP file I see that your prototype for the Fortran function WIND has one error: Intel Fortran expects the lengths of CHARACTER arguments to be made available as hidden arguments added to the end of the original argument list, and these string lengths are passed by value.

Therefore instead of ",size_t* seaslen, size_t* fnamelen" you should have "size_t seaslen, size_t fnamelen" (corrected following Dr. Fortran below).

Please post the Java code that calls the C++/Fortran DLL, so that we can see if the Fortran subroutine is receiving the intended argument values.

0 Kudos
Samantha_G_
Beginner
1,970 Views

Thanks mecej4, I missed that.  Good news everybody!  I can report that all the hookups are working now.  I did a temporary hack of the code to confirm that I am getting inside the Fortran subroutine.  That worked.  However the Fortran subroutine is not performing the calculations correctly.  I need to investigate that all the inputs made it to the other side correctly.  I'm glad the hard part has been done.  I can debug Fortran code in my sleep.

If I could, I'd buy beers for all you guys!

0 Kudos
Steven_L_Intel1
Employee
1,970 Views

mecej4 wrote:

Therefore instead of ",size_t* seaslen, size_t* fnamelen" you should have "int seaslen, int fnamelen".

Almost.  size_t is correct, not int. But no *.  So, "size_t seaslen, size_t fnamelen". If you know you'll always be running a 32-bit application, you can get away with int but I don't recommend it.

Samantha, I'm glad that we've helped you make such good progress! Be sure to tell your bosses what good support you got from Intel and its user forums! (See why I kept steering you back to the forum rather than your private messages to me?)

0 Kudos
Samantha_G_
Beginner
1,970 Views

I have attached my latest C++ code and the calling Java class.

After doing some debugging this morning, I've figured out the problem.  The input file it's trying to read swind.dat which is a binary file was written using another Fortran compiler.  I need to contact the group that created the input file and get another file created using the Intel or compatible compiler.  I experienced this issue before when I was porting Fortran code from HPUX to LINUX.  The systems were using different Fortran compilers to write and read their binary files.  I had to regenerate the binaries on the new system before the newly compiled code could read them.

I'm trying to build this for a 64bit application.

Will do Steve.  BTW, I tried to upload my file "WindTemp.java" but the webpage refused to let me saying it was an invalid file type.  I had to change the name to "WindTemp.java.txt" for the website to take it.

0 Kudos
Steven_L_Intel1
Employee
1,970 Views

You can always put files into a ZIP for uploading.

Which other Fortran compiler? Intel Fortran can handle unformatted data from most, with some options possiblt needed.

0 Kudos
Samantha_G_
Beginner
1,970 Views

Steve

Most of our codes and binary input files are built on HPUX compilers.  They use f90 or gcc.  When I was building on the LINUX side, I was building using ifort and gcc since f90 was not installed there.  Unfortunately a lot of our codes were a mix of f77 and f90 code so sometimes the gcc compiler was insuffcient for getting everything to work correctly.

When we need this code on the PC side we have an old xp machine that contained MS Powerstation and Digital Fortran.  The old compilers were being used because of downstream requirements of old programs.  Our office is hodge podge of lots of code on various compilers which makes things a lot more difficult than it has to be.

Our Fortran gurus here have somehow made sense of it all and gotten them to work.  Our challenge these days is trying to get our old codes to talk to our new codes like Java.

If you guys could build some magical Fortran to Java converter that would be awesome. :)

0 Kudos
Steven_L_Intel1
Employee
1,970 Views

Ewww - that's the wrong direction! How about converting all that yucky and security-problematic Java to nice and fast Fortran?

If you have unformatted files written by PowerStation, compile the Fortran routine that opens the file with the /fpscomp:ioformat option. I suggest writing a small program that opens the file with the option, then calls a routine in a file compiled normally to write it back out in the Intel format.

HPUX can be handled by using CONVERT='BIG_ENDIAN' on the OPEN.

0 Kudos
Samantha_G_
Beginner
1,970 Views

Steve Lionel (Intel) wrote:

Ewww - that's the wrong direction! How about converting all that yucky and security-problematic Java to nice and fast Fortran?

Haha.  If it was up to me, everybody would be running Fortran from the linux cluster and we'd toss out all the PCs.  No more pretty GUIs and force everybody to use command prompts.  However we have a requirement to run a GUI interface on Windows WITHOUT an internet connection.

I did successfully use the convert option on LINUX.  I need to talk to the creator of these input files to see if he can fix the files for me or talk to the others about updating the Fortran code.  Sadly that's the way it goeswhen you are trying to use somebody else stuff.

0 Kudos
mecej4
Honored Contributor III
1,970 Views

If you know that all the input files to be converted were written as unformatted Fortran files on HP UX using code compiled by the native F90 compiler, it would be a fairly simple matter to write a utility to convert the files to the native format of Intel Fortran on Windows.

0 Kudos
Samantha_G_
Beginner
1,970 Views

Okay last update.  Code is running now and returning the correct values.  I rebuilt the program that wrote the binary input files that I needed using the Intel Fortran compiler.  I had to use /assume:byterecl flag on this program and on my Fortran library wndtmp and everything works now as intended.

I'm uploading a zip file of my final Java, cpp, and h files.  I moved my Java code into a Junit test to compare the values my Java code gets back from the Fortran library against the UNIX version of the code an an old VB6 version of the code.  Everything is within a tolerance of 0.1 which is acceptable.

Hope this helps somebody else who is unlucky enough to have to do this.

0 Kudos
Steven_L_Intel1
Employee
1,970 Views

Thanks for the update and the code example! I am sure it will help others.

0 Kudos
Reply