tester
tester

Reputation: 77

creating and accessing fortran dynamic array in c function

I can create and use dynamic two dimensional array in Fortran (in 77 standard). Now, I wanted to create my dynamic two dimensional array in C function (using let's say 'malloc') from Fortran program and be able to access it through Fortran program. In Fortran I also want to be able to do smth like a(1:n,2) or a(1,2), and also be able to pass and retrieve my array from Fortran subroutines. Please, can you show me example, and take your time to explain (if possible, I would really appreciate it) how the memories will be aligned? Thanks a ton! Also if two dimensional will not be possible to work directly, I am fine with creation of single dimensional array in C function, but accessing it from Fortran as it was a two dimensional array... Thanks!!!

Upvotes: 4

Views: 1080

Answers (3)

M. S. B.
M. S. B.

Reputation: 29401

Why must you do these things in FORTRAN 77? They are much easier in Fortran 2003, or Fortran 95 with the ISO C Binding. Virtually all current Fortran compilers at the level of Fortran 95 with the ISO C Binding. The combination provides the capabilities that you want, as part of the language standard, and therefore in a platform and compiler independent manner.

If you merely need to create dynamic arrays, you can do that directly in Fortran 95 with allocatable arrays. If you have FORTRAN 77 code that you don't want to alter, you can write some Fortran 95 code and mix the two. You can pass an allocatable array created in Fortran 95 to another Fortran procedure that doesn't declare it as an allocatable.

If there is some reason that the arrays need to be created in C, you use the ISO C Binding to describe the C routine in Fortran. The array created in C with malloc is passed to Fortran with the Fortran type C_PTR. That storage is then connected to a Fortran array with the Fortran intrinsic subroutine c_f_pointer. After that you use the Fortran array and it is the same as the Fortran array.

It is true that the index order of multi-dimensional arrays is different between the languages. This is because Fortran is a column-major language and C is a row-major language. However, it is not necessary for Fortran arrays to be one indexed. That is merely the default. You can change the starting index in the declaration: real array (0:99). Or for a pointer array setup with c_f_pointer with pointer bounds reassignment: array (0:99) => array

Upvotes: 2

No you can not create dynamic array in FORTRAN 77 standard.

You also can not create Fortran "dynamic" array using malloc, any try to deallocate it from Fortran will lead to crash. (You can of course use it in normal ways as a static a array.)

Also If you explicitly request FORTRAN 77, don't use notation like a(1:n,2). It is not supported in this standard.

In Fortran 2003 there is iso_c_binding, but nothing like that exists in FORTRAN 77, you can only pass assumed size arrays and take care of any name mangling used by your compiler (i.e. trailing underscores in Fotran procedure names from C).

Upvotes: 3

Viktor Latypov
Viktor Latypov

Reputation: 14467

The most important difference is the index order. Fortran uses mathematical notation, so the first index is the column index, the second index being the row. C is different and the first index is row.

The macro explains this

#define AccessFortranArray(ArrayName, i,j) ArrayName[j][i]

To do something like a(1:n, 2) cannot be done in C, only the creation of temporary array and extracting the elements in a loop (excluding the case where you want to extract a range of rows - in this case you may use pointer arithmetics in C)

There are good references for the C <-> Fortran interop, like this one

Here's a multidimensional sample as well: Passing Array To/From Fortran

"One more thing".

The names of C functions must contain the underscore at the end to be visible in Fortran. They must be lowercase also. This all refers to the gcc/gfortran pair.

And another one. You've told you're able to pass the array so you know (Jim Balter says this in comment) that Fortran arrays are 1-based and C arrays a 0-based.

And the third one. If all you need is a big block of data, then instead of messing with the linking setup and function calling conventions use the COMMON block.

Like this

/* C Code */

extern struct
{
   double arr[100];
} thearr_;

And the Fortran:

real*8 arr(100)

common/TheArr/ arr

Upvotes: 3

Related Questions