Calling Fortran from Julia (iii) : passing 2D arrays

Passing 2D arrays between Julia and Fortran can be somewhat problematic. Firstly, don’t return an array pass it as a parameter in a subroutine. This is much easier. The trick with 2D arrays is that C uses call-by-value by default while Fortran behaves more like call-by-reference. A Fortran subroutine becomes interoperable if it has an explicit interface and is declared with the bind attribute:

Consider the following piece of code, which returns an identity matrix of size n.

module matrix

contains

pure subroutine identityMatrix(n,zImage) bind(C,name="identityMatrix")
   use, intrinsic :: iso_c_binding, only: c_int
   implicit none
   integer(c_int), intent(in) :: n
   integer(c_int), intent(inout), dimension(n,n) :: zImage

   integer :: i, j

   do j=1,n
      do i=1,n
         if (i == j) then
            zImage(i,j) = 1
         end if
      end do
   end do
end subroutine identityMatrix

end module matrix

This uses the intrinsic module to import the interoperable type c_int, the “in-between” between Fortran’s integer and C’s int. The bind(C) attribute declaration to indicate that an external function is a C language function.

This can now be compiled into a shared library:

gfortran -shared -fPIC -o array2d.so array2d.f95

Then it can be called from a Julia program, say testFort2d.jl, which passes a 2D array of zeros in (zIm), and returns the modified array:

n = 8
zIm = zeros(Int32, n, n)
ccall((:identityMatrix, "array2d.so"), Void, (Ptr{Int32}, Ptr{Array{Int32,2}}), &n, zIm)
println(zIm)

Now there is a second way, which is easier. Here is the Fortran subroutine (in the file array.f95):

subroutine identityMatrix(n,zImage)
   implicit none
   integer, intent(in) :: n
   integer, intent(inout), dimension(n,n) :: zImage

   integer :: i, j

   do j=1,n
      do i=1,n
         if (i == j) then
            zImage(i,j) = 1
         end if
      end do
   end do

end subroutine identityMatrix

Compiled into a library:

gfortran -shared -fPIC -o array.so array.f95

And the accompanying Julia code is:

n = 8
zIm = zeros(Int32, n, n)
ccall((:identitymatrix_, "array.so"), Void, (Ptr{Int32}, Ptr{Array{Int32,2}}), &n, zIm)
println(zIm)

 

 

 

Advertisements

One thought on “Calling Fortran from Julia (iii) : passing 2D arrays

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s