从 Julia 调用 Fortran 函数,返回数组:未知函数,段错误?

2023-11-25

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

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 也无法在没有显式接口的情况下使用可选参数调用 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 名称绑定到过程。您可以按照您的问题进行编译。

在 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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Julia 调用 Fortran 函数,返回数组:未知函数,段错误? 的相关文章

随机推荐

  • Flyway 找不到类路径:db/migrations

    我现在刚刚在 Intellij 中启动了一个新项目 使用 Spring Boot 版本 2 1 3 和 Flyway 5 2 4 以及 Java 11 尝试启动我的项目后 我得到 Caused by org springframework
  • LibGDX:过滤缩放的TextureRegion

    我有几个具有不同状态的不同纹理的对象 所以我使用TextureAtlas用TexturePacker制作 并调整大小TextureRegion我需要它的地方 我必须调整大小 因为我不仅要尝试支持 720p 和 1080p 而且我的一些对象是
  • pandas:使用不带引号的文字选项卡编写制表符分隔的数据框

    我必须为遗传学软件重新格式化数据 该软件需要将每一列分成两列 例如0 gt G G 1 gt A G 2 gt A A 输出文件应该以制表符分隔 我正在尝试在 pandas 中做到这一点 import csv import pandas a
  • React.js 每第 n 项添加开始标签或结束标签

    我在这个逻辑上遇到了麻烦 因为 React jsx 不允许将非结束标签添加到数组 子组件中 例如 使用 bootstrap css 我想添加一行every4 列 所以逻辑如下 添加一个起始行例如 div 然后在该行内循环 并且每个循环附加一
  • 应使用什么语义 HTML 标记来创建面包屑?

    应该使用什么有意义的 HTML 标签来创建面包屑 我有一个使用未排序列表创建的菜单栏 因为它是一个列表 ul li li li li ul 现在 我决定在菜单下方放置一个面包屑 问题是 我不知道应该使用什么标签 我想尽可能使用有意义的标签
  • 使用Python从另一个应用程序中提取ListView项目

    我有一个带有 ListView SysListView32 控件的应用程序 我想从中提取数据 该控件有 4 列 仅文本数据 我一直在玩以下几行 在网上某处找到 VALUE LENGTH 256 bufferlength int struct
  • 如何获取网页的字数? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我需要获取网页上的总字数 我知道关于System Net WebClient班级 但它是DownloadString 方法返回整个 HTML 标记
  • AudioContext.decodeAudioData(...) 不适用于 iPhone,但适用于其他地方

    我有以下非常基本的代码 它是更复杂问题的一部分 我的问题是这个函数 context decodeAudioData arrayBuffer 不工作iPhone 试穿Safari and Chrome nor Mac Safari 但它可以在
  • Python 3.8 中的 MD4 hashlib 支持

    我正在尝试为使用 NTLM 身份验证的服务器实现肥皂客户端 我使用的库 依赖于 ntlm auth 的 requests ntlm2 通过标准库的 hashlib 实现了 NTLM 协议核心的 MD4 算法 虽然hashlib似乎支持MD4
  • Angular http post 请求内容类型从“text/plain”到“application/json”

    我正在尝试使用 POST 请求从服务获取数据 但我无法更改标头 TS 无法编译 或内容类型 我在控制台中收到此错误 状态 415 错误 不支持的媒体类型 异常 org springframework web HttpMediaTypeNot
  • 在 PHP 中解析 CSV 并尝试在字段内容中保留换行符

    我有一个 csv 文件 其中一列有换行符 该列是一个描述字段 因此它存储文本行 项目符号点和最重要的换行符 有时还存储段落之间的两个换行符 让事情变得复杂的是 描述字段还包含引号 我已经尝试了我所知道的一切来将内容 并保持格式 放入变量中
  • 是否可以使用 git 来区分 PowerPoint 版本控制?

    我有一些 PowerPoint 文档 我使用 git 对其进行版本控制 我想知道文件版本之间有什么差异 文本是最重要的 图像和格式不是那么重要 至少在这一点上不是 我编写此代码是为了在命令行上与 git 一起使用 需要 Python 和 p
  • 可以使用 Web Audio API 和 createMediaElementSource 分析来自 Icecast 的流音频吗?

    使用 Web Audio API 和 createMediaElement 方法 您可以使用类型化数组从音频播放中获取频率数据
  • ASP.NET Web 应用程序中未命中 Application_Start

    我正在尝试调试 ASP NET Web 应用程序中的 global asax cs 文件中的某些内容 并在 Application Start 事件中设置了断点 但是当我在 VS2008 中启动 Web 应用程序时 该事件没有被触发 我的目
  • 我的 matplotlib.pyplot 图例被切断

    我正在尝试使用 matplotlib 创建一个侧面带有图例的绘图 我可以看到正在创建绘图 但图像边界不允许显示整个图例 lines ax plt subplot 111 for filename in args lines append p
  • 如何摆脱 SIGTERM 错误

    我一直在新的 xcode4 中开发这个 iphone 应用程序 实际上 每次我在模拟器中退出应用程序时 我都会在 main m 中的代码行上收到错误 这是我的代码行 然后是下一行的错误 int retVal UIApplicationMai
  • 如何在 CANalyzer 中播放 blf 文件

    我对使用 CANalyzer 有点陌生 从未使用过该产品中的日志记录功能 我收到了一个 BLF 文件来分析 但不确定如何使用它 有人能指出我正确的方向吗 谢谢 更具体一点 在标准工具栏中设置离线模式 单击配置选项卡 通常位于窗口底部 你会看
  • 更改 WinRT 中的 UI 文化

    是否可以动态更改 WinRT 中的 UI 文化 我发现了ApplicationLanguages PrimaryLanguageOverride en 但这仅在显示应用程序 UI 之前有效 而不是在显示之后 例如 我想通过设置更改 UI 语
  • 无法设置桌子高度[重复]

    这个问题在这里已经有答案了 我有一个简单的 html 表格 我无法设置该桌子的高度 我错过了什么吗 table border 1 height 10px tr td b Name b td tr tr td b Name b td tr t
  • 从 Julia 调用 Fortran 函数,返回数组:未知函数,段错误?

    我想从 Julia 调用 Fortran 库中的函数 在这种情况下 我有一个函数eye它接受一个 Integer 并返回一个二维整数数组 Fortran 模块被编译成共享库 使用 gfortran shared fPIC o matrix