Я пытаюсь узнать, как выполнить код FORTRAN в DLL, которую я могу вызвать из Python с использованием ctypes. Даже простой пример не работает, может ли кто-нибудь помочь?Вызов библиотеки FORTRAN с использованием ctypes
У меня есть одну процедуру в FORTRAN:
subroutine ex(i)
integer i
i=i+1
return
end
Тогда я пытаюсь запустить это из Python
я скомпилировать его с компилятором 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)
Так что, хотя эта функция есть, я не называю это правильно. Я в тупике.
Я использую питона 2.7.10 (32 бит) на 64-разрядной ОС Windows-7 машине, у меня есть последняя версия компилятора MinGW:
$ gfortran -v
Using built-in specs.
COLLECT_GCC=c:\mingw\bin\gfortran.exe
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/4.8.1/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.8.1/configure --prefix=/mingw --host=mingw32 --build=mingw32 --without-pic --enable-shared --e
nable-static --with-gnu-ld --enable-lto --enable-libssp --disable-multilib --enable-languages=c,c++,fortran,objc,obj-c++
,ada --disable-sjlj-exceptions --with-dwarf2 --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific
-runtime-libs --with-gmp=/usr/src/pkg/gmp-5.1.2-1-mingw32-src/bld --with-mpc=/usr/src/pkg/mpc-1.0.1-1-mingw32-src/bld --
with-mpfr= --with-system-zlib --with-gnu-as --enable-decimal-float=yes --enable-libgomp --enable-threads --with-libiconv
-prefix=/mingw32 --with-libintl-prefix=/mingw --disable-bootstrap LDFLAGS=-s CFLAGS=-D_USE_32BIT_TIME_T
Thread model: win32
gcc version 4.8.1 (GCC)
Может кто-нибудь предложить решение?
Thanks
Подпрограмма Fortran в DLL, вероятно, действительно ожидает указателя. Попробуйте 'x = byref (3)' в вашем Python вместо 'x = c_int (3)'. Если это сработает, я отправлю более длинное объяснение в качестве ответа. – Brick
Я вижу, что вы отредактировали свой вопрос с моего первого комментария, и сообщение об ошибке изменилось. Это хорошо, потому что одна проблема. Теперь похоже, что вы получаете некоторую несовместимость между указателями разных размеров. Трудно видеть, что именно не так, но похоже, что вы передаете 64-битный указатель в библиотеку, ожидающую 32-битного указателя. (Это разница в 4 байта.). @Blair – Brick
В вашей библиотеке используется [cdecl] (https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl) (вызывающий очищает стек), not [stdcall] (https://en.wikipedia.org/wiki/X86_calling_conventions#stdcall) (очистка вызываемого абонента). Загрузите его как 'dll = CDLL ('test')'. – eryksun