Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

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:

I have coded
ap.TEST_02(byref(len(mychar)),mychar)
and the message error is similar
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.

On 6 jun, 17:16, "Jugoslav Dujic" <jdu@yahoo.com> wrote:

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

soli@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.

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.

On 7 jun, 11:39, "Jugoslav Dujic" <jdu@yahoo.com> wrote:

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

soli@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.

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).

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc