Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.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
Python 使用ctypes调用FORTRAN DLL_Python_Dll_Fortran_Mingw_Ctypes - Fatal编程技术网

Python 使用ctypes调用FORTRAN DLL

Python 使用ctypes调用FORTRAN DLL,python,dll,fortran,mingw,ctypes,Python,Dll,Fortran,Mingw,Ctypes,我正在尝试学习如何将FORTRAN代码编译成一个DLL,我可以使用ctypes从Python调用该DLL。即使是一个简单的例子也不起作用,有人能帮忙吗 我有一个FORTRAN程序: subroutine ex(i) integer i i=i+1 return end 然后我试着从Python运行它 from ctypes import * DLL = windll.test print DLL print getattr(DLL,'ex_') print DLL[1

我正在尝试学习如何将FORTRAN代码编译成一个DLL,我可以使用ctypes从Python调用该DLL。即使是一个简单的例子也不起作用,有人能帮忙吗

我有一个FORTRAN程序:

  subroutine ex(i)
  integer i
  i=i+1
  return
  end 
然后我试着从Python运行它

from ctypes import *

DLL = windll.test
print DLL

print getattr(DLL,'ex_')
print DLL[1]
print DLL.ex_

x = pointer( c_int(3) )
DLL.ex_( x )
我使用MinGW编译器编译它,如下所示

gfortran -c test.f
gfortran -shared -mrtd -o test.dll test.o
查看创建的DLL,我看到

Microsoft (R) COFF/PE Dumper Version 12.00.30723.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file test.dll

File Type: DLL

Section contains the following exports for test.dll

00000000 characteristics
       0 time date stamp Thu Jan 01 13:00:00 1970
    0.00 version
       1 ordinal base
       1 number of functions
       1 number of names

ordinal hint RVA      name

      1    0 00001280 ex_

Summary

    1000 .CRT
    1000 .bss
    1000 .data
    1000 .edata
    1000 .eh_fram
    1000 .idata
    1000 .rdata
    1000 .reloc
    1000 .text
    1000 .tls
然后我尝试从Python访问它

from ctypes import *

DLL = windll.test
print DLL

print getattr(DLL,'ex_')
print DLL[1]
print DLL.ex_

x = pointer( c_int(3) )
DLL.ex_( x )
输出是

<WinDLL 'test', handle 6bec0000 at 2143850>

<_FuncPtr object at 0x020E88A0>
<_FuncPtr object at 0x020E8918>
<_FuncPtr object at 0x020E88A0>
Traceback (most recent call last):
  File "C:\proj_py\test.py", line 20, in <module>
    DLL.ex_( x )
ValueError: Procedure probably called with too many arguments (4 bytes in excess) 
有人能提供解决方案吗


谢谢

Fortran通常是通过引用传递的。当从其他语言(如C)调用时,这意味着将内存地址传递给Fortran子例程。显然,Python实现是类似的。在编辑之前,您出现了一个错误,该错误表示“0x000003处的非法访问”,该值可能与您尝试传递的值“3”相同。您很好地输入了Fortran子例程,但当它尝试进行加法时,它在内存位置3查找整数,而不是在加法本身中使用值3


编辑之后,您正在传递一个指针(我想是根据我的评论)。这给出了一个不同的错误。它表明您传递了一个额外的参数,因为它得到的数据比预期的多4字节。我认为这可能是一些32位库和一些64位库之间的不兼容,两种体系结构中指针的长度可能相差4个字节。

DLL中的Fortran子程序可能真的需要指针。在Python中尝试
x=byref(3)
,而不是
x=c_int(3)
。如果行得通,我会发布一个较长的解释作为答案。我看到你在我第一次发表评论后编辑了你的问题,错误消息也发生了变化。这很好,因为一个问题解决了。现在看来,不同大小的指针之间存在一些不兼容。从这里很难看出到底是什么错误,但看起来您正在将64位指针传递到一个库中,而该库需要32位指针。(这是一个4字节的差异-正是您的错误消息报告的内容。)@blair您的库正在使用(调用者清理堆栈),而不是(调用者清理)。将其加载为
dll=CDLL('test')
。似乎@eryksun已经给出了答案。谢谢:-)当链接调用stdcall时,我想使用选项-mrtd。那个选项在做什么?对不起,我错过了
-mrtd
是一个编译选项,而不是链接选项。如果需要stdcall,请使用
gfortran-c-mrtd test.f
。在这种情况下,使用
DLL=windl('test')
加载DLL。