Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过FORTRAN(DLL)返回双数组,以便在python中进一步处理_Python_Dll_Fortran_Ctypes_Fortran77 - Fatal编程技术网

通过FORTRAN(DLL)返回双数组,以便在python中进一步处理

通过FORTRAN(DLL)返回双数组,以便在python中进一步处理,python,dll,fortran,ctypes,fortran77,Python,Dll,Fortran,Ctypes,Fortran77,我已经为这个问题挣扎了一段时间,搜索查询/适用文档也没有产生任何可行的结果;所以把它贴在这里 我想要完成什么: 我有一些用FORTRAN77编写的程序,它接受一些参数并返回一个固定长度的双精度数组 我希望使用另一种编程语言来调用此函数(目前我使用python进行测试;但这可能会发生变化,因此f2py在这里不是一个选项) FORTRAN例程可以概括如下: FUNCTION TST (IIN) IMPLICIT LOGICAL (A-Z) cGCC$ ATTRIBUTES

我已经为这个问题挣扎了一段时间,搜索查询/适用文档也没有产生任何可行的结果;所以把它贴在这里

我想要完成什么:

  • 我有一些用FORTRAN77编写的程序,它接受一些参数并返回一个固定长度的双精度数组
  • 我希望使用另一种编程语言来调用此函数(目前我使用python进行测试;但这可能会发生变化,因此f2py在这里不是一个选项)
FORTRAN例程可以概括如下:

      FUNCTION TST (IIN)
      IMPLICIT LOGICAL (A-Z)
cGCC$ ATTRIBUTES DLLEXPORT, STDCALL :: TST
      INTEGER           II,IIN
      DOUBLE PRECISION, DIMENSION(3) :: TST
C
C     Test function:
      DO 1001 II = 1,3
         TST(II) = II * 1.11D0 + IIN
 1001 CONTINUE
      RETURN
      END
gfortran -static -c -fdollar-ok -fno-align-commons TEST.for
gfortran -shared -mrtd -static -o TEST.dll TEST.def TEST.o
import ctypes as cs
import numpy as np

#import dll library hooks:
tdll = cs.WinDLL(pathToDLL)
#test:
tdll.TST.restype = None
tdll.TST.argtypes = [cs.POINTER(cs.c_long), cs.POINTER(cs.c_double*3)]

#start testing:
Ar = [0.0, 0.0, 0.0]
_A = np.array(Ar).ctypes.data_as(cs.POINTER(cs.c_double*len(Ar)))
_L = cs.c_long(3)
tdll.TST(cs.byref(_L), _A)
这是使用gcc fortran编译的,如下所示:

      FUNCTION TST (IIN)
      IMPLICIT LOGICAL (A-Z)
cGCC$ ATTRIBUTES DLLEXPORT, STDCALL :: TST
      INTEGER           II,IIN
      DOUBLE PRECISION, DIMENSION(3) :: TST
C
C     Test function:
      DO 1001 II = 1,3
         TST(II) = II * 1.11D0 + IIN
 1001 CONTINUE
      RETURN
      END
gfortran -static -c -fdollar-ok -fno-align-commons TEST.for
gfortran -shared -mrtd -static -o TEST.dll TEST.def TEST.o
import ctypes as cs
import numpy as np

#import dll library hooks:
tdll = cs.WinDLL(pathToDLL)
#test:
tdll.TST.restype = None
tdll.TST.argtypes = [cs.POINTER(cs.c_long), cs.POINTER(cs.c_double*3)]

#start testing:
Ar = [0.0, 0.0, 0.0]
_A = np.array(Ar).ctypes.data_as(cs.POINTER(cs.c_double*len(Ar)))
_L = cs.c_long(3)
tdll.TST(cs.byref(_L), _A)
其中TEST.def将TST映射到TST_

到目前为止没有问题,但是在python中出现了问题“如何调用此函数并处理返回值?”

使用“depwalker”工具;TST函数显然需要2个参数(TST_u@8)。除了整数之外,我假设这应该是指向输出数组的指针或其长度

我的python代码如下所示:

      FUNCTION TST (IIN)
      IMPLICIT LOGICAL (A-Z)
cGCC$ ATTRIBUTES DLLEXPORT, STDCALL :: TST
      INTEGER           II,IIN
      DOUBLE PRECISION, DIMENSION(3) :: TST
C
C     Test function:
      DO 1001 II = 1,3
         TST(II) = II * 1.11D0 + IIN
 1001 CONTINUE
      RETURN
      END
gfortran -static -c -fdollar-ok -fno-align-commons TEST.for
gfortran -shared -mrtd -static -o TEST.dll TEST.def TEST.o
import ctypes as cs
import numpy as np

#import dll library hooks:
tdll = cs.WinDLL(pathToDLL)
#test:
tdll.TST.restype = None
tdll.TST.argtypes = [cs.POINTER(cs.c_long), cs.POINTER(cs.c_double*3)]

#start testing:
Ar = [0.0, 0.0, 0.0]
_A = np.array(Ar).ctypes.data_as(cs.POINTER(cs.c_double*len(Ar)))
_L = cs.c_long(3)
tdll.TST(cs.byref(_L), _A)
问题是,这段代码(以及我尝试的任何变体)将生成一个 错误:
o错误:异常:访问冲突写入0x0000000F
。如果我试图通过value传递第一个参数,它将导致
OSError:exception:access违规读取0x0000000F


有人能给我指一下正确的方向吗

经过一些加工后;此外,还感谢各位提出的宝贵建议,找到了上述问题的解决方案

为了使其正常工作,需要对python方面进行一些细微的更改:

import ctypes as cs
import numpy as np

#import dll library handle:
tdll = cs.WinDLL(pathToDLL)
#specify result and argument types
tdll.TST.restype = None
tdll.TST.argtypes = [cs.POINTER(cs.POINTER(cs.c_double*3)), cs.POINTER(cs.c_long)]

#call the dll function 'TST':
Ar = (cs.c_double*3)()
_A = cs.pointer(Ar)
tdll.TST(cs.byref(_A), cs.byref(cs.c_long(3)))
result = Ar[:]

希望这篇文章能对其他人有所帮助。

不要在没有通用标签的情况下使用特定于版本的标签。为什么需要stdcall?您最终计划使用哪种语言?编译后的DLL的某些功能也可在Excel/VBA中使用——最终语言将是C#或python,与VBA结合使用,用于单元测试/通用计算。预期该函数将实现为
void
函数,并带有指向结果的附加参数这正是我的假设,但将数组(或其指针)作为附加参数传递仍然会导致访问冲突