Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29277 Discussions

Linking visual fortran program with c++ program

osamaintel
Beginner
976 Views
Hi guys;

I'm trying to connect Java to intel visual fortran using JNI. One of the steps in the way is to create a dll library that contains visual fortran files and c++ files.

Do you know how to build a dll library that contains visual fortran files and C++ (or visual c++)files?

Thank you.
0 Kudos
1 Solution
IanH
Honored Contributor III
976 Views
Elaborating on tim18's suggestion - if you are using IVF 11.x, use the F2003 C-interoperability feature to make things easier.

On the C++ simply declare the function as:

[cpp]extern "C" void fortprinthello();[/cpp]

Then, on the fortran side add the bind suffix to the subroutine call. The bind NAME= argument needs to match (case sensitive) the C++ declaration of the function, your fortran subroutine name can then be whatever you want (alternatively, without a NAME= specifier the C++ side wants a lower case version of the fortran name).

[plain]subroutine WhateverYouWant() bind(C, NAME='fortprinthello')
  print *, 'Hello World'
end subroutine
[/plain]

Getting the Fortran and C++ symbol names and calling convention to match up is then the compiler's problem, not yours.

The dynamic library suggestion relates to dynamically linking to the the C and fortran runtime libraries. This can avoid problems with "multiple runtime library syndrome" down the track, which has been known to cause premature aging. Add /MD to both command lines. To get ifort to actually build a DLL you'll also need the /dll option on its command line.

Good luck.

View solution in original post

0 Kudos
6 Replies
TimP
Honored Contributor III
976 Views
Quoting - osamaintel

Do you know how to build a dll library that contains visual fortran files and C++ (or visual c++)files?


If it fits your intentions, declare the interoperable object on the C++ side with extern "C" and, on the Fortran side
USE iso_c_interop and the corresponding data types. In my limited Windows experience, using Fortran to create the .dll should automatically refer to all necessary basic libraries, with dynamic linking probably being easier.
0 Kudos
osamaintel
Beginner
976 Views
Quoting - tim18
If it fits your intentions, declare the interoperable object on the C++ side with extern "C" and, on the Fortran side
USE iso_c_interop and the corresponding data types. In my limited Windows experience, using Fortran to create the .dll should automatically refer to all necessary basic libraries, with dynamic linking probably being easier.

I don't exactly understand your answer. But, let me give you a more detailed scenario:

1- I have the following C++ file CCode.cpp

#include
#include "JavaCode.h"
extern "C" void __stdcall fortprinthello();

JNIEXPORT void JNICALL Java_JavaCode_printhello(JNIEnv *env,jobject obj)
{
fortprinthello();
}

2- I have the following fortran 90 program (FortranCode.f90)

subroutine fortprinthello()
print *, 'Hello World'
end subroutine

I'm trying to compile and link those 2 programs together using visual studio command line and intel visual fortran command line. So, what I'm doing is the following:
a- Compile cpp file using visual studio command line compiler:

cl -I"c:Program FilesJavajdk1.6.0_14include" -I"c:Program FilesJavajdk1.6.0_14includewin32" /c CCode.cpp

b- This works and generates CCode.obj, then I execute this command using intel visual fortran compiler

ifort CCode.obj FortranCode.f90

I get the following error:

CCode.obj : error LNK2019: unresolved external symbol _fortprinthello@0 referenced in function _Java_JavaCode_printhello@8

Any idea what is happening?

Thank you

0 Kudos
IanH
Honored Contributor III
977 Views
Elaborating on tim18's suggestion - if you are using IVF 11.x, use the F2003 C-interoperability feature to make things easier.

On the C++ simply declare the function as:

[cpp]extern "C" void fortprinthello();[/cpp]

Then, on the fortran side add the bind suffix to the subroutine call. The bind NAME= argument needs to match (case sensitive) the C++ declaration of the function, your fortran subroutine name can then be whatever you want (alternatively, without a NAME= specifier the C++ side wants a lower case version of the fortran name).

[plain]subroutine WhateverYouWant() bind(C, NAME='fortprinthello')
  print *, 'Hello World'
end subroutine
[/plain]

Getting the Fortran and C++ symbol names and calling convention to match up is then the compiler's problem, not yours.

