Home > Archive > Fortran > June 2007 > calling a fortran dll from python with ctypes module
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
calling a fortran dll from python with ctypes module
|
|
| solisgb@gmail.com 2007-06-06, 4:09 am |
| 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 !
| |
| highegg 2007-06-06, 4:09 am |
| 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 :)
| |
| SimonG 2007-06-06, 4:09 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
| |
| solisgb@gmail.com 2007-06-06, 7:16 pm |
| 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
| |
| solisgb@gmail.com 2007-06-06, 7:16 pm |
| On 6 jun, 10:57, SimonG <s...@whiteowl.co.uk> wrote:
> On Jun 6, 7:53 am, highegg <high...@gmail.com> wrote:
>
>
> 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
| |
| Jugoslav Dujic 2007-06-06, 7:16 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.
| |
| solisgb@gmail.com 2007-06-06, 7:16 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
| |
| Beliavsky 2007-06-06, 7:16 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.
| |
| Jugoslav Dujic 2007-06-07, 8:08 am |
| 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.
| |
| Jugoslav Dujic 2007-06-07, 8:08 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.
| |
| solisgb@gmail.com 2007-06-08, 4:11 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
| |
| Jugoslav Dujic 2007-06-08, 4:11 am |
| 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 (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.
| |
| solisgb@gmail.com 2007-06-08, 4:11 am |
| 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).
| |
|
|
|
|
|
|
|