我是Python(以及FORTRAN)的新手,但碰巧正在编写FORTRAN解算器的接口,我将从我的Python代码中调用它。我现在正在使用Python 3并尝试使用ctypes来编写接口。由于求解器SUBROUTINE有大约40个参数,我将使用FORTRAN和Python中的一个简单示例来显示我的问题。
首先,考虑ex3_func.f
中的主要FORTRAN子例程subroutine ex3_func (PP,num,dim,funptrObjFun)
implicit none
integer, intent(in) :: num, dim
real(8), intent(inout) :: PP(num,dim)
external funptrObjFun
PP = (PP+PP)*3.0
call funptrObjFun(PP,num,dim)
return
end subroutine
使用以下方法进行编译:$> gfortran -c ex3_func.f 完全没有问题。
我也有这个子程序的c接口,作为ex3_cfunc.f中的一个模块
module cwrapper_ex3cfunc
use iso_c_binding, only: c_int, c_double, c_funptr
implicit none
contains
subroutine ex3_cfunc(PP, num, dim, ptrfunObjFun) bind(c)
integer(c_int), intent(in) :: num, dim
real(c_double), intent(inout) :: PP(num,dim)
type(c_funptr), intent(inout) :: ptrfunObjFun
call ex3_func(PP,num,dim,ptrfunObjFun)
return
end subroutine
end module
使用以下方法进行编译:$> gfortran -c ex3_cfunc.f 也没有问题。
最后,我运行:$> gfortran -shared -O2 ex3_func.o ex3_cfunc.o -o lib_ex3func.so -fPIC
没有问题,并生成文件lib_ex3func.so
在转向Python代码之前,请注意funptrObjFunc(指向函数的指针)将在Python主程序中调用名为writetomatrix()的Python函数 - 见下文。
这是将调用此FORTRAN库的Python代码。
import ctypes as ct
import numpy as np
num=3
dim=4
AA = ((ct.c_double *dim) *num)
print(type(AA))
print(AA)
XX = AA()
<class '_ctypes.PyCArrayType'>
<class '__main__.c_double_Array_4_Array_3'>
#Fill XX with anything:
for i in range(0,num):
for j in range(0,dim):
XX[i][j]= (i+1)*(j+1)
def writetomatrix (FF,num,dim):
print("num x dim : ",num[0],dim[0])
print(FF)
print(np.shape(FF),'\n')
#Write to an element
FF[2][3]=99.0
print(np.ctypeslib.as_array(FF))
ptrfunc = ct.CFUNCTYPE(None,AA,ct.POINTER(ct.c_int),ct.POINTER(ct.c_int))
FORTRAN = ct.cdll.LoadLibrary('lib_ex3func.so')
#Execution!
FORTRAN.ex3_cfunc(XX,ct.byref(ct.c_int(num)),ct.byref(ct.c_int(dim)),ptrfunc(writetomatrix))
#output
num x dim : 3 4
<__main__.c_double_Array_4_Array_3 object at 0x106de1840>
(3, 4)
[[ 2.16962762e-314 1.97626258e-323 6.95321987e-310 2.16813588e-314]
[ 6.95321987e-310 6.95321987e-310 6.95321987e-310 6.95321987e-310]
[ 6.95321987e-310 2.16918622e-314 2.12199579e-314 9.90000000e+001]]
# As you can see (above) writetomatrix can't see nor access the original XX.
# It prints garbage and the 99.0 value in the last element! The FORTRAN
# procedure, however, does what it's suppoosed to do, and the answer below is
# correct. My question is how writetomatrix can access XX and modify it's
# elements?
ZZ=np.ctypeslib.as_array(XX)
ZZ
array([[ 6., 12., 18., 24.],
[ 12., 24., 36., 48.],
[ 18., 36., 54., 72.]])
我的问题和我的问题是我需要访问XX的元素并从writetomatrix()修改XX的元素。我无法弄清楚如何做到这一点。它是Python代码,FORTRAN代码,还是两者兼而有之?!非常感谢您的帮助和解释:)
感谢您抽出宝贵时间阅读本文!