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

如何通过Python从Fortran DLL获取数据?解决ctypes.cast执行异常问题

问题根源

你这段代码的核心问题是Fortran函数返回了局部变量的内存地址:函数里的y是栈上的局部自动变量,当FortAddr执行完毕返回后,栈上的y会被销毁,对应的内存空间会被系统回收或重新分配。此时Python拿到的地址是无效的,调用ctypes.cast访问这块内存必然会导致程序崩溃或未定义行为。

正确解决方案

根据你的需求(获取Fortran计算的数据用于Python可视化),有两种常用的正确实现方式:

方式一:直接返回计算结果(适合单个值)

不需要传递内存地址,直接让Fortran函数返回计算后的数值,这是最简单安全的方式。

修改后的Fortran代码

integer(c_int) function FortCalc(x) bind(c, name="FORTCALC")
!DEC$ ATTRIBUTES DLLEXPORT::FortCalc
use, intrinsic :: iso_c_binding
integer(kind=c_int), intent(in) :: x
integer :: y

y = 2 * x
FortCalc = int(y, c_int)  ! 显式转换为C兼容的int类型
end function

对应的Python调用代码

import ctypes

flib = ctypes.CDLL('FortDll.dll')
# 显式声明函数返回类型,避免ctypes默认推断的潜在问题
flib.FORTCALC.restype = ctypes.c_int

x = ctypes.c_int(15)
result = flib.FORTCALC(x)
print(result)  # 输出30,可直接用于可视化

方式二:通过内存缓冲区传递数据(适合数组/大数据)

如果需要传递大量数据(比如用于可视化的数组),可以让Python预先分配内存缓冲区,Fortran直接写入这块内存,避免内存所有权问题。

Fortran代码(填充数组)

subroutine FortFillArray(arr, length) bind(c, name="FORTFILLARRAY")
!DEC$ ATTRIBUTES DLLEXPORT::FortFillArray
use, intrinsic :: iso_c_binding
integer(kind=c_int), intent(out) :: arr(*)
integer(kind=c_int), intent(in) :: length
integer :: i

do i = 1, length
    arr(i) = 2 * i  ! 示例:生成2倍的序列值
end do
end subroutine

Python调用代码

import ctypes

flib = ctypes.CDLL('FortDll.dll')
# 显式声明函数参数类型和返回类型
flib.FORTFILLARRAY.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int]
flib.FORTFILLARRAY.restype = None

# 定义数组长度并分配内存
data_length = 10
arr_buffer = (ctypes.c_int * data_length)()

# 调用Fortran子程序填充数组
flib.FORTFILLARRAY(arr_buffer, data_length)

# 转换为Python列表,方便后续可视化
py_data = [val for val in arr_buffer]
print(py_data)  # 输出[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:46:01