gpt4 book ai didi

fortran - GNU Fortran - 控制符号大小写

转载 作者:行者123 更新时间:2023-12-04 15:43:50 27 4
gpt4 key购买 nike

有没有办法控制 GNU Fortran 4.8 发出的符号的大小写?

旧版本(如 3.4)有 -fcase-lower , -fcase-preserve-fcase-upper强制小写,源中使用的大小写和大写分别,但这些似乎已被丢弃。是否有一些新的方法来控制它?

编辑

我正在尝试将大型混合 C/Fortran 代码库从英特尔编译器移植到 GNU 编译器。

我知道我们可以使用 BIND(C, name='...')给出一个特定于大小写的符号名称。但是,这还有其他影响。考虑这个 C 函数:

void print(char *str, size_t len) {
for(int ii = 0; ii < len; ii++) {
putchar(str[ii]);
}
putchar('\n');
}

我们可以像这样从 Fortran 程序中调用它:
program test
implicit none
interface
subroutine printstr(str)
character :: str(*)
end subroutine
end interface

call printstr("Hello, world.");
end

如果 C 函数名称不是全部小写(例如 PrintStr),那么我们可能会尝试像这样修复 Fortran 程序:
program test
implicit none
interface
subroutine printstr(str) bind(C, name='PrintStr')
use iso_c_binding
character :: str(*)
end subroutine
end interface

call printstr("Hello, world.");
end

但是,这不起作用,因为 bind(C, ...)更改字符串参数的处理方式并且不再提供长度参数(我不确定这是否会导致堆栈损坏或只是缓冲区溢出 - 给出的示例总是来自缓冲区溢出的段错误)。

我认为可能是时候提出一个关于如何解决这个问题的新问题了。

最佳答案

这是使用 Fotran iso_c_binding 模块解决此问题的一种方法。

首先,C 代码,就像在您的示例中一样:

void PrintStr(char *str, size_t len)
{
for (int ii=0; ii < len; ++ii)
putchar(str[ii]);
putchar('\n');
}

和一个合适的 Fortran 接口(interface):
interface
subroutine printstr_c(str, len) bind(C, name='PrintStr')
use iso_c_binding, only: c_char, c_size_t
implicit none
character(kind=c_char) :: str(*)
integer(c_size_t),value :: len
end subroutine printstr_c
end interface

这将允许您将 C 函数调用为:
character(len=20) :: string = 'Hello ISO C env!'
call printstr_c(string, int(len(string),kind=c_size_t))

这可行,但需要明确指定长度参数。我们可以做得更好,并围绕它创建一个 Fortran 函数包装器,以向调用者隐藏长度。
subroutine printstr(str)
use iso_c_binding, only: c_size_t
implicit none
character(len=*) :: str
call printstr_c(str, int(len(str),kind=c_size_t))
end subroutine

现在我们可以调用:
character(len=20) :: string = 'Hello ISO C env!'
call printstr(string)

请注意,当您的 C 函数在 length 参数上循环时,我没有担心 null 终止字符串。如果您需要一个空终止符,您可以在 printstr 中添加一个子程序。

如果你有很多这样的函数要调用,所有的形式都是 void f(str, len)。 ,然后我们可以做更多的工作并进一步抽象 printstr函数只是从 Fortran 字符变量到适合 iso_c_binding 调用的配对 char,len 变量的通用转换器。考虑这个例子:
module cfuncs
implicit none
interface
! this interface is for an actual C function
subroutine printstr_c(str, len) bind(C, name='PrintStr')
use iso_c_binding, only: c_char, c_size_t
implicit none
character(kind=c_char) :: str(*)
integer(c_size_t),value :: len
end subroutine printstr_c
end interface
end module

module ffuncs
use cfuncs
implicit none
interface
! this interface is to constrain procedures passed to printstr()
subroutine string_and_len(str, len)
use iso_c_binding, only: c_char, c_size_t
implicit none
character(kind=c_char) :: str(*)
integer(c_size_t),value :: len
end subroutine string_and_len
end interface
contains
! this routine takes the C function you want to call and a string to pass
! and does the translation to call funct(str,len)
subroutine printstr(func,str)
use iso_c_binding, only: c_size_t
implicit none
procedure(string_and_len) :: func
character(len=*) :: str
call func(str, int(len(str),kind=c_size_t))
end subroutine
end module

program main
use ffuncs
implicit none
character(len=20) :: string = 'Hello ISO C env!'
call printstr(printstr_c, string)
end program

对于这个特定示例来说,这可能有点过头了,但它允许一个 Fortran 包装器调用许多具有相同类型签名的 C 函数。反过来,这只需要您在要移植的代码中修饰 Fortran 调用,以由包装函数包装。例如假设 printstrc_c是对外接口(interface):
! old F77 non iso_c_binding call
call printstr_c("Hello World")

变成
! wrapping the old F77 call through our Fortran wrapper handling iso_c_binding
call printstr(printstr_c, "Hello World")

这不像你做事的旧方式那样优雅,但是 gfortran 的新版本(3.x gcc 是 g77,4.x 是 gfortran,afaik 完全重写)似乎不能强制案件保全。如果您想避免我演示的困惑,另一种选择是在链接之前对已编译的 Fortran 对象进行后处理并重写函数名称以具有正确的大小写,但我认为处理起来更糟(以及肮脏的黑客)。

关于fortran - GNU Fortran - 控制符号大小写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26356290/

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