446,361 Members | 1,700 Online
Need help? Post your question and get tips & solutions from a community of 446,361 IT Pros & Developers. It's quick & easy.

# Calling Fortran from Python

 P: n/a Howdy, I have been trying to call the following Fortran function from Python (using Windows XP, Compaq Fortran and Python 2.4). I tried F2Py, Pyfort and calldll with no success. I think I came very close with calldll. Here is a short summary Fortran code: SUBROUTINE SAMPLE(IERR1,IERR2,AIN,AOUT) C C SIMPLE SAMPLE OF A DLL C !DEC\$ATTRIBUTES DLLEXPORT :: SAMPLE !DEC\$ATTRIBUTES ALIAS:'SAMPLE' :: SAMPLE INTEGER,INTENT(OUT) :: IERR1,IERR2 REAL*8,INTENT(IN) :: AIN(*) REAL*8,INTENT(OUT) :: AOUT(*) C C *** SET MAXIMUM EXPECTED ELEMENTS OF ARRAY AIN AND AOUT C PARAMETER (MAXNVIN=101,MAXNVOUT=200) C C *** SET ERROR INDICATORS TO ZERO C IERR1=0 IERR2=0 C C *** GET NUMBER OF INPUT VALUES C NVIN=AIN(1) C *** IF NUMBER EXCEEDS MAXIMUM EXPECTED SET ERRORS AND RETURN IF(NVIN .GT. MAXNVIN) THEN IERR1=1 IERR2=1 RETURN ENDIF C C *** SET NUMBER OF OUTPUT VALUES C NVOUT=2*NVIN C *** IF NUMBER EXCEEDS MAXIMUM EXPECTED SET ERRORS AND RETURN IF(NVOUT .GT. MAXNVOUT) THEN IERR1=1 IERR2=2 RETURN ENDIF C C *** INITIALIZE AOUT INDEX C JOUT=0 C C *** COMPUTE TWO OUTPUT VALUES FOR EACH INPUT VALUE C DO I=1,NVIN JOUT=JOUT+1 AOUT(JOUT)=2.*AIN(I+1) JOUT=JOUT+1 AOUT(JOUT)=3.*AIN(I+1) END DO RETURN END compiled it to a dll and called this dll from another Fortran program with success, so this tells me that dll is OK. This is how I tried to call it from python 2.4 import calldll handle = calldll.load_library('c:/sample_dll.dll') addr = calldll.get_proc_address(handle, 'SAMPLE') #so far so good, I got a handle and address e1 = 0 e2 = 0 ain = [2, 3, 4] aout = [ ] calldll.call_foreign_function(addr, 'hhll', 'l',(e1, e2,ain,aout)) Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required Has anyone provide a similar example with Pyfort, F2Py or calldll? Thanks in advance. Apr 3 '07 #1
