Creating and accessing a fortran dynamic array in c function

I can create and use a dynamic two-dimensional array in Fortran (in standard 77). Now I wanted to create my dynamic two-dimensional array in the C function (using let say 'malloc') from the Fortran program and access it through the Fortran program. In Fortran, I also want to be able to do smth as (1: n, 2) or (1,2), and also be able to pass and retrieve my array from Fortran routines. Please, you can show me an example and do not rush to explain (if possible, I would really appreciate it) how the memories will be built? Thanks a ton! In addition, if two-dimensional is not possible to work directly, I am well versed in creating a one-dimensional array in the C function, but access it from Fortran, since it was a two-dimensional array ... Thanks !!!

+4
source share
3 answers

No, you cannot create a dynamic array in the FORTRAN 77 standard.

You also cannot create a dynamic Fortran array using malloc, any attempt to free it from Fortran will fail. (Of course, you can use it in the usual way as a static array.)

Also, if you explicitly request FORTRAN 77, do not use a type notation a (1: n, 2). It is not supported in this standard.

Fortran 2003 has iso_c_binding , but nothing similar exists in FORTRAN 77, you can only pass the accepted size arrays and take care of any name used by your compiler (i.e. ending the underscore in Fotran procedure names with C).

+3
source

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

The macro explains this

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

To do something like (1: n, 2), it is impossible to do in C, only creating a temporary array and extracting elements in a loop (except when you want to extract a series of lines - in this case, when you can use pointer arithmetic in C)

There are good links for C ↔ Fortran interop, like this one

Here's also a multi-dimensional pattern: Transferring an array to / from Fortran

"One more thing."

C function names must have an underscore at the end to be visible in Fortran. They must also be lowercase. All this applies to the gcc / gfortran pair.

And one more. You said you could pass an array so you know (Jim Balter comments in a comment) that Fortran arrays are based on 1 and C arrays are based on 0.

And the third one. If all you need is a large data block, then instead of messing around with link layout settings and function calls, use a COMMON block.

Like this

 /* C Code */ extern struct { double arr[100]; } thearr_; 

And fortran:

 real*8 arr(100) common/TheArr/ arr 
+3
source

Why would you do this in FORTRAN 77? They are much simpler in Fortran 2003 or Fortran 95 with ISO C binding. Almost all current Fortran compilers at Fortran 95 level with ISO C binding. The combination provides the features you want as part of the standard language, and therefore, regardless of platform or compiler .

If you just need to create dynamic arrays, you can do this directly in Fortran 95 using distributed arrays. If you have FORTRAN 77 code that you do not want to change, you can write Fortran 95 code and mix the two. You can pass the distributed array created in Fortran 95 to another Fortran procedure that does not declare it as allocatable.

If there is any reason that arrays should be created in C, you use the ISO C binding to describe the C routine in Fortran. An array created in C using malloc is passed to Fortran using the C_PTR type of Fortran type. Then this storage is connected to the Fortran array with the Fortran c_f_pointer built-in routine. After that, you use the Fortran array, and it matches the Fortran array.

It is true that the order of the indices of multidimensional arrays differs between languages. This is because Fortran is the main language of the column, and C is the main language. However, Fortran arrays do not need to be indexed. This is just a default. You can change the starting index in the declaration: real array (0:99). Or to configure an array of pointers using c_f_pointer with overriding pointer boundaries: array (0:99) => array

+2
source

All Articles