|
|
 |
 |
 |
 |
Fortran Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
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 !
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 :)
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
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
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
| 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.
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
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.
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).
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
| On 6 jun, 17:16, "Jugoslav Dujic" <jdu@yahoo.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.
| 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.
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
| On 7 jun, 11:39, "Jugoslav Dujic" <jdu@yahoo.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.
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).
|
 |
 |
 |
 |
|