13 Replies

 P: n/a Mangabasi wrote: Has anyone provide a similar example with Pyfort, F2Py or calldll? With the latest f2py in numpy: \$ cat sample.pyf ! -*- f90 -*- ! Note: the context of this file is case sensitive. python module sample ! in interface ! in :sample subroutine sample(ierr1,ierr2,ain,aout) ! in :sample:sample.f integer intent(out) :: ierr1 integer intent(out) :: ierr2 real*8 dimension(*),intent(in) :: ain !! This is what I had to modify from the generated interface. I !! changed 'dimension(*)' to 'dimension(len(ain))'. real*8 dimension(len(ain)),intent(out) :: aout end subroutine sample end interface end python module sample ! This file was auto-generated with f2py (version:2_3582). ! See http://cens.ioc.ee/projects/f2py2e/ ]\$ f2py -c -m sample sample.pyf sample.f running build running config_fc running build_src building extension "sample" sources creating /tmp/tmpZL8qAw creating /tmp/tmpZL8qAw/src.macosx-10.3-fat-2.5 f2py options: [] f2py: sample.pyf Reading fortran codes... Reading file 'sample.pyf' (format:free) Post-processing... Block: sample Block: sample Post-processing (stage 2)... Building modules... Building module "sample"... Constructing wrapper function "sample"... ierr1,ierr2,aout = sample(ain) Wrote C/API module "sample" to file "/tmp/tmpZL8qAw/src.macosx-10.3-fat-2.5/samplemodule.c" adding '/tmp/tmpZL8qAw/src.macosx-10.3-fat-2.5/fortranobject.c' to sources. adding '/tmp/tmpZL8qAw/src.macosx-10.3-fat-2.5' to include_dirs. .... Etc. \$ ipython Activating auto-logging. Current session state plus future input saved. Filename : /Users/rkern/.ipython/ipython.log Mode : backup Output logging : False Raw input log : False Timestamping : False State : active In [1]: import sample In [2]: sample.sample([1, 2, 3]) Out[2]: (0, 0, array([ 4., 6., 0.])) -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco Apr 3 '07 #2

 P: n/a Robert, Thanks for your prompt response. I think I got a lot closer but no cigar yet. This is the output C:\fortrandll>f2py -c -m sample sample.pyf sample.for numpy_info: FOUND: define_macros = [('NUMERIC_VERSION', '"\\"24.2\\""')] include_dirs = ['C:\\Python24\\include'] running build running config_fc running build_src building extension "sample" sources creating c:\docume~1\fb\locals~1\temp\tmpcosvgv creating c:\docume~1\fb\locals~1\temp\tmpcosvgv\src f2py: sample.pyf Reading fortran codes... Reading file 'sample.pyf' Post-processing... Block: sample Block: sample Post-processing (stage 2)... Building modules... Building module "sample"... Constructing wrapper function "sample"... ierr1,ierr2,aout = sample(ain) Wrote C/API module "sample" to file "c:\docume~1\fb \locals~1\temp\tmpcos vgv\src/samplemodule.c" adding 'c:\docume~1\fb\locals~1\temp\tmpcosvgv\src\fortra nobject.c' to sources .. adding 'c:\docume~1\fb\locals~1\temp\tmpcosvgv\src' to include_dirs. copying C:\python24\lib\site-packages\f2py2e\src\fortranobject.c -c: \docume~1\ fb\locals~1\temp\tmpcosvgv\src copying C:\python24\lib\site-packages\f2py2e\src\fortranobject.h -c: \docume~1\ fb\locals~1\temp\tmpcosvgv\src running build_ext No module named msvccompiler in scipy_distutils, trying from distutils.. error: The .NET Framework SDK needs to be installed before building extensions f or Python. I think I have a problem with distutils' msvccompiler.py. It may be the MacroExpander in distutils guessing the visual studio path incorrectly or something related to the registry keys. Is there a way to specify the C compiler path to f2py so that it does not rely on the distutils? Or maybe I am totally off base here, I don't know. Any thoughts? Apr 4 '07 #3

 P: n/a There may be a way to finish this without having to deal with distutils. F2py created three files so far samplemodule.c fortranobject.h fortranobject.c Is there a way to create the sample.pyd from these files? Apr 4 '07 #4

 P: n/a Mangabasi wrote: Robert, Thanks for your prompt response. I think I got a lot closer but no cigar yet. This is the output C:\fortrandll>f2py -c -m sample sample.pyf sample.for numpy_info: FOUND: define_macros = [('NUMERIC_VERSION', '"\\"24.2\\""')] include_dirs = ['C:\\Python24\\include'] running build running config_fc running build_src building extension "sample" sources creating c:\docume~1\fb\locals~1\temp\tmpcosvgv creating c:\docume~1\fb\locals~1\temp\tmpcosvgv\src f2py: sample.pyf Reading fortran codes... Reading file 'sample.pyf' Post-processing... Block: sample Block: sample Post-processing (stage 2)... Building modules... Building module "sample"... Constructing wrapper function "sample"... ierr1,ierr2,aout = sample(ain) Wrote C/API module "sample" to file "c:\docume~1\fb \locals~1\temp\tmpcos vgv\src/samplemodule.c" adding 'c:\docume~1\fb\locals~1\temp\tmpcosvgv\src\fortra nobject.c' to sources . adding 'c:\docume~1\fb\locals~1\temp\tmpcosvgv\src' to include_dirs. copying C:\python24\lib\site-packages\f2py2e\src\fortranobject.c -c: \docume~1\ fb\locals~1\temp\tmpcosvgv\src copying C:\python24\lib\site-packages\f2py2e\src\fortranobject.h -c: \docume~1\ fb\locals~1\temp\tmpcosvgv\src running build_ext No module named msvccompiler in scipy_distutils, trying from distutils.. error: The .NET Framework SDK needs to be installed before building extensions f or Python. I think I have a problem with distutils' msvccompiler.py. It may be the MacroExpander in distutils guessing the visual studio path incorrectly or something related to the registry keys. Is there a way to specify the C compiler path to f2py so that it does not rely on the distutils? Or maybe I am totally off base here, I don't know. What C and Fortran compilers are you trying to use? You can look at f2py's help for flags that you can use to help control where the compilers get picked up, but you can't avoid distutils. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco Apr 4 '07 #5

 P: n/a On Apr 4, 12:22 pm, Robert Kern f2py -c -m sample sample.pyf sample.for numpy_info: FOUND: define_macros = [('NUMERIC_VERSION', '"\\"24.2\\""')] include_dirs = ['C:\\Python24\\include'] running build running config_fc running build_src building extension "sample" sources creating c:\docume~1\fb\locals~1\temp\tmpcosvgv creating c:\docume~1\fb\locals~1\temp\tmpcosvgv\src f2py: sample.pyf Reading fortran codes... Reading file 'sample.pyf' Post-processing... Block: sample Block: sample Post-processing (stage 2)... Building modules... Building module "sample"... Constructing wrapper function "sample"... ierr1,ierr2,aout = sample(ain) Wrote C/API module "sample" to file "c:\docume~1\fb \locals~1\temp\tmpcos vgv\src/samplemodule.c" adding 'c:\docume~1\fb\locals~1\temp\tmpcosvgv\src\fortra nobject.c' to sources . adding 'c:\docume~1\fb\locals~1\temp\tmpcosvgv\src' to include_dirs. copying C:\python24\lib\site-packages\f2py2e\src\fortranobject.c -c: \docume~1\ fb\locals~1\temp\tmpcosvgv\src copying C:\python24\lib\site-packages\f2py2e\src\fortranobject.h -c: \docume~1\ fb\locals~1\temp\tmpcosvgv\src running build_ext No module named msvccompiler in scipy_distutils, trying from distutils.. error: The .NET Framework SDK needs to be installed before building extensions f or Python. I think I have a problem with distutils' msvccompiler.py. It may be the MacroExpander in distutils guessing the visual studio path incorrectly or something related to the registry keys. Is there a way to specify the C compiler path to f2py so that it does not rely on the distutils? Or maybe I am totally off base here, I don't know. What C and Fortran compilers are you trying to use? You can look at f2py's help for flags that you can use to help control where the compilers get picked up, but you can't avoid distutils. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco- Hide quoted text - - Show quoted text - I am using Visual Studio 6.0 and Compaq Visual Fortran 6.6. Apr 4 '07 #6

 P: n/a Mangabasi wrote: I am using Visual Studio 6.0 and Compaq Visual Fortran 6.6. Ah. You can't use VS6 with that version of Python. I believe you need the .NET SDK 2003. You could also use gcc, but I'm not sure if that will work well with Compaq Visual Fortran; you might have to use gfortran. http://www.develer.com/oss/GccWinBinaries -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco Apr 4 '07 #7

 P: n/a On Apr 4, 4:39 pm, Robert Kern

 P: n/a Mangabasi wrote: Would Python 2.5 work with Visual Studio 6.6? No. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco Apr 4 '07 #9

 P: n/a On Apr 4, 5:48 pm, Robert Kern

 P: n/a Mangabasi wrote: On Apr 4, 5:48 pm, Robert Kern Mangabasi wrote: >>Would Python 2.5 work with Visual Studio 6.6? No.--Robert Kern"I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco I will try the GCC then. It is a shame that I could not get calldll to work. It was very simple to use. I think I am making a mistake with the argument types but not sure. Thanks for your help, it is greatly appreciated. Did you try ctypes? >>from ctypes import *sample=cdll.sample.sample_sample.restype=Nonesample.argtypes=[POINTER(c_int), POINTER(c_int), POINTER(c_double), POINTER(c_double)] >>e1 = c_int(0)e2 = c_int(0)ain = (c_double*3)(2.0, 3.0, 4.0)aout = (c_double*4)()sample(e1, e2, ain, aout)aout[:] [6.0, 9.0, 8.0, 12.0] >>e1.value 0 >>e2.value 0 I compile the SAMPLE example with mingw g77 3.4.5: g77 -shared -o sample.dll sample.for I had to take out the "INTENT(OUT)"s because g77 didn't like them. And "SAMPLE" became "sample_" in the dll. Also note that argument passing to Fortran subroutines is strictly pass-by-reference. Thus the ain pointer. Lenard Lindstrom Apr 5 '07 #11

 P: n/a On Apr 4, 10:10 pm, Lenard Lindstrom >from ctypes import * >>sample=cdll.sample.sample_ >>sample.restype=None >>sample.argtypes=[POINTER(c_int), POINTER(c_int), POINTER(c_double), POINTER(c_double)] >>e1 = c_int(0) >>e2 = c_int(0) >>ain = (c_double*3)(2.0, 3.0, 4.0) >>aout = (c_double*4)() >>sample(e1, e2, ain, aout) >>aout[:] [6.0, 9.0, 8.0, 12.0] >>e1.value 0 >>e2.value 0 I compile the SAMPLE example with mingw g77 3.4.5: g77 -shared -o sample.dll sample.for I had to take out the "INTENT(OUT)"s because g77 didn't like them. And "SAMPLE" became "sample_" in the dll. Also note that argument passing to Fortran subroutines is strictly pass-by-reference. Thus the ain pointer. Lenard Lindstrom- Hide quoted text - - Show quoted text - Lenard, Now I tried it as you suggested. I did not install G77 yet. I tried it with the dll I already had. Something interesting happened: >>from ctypes import *sample=cdll.sample_dll.SAMPLEsample.restype=Nonesample.argtypes=[POINTER(c_int), POINTER(c_int), POINTER(c_double), POINTER(c_double)]sample.argtypes=[POINTER(c_int), POINTER(c_int), POINTER(c_double), POINTER(c_double)]e1 = c_int(-10)e2 = c_int(-10)ain = (c_double*3)(2.0, 3.0, 4.0)ain = (c_double*3)(2.0, 3.0, 4.0)aout = (c_double*4)()aout = (c_double*4)()sample(e1, e2, ain, aout) Traceback (most recent call last): File "", line 1, in ? ValueError: Procedure called with not enough arguments (16 bytes missing) or wrong calling convention >>aout[:] [6.0, 9.0, 8.0, 12.0] I got an error message and the expected answer! Any guesses? Apr 5 '07 #12

 P: n/a On Apr 4, 10:10 pm, Lenard Lindstrom >from ctypes import * >>sample=cdll.sample.sample_ >>sample.restype=None >>sample.argtypes=[POINTER(c_int), POINTER(c_int), POINTER(c_double), POINTER(c_double)] >>e1 = c_int(0) >>e2 = c_int(0) >>ain = (c_double*3)(2.0, 3.0, 4.0) >>aout = (c_double*4)() >>sample(e1, e2, ain, aout) >>aout[:] [6.0, 9.0, 8.0, 12.0] >>e1.value 0 >>e2.value 0 I compile the SAMPLE example with mingw g77 3.4.5: g77 -shared -o sample.dll sample.for I had to take out the "INTENT(OUT)"s because g77 didn't like them. And "SAMPLE" became "sample_" in the dll. Also note that argument passing to Fortran subroutines is strictly pass-by-reference. Thus the ain pointer. Lenard Lindstrom- Hide quoted text - - Show quoted text - A little bit of googling solved the problem. instead of >>sample = cdll.sample_dll.SAMPLE I used >>sample = windll.sample_dll.SAMPLE and now it seems to be working without error messages. Thanks a lot. Apr 5 '07 #13

 P: n/a Mangabasi wrote: A little bit of googling solved the problem. instead of >>>sample = cdll.sample_dll.SAMPLE I used >>>sample = windll.sample_dll.SAMPLE and now it seems to be working without error messages. Thanks a lot. I remember someone on the ctypes mailing list mentioning that g77 uses the C calling convention for exported functions. Other compilers might default to standard calls. At least with ctypes one can tinker with calling convention and function arguments to make a call work. Lenard Apr 5 '07 #14

### This discussion thread is closed

Replies have been disabled for this discussion.