如何正确地将 C 字符串读入未指定长度的 Fortran 字符串?

GPM*_*ler 4 fortran fortran-iso-c-binding

以下函数应该将 C 字符串转换为 Fortran 字符串,并且在 Release 版本中可以正常工作,但在 Debug 中不能:

! Helper function to generate a Fortran string from a C char pointer
function get_string(c_pointer) result(f_string)
    use, intrinsic :: iso_c_binding
    implicit none
    type(c_ptr), intent(in)         :: c_pointer
    character(len=:), allocatable   :: f_string

    integer(c_size_t)               :: l_str
    character(len=:), pointer       :: f_ptr

    interface
        function c_strlen(str_ptr) bind ( C, name = "strlen" ) result(len)
        use, intrinsic :: iso_c_binding
            type(c_ptr), value      :: str_ptr
            integer(kind=c_size_t)  :: len
        end function c_strlen
    end interface

    l_str = c_strlen(c_pointer)
    call c_f_pointer(c_pointer, f_ptr)

    f_string = f_ptr(1:l_str)
end function get_string
Run Code Online (Sandbox Code Playgroud)

但是,它似乎c_f_pointer没有告诉 Fortran 字符串指针,f_ptr它指向的字符串的长度。在 Debug 版本中,边界检查处于活动状态,这会导致

Fortran runtime error: Substring out of bounds: upper bound (35) of 'f_ptr' exceeds string length (0)
Run Code Online (Sandbox Code Playgroud)

我正在使用gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0并将标准设置为 2008。

我的问题:有没有办法在f_ptr不改变声明的情况下告诉它的长度,或者我在这里做的事情根本上是错误的?


如果我指定形状,它似乎可以正确运行,但为此f_ptr需要是一个数组:

character(len=:), allocatable   :: f_string
character(len=1), dimension(:), pointer :: f_ptr
...
call c_f_pointer(c_pointer, f_ptr, [l_str])
Run Code Online (Sandbox Code Playgroud)

但是,我找不到将等级 1 的字符串转换为 的方法,该字符串character(len=:), allocatable :: f_string显然具有等级 0。

我的第二个问题:有没有办法将f_ptr数据传输到f_string这个例子中?

fra*_*lus 5

不能用于c_f_pointer设置 Fortran 字符指针的长度(F2018, 18.2.3.3):

FPTR 应为指针,不应具有延迟类型参数 [...]

因此不能使用延迟长度的字符标量(或数组)(长度是一个类型参数)。

您确实可以使用延迟形状的字符数组 asfptr然后使用任意数量的技术将该数组的元素复制到标量(如所述的 rank-0)。

例如,使用子字符串赋值(在显式分配延迟长度标量之后):

allocate (character(l_str) :: f_string)
do i=1,l_str
  f_string(i:i)=fptr(i)
end
Run Code Online (Sandbox Code Playgroud)

或者考虑是否可以简单地使用字符数组而不是复制到标量。