The dynamic library suggestion relates to dynamically linking to the the C and fortran runtime libraries. This can avoid problems with "multiple runtime library syndrome" down the track, which has been known to cause premature aging. Add /MD to both command lines. To get ifort to actually build a DLL you'll also need the /dll option on its command line.

Good luck.

0 Kudos
osamaintel
Beginner
976 Views
Quoting - IanH
Elaborating on tim18's suggestion - if you are using IVF 11.x, use the F2003 C-interoperability feature to make things easier.

On the C++ simply declare the function as:

[cpp]extern "C" void fortprinthello();[/cpp]

Then, on the fortran side add the bind suffix to the subroutine call. The bind NAME= argument needs to match (case sensitive) the C++ declaration of the function, your fortran subroutine name can then be whatever you want (alternatively, without a NAME= specifier the C++ side wants a lower case version of the fortran name).

[plain]subroutine WhateverYouWant() bind(C, NAME='fortprinthello')
  print *, 'Hello World'
end subroutine
[/plain]

Getting the Fortran and C++ symbol names and calling convention to match up is then the compiler's problem, not yours.

The dynamic library suggestion relates to dynamically linking to the the C and fortran runtime libraries. This can avoid problems with "multiple runtime library syndrome" down the track, which has been known to cause premature aging. Add /MD to both command lines. To get ifort to actually build a DLL you'll also need the /dll option on its command line.

Good luck.


Thank you Tim and Ian, your comments are really useful. Just for the benefit of everyone, I will list all the files and command I used:

1- The general problem is: create a java program that uses JNI to invoke fortran method through C++ given that the following compilers will be used:
* Intel Visual Fortran command line compiler
* Visual C++ command line compiler
* javac java compiler

2- The complete solution (Thanks to Tim and Ian) is the following:

Java File (JavaCode.java):
----------------------------------

class JavaCode
{
private native void printhello();

public static void main(String[] args)
{
new JavaCode().printhello();
}

static
{
try
{
System.out.println("java.library.path="+System.getProperty("java.library.path"));
System.loadLibrary("HelloWorld");
}
catch(Exception x)
{
System.out.println("exception loading library");
x.printStackTrace();
}
}
}
--------------------------------------------
I compile it using: javac JavaCode.java
The result is JavaCode.class
Next, I use javah to generate C++ header file as follows javah -jni JavaCode
The result is the following file JavaCode.h
-----------------------------------------------
JavaCode.h
-----------------------------------------------

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class JavaCode */

#ifndef _Included_JavaCode
#define _Included_JavaCode
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JavaCode
* Method: printhello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JavaCode_printhello
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
------------------------------------------
Next I write my simple fortran file:
------------------------------------------
FortranCode.f90
------------------------------------------
subroutine fortprinthello() bind(C, NAME='fortprinthello')
print *, 'Hello World'
end subroutine
-----------------------------------------
Next I compile fortran code using intel visual fortran command line prompt
ifort /c FortranCode.f90
The result is FortranCode.obj
-----------------------------------------
Next I write the C++ file which implements method in JavaCode.h and calls fortran routine
-----------------------------------------
CCode.cpp
-----------------------------------------

#include
#include "JavaCode.h" // Required header for JNI


extern "C" void fortprinthello();

JNIEXPORT void JNICALL Java_JavaCode_printhello(JNIEnv *env,jobject obj) {
fortprinthello();
}

void main()
{
fortprinthello();
}
-------------------------------------------------------------------
Next I compile it using visual c++ command line
cl -I"c:Program FilesJavajdk1.6.0_14include" -I"c:Program FilesJavajdk1.6.0_14includewin32" -LD FortranCode.obj CCode.cpp -FeHelloWorld.dll

The result is CCode.obj and HelloWorld.dll

The last thing to do is to set the library path and run the java code
java -Djava.library.path=. JavaCode

I hope you find this information useful.

0 Kudos
veitner
Beginner
976 Views
Quoting - osamaintel
Hi guys;

I'm trying to connect Java to intel visual fortran using JNI. One of the steps in the way is to create a dll library that contains visual fortran files and c++ files.

Do you know how to build a dll library that contains visual fortran files and C++ (or visual c++)files?

Thank you.

A few days ago I posted a tiny sample in how to do that:

http://software.intel.com/en-us/forums/showthread.php?t=67274

Veit
0 Kudos
Amrin_Fathima
Beginner
976 Views
Thanks a ton!!!

I helped me a lot
0 Kudos
Reply