CTypes,Python回调和FORTRAN

时间:2016-02-03 02:30:53

标签: python-3.x callback fortran ctypes

我是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代码,还是两者兼而有之?!非常感谢您的帮助和解释:)

感谢您抽出宝贵时间阅读本文!

0 个答案:

没有答案