f



calling a fortran dll from python with ctypes module

I'm using ctypes to call a fortran dll from python. I have no problems
passing arguments of integer or double types, both scalars or arrays,
single or double precission, but I have errors with python strings.

For example:

(sorry, is python code)
.....
n = c_int(10)
Vector= c_double * m
f_x=Vector()
for i in range(m):
....f_x[i] = float(1.0)

ap = windll.LoadLibrary(locationDll)
ap.TEST_01(byref(n),byref(f_x),byref(y))
print y.value # ok

Char= c_char_p
mychar=Char('0123456789')
mychar2=Char(m*' ')
ap.TEST_02(mychar) #error

the error text is
ValueError: Procedure probably called with not enough arguments (4
bytes missing)

fortran code (CVF compiler)

subroutine TEST_01(n,x,out)
....!DEC$ ATTRIBUTES DLLEXPORT :: TEST_01
....INTEGER(4) n
....REAL(8), dimension(n):: x
....real(8):: out
....out=sum(x)
....return
END subroutine

subroutine TEST_02(a)
....!DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
....CHARACTER(10):: a
....open(31,file='pru.txt')
....write(31,*) a
....close(31)
....return
END subroutine

Some suggestions are wellcome !

0
solisgb (21)
6/6/2007 6:40:57 AM
comp.lang.fortran 11856 articles. 1 followers. Post Follow

14 Replies
1267 Views

Similar Articles

[PageSpeed] 44

Fortran compilers sometimes pass a hidden integer length argument
along with a string. This is typically done for character(*)
arguments, for fixed-len characters it's not necessary, but CVF is
old, so who knows? I suggest you try defining TEST_02 with
CHARACTER(*):: a
and calling it from Python as
ap.TEST_02(mychar,byref(len(mychar)))
No warranty :)

0
highegg (245)
6/6/2007 6:53:12 AM
On Jun 6, 7:53 am, highegg <high...@gmail.com> wrote:
> Fortran compilers sometimes pass a hidden integer length argument
> along with a string. This is typically done for character(*)
> arguments, for fixed-len characters it's not necessary, but CVF is
> old, so who knows? I suggest you try defining TEST_02 with
> CHARACTER(*):: a
> and calling it from Python as
> ap.TEST_02(mychar,byref(len(mychar)))
> No warranty :)

Some compilers add the length argument to the end of the arg list
whilst others (like CVF) add it immediately after the character(*)
argument - and some have options to enable you to choose (ifort I
think).

Simon Geard

0
simon9085 (164)
6/6/2007 8:57:11 AM
On 6 jun, 08:53, highegg <high...@gmail.com> wrote:
> Fortran compilers sometimes pass a hidden integer length argument
> along with a string. This is typically done for character(*)
> arguments, for fixed-len characters it's not necessary, but CVF is
> old, so who knows? I suggest you try defining TEST_02 with
> CHARACTER(*):: a
> and calling it from Python as
> ap.TEST_02(mychar,byref(len(mychar)))
> No warranty :)

I try with your suggestions and the error persists, now with the text
WindowsError: exception: access violation reading 0x00C25000


0
solisgb (21)
6/6/2007 12:04:47 PM
On 6 jun, 10:57, SimonG <s...@whiteowl.co.uk> wrote:
> On Jun 6, 7:53 am, highegg <high...@gmail.com> wrote:
>
> > Fortran compilers sometimes pass a hidden integer length argument
> > along with a string. This is typically done for character(*)
> > arguments, for fixed-len characters it's not necessary, but CVF is
> > old, so who knows? I suggest you try defining TEST_02 with
> > CHARACTER(*):: a
> > and calling it from Python as
> > ap.TEST_02(mychar,byref(len(mychar)))
> > No warranty :)
>
> Some compilers add the length argument to the end of the arg list
> whilst others (like CVF) add it immediately after the character(*)
> argument - and some have options to enable you to choose (ifort I
> think).
>
> Simon Geard

I have coded
ap.TEST_02(byref(len(mychar)),mychar)
and the message error is similar

