You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过ctypes向Fortran模块传递字符串数组并实现Fortran端读取

Python通过ctypes传递字符串数组到Fortran模块的实现方案

问题背景

通过Python的ctypes将字符串数组传递给Fortran模块,已有的Python代码如下:

import ctypes as ct

files = [b"FILE1.RSX", b"FILE2.RSX"] 
file_ptrs = (ct.c_char_p * len(files))(*files) 
lib2 = ct.CDLL('./reader.so') 
lib2.read_data.argtypes = [ct.POINTER(ct.c_char_p)]
lib2.read_data(file_ptrs)

需要修改Fortran子程序框架,实现对该字符串数组的读取,原Fortran框架存在参数缺失和类型声明问题:

subroutine read_rsx(files) bind(c, name="read_data")
    use iso_c_binding   
    IMPLICIT DOUBLE PRECISION (A-H,O-Z)
    integer(c_int), value :: numFile
    type(c_ptr), intent(in) :: files(numFile)
...
end subroutine read_data

解决步骤及代码实现

1. 调整Python代码:传递数组长度

C风格的指针数组不包含长度信息,Fortran无法自动获取数组元素个数,因此需要额外传递数组长度参数:

import ctypes as ct

files = [b"FILE1.RSX", b"FILE2.RSX"] 
file_count = len(files)
# 创建C风格的字符指针数组
file_ptrs = (ct.c_char_p * file_count)(*files) 
lib2 = ct.CDLL('./reader.so') 
# 更新函数参数类型声明,添加整数类型的长度参数
lib2.read_data.argtypes = [ct.c_int, ct.POINTER(ct.c_char_p)]
# 传递长度和指针数组
lib2.read_data(file_count, file_ptrs)

2. 修正Fortran子程序:读取字符串数组

修改Fortran代码,解决类型冲突问题,并实现C字符串到Fortran字符串的转换:

subroutine read_data(num_file, files) bind(c, name="read_data")
    use iso_c_binding   
    implicit none  ! 替代旧的隐式声明,避免类型混淆
    integer(c_int), intent(in), value :: num_file  ! 接收数组长度
    type(c_ptr), intent(in) :: files(num_file)     ! C风格的字符指针数组
    character(kind=c_char), pointer :: c_str(:)    ! 用于指向C字符串的指针
    character(len=:), allocatable :: fortran_str   ! 转换后的Fortran字符串
    integer :: i, str_len

    ! 遍历每个字符串指针
    do i = 1, num_file
        ! 将C指针绑定到Fortran字符数组
        call c_f_pointer(files(i), c_str, [1])
        
        ! 计算C字符串的实际长度(直到遇到终止符\0)
        str_len = 0
        do while(c_str(str_len+1) /= c_null_char)
            str_len = str_len + 1
        end do
        
        ! 分配对应长度的Fortran字符串并复制内容
        allocate(character(len=str_len) :: fortran_str)
        fortran_str = transfer(c_str(1:str_len), fortran_str)
        
        ! 这里可以添加自定义处理逻辑,比如打印字符串
        print *, "第", i, "个文件:", trim(fortran_str)
        
        ! 释放临时资源
        deallocate(fortran_str)
        nullify(c_str)
    end do

end subroutine read_data

3. 编译Fortran代码

使用gfortran编译为共享库:

gfortran -shared -fPIC -o reader.so your_fortran_file.f90

关键说明

  • 隐式声明问题:原代码中的IMPLICIT DOUBLE PRECISION会导致c_int等C绑定类型被错误隐式声明为双精度,改用implicit none可以避免这类问题。
  • 字符串转换:C字符串以\0作为终止符,需要手动遍历获取长度,再通过transfer函数转换为Fortran风格的字符串。
  • 数组长度传递:必须显式传递数组长度,否则Fortran无法确定指针数组的元素个数。

内容的提问来源于stack exchange,提问作者Michael Leanza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:30:09