Ctypes调用FORTRAN DLL示例

my_exam.f90

module example
    use iso_c_binding
    implicit none
contains
    subroutine my_exam(m,n,val) BIND(C,name='my_exam')
    !DEC$ ATTRIBUTES DLLEXPORT :: my_exam 
    integer,intent(in) :: m,n
    real(8),dimension(m,n),intent(inout) :: val
    integer :: i,j
    open(1,file = 'fortran_output.dat')
    write(1,'(a)') 'input arrary'
    write(1,100) ((val(i,j),j=1,n),i = 1,m)
    do i = 1,m
        do j = 1,n
            val(i,j) = val(i,j) * (i+j)
        end do
    end do
    write(1,'(a)') 'output arrary'
    write(1,100) ((val(i,j),j=1,n),i = 1,m)
    close(1)
100 format(<n>F10.3)    
    end subroutine
end module

ifort生成DLL

打开命令行形式的intel 64 visual studio 2012 mode
>ifort /dll my_exam.f90

my_exam.py

import ctypes as ct
import numpy as np

#导入dll
flib = ct.CDLL('my_exam.dll')

#创建矩阵
m = 10
n = 5
rng = np.random.RandomState()
val = rng.random_sample(size=(m, n)) * 10
f = open('expample_output.dat','w')
f.write('input array\n')
for line in val:
    for ele in line:
        f.write("{0:10.3f}".format(ele))
    f.write( '\n')

# 方式1:
# m_p = ct.pointer(ct.c_int(m))
# n_p = ct.pointer(ct.c_int(n))
# val = np.asfortranarray(val).T  #若不转置将面临fortran和C数组在内存中储存顺序不同的问题
# result = flib.my_exam(m_p, n_p, np.ctypeslib.as_ctypes(val))
# val = val.T
# print(val)


# 方式2:
def numpy_pointer(array):
    return array.ctypes.data_as(ct.POINTER(ct.c_double))
def my_exam(m, n, val):
    return flib.my_exam(ct.byref(ct.c_int(m)), ct.byref(ct.c_int(n)), numpy_pointer(val))
val = np.asfortranarray(val)   #按照Fortran方式储存(fortran列主序,C行主序)
result = my_exam(m, n, val)


f.write('output array\n')
for line in val:
    for ele in line:
        f.write("{0:10.3f}".format(ele))
    f.write( '\n')
f.close()
···

推荐阅读更多精彩内容