0
solisgb (21)
6/6/2007 12:08:13 PM
solisgb@gmail.com wrote:
| On 6 jun, 08:53, highegg <high...@gmail.com> wrote:
|| Fortran compilers sometimes pass a hidden integer length argument
|| along with a string. This is typically done for character(*)
|| arguments, for fixed-len characters it's not necessary, but CVF is
|| old, so who knows? I suggest you try defining TEST_02 with
|| CHARACTER(*):: a
|| and calling it from Python as
|| ap.TEST_02(mychar,byref(len(mychar)))
|| No warranty :)
| 
| I try with your suggestions and the error persists, now with the text
| WindowsError: exception: access violation reading 0x00C25000

Should be byval, actually.

Alternatively, on the CVF side, you can add 

!DEC$ATTRIBUTES REFERENCE:: stringarg

to suppress the hidden length argument; in that case, you also have to 
pass the character length by other means (normally, as a separate real
argument) and declare the argument as CHARACTER(length) (as opposed to
CHARACTER(*))


-- 
 Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.
0
jdujic (694)
6/6/2007 3:16:04 PM
On 6 jun, 17:16, "Jugoslav Dujic" <jdu...@yahoo.com> wrote:
> soli...@gmail.com wrote:
>
> | On 6 jun, 08:53, highegg <high...@gmail.com> wrote:
> || Fortran compilers sometimes pass a hidden integer length argument
> || along with a string. This is typically done for character(*)
> || arguments, for fixed-len characters it's not necessary, but CVF is
> || old, so who knows? I suggest you try defining TEST_02 with
> || CHARACTER(*):: a
> || and calling it from Python as
> || ap.TEST_02(mychar,byref(len(mychar)))
> || No warranty :)
> |
> | I try with your suggestions and the error persists, now with the text
> | WindowsError: exception: access violation reading 0x00C25000
>
> Should be byval, actually.
>
> Alternatively, on the CVF side, you can add
>
> !DEC$ATTRIBUTES REFERENCE:: stringarg
>
> to suppress the hidden length argument; in that case, you also have to
> pass the character length by other means (normally, as a separate real
> argument) and declare the argument as CHARACTER(length) (as opposed to
> CHARACTER(*))
>
> --
>  Jugoslav
> ___________www.xeffort.com
>
> Please reply to the newsgroup.
> You can find my real e-mail on my home page above.

I change the fortran subroutine to

subroutine TEST_02(a,n)
!DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
INTEGER(4):: n
CHARACTER(len=n):: a
....
passing a and n by value and by reference from python the error
message is ValueError: Procedure probably called with not enough
arguments (4 bytes missing).

I also have used the /iface:nomixed_str_len_arg compiler option with
the same result


0
solisgb (21)
6/6/2007 4:45:50 PM
You should have cross-posted your message to comp.lang.python from the
beginning. Since you still have a problem, I suggest summarizing what
you have tried so far in a new message to comp.lang.python . Questions
about how to interface Python to other languages (most often C) arise
often there and are considered on-topic.

0
beliavsky (2212)
6/6/2007 4:55:59 PM
On 6 jun, 18:55, Beliavsky <beliav...@aol.com> wrote:
> You should have cross-posted your message to comp.lang.python from the
> beginning. Since you still have a problem, I suggest summarizing what
> you have tried so far in a new message to comp.lang.python . Questions
> about how to interface Python to other languages (most often C) arise
> often there and are considered on-topic.

I did, without a solution. My feeling is:

1.- There are not a simple solution.
2.- Is a problem between C and fortran. In python, the module ctypes
exports python types to c, not to fortran (not is ftypes).

