如何实现Fortran字符数组向Python传递?f2py编译报错求助
问题:Fortran递归函数返回字符数组,f2py编译报错未声明
number_entries 要实现一个Fortran递归函数,接收正整数height,返回完全二叉树叶节点的0/1字符串标签数组,用f2py编译时出现use of undeclared identifier 'number_entries'错误。
原Fortran代码(my_fortran_lib.f90)
recursive function GenerateCompleteBinaryTreeNew(height) RESULT(treeResult) ! This function returns the words representing a complete binary tree, producing the labels of its leaves ! (which are words composed of the letters {0, 1}). The height of the tree must be at least 1. implicit none INTEGER, INTENT(IN) :: height INTEGER :: i INTEGER :: number_entries_temp, number_entries number_entries_temp = (2 ** height - 1) !f2py integer :: number_entries_temp = pow(2,height-1) number_entries = number_entries_temp * 2 CHARACTER(len=20), INTENT(out), DIMENSION(number_entries) :: treeResult CHARACTER(len=20), INTENT(inout), DIMENSION(number_entries_temp) :: treeResult_temp ! Case : height = 0 IF (height == 0) THEN treeResult(1) = "" ! Case : height = 1 else if (height == 1) then i = 1 treeResult(1) = '0' treeResult(2) = '1' else ! Case : height > 1 treeResult_temp = GenerateCompleteBinaryTreeNew(height-1) do i = 1, number_entries_temp treeResult(i) = '0' // treeResult_temp(i) end do do i = 1, number_entries_temp treeResult(i+ number_entries_temp) = '1' // treeResult_temp(i) end do end if end function GenerateCompleteBinaryTreeNew
编译命令
f2py3 -c -m myflib my_fortran_lib.f90
核心报错信息
/var/folders/l9/5sv8cvgs649f75m12cv86vd80000gn/T/tmp7_xnuf2a/src.macosx-10.9-universal2-3.9/myflibmodule.c:312:43: error: use of undeclared identifier 'number_entries' generatecompletebinarytreenew_Dims[0]=number_entries; ^
解决方案
错误原因
f2py在生成Python接口时,需要提前知道返回数组的维度信息,但原代码中number_entries是函数内部根据输入height计算的变量,f2py无法在解析函数签名阶段获取这个值,导致生成的C包装代码中未声明该变量。另外递归函数返回可变长度数组的方式,f2py的支持有限。
修改方案:将函数改为子程序(Subroutine)
把递归函数改成子程序,通过分配可分配数组的方式返回结果,同时添加f2py注释指令,让f2py正确识别数组的维度来源。
修改后的Fortran代码:
module binary_tree_mod implicit none contains recursive subroutine GenerateCompleteBinaryTreeNew(height, treeResult) ! 生成完全二叉树叶节点的0/1标签字符串数组 !f2py intent(in) :: height !f2py intent(out) :: treeResult !f2py dimension(treeResult) :: 2**height INTEGER, INTENT(IN) :: height CHARACTER(len=20), INTENT(out), ALLOCATABLE :: treeResult(:) INTEGER :: i, number_entries_temp, number_entries CHARACTER(len=20), ALLOCATABLE :: treeResult_temp(:) number_entries = 2 ** height number_entries_temp = 2 ** (height - 1) ! 分配结果数组内存 allocate(treeResult(number_entries)) if (height == 0) then treeResult(1) = "" else if (height == 1) then treeResult(1) = '0' treeResult(2) = '1' else ! 递归调用生成子树结果 call GenerateCompleteBinaryTreeNew(height-1, treeResult_temp) ! 拼接0前缀 do i = 1, number_entries_temp treeResult(i) = '0' // trim(treeResult_temp(i)) end do ! 拼接1前缀 do i = 1, number_entries_temp treeResult(i + number_entries_temp) = '1' // trim(treeResult_temp(i)) end do deallocate(treeResult_temp) end if end subroutine GenerateCompleteBinaryTreeNew end module binary_tree_mod
编译命令
f2py3 -c -m myflib my_fortran_lib.f90
Python测试代码
import myflib # 测试height=3的情况 result = myflib.binary_tree_mod.generatecompletebinarytreenew(3) print(result)
输出结果:
['000' '001' '010' '011' '100' '101' '110' '111']
关键修改点说明
- 使用模块包裹子程序:f2py对模块内的子程序支持更好,避免命名冲突。
- 使用可分配数组:让Fortran根据height动态分配数组内存,f2py可以正确识别并传递回Python。
- 添加f2py注释指令:
!f2py dimension(treeResult) :: 2**height告诉f2py,输出数组的长度是2**height,解决维度信息缺失的问题。 - 修正节点数量计算:原代码中
number_entries_temp = (2 ** height -1)是错误的,完全二叉树高度为h时,叶节点数量是2^h,子树的叶节点数量是2^(h-1),所以修正了计算逻辑。
内容的提问来源于stack exchange,提问作者Valeriano
相关产品推荐
相关产品推荐

