经验:
fortran 约 3 个月
python - 中级:在此之前从未在 python 中使用过 ctypes 模块
我正在寻找一种将 fortran 代码用于我在 python 中的博士工作的方法 - 随后使用计算进行动态可视化,以使用 matplotlib 进行可视化。
这篇文章有帮助(这表明可以使用 ctypes 模块在 python 中使用/调用 fortran 代码 - 并且鉴于 fortran 函数具有绑定到它们的备用名称 - 这在逻辑上对我来说很有意义,尽管我不知道这是如何工作的细节。但我们确实明智地选择了我们的战斗!)。
然后这个 SO 帖子也处理从 python 调用 fortran 函数。
下一个合乎逻辑的步骤是查找python 模块 ctypes 的文档。这讨论了如何在 API 级别使用 python 访问共享库。
我有所有的东西来制作一个最小的工作示例,另一个答案已经完成了。但我想看看输出机制和涉及真实浮点数的数学运算。这是我制作的测试用例。
测试.f90
function prnt(s)
character(80):: s
logical :: prnt
print*, s
prnt = .true.
end function prnt
function sin_2(r)
real:: r,sin_2
sin_2 = sin(r)**2
end function sin_2
制作共享对象
$gfortran -shared -g -o test.so test.f90
编辑:出于某种原因,我的工作计算机需要 -fPIC 选项来编译
为了确保我的两个功能prnt
都sin_2
在某个地方,我检查了nm
:
$ nm test.so | tail -3
0000067f T prnt_
0000065c T sin_2_
U sinf@@GLIBC_2.0
到现在为止还挺好。我的函数prnt
和sin_2
已映射到库中prnt_
和sin_2_
库中。
从 python 解释器调用 fortran 函数
这就是所有这些都变得有点湿透的地方。使用python-ctypes 文档中的表格,我输入了以下内容 -
>>> from ctypes import byref, cdll, c_float,c_char_p
>>> t = cdll.LoadLibrary('./test.so')
>>> c = c_char_p("Mary had a little lamb")
>>> t.prnt_('Mary had a little lamb')
Mary had a little lambe
1
>>> t.prnt_("Mary had a little lamb")
Mary had a little lambe
1
>>> t.prnt_(c)
Mary had a little lambe[� .prnt_(c)
1
我想在每个输出末尾打印的 1 是 python 让我知道布尔输出的方式t.prnt_
是.true.
.
我有点担心t.prnt_
当我切换到正确的字符串数据类型时情况会变得更糟。文字打印没问题,只有e
最后有 a 。那是EOL字符吗?
然后是t.sin_2_
功能。我决定用它来计算 sin(4.56)**2。这是怎么回事 -
>>> f = c_float(4.56)
>>> t.sin_2_(4.56)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how to convert parameter 1
>>> t.sin_2_(f)
Segmentation fault (core dumped)
我在这里哪里出错了?我试图解释我是如何解决这个问题的,这样如果我在某处犯了明显的错误就会很明显。
指向其他 SO 帖子的大量链接是为了帮助其他提出与我现在一样的问题的人。