CuriousAlpaca
CuriousAlpaca

Reputation: 163

passing an allocatable multi dimensional fortran array to a C function

I have the following main program in Fortran

program test
use iso_c_binding
implicit none

real(c_double), dimension(:,:), allocatable :: a

allocate(a(2,3))

call c_func(a)

print *,a

end program test

c_func is a function in C that takes in the multi dimensional array a and modifies it.

void c_func (double **arr) {
      modifies the array arr here
}

Is there a way to do this? I can do it for 1 dimensional allocatable array, but not for higher dimensions. And I don't want to flatten the array.

Upvotes: 2

Views: 133

Answers (2)

PierU
PierU

Reputation: 2689

To complete the answer of @EricPostpischil, on the Fortran side the code should ideally define an explicit interface for the C function. And for if you really want to work on the array in the C function you should pass the 2 dimensions:

void c_func(int N, int M, double (*arr)[N])
interface
   subroutine c_func(n,m,arr) bind(C,name="c_func")
      integer(c_int), value :: n,m
      real(c_double) :: a(n,m)   ! a(n,*) or a(*) would also do
   end subroutine c_func
end interface

...

real(c_double), dimension(:,:), allocatable :: a
integer :: n, m
...
allocate( a(n,m) )
...
call c_func( n, m, a )
...

Upvotes: 1

Eric Postpischil
Eric Postpischil

Reputation: 222272

In C, double **arr does not declare a multidimensional array. It declares, at best, a pointer to an array of pointers to double. (Technically, it declares a pointer to one pointer to double, and it is common to put multiple pointers one after the other, making an array of pointers, so arr would be a pointer to the first element of an array of pointers to double.)

Due to C semantics, such a pointer can be used in source code with two subscripts like a multidimensional array, as in arr[i][j], but the layout in memory is very different. arr points to memory where there are pointers, not memory where there are many double values laid out in rows and columns.

To declare a pointer to (the start of) a multidimensional array, use double (*arr)[N], where N is the number of columns (in the C view) of the array. You may need to pass N to the function in an earlier parameter, unless it is a fixed value. The function declaration could be void c_func(size_t N, double (*arr)[N]). You might need to change size_t there to match the type the Fortran code is passing.

Upvotes: 3

Related Questions