Calling Fortran subroutine from Julia. Arrays work

2020-07-10 02:58发布

问题:

I have this simple Fortran 90 program:

subroutine apc_wrapper(i, j, k)
implicit none

integer*8, intent(in) :: i, j
integer*8, intent(out) :: k
double precision t

k = i + js 
end subroutine

compiled as a shared library

gfortran -O2 -shared -fPIC apc_wrapper.f90 -o apc_wrapper.so

Now, I want to call this subroutine from Julia, with all integer arguments, like this

i = 2
j = 3
k = 0

ccall( (:apc_wrapper_, "./apc_wrapper.so"), Void, (Ptr{Int64}, Ptr{Int64}, Ptr{Int64}), &i, &j, &k)

But it won't work. k won't change its value and keep evaluating to 0.

But, if I do this

 i = 2
 j = 3
 kk = [0]

 ccall( (:apc_wrapper_, "./apc_wrapper.so"), Void, (Ptr{Int64}, Ptr{Int64}, Ptr{Int64}), &i, &j, kk)

That is, use an array to store the output, it works! After calling the subroutine, kk evaluates to

 1-element Array{Int64,1}:
 5

And I didn't change the Fortran code at all, it didn't even know it was dealing with an array, just a block of memory.

So, if Fortran is able to read blocks of memory (i and j were properly red) why isn't able to write into them?

I don't have any problem with this. Actually, I want to use an array as output but still, this behavior surprised me.

回答1:

Well, Julia is a fast-paced developing language and it turns out that the &variable syntax is deprecated. This would be the proper way to do this:

i = 2
j = 3
k = 0
i_ref = Ref{Int64}(i)
j_ref = Ref{Int64}(j)
k_ref = Ref{Int64}(k)

ccall( (:apc_wrapper_, "./apc_wrapper.so"), Void,
(Ref{Int64}, Ref{Int64}, Ref{Int64}),
i_ref, j_ref, k_ref)

and then k_ref.x will evaluate to 5.