如何将Dynamic数组从Python传递给Fortran DLL?

时间:2015-07-17 13:35:37

标签: python arrays dll fortran ctypes

我在Python中调用fortran dll时遇到了一些麻烦,并且真的需要一些帮助和建议。 我的问题是将动态数组传递给函数(由我的Fortran DLL提供)。

例如,我有一个带动态数组的类型:

Module Class_Rotor 
    Implicit None 
    Type,Public ::Type_Rotor 
        Real(kind=8),Public::Mass 
        Real(kind=8),Allocatable,Public::Lamda(:,:) 
    End Type Type_Rotor 
End Module Class_Rotor 

Module Class_Trim 
    Implicit None 
    Type,Public::Type_Trim 
        Real(kind=8),Public::COLL 
        Real(kind=8),Public::LNGCYC 
    End Type Type_Trim 
End Module Class_Trim 

我想在fortran子程序中使用动态数组

Subroutine CalculateRotor(Trim,Rotor)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, MIXED_STR_LEN_ARG, ALIAS:"CalculateRotor" :: CalculateRotor
    Use Class_Rotor
    Use Class_Trim
    TYPE(Type_Trim),Intent(in)::Trim
    TYPE(Type_Rotor),Intent(inout)::Rotor

    Rotor%Mass = Trim%COLL + Trim%LNGCYC
End Subroutine CalculateRotor

Subroutine CalculateTrim(Rotor,Trim)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, MIXED_STR_LEN_ARG, ALIAS:"CalculateTrim" :: CalculateTrim
    Use Class_Rotor
    Use Class_Trim
    TYPE(Type_Rotor),Intent(in)::Rotor
    TYPE(Type_Trim),Intent(inout)::Trim

    Trim%COLL = Rotor%Mass+Rotor%Lamda(2,2)

End Subroutine CalculateTrim

另外,我定义了一个sunroutine Alc来分配Rotor%Lamda的空间,并将值传递给它。

Subroutine Alc(Rotor,n,LamArray)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, MIXED_STR_LEN_ARG, ALIAS:"Alc" :: Alc
    Use Class_Rotor
    TYPE(Type_Rotor),intent(inout):: Rotor
    Integer(kind=4)::I,J
    Integer(kind=4),intent(in)::n
    Real(kind = 8),DIMENSION(n,n),intent(in)::LamArray

    IF(Allocated(Rotor%Lamda))Then
        DeAllocate(Rotor%Lamda)
    ENDIF

    Allocate(Rotor%Lamda(n,n))  
    Do I=1,n
        Do J=1,n
            Rotor%Lamda(I,J)=LamArray(I,J)  
        EndDo
    EndDo
End Subroutine Alc

我试着这样: 新的Fortran DLL项目(vs2010 + IVF),然后我在python中使用这个DLL:

from ctypes import *
import numpy as np
from numpy.ctypeslib import load_library,ndpointer

class Type_Rotor(Structure):
    _fields_ = [             
    ('Mass', c_double),
    ('Lamda', POINTER(c_double)),
    ]
    def __init__(self,cols):
        self.cols_count = cols 
        pc = (POINTER(c_double)*cols*cols)()
        self.Lamda = cast(pc,POINTER(c_double))

class Type_Trim(Structure):
    _fields_ = [             
    ('COLL', c_double),
    ('LNGCYC', c_double),
    ]  

def run():
    mydll = windll.LoadLibrary('Dll3.dll')
    CalculateRotor = mydll.CalculateRotor
    CalculateTrim = mydll.CalculateTrim
    Rotor = Type_Rotor(3)
    Trim = Type_Trim()

    Rotor.Mass = 1.0

    temp = (c_double *3*3) ((1,2,3),(4,5,6),(7,8,9))

    Trim.COLL = 11.0
    Trim.LNGCYC = -3.0

    mydll.Alc(byref(Rotor),byref(c_int(Rotor.cols_count)),byref(temp))
    for i in range(15):
        CalculateRotor(byref(Trim), byref(Rotor))
        print Trim.COLL,Trim.LNGCYC,Rotor.Mass
        CalculateTrim(byref(Rotor), byref(Trim))
    print Trim.COLL,Trim.LNGCYC,Rotor.Mass

if __name__=="__main__":
    run()    
在Win7下,第一次使用命令行运行python脚本,返回以下答案:传递给DeAllocate的指针指向一个无法解除分配的对象, 但第二次给出了正确的答案

在Winxp下,第一次使用命令行运行python脚本,返回以下答案:传递给DeAllocate的指针指向一个无法释放的对象, 但第二次它给出了正确的答案,但是,然后它粉碎!!! somtimes,它也返回:可分配的数组已经分配

我真的不知道为什么?以及如何使用动态数组?

0 个答案:

没有答案