【问题标题】:Compiling forpy to call Python object in Fortran编译 forpy 以在 Fortran 中调用 Python 对象
【发布时间】:2021-08-18 21:30:56
【问题描述】:

我的问题
我意识到需要在我的项目中实现从 Fortran 到 Python 的正式连接(上下文如下),我的场景对于 f2pyforpy 来说似乎是完美的场景。我选择了 forpy,因为它似乎更适合从 Fortran 调用 Python,而这在 f2py 中似乎更困难。

我克隆了 git repo 并浏览了 Getting Started 部分,但在编译 forpy_mod.F90 时遇到了一个奇怪的错误(粘贴在下面)。有谁知道这个错误的原因/解决方法?

  • 在 linux 机器上使用 python 3.8.8 运行 miniconda
  • [编辑:] 使用 GNU Fortran (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)

可能是不必要的上下文
我正在使用一个基于 Fortran 的大型轨道软件,该软件由数千个 Fortran 子例程组成。我的任务是在其中一个子例程中调用 Python 代码,然后调用 Python API,该 API 已简化为将单个值返回给 Fortran 程序。这一序列将在一次轨道运行中发生数万到数十万次。

我已经使用 Fortran 的 EXECUTE_COMMAND_LINE() 函数成功地在这两个程序之间建立了连接,但是 Python 代码本身有很大的开销,当从命令行调用时,它会重新导入包(其中有很多) 每次调用该函数时。这会导致运行时间非常长(使用默认值只需要大约 6 分钟)。我已经尽我所能减少了 Python API 的开销。

尝试编译 forpy 时出错

 $ gfortran -c forpy_mod.F90

forpy_mod.F90:1924.54:

  character(kind=C_CHAR, len=:), pointer :: doc_string
                                                      1
Error: Deferred-length character component 'doc_string' at (1) is not yet supported
forpy_mod.F90:1961.54:

  character(kind=C_CHAR, len=:), pointer :: doc_string
                                                      1
Error: Deferred-length character component 'doc_string' at (1) is not yet supported
forpy_mod.F90:1961.54:

  character(kind=C_CHAR, len=:), pointer :: doc_string
                                                      1
Error: Deferred-length character component 'doc_string' at (1) is not yet supported
forpy_mod.F90:11788.12:

  m = c_loc(self%methods)
            1
Error: Argument 'self' to 'c_loc' at (1) must be an associated scalar POINTER
forpy_mod.F90:9581.41:

      flag = strcmp(buffer_format, c_loc(format_code))
                                         1
Error: CHARACTER argument 'format_code' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9586.43:

        flag = strcmp(buffer_format, c_loc(format_code))
                                           1
Error: CHARACTER argument 'format_code' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9595.41:

      flag = strcmp(buffer_format, c_loc(format_code))
                                         1
Error: CHARACTER argument 'format_code' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9600.43:

        flag = strcmp(buffer_format, c_loc(format_code))
                                           1
Error: CHARACTER argument 'format_code' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9606.43:

        flag = strcmp(buffer_format, c_loc(format_code))
                                           1
Error: CHARACTER argument 'format_code' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9613.37:

  flag = strcmp(buffer_format, c_loc(format_c_string))
                                     1
Error: CHARACTER argument 'format_c_string' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9292.24:

  buffer%format = c_loc(format_c_string)
                        1
Error: CHARACTER argument 'format_c_string' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9186.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:9102.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:9018.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8934.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8850.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8766.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8682.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8598.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8514.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8430.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8346.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8262.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8178.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:8094.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
Fatal Error: Error count reached limit of 25.

【问题讨论】:

  • 4.8.5,虽然是许多基于 RH 的发行版的默认版本,但太旧了,无法让编程和使用 Fortran 成为一种愉快的体验。
  • 感谢所有这些有用的信息和捕捉我的编辑哈哈

标签: python compiler-errors fortran gfortran


【解决方案1】:

您使用的编译器版本不支持代码中使用的多个功能。您应该使用更高版本的编译器或不同的编译器(或避免使用这些功能)。

这里有两个不同的方面。

第一:


  character(kind=C_CHAR, len=:), pointer :: doc_string
                                                      1
Error: Deferred-length character component 'doc_string' at (1) is not yet supported
forpy_mod.F90:1961.54:

这里编译器非常明确地说“我知道你的代码很好,但我不知道如何处理它。但是。”这个“尚不支持”是寻找更高版本编译器的重要提示。

派生类型的延迟长度字符组件是 Fortran 2003 的一项功能,但直到 gfortran 4.9 才支持此功能,即使语法已被理解。

第二:

  buffer%format = c_loc(format_c_string)
                        1
Error: CHARACTER argument 'format_c_string' to 'c_loc' at (1) must have a length of 1
forpy_mod.F90:9186.51:

  ierror = ndarray_create_nocopy_helper(res, c_loc(array), shape(array, kind=PY
                                                   1
Error: Assumed-shape array 'array' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable
forpy_mod.F90:9102.51:

这里编译器的抱怨方式略有不同。虽然我们的第一个案例是“我知道你的代码很好,但我不知道如何处理它”。这里我们有“你的代码是错误的,我没有按照你的要求做。”

Fortran 是一种不断发展的语言。与添加延迟长度字符(并作为派生类型的组件可用)一样,限制可能会随语言而变化。

Fortran 2003 c_loc 通常要求它的参数是 C 互操作的。在 Fortran 2003 解释下,假定形状的数组不能作为 c_loc 的参数,长度不为 1 的字符也不能。Fortran 2008 放宽了对 c_loc 参数的限制:对于此代码,您需要一个编译器执行 Fortran 2008(或更高版本)中的规则,而不是 Fortran 2003 中的规则。

【讨论】:

  • 感谢您的反馈!我会尝试更新我的 gfortran 编译器和 fortran 版本!我将尝试在单独的 conda 环境中执行此操作,以免破坏其余代码中的任何内容
  • An issue 建议您可能需要小心使用 GCC 9,但也建议它可以与 GCC 7 一起使用。
  • 如何检查实际使用的是哪个编译器?我在我的 conda 环境中更新了 gfortran,但仍然遇到问题。我仍然得到:!which gfortran -> /bin/gfortran!gfortran --version -> GNU Fortran (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44) 这是需要通过我的系统管理员更新 gfortran 的问题吗?
  • 是否更新了 conda 路径以包含新安装的编译器?也就是说,拥有一个新的系统范围的编译器似乎在其他方面也很好
  • 我刚刚意识到我没有使用您在上面发布的问题(x86_64-conda_cos6-linux-gnu-gfortran 而不是gfortran)与新安装/升级的编译器所指示的正确调用。因此,只需调用 gfortran 默认为系统上的编译器,这与 miniconda 中的编译器是分开的。现在运行代码就可以了!谢谢大家的帮助!
猜你喜欢
  • 2011-02-17
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 2023-03-11
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多