ctypes: error passing a list of str to a fortran dll

luis solisgb at gmail.com
Thu Jun 7 17:24:16 CEST 2007


On 5 jun, 06:15, Charles Sanders <C.delete_this.Sand... at BoM.GOv.AU>
wrote:
> luis wrote:
> > I'm using ctypes to call afortrandllfrom python. I have no problems
> > passing integer and double arryas, but I have an error with str arrys.
> > For example:
>
> [snip]
>
> I do not know about MicrosoftFortrancompilers (your mention
> ofdllindicates you are probably using MS), nor much about
> Python, but the C equivalent of a givenFortrancall is operating
> system and compiler dependent. You should consult theFortran
> compiler manual for the compiler used to create theDLL.
>
> Despite this, many (but not all) C toFortraninterfaces have
> the following characteristics
>
>         + C name isFortranname in lower case
>         +FortranREAL, DOUBLE PRECISION, INTEGER etc parameters
>           are pointers to the parameter in C, ie float*, etc
>         +FortranREAL etc arrays are pointers in C (same as
>           C arrays decay to pointers).
>         +FortranCHARACTER and CHARACTER arrays are passed as TWO
>           parameters, one a pointer to the start of the variable
>           or array, and the other the length as an integer, not
>           a pointer. The length parameters follow all other
>           parameters, in order of the character variables/arrays.
>
> Variations I have seen (all on Unix) include using upper case
> instead of lower, prepending (or postpending) an underscore (or
> other character(s)) to the subroutine or function name, and
> using special "character descriptors" (packing address and
> length into one "word") for character variables. There are
> almost certainly more variations that I have not seen.
>
> For example, given aFORTRANdeclaration
>
>         SUBROUTINE X( CV, RV, CA, N )
>         CHARACTER*(*) CV
>         REAL          RV
>         CHARACTER*(*) CA(*)
>         INTEGER       N
>
> The C equivalent is likely to be
>
>         void x( char *pcv, float *prv, char *pca, int *pn,
>             int lv, int la)
>
> Where lv will hold the length  of cv and la the length of
> each element of ca (required to be the same for all elements
> of the array).Fortranuses fixed length character strings,
> padded with blanks.
>
> Given the error message
>
>  > ValueError: Procedure probably called with not enough
>  > arguments (4 bytes missing)
>
> I suspect that yourFortrancompiler is one of the many which
> do this, and the missing 4 bytes are the integer length of
> each element of the character array.
>
> Also, I noticed you seem to be passing an array of character
> pointers rather than an array of characters. It is doubtful thatFortrancan handle this. You will probably have to pad the strings
> to a maximal length with spaces, concatanate then into one big
> string, and pass this by reference together with their padded
> length. YourFortranmay (but probably won't) have extensions
> that allow you to pass an array of character pointers.
>
> Charles

The solution proposed by Jugoslav Dujic, from comp lang fortran is

#Python script calling fortran subroutine
from ctypes import *
ap = windll.LoadLibrary(self.locationDll)
ap.TEST_02.restype=None
myCadena='D:\BBDD\PythonScripts\pru.txt'
strLen=len(myCadena)
pf_myCadena = c_char_p(myCadena)
pf_srLen = c_int(strLen)
ap.TEST_02(pf_myCadena,pf_srLen)

!fortran dll
subroutine TEST_02(s)
  !DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
  !DEC$ATTRIBUTES REFERENCE:: s
  !INTEGER(4):: n
  CHARACTER(*):: s

  open (unit=31,file=trim(s))
  write(31,'(f0.1)') 1.0
  write(31,*) trim(s)
  write(31,'(i0)') len_trim(s)
  close(31)
  return
END subroutine

Regards




More information about the Python-list mailing list