gpt4 book ai didi

fortran - 从 Julia 调用 Fortran 函数,返回数组 : unknown function, 段错误?

转载 作者:行者123 更新时间:2023-12-04 15:57:11 26 4
gpt4 key购买 nike

我想从 Julia 调用我的 Fortran 库中的函数。在这种情况下,我有一个函数 eye它接受一个整数,并返回一个二维整数数组。

Fortran 模块被编译成一个共享库,使用

$ gfortran -shared -fPIC -o matrix_routines.so matrix_routines.f90

此后,我试图从交互式 Julia 解释器中调用它(名称来自 nm):
julia> n=5
5

julia> ccall( (:__matrix_routines_MOD_eye, "/path/to/library/matrix_routines.so"), Array{Int64,2} , (Ptr{Int64},), &n )

然而,这立即导致 Julia 向我抛出一个段错误:
signal (11): Segmentation fault
__matrix_routines_MOD_eye at /path/to/library/matrix_routines.so (unknown line)
anonymous at no file:0
unknown function (ip: -1137818532)
jl_f_top_eval at /usr/bin/../lib/julia/libjulia.so (unknown line)
eval_user_input at REPL.jl:53
jlcall_eval_user_input_19998 at (unknown line)
jl_apply_generic at /usr/bin/../lib/julia/libjulia.so (unknown line)
anonymous at task.jl:95
jl_handle_stack_switch at /usr/bin/../lib/julia/libjulia.so (unknown line)
julia_trampoline at /usr/bin/../lib/julia/libjulia.so (unknown line)
unknown function (ip: 4199613)
__libc_start_main at /usr/bin/../lib/libc.so.6 (unknown line)
unknown function (ip: 4199667)
unknown function (ip: 0)
zsh: segmentation fault (core dumped) julia

我是否以错误的方式调用该函数?函数的正确名称是什么? (它似乎不仅仅是 eye ,因为这也不起作用。)

作为另一个问题:Julia 是否对结果数组的内存方向做任何事情? Fortran 和 Julia 都是列专业的,但我想知道是否由于 ccall() Julia 可能认为它应该转置它们?
module matrix_routines
implicit none

private

public :: eye

contains

pure function eye(n,offset) result(um) !{{{
integer, intent(in) :: n
integer, intent(in), optional :: offset

integer, dimension(n,n) :: um

integer :: i, l, u, os

um = 0

l = 1
u = n
os = 0

if (present(offset)) then
os = offset
end if

if (abs(os) < n) then
if (os > 0) then
u = n - os
else if (os < 0) then
l = 1 - os
end if

do i=l, u
um(i, i+os) = 1
end do
end if

end function eye !}}}
end module matrix_routines

最佳答案

你的方法有几个问题。将数组直接返回给 julia 是有问题的,因为除非满足特定条件,否则 Fortran 数组不能与 C 互操作。当您使数组可互操作时(将 bind(C) 添加到您的过程并给数组一个 C 类型),编译器( gfortran )会报错:

Error: Return type of BIND(C) function 'um' at (1) cannot be an array

为了解决这个问题,我们可以通过一个虚拟参数返回数组。您需要将其设为 intent(inout)参数并在 julia 中构造数组以避免在 Fortran 中创建数组时出现任何内存/范围问题。

其次,可选参数是有问题的,浏览 Julia 文档我不确定它是否受支持。请注意,即使是 Fortran 也不能在没有显式接口(interface)的情况下使用可选参数调用 Fortran,因为 Julia 不与 .mod 交互。文件并且似乎期望 C 做事的方式,它可能不起作用(并且 Fortran 2008 15.3.7 p2.6 似乎说它不受支持)。但是有一些解决方法——您可以创建多个具有不同数量参数的 Fortran 过程,然后使用它们中的可选参数调用该过程。

首先,考虑这个 Fortran 模块,它从您的示例开始,但被缩减为​​演示互操作所需的内容:
module matrix_routines
implicit none

private
public :: eye

contains

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

integer :: i, j

do j=1,n
do i=1,n
um(i,j) = i+j
end do
end do

end subroutine eye !}}}
end module matrix_routines

请注意,我已移动 um成为 inout虚拟参数,并且由于我们没有返回值,因此将过程更改为子例程。我还删除了可选参数。我还使用了 C 互操作类型并将 C 名称绑定(bind)到该过程。您可以按照您的问题进行编译。

在 Julia 中,您现在可以执行以下操作:
julia> n = 2
2

julia> um = zeros(Int32, n, n)
2x2 Array{Int32,2}:
0 0
0 0

julia> ccall((:eye, "matrix_routines.so"), Void, (Ptr{Int32}, Ptr{Array{Int32,2}}), &n, um)

julia> um
2x2 Array{Int32,2}:
2 3
3 4

julia> n = 4
4

julia> um = zeros(Int32, n, n)
4x4 Array{Int32,2}:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

julia> ccall((:eye, "matrix_routines.so"), Void, (Ptr{Int32}, Ptr{Array{Int32,2}}), &n, um)

julia> um
4x4 Array{Int32,2}:
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8

请注意,我们可以将函数调用为 :eye因为我们使用了 bind(C,name="eye")我们的 Fortran 中的 C 互操作。

最后,如果我们将我的 Fortran 示例中的 do 循环更改为 um(i,j) = i*10+j ,我们可以看到数组中没有发生转置:
julia> um
3x3 Array{Int32,2}:
11 12 13
21 22 23
31 32 33

段错误的具体原因可能有很多——数据类型不匹配、返回类型问题、可选参数问题或实际调用和传递的变量不匹配。

关于fortran - 从 Julia 调用 Fortran 函数,返回数组 : unknown function, 段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28373693/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com