Calling FORTRAN Shared Libraries from Gambas

Post your Gambas programming questions here.
Post Reply
User avatar
Cedron
Posts: 156
Joined: Thursday 21st February 2019 5:02pm
Location: The Mitten State
Contact:

Calling FORTRAN Shared Libraries from Gambas

Post by Cedron »

Why?

Uhh, because we can?

No, seriously, there are a lot of old FORTRAN libraries and old FORTRAN codgers. Some of those routines are quite clever.

So, just because we can. A few things to watch out for:

* FORTRAN mangles the routine names. I had to do a "nm -D" to figure that out.

* FORTRAN passes by reference

* I didn't test much except passing values to the routines for each of the FORTRAN types.

So without further ado, here is the source code for the FORTRAN library, Test1.for. Compiling instructions at the bottom.

Code: Select all

      SUBROUTINE Test1()
      WRITE( *, * ) "Hello from FORTRAN land!"
      END

      SUBROUTINE Test2( N )
      INTEGER N
      WRITE( *, * ) N
      N = N + 1
      END

      SUBROUTINE Test3( R )
      REAL R
      WRITE( *, * ) R
      R = R + 1.0
      END

      SUBROUTINE Test4( D )
      DOUBLE PRECISION D
      WRITE( *, * ) D
      D = D + 1.0
      END

      SUBROUTINE Test5( L )
      LOGICAL L
      WRITE( *, * ) L
      L = (4.GT.5)
      END

      SUBROUTINE Test6( C )
      CHARACTER*20 C
      WRITE( *, * ) C
      C = "98765432109876543210"
      END

      SUBROUTINE Test7( E )
      COMPLEX E
      WRITE( *, * ) E
      E = E + 1.0
      END

C  gfortran -shared -fPIC -o Test1.so Test1.for 

C nm -D Test1.so
Here is the Gambas calling routine:
' Gambas module file

Extern test1_() In "~/Gambas/Fortran/Test1"
Extern test2_(argIntegerPtr As Pointer) In "~/Gambas/Fortran/Test1"
Extern test3_(argSinglePtr As Pointer) In "~/Gambas/Fortran/Test1"
Extern test4_(argFloatPtr As Pointer) In "~/Gambas/Fortran/Test1"
Extern test5_(argIntegerPtr As Pointer) In "~/Gambas/Fortran/Test1"
Extern test6_(argAllocPtr As Pointer) In "~/Gambas/Fortran/Test1"
Extern test7_(argAllocPtr As Pointer) In "~/Gambas/Fortran/Test1"

Public Sub Main()

  Print "Hello world"
  
  Dim I As Integer  ' FORTRAN INTEGER
  Dim R As Single   ' FORTRAN REAL
  Dim D As Float    ' FORTRAN DOUBLE PRECISION
  Dim L As Integer  ' FORTRAN LOGICAL
  Dim C As Pointer  ' FORTRAN CHARACTER
  Dim E As Pointer  ' FORTRAN COMPLEX

  Dim O As Stream  

  I = 3122
  R = Pi(2)  
  D = Exp(1)
  L = CInt(True) And 1
  C = Alloc("12345678901234567890")
  E = Alloc(8)

  O = Open Memory E For Write
  Print #O, MkSingle(3);
  Print #O, MkSingle(4);
  Close #O
  
  test1_()
  test2_(VarPtr(I))
  test3_(VarPtr(R))
  test4_(VarPtr(D))
  test5_(VarPtr(L))
  test6_(C)
  test7_(E)
  
  Print "I,m back"
  Print I
  Print R
  Print D
  Print (L <> 0)
  Print Left(String@(C), 20)
  Print Single@(E), Single@(E + 4)

  Free(C)
  Free(E)

End
Here is the output:

Code: Select all

Hello world
 Hello from FORTRAN land!
        3122
   6.28318548    
   2.7182818284590451     
 T
 12345678901234567890
 (  3.00000000    ,  4.00000000    )
I,m back
3123
7.2831855
3.71828182845905
False
98765432109876543210
4       4
Now, if anybody has a better way to do the character and complex types without resorting to a Alloc/Free pair, I'd appreciate knowing about it.

Ced
.... and carry a big stick!
User avatar
Cedron
Posts: 156
Joined: Thursday 21st February 2019 5:02pm
Location: The Mitten State
Contact:

Re: Calling FORTRAN Shared Libraries from Gambas

Post by Cedron »

After a little digging around, I found out that FORTRAN wants its Booleans as a 4 byte Integer with values restricted to 0 and 1. I smell some C.

Anyway, I have updated the code to reflect this, made the subroutines modify the calling arguments, and have the Gambas program print the results.

The updates have been applied to the previous post.

Use at your own risk, yada, yada.

I'm still interested in improving the Character and Complex cases.
.... and carry a big stick!
Post Reply