从 Julia 调用带有数组参数的 Fortran 子例程
Calling Fortran subroutines with array arguments from Julia
我可以调用编译这个 fortran 代码 'test.f90'
subroutine test(g,o)
double precision, intent(in):: g
double precision, intent(out):: o
o=g*g
end subroutine
和
gfortran -shared -fPIC test.f90 -o test.so
并为 Julia 创建这个包装函数 test.jl:
function test(s)
res=Float64[1]
ccall((:test_, "./test.so"), Ptr{Float64}, (Ptr{Float64}, Ptr{Float64}), &s,res);
return res[1]
end
和 运行 这些命令与寻求的输出:
julia> include("./test.jl")
julia> test(3.4)
11.559999999999999
但我想 return 数组而不是标量。我想我已经尝试了一切,包括在 this 答案中使用 iso_c_binding。但是我尝试的一切都会像这样向我抛出错误:
ERROR: MethodError: `convert` has no method matching convert(::Type{Ptr{Array{Int32,2}}}, ::Array{Int32,2})
This may have arisen from a call to the constructor Ptr{Array{Int32,2}}(...),
since type constructors fall back to convert methods.
Closest candidates are:
call{T}(::Type{T}, ::Any)
convert{T}(::Type{Ptr{T}}, ::UInt64)
convert{T}(::Type{Ptr{T}}, ::Int64)
...
[inlined code] from ./deprecated.jl:417
in unsafe_convert at ./no file:429496729
例如,我想从 julia 调用以下代码:
subroutine arr(array) ! or arr(n,array)
implicit none
integer*8, intent(inout) :: array(:,:)
!integer*8, intent(in) :: n
!integer*8, intent(out) :: array(n,n)
integer :: i, j
do i=1,size(array,2) !n
do j=1,size(array,1) !n
array(i,j)= j+i
enddo
enddo
end subroutine
使用注释掉的变体也是一种替代方法,因为从 julia 调用时仅更改参数似乎没有用。
那么如何使用 Julia 中的数组调用 fortran 子例程?
使用 ccall
时,Julia 数组应作为元素类型的指针以及描述大小的额外参数传递。
您的示例 test.f90
应该是:
subroutine arr(n,array)
implicit none
integer*8, intent(in) :: n
integer*8, intent(out) :: array(n,n)
integer :: i, j
do i=1,size(array,2) !n
do j=1,size(array,1) !n
array(i,j)= j+i
enddo
enddo
end subroutine
像以前一样编译
gfortran -shared -fPIC test.f90 -o test.so
然后在 Julia 中:
n = 10
X = zeros(Int64,n,n) # 8-byte integers
ccall((:arr_, "./test.so"), Void, (Ptr{Int64}, Ptr{Int64}), &n, X)
建议:
'&n' 将导致较新版本的无效语法错误。
而且,使用 Ref 比 Ptr 更安全。
你可以试试:
ccall((:arr_, "./test.so"), Cvoid, (Ref{Int64}, Ref{Int64}), Ref(n), X)
我可以调用编译这个 fortran 代码 'test.f90'
subroutine test(g,o)
double precision, intent(in):: g
double precision, intent(out):: o
o=g*g
end subroutine
和
gfortran -shared -fPIC test.f90 -o test.so
并为 Julia 创建这个包装函数 test.jl:
function test(s)
res=Float64[1]
ccall((:test_, "./test.so"), Ptr{Float64}, (Ptr{Float64}, Ptr{Float64}), &s,res);
return res[1]
end
和 运行 这些命令与寻求的输出:
julia> include("./test.jl")
julia> test(3.4)
11.559999999999999
但我想 return 数组而不是标量。我想我已经尝试了一切,包括在 this 答案中使用 iso_c_binding。但是我尝试的一切都会像这样向我抛出错误:
ERROR: MethodError: `convert` has no method matching convert(::Type{Ptr{Array{Int32,2}}}, ::Array{Int32,2})
This may have arisen from a call to the constructor Ptr{Array{Int32,2}}(...),
since type constructors fall back to convert methods.
Closest candidates are:
call{T}(::Type{T}, ::Any)
convert{T}(::Type{Ptr{T}}, ::UInt64)
convert{T}(::Type{Ptr{T}}, ::Int64)
...
[inlined code] from ./deprecated.jl:417
in unsafe_convert at ./no file:429496729
例如,我想从 julia 调用以下代码:
subroutine arr(array) ! or arr(n,array)
implicit none
integer*8, intent(inout) :: array(:,:)
!integer*8, intent(in) :: n
!integer*8, intent(out) :: array(n,n)
integer :: i, j
do i=1,size(array,2) !n
do j=1,size(array,1) !n
array(i,j)= j+i
enddo
enddo
end subroutine
使用注释掉的变体也是一种替代方法,因为从 julia 调用时仅更改参数似乎没有用。
那么如何使用 Julia 中的数组调用 fortran 子例程?
使用 ccall
时,Julia 数组应作为元素类型的指针以及描述大小的额外参数传递。
您的示例 test.f90
应该是:
subroutine arr(n,array)
implicit none
integer*8, intent(in) :: n
integer*8, intent(out) :: array(n,n)
integer :: i, j
do i=1,size(array,2) !n
do j=1,size(array,1) !n
array(i,j)= j+i
enddo
enddo
end subroutine
像以前一样编译
gfortran -shared -fPIC test.f90 -o test.so
然后在 Julia 中:
n = 10
X = zeros(Int64,n,n) # 8-byte integers
ccall((:arr_, "./test.so"), Void, (Ptr{Int64}, Ptr{Int64}), &n, X)
建议: '&n' 将导致较新版本的无效语法错误。 而且,使用 Ref 比 Ptr 更安全。
你可以试试:
ccall((:arr_, "./test.so"), Cvoid, (Ref{Int64}, Ref{Int64}), Ref(n), X)