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

Fortran and C++ working together

Katarina_R_
Beginner
677 Views

Hi,
I want to have Fortran code that will call some functions in C++. The thing is I want to create arrays of objects, some variables and I want C++ code to keep running after Fortran call. Basically I need something like this. Fortran calls C++ function that reads numbers from file and save it in a object variable, after that Fortran sleeps for a while and calls C++ function and gets the saved numbers. So I need to call C++ once to save some data, then call it again later on and work with the data that was saved. I need data in objects. I've read about external variables in Fortran and I saw that it can work with C++ through subroutines but I need a lot of objects in C++ code and don't want to store values in Fortran too. I work in VisualStudio.
Can this be done?


 

0 Kudos
10 Replies
PaulF_IntelCorp
Employee
677 Views

Katarina -- your thread was posted in the wrong forum. I'm moving it to a forum that I believe can help.

0 Kudos
FortranFan
Honored Contributor II
677 Views

@katarina_ralevic,

Just for starters, take a look at this thread, particularly message #12 where a small but complete working example of C++ main working with a Fortran 'library' is shown:

https://software.intel.com/en-us/node/697150#comment-form

With the above thread as background, if you can provide specific details of your need - better yet, take a shot at some coding and post any difficulties here - you can get a lot more help.

Good luck,

 

0 Kudos
Katarina_R_
Beginner
677 Views

@FortranFan

I have a simple question. I've made C++ static library and called it something.lib and I tried calling it from another C++ program to see if it works and it works fine. Then I've tried to call it from Fortran and I'm not sure should I write include or use in order to do that. And how exactly to write that call, I have a compiler problem when I write use something.lib it says that compiler can't find .mod files and when i write include  'something' it says cannot open include file 'something'.

0 Kudos
jimdempseyatthecove
Honored Contributor III
677 Views

C/C++/?? libraries are not module. When Fortran calls such a library you must declare the subroutine/function using an interface block. However, note that you will also (usually) require a BIND C or !DIR$ ATTRIBUTE to specify the calling convention. The normal procedure to to use C calling convention as opposed to C++.

Check the IVF documentation under:

interoperability with C
   Standard Fortran and C Interoperability

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
677 Views

Katarina R. wrote:

@FortranFan

I have a simple question. I've made C++ static library and called it something.lib and I tried calling it from another C++ program to see if it works and it works fine. Then I've tried to call it from Fortran and I'm not sure should I write include or use in order to do that. And how exactly to write that call, I have a compiler problem when I write use something.lib it says that compiler can't find .mod files and when i write include  'something' it says cannot open include file 'something'.

@Katarina R.,

Shown below is a simple but reasonably complete example, please note your C++ functions and library will be "external" to Fortran, so you would need to define those somewhere, preferably provide explicit interfaces (C type of function prototypes) in a Fortran module and inform the linker about the static library.  Attached zip file has the Visual Studio solution and project files for this; note it was created using VS 2013.

As suggested by Jim Dempsey, using the standard facilities in Fortran for interoperability with C may work out best for you; please note the companion C processor becomes the common platform for C++ and Fortran to interoperate.

Hope this helps,

#include <iostream>
using namespace std;

extern "C" {

   // Prototype for a function with extern attribute 
   int cpp_foo(char *string, int i, double d[], size_t size_d, void *add_d);

}

int cpp_foo(char *string, int i, double d[], size_t size_d, void *add_d)
{

   cout << "In cpp_foo: " << endl;
   cout << string << endl;
   cout << "i = " << i << endl;
   cout << "d = " << endl;

   for (size_t j = 0; j < size_d; j++)
   {
      cout << "[" << j << "] = " << d << endl;
   }

   cout << "address of d: = " << add_d << endl;

   return(0);
}
module m

   use, intrinsic :: iso_c_binding, only : c_int, c_char, c_double, c_size_t, c_ptr, c_loc, c_null_char

   implicit none

   private

   interface
   
      function cpp_foo(string, i, d, size_d, m) result( iret) bind(C, name="cpp_foo")
 
         import :: c_int, c_char, c_double, c_size_t, c_ptr

         implicit none
         
         !.. Argument list
         character(kind=c_char,len=1)  :: string(*)
         integer(kind=c_int), value    :: i
         real(kind=c_double)           :: d(*)
         integer(kind=c_size_t), value :: size_d
         type(c_ptr), value            :: m
      
         !.. return value
         integer(c_int) :: iret
               
      end function cpp_foo
         
   end interface
   
   public :: cpp_foo
 
end module m
program p

   use, intrinsic :: iso_c_binding, only : c_int, c_char, c_double, c_size_t, c_ptr, c_loc, c_null_char
   use m, only : cpp_foo

   implicit none

   character(kind=c_char,len=:), allocatable :: msg
   integer(kind=c_int) :: i
   real(c_double), target :: d(10)
   integer(kind=c_size_t) :: size_d
   type(c_ptr) :: add_d
   integer(kind=c_int) :: iret

   msg = c_char_"Hello World!" // c_null_char
   d = [( real(i, kind=kind(d)), i = 1, size(d) )]
   size_d = int( size(d), kind=kind(size_d) )
   i = 42
   add_d = c_loc( d )

   iret = cpp_foo( msg, i, d, size_d, add_d )
   print *, "cpp_foo returns ", iret

   stop

end program p

Upon execution, you should get:

In cpp_foo:
Hello World!
i = 42
d =
[0] = 1
[1] = 2
[2] = 3
[3] = 4
[4] = 5
[5] = 6
[6] = 7
[7] = 8
[8] = 9
[9] = 10
address of d: = 000000000021F9F0
 cpp_foo returns  0
Press any key to continue . . .

 

0 Kudos
Katarina_R_
Beginner
677 Views

@FortranFan and @jimdempseyatthecove

Thank you both so much. I've tried the example and it works, the last problem I have is that Fortran program that I have is .for and this example is .f90. Is there some way that are not modules to connect C++ and Fortran since .for  doesn't support modules? Or is it possible that my .for program calls .f90 and then I can leave everything like it is in the example?

0 Kudos
Arjen_Markus
Honored Contributor I
677 Views

You misunderstand the meaning of the two extensions. They represent different forms of the source code, not different capabilities. .for (or .f) is typically used for "fixed form" source and .f90 is used for "free form". So you can use modules in a file with the extension .for, as you can use all other features of the Fortran language.

0 Kudos
Katarina_R_
Beginner
677 Views

 

I've already tried to just write this example in .for and it's not working. I've read about "fixed form" files and conventions for writing them and I guess made some mistake since I'm new to Fortran.

0 Kudos
Arjen_Markus
Honored Contributor I
677 Views

Can you post your code and elaborate on what is not working? Compiler errors?

0 Kudos
FortranFan
Honored Contributor II
677 Views

Katarina R. wrote:

.. the last problem I have is that Fortran program that I have is .for and this example is .f90. Is there some way that are not modules to connect C++ and Fortran since .for  doesn't support modules? Or is it possible that my .for program calls .f90 and then I can leave everything like it is in the example?

@Katarina R.,

Now you're asking basic questions related to FORTRAN and Fortran: I suggest you go through sources like the one below fully:

http://fortranwiki.org/fortran/show/HomePage

0 Kudos
Reply