首先,我没有用fortran编写代码的经验。我试图用python ctypes运行fortran代码。我使用命令gfortran -shared -g -o test.so test.f90
将我的 test.f90 文件(代码如下)转换为 * test.so *。
在阅读了“基本数据类型”一章中通过ctypes从Python调用的C函数返回不正确的值和表之后,https://docs.python.org/3/library/ctypes.html#module-ctypes我对在我的Python代码中传递正确的数据类型有了一个线索,比如ctypes.c_double(123)
为real(kind=c_double)
。我收到了一个Type Error: wrong type
。我不知道如何将正确的数据类型传递给real(kind=c_double),dimension(*)
,它对我来说似乎是一个数组。在Numpy array to ctypes with FORTRAN ordering和https://numpy.org/doc/stable/reference/generated/numpy.ndarray.ctypes.html上,很好地解释了numpy提供了ctype转换。所以我尝试了一些随机数组来传递np.array([[1,2],[3,4]]).ctypes.data_as(POINTER(c_double))
的值。现在我收到另一个类型错误:TypeError: item 2 in _argtypes_ has no from_param method
。
我也在下面分享了我的python代码。我不知道我需要在我的函数中传递哪些数据类型。我将非常感谢你的解释。
function sticksum( anzd, w, b, a, weight, val, maxTchan, sthresh) result(spek) bind(c, name="sticksum")
use, intrinsic :: iso_c_binding
real(kind=c_double) :: anzd
real(kind=c_double) :: b,a
real(kind=c_double),dimension(*) :: w,weight
real(kind=c_double),dimension(*) :: val
integer(kind=c_int) :: maxTchan
real(kind=c_double) :: sthresh
real(kind=c_double) :: spek
integer :: i, t, j,anz
real :: stick, maxw
anz = anzd
spek = 123
i=1
t = w(i) * b + a + 1.5
if(t >= 1) THEN
spek = anz
stick = 0. + val(t)
maxw = weight(i)*stick
do i=2,anz
t = w(i) * b + a + 1.5
if(t > maxTchan) exit
stick = val(t)
maxw = max(weight(i)*stick,maxw)
if( (w(i)*w(i)-w(i-1)*w(i-1)) > 0.5) THEN
spek = spek + maxw
maxw = 0
end if
end do
end if
end function sticksum
from ctypes import *
import numpy as np
so_file = "./test.so"
my_functions = CDLL(so_file)
print(type(my_functions))
my_functions.sticksum_4.argtypes = [c_double,np.ndarray.ctypes,c_double,c_double,np.ndarray.ctypes,np.ndarray.ctypes,c_int, c_double]
my_functions.restype = c_double
anzd = c_double(123)
w = np.array([[1,2],[3,4]]).ctypes.data_as(POINTER(c_double))
b=c_double(123)
a=c_double(123)
weight=np.array([[1,2],[3,4]]).ctypes.data_as(POINTER(c_double))
val=np.array([[1,2],[3,4]]).ctypes.data_as(POINTER(c_double))
maxTchan=c_int(123)
sthresh=c_double(123)
sum = my_functions.sticksum_4(anzd,w,b,a,weight,val,maxTchan,sthresh)
1条答案
按热度按时间eit6fx6z1#
我想先声明 Fortran 不是我的技能之一-我接触过它~5次(SO 的其他问题)。
我发现了一堆问题:
*参数通过引用传递给函数/子例程([GNU.GCC]: Argument passing conventions).这花了我一个小时的时间来弄清楚.在我修复了所有的休息,我得到 * 访问冲突 * 甚至打印一个这样的参数.我在调查期间添加了虚拟函数.无论如何,最简单的版本是指定 value 作为按值传递的值(反之则是从调用代码传递指针)
请注意,在使用多维数组时,Fortran 和 C 中的轴顺序不同(例如,对于 2D,前者是column major)
设法让示例工作(我不知道 sticksum 的所有操作都应该做什么)。
输出:
读起来可能也很有趣: