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

Passing 2D array from C++ to Fortran

efnacy
New Contributor I
1,512 Views

Not really a problem, I just want some assessment of my method for passing multidimensional array from C++ main program to a Fortran subroutine.

The C++ code reads

#include <iostream>                                                                                                                        
                                                                                                                                           
extern "C"                                                                                                                                 
{ void FTN_for_sub2(const long int *, const long int *, const double *);}

int main()                                                                                                                                 
{                                                                                                                                                                                                                                                                
  long int m=2;                                                                                                                            
  long int n=3;                                                                                                                                                                                                                  
  double z;                                                                                                                          
                                                                                                                                           
  z[0][0] = 1.0;                                                                                                                           
  z[0][1] = 5.0;                                                                                                                           
  z[0][2] = 6.0;                                                                                                                           
  z[1][0] = 3.0;                                                                                                                           
  z[1][1] = 2.0;                                                                                                                           
  z[1][2] = 10.0;                                                                                                                                                             
                                                                                                                                                                                                                                              
  FTN_for_sub2(&m, &n, &z[0][0]);                                                                                           
                                                                                                                                            
  return 0;                                                                                                                                
}                                                                                                                                          

whereas the Fortran routine is

subroutine FOR_SUB2(m, n, z) bind(C, name="FTN_for_sub2")                                                                         
  use, intrinsic :: iso_c_binding                                                                                                          
  implicit none                                                             
  integer(c_long), intent(in) :: m, n                                          
  real(c_double), intent(in) :: z(n,m)       ! z must declared as z in the C++ side.                                                 
                                                                                                                                           
  character :: dummy_str*4, fmt*100                                                                                                        
  integer(c_long) :: i
 
  write(dummy_str, "(i4)") m 
  fmt = "("//trim(adjustl(dummy_str))//"f12.4)"
  do i = 1,n
     write(*,fmt) z(i,1:m)
  end do                                                                                                                                                                                                                                                                              
                                                                                                                                           
end subroutine FOR_SUB2    

These codes compiled and ran well but one thing that still bothers me is the way I pass 2D array z from C++ side which is

&z[0][0] 

I searched many resources about passing multidimensional array from C++ to Fortran and I never encountered my method suggested in any of those sources. My question is are there any drawbacks in my method, is it frowned upon or something else?

0 Kudos
5 Replies
mecej4
Honored Contributor III
1,512 Views

Fortran uses column-major storage order, C uses row-major order. See https://en.wikipedia.org/wiki/Row-_and_column-major_order .

As long as your C and Fortran source codes handle the arrays correctly in conformity with the rules of each language, there is no reason to frown on the code. On the other hand, if you wish to write subroutines/functions that have to process 2-D arrays of arbitrary dimensions, you will need full awareness of the differences between the two languages and the calling conventions of the compiler+platform.

When array arguments are passed to subroutines, Fortran allows you several ways in which to pass information regarding the extents of the array indices, whether the array may be allocated or its allocation changed, etc., and C does not do things in the same ways. Fortran 2003 and 2008 provide an extensive set of rules and facilities for interoperability with C.

 

0 Kudos
efnacy
New Contributor I
1,512 Views

I asked that because I am about to write a moderate size project mixing C++ and Fortran. I am new to C++, let alone the interoperability issues with Fortran. Until now in Fortran I almost always declare dummy array arguments to be of assumed-shape but then I learned that assumed-shape is not interoperable with C/C++. Some examples use assumed-size but to me assumed-size declaration is not quite elegant. That's why I decided to use adjustable type.

0 Kudos
Steve_Lionel
Honored Contributor III
1,512 Views

Assumed-shape is now interoperable with C, but on the C side it must process it using a "C descriptor" as declared in ISO_Fortran_binding.h that Intel Fortran supplies. This is a Fortran 2018 feature supported as of version 16.

0 Kudos
efnacy
New Contributor I
1,512 Views

Ok I will take a look, but is this header file usable from C++ code too?

0 Kudos
mecej4
Honored Contributor III
1,512 Views

Yes, you can use the header file in C++ code. If you look at the file itself, you will see the following near the beginning

#if defined(__cplusplus)
extern "C" {
#endif

and matching conditionally included code near the end of the file to supply the closing "}".

0 Kudos
Reply