0
solisgb (21)
6/6/2007 8:10:27 PM
On 6 Jun, 21:10, soli...@gmail.com wrote:
> On 6 jun, 18:55, Beliavsky <beliav...@aol.com> wrote:
>
> > You should have cross-posted your message to comp.lang.python from the
> > beginning. Since you still have a problem, I suggest summarizing what
> > you have tried so far in a new message to comp.lang.python . Questions
> > about how to interface Python to other languages (most often C) arise
> > often there and are considered on-topic.
>
> I did, without a solution. My feeling is:
>
> 1.- There are not a simple solution.
> 2.- Is a problem between C and fortran. In python, the module ctypes
> exports python types to c, not to fortran (not is ftypes).

I can reassure you at least that there is no problem cross-calling
between fortran and c if you're using simple data types (real,
character, integer or arrays thereof). CAD systems often have mixtures
of c and fortran and such cross-calling is bread an butter to them. c
interoperability is part of f2003 so you might make life easier for
yourself if you try a compiler that supports that functionality (I
think g95 is one). I suggest you look at the interface between python
and c. If python is passing structs then cross calling gets harder.

Simon Geard

0
simon9085 (164)
6/6/2007 10:10:56 PM
solisgb@gmail.com wrote:
| On 6 jun, 17:16, "Jugoslav Dujic" <jdu...@yahoo.com> wrote:
|| soli...@gmail.com wrote:
|| 
||| On 6 jun, 08:53, highegg <high...@gmail.com> wrote:
|||| Fortran compilers sometimes pass a hidden integer length argument
|||| along with a string. This is typically done for character(*)
|||| arguments, for fixed-len characters it's not necessary, but CVF is
|||| old, so who knows? I suggest you try defining TEST_02 with
|||| CHARACTER(*):: a
|||| and calling it from Python as
|||| ap.TEST_02(mychar,byref(len(mychar)))
|||| No warranty :)
||| 
||| I try with your suggestions and the error persists, now with the text
||| WindowsError: exception: access violation reading 0x00C25000
|| 
|| Should be byval, actually.
|| 
|| Alternatively, on the CVF side, you can add
|| 
|| !DEC$ATTRIBUTES REFERENCE:: stringarg
|| 
|| to suppress the hidden length argument; in that case, you also have to
|| pass the character length by other means (normally, as a separate real
|| argument) and declare the argument as CHARACTER(length) (as opposed to
|| CHARACTER(*))
|| 
|| --
||  Jugoslav
|| ___________www.xeffort.com
|| 
|| Please reply to the newsgroup.
|| You can find my real e-mail on my home page above.
| 
| I change the fortran subroutine to
| 
| subroutine TEST_02(a,n)
| !DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
| INTEGER(4):: n
| CHARACTER(len=n):: a
| ...
| passing a and n by value and by reference from python the error
| message is ValueError: Procedure probably called with not enough
| arguments (4 bytes missing).

But you didn't specify !DEC$ATTRIBUTES REFERENCE:: a. 

CHARACTER(*) and CHARACTER(n) don't make difference from the
caller's perspective. !DEC$ATTRIBUTES REFERENCE specifies
"I don't want the hidden length passed; I'll declare it 
by other means".
 
| I also have used the /iface:nomixed_str_len_arg compiler option with
| the same result

....because you didn't specify REFERENCE, but just swapped the order
of the "real" arguments.

-- 
 Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.
0
jdujic (694)
6/7/2007 9:36:20 AM
solisgb@gmail.com wrote:
| On 6 jun, 18:55, Beliavsky <beliav...@aol.com> wrote:
|| You should have cross-posted your message to comp.lang.python from the
|| beginning. Since you still have a problem, I suggest summarizing what
|| you have tried so far in a new message to comp.lang.python . Questions
|| about how to interface Python to other languages (most often C) arise
|| often there and are considered on-topic.
| 
| I did, without a solution. My feeling is:
| 
| 1.- There are not a simple solution.

There is. You just fail to pick up the correct combination.
To repeat, those are:

1)
ap.TEST_02(mychar,byval(len(mychar))) //or whatever is Python correct syntax
subroutine TEST_02(a)
....!DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
....CHARACTER(*):: a
end subroutine

2)
ap.TEST_02(mychar,byref(len(mychar)))
subroutine TEST_02(a,n)
....!DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
   !DEC$ATTRIBUTES REFERENCE:: a
   INTEGER:: n
