如何正确地将c字符串读取为未指定长度的Fortran字符串?



下面的函数应该将C字符串转换为Fortran字符串,并且在发布版本中工作良好,但在调试中不工作:

! 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

然而,c_f_pointer似乎没有告诉指向字符串的Fortran指针f_ptr,它所指向的字符串的长度。在调试版本中,边界检查是活动的,这会导致

Fortran runtime error: Substring out of bounds: upper bound (35) of 'f_ptr' exceeds string length (0)

我使用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])

然而,我找不到一种方法将排名为1的字符串转换为排名为0的character(len=:), allocatable :: f_string

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

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

ftr应该是一个指针,不能有延迟的类型参数[…]

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

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

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

allocate (character(l_str) :: f_string)
do i=1,l_str
f_string(i:i)=fptr(i)
end

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

最新更新