使用ctypes传递整数数组至Fortran时出现间隔零值问题求助
问题:Python通过ctypes向Fortran传递整数数组时元素间出现零值
我是ctypes新手,尝试从Python向Fortran传递整数数组,但发现Fortran接收的数组中每个元素间都存在零值。具体情况如下:
Python代码
import ctypes import numpy as np f90 = ctypes.CDLL('./ctypes_test.so') dim=int(10) intarr = np.arange(0,dim,dtype=int) intarr_ = intarr.ctypes.data_as(ctypes.POINTER(ctypes.c_int)) dim_INT = ctypes.c_int(dim) f90.integerarray_(intarr_, ctypes.byref(dim_INT))
Fortran代码
SUBROUTINE integerarray(arr, dim) INTEGER :: arr, dim DIMENSION :: arr(dim) PRINT*, arr END
预期与实际输出
- 预期输出:0到9的连续整数
- 实际输出:
0 0 1 0 2 0 3 0 4 0 0
原因与解决方案
核心原因
- 数据类型字节长度不匹配:
Python中numpy.int默认是64位(8字节),而ctypes.c_int对应32位(4字节)整数。当你把64位数组强制转换成32位指针时,每个原元素会被拆成两个32位内存单元,高4字节为0,Fortran读取时会将这两个单元视为独立元素,导致原数值和0交替出现。 - Fortran未使用C兼容接口:
原Fortran子程序没有绑定到C接口,Fortran默认的数组传递规则与C(ctypes依赖的接口)不兼容,进一步加剧了内存解析错误。
解决方法
1. 统一整数类型为32位
修改Python代码,创建numpy数组时指定np.int32,匹配ctypes.c_int和Fortran的32位整数:
import ctypes import numpy as np f90 = ctypes.CDLL('./ctypes_test.so') dim = 10 # 显式指定32位整数类型 intarr = np.arange(0, dim, dtype=np.int32) intarr_ = intarr.ctypes.data_as(ctypes.POINTER(ctypes.c_int)) dim_INT = ctypes.c_int(dim) f90.integerarray_(intarr_, ctypes.byref(dim_INT))
2. 修改Fortran代码使用C兼容绑定
使用Fortran的ISO_C_BINDING模块,显式声明与C兼容的类型和接口:
SUBROUTINE integerarray(arr, dim) BIND(C, NAME='integerarray_') USE, INTRINSIC :: ISO_C_BINDING INTEGER(C_INT), INTENT(IN) :: arr(dim) ! 匹配C的int类型 INTEGER(C_INT), INTENT(IN) :: dim PRINT*, arr END SUBROUTINE integerarray
BIND(C, NAME='integerarray_'):确保子程序以C兼容的方式暴露,名称与Python中调用的integerarray_一致。INTEGER(C_INT):使用与C语言int对应的Fortran类型,保证字节长度和内存布局匹配。
3. 重新编译Fortran代码
用gfortran编译生成共享库:
gfortran -shared -fPIC ctypes_test.f90 -o ctypes_test.so
验证结果
修改后运行Python代码,Fortran将输出预期的连续整数:
0 1 2 3 4 5 6 7 8 9
内容的提问来源于stack exchange,提问作者patrick7
相关产品推荐
相关产品推荐