....CHARACTER(n):: a
end subroutine

-- 
 Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.
0
jdujic (694)
6/7/2007 9:39:05 AM
On 7 jun, 11:39, "Jugoslav Dujic" <jdu...@yahoo.com> wrote:
> soli...@gmail.com wrote:
>
> | On 6 jun, 18:55, Beliavsky <beliav...@aol.com> wrote:
> || You should have cross-posted your message to comp.lang.python from the
> || beginning. Since you still have a problem, I suggest summarizing what
> || you have tried so far in a new message to comp.lang.python . Questions
> || about how to interface Python to other languages (most often C) arise
> || often there and are considered on-topic.
> |
> | I did, without a solution. My feeling is:
> |
> | 1.- There are not a simple solution.
>
> There is. You just fail to pick up the correct combination.
> To repeat, those are:
>
> 1)
> ap.TEST_02(mychar,byval(len(mychar))) //or whatever is Python correct syntax
> subroutine TEST_02(a)
> ...!DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
> ...CHARACTER(*):: a
> end subroutine
>
> 2)
> ap.TEST_02(mychar,byref(len(mychar)))
> subroutine TEST_02(a,n)
> ...!DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
>    !DEC$ATTRIBUTES REFERENCE:: a
>    INTEGER:: n
> ...CHARACTER(n):: a
> end subroutine
>
> --
>  Jugoslav
> ___________www.xeffort.com
>
> Please reply to the newsgroup.
> You can find my real e-mail on my home page above.


1) runs fine, 2) not

The final example must be:

#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


Thanks

0
solisgb (21)
6/7/2007 3:19:12 PM
solisgb@gmail.com wrote:
| On 7 jun, 11:39, "Jugoslav Dujic" <jdu...@yahoo.com> wrote:
|| soli...@gmail.com wrote:

| 1) runs fine, 2) not
|
| The final example must be:
|
| !fortran dll
| subroutine TEST_02(s)
|  !DEC$ ATTRIBUTES DLLEXPORT :: TEST_02
|  !DEC$ATTRIBUTES REFERENCE:: s
|  !INTEGER(4):: n
|  CHARACTER(*):: s
|
| END subroutine

Uh, you're right; my bad. Sorry, I was so convinced that I didn't
bother looking at the manual. After I did, I discovered that they made
it so complicated that, after 10 years of mixed-language programming
experience with CVF, I got confused (again):

<quote>
1) If REFERENCE (only) is specified for a character argument, the following 
occurs:

 *On Windows systems, hidden lengths immediately follow the variable....
2) If REFERENCE is specified for a character argument, and C (or STDCALL) has 
been specified for the routine, the string is passed with no length. This is 
true even if REFERENCE is also specified for the routine.
3) If REFERENCE and C (or STDCALL) are specified for a routine, but REFERENCE 
has not been specified for the argument, the string is passed with the length.
</quote>

I have always used REFERENCE in combination with C or STDCALL (case 2),
so I naively expected that it also holds to case 1 (i.e. yours). In
other words, in your last version, REFERENCE is spurious :-D

Blame Can^H^H^H Microsoft, as always (AFAIK it's originally their semantics)

And morale: prefer RTFM to random usenet users :-).
-- 
 Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above. 

0
jdujic (694)
6/7/2007 3:38:13 PM
On 6 jun, 18:55, Beliavsky <beliav...@aol.com> wrote:
> You should have cross-posted your message to comp.lang.python from the
> beginning. Since you still have a problem, I suggest summarizing what
> you have tried so far in a new message to comp.lang.python . Questions
> about how to interface Python to other languages (most often C) arise
> often there and are considered on-topic.

I did, without a solution. My feeling is:

1.- There are not a simple solution.
2.- Is a problem between C and fortran. In python, the module ctypes
exports python types to c, not to fortran (not is ftypes).

0
solisgb (21)
6/8/2007 9:06:25 AM
Reply: