I am looking for a minimal example of the FFI between these two languages, a very simple hello world of a Go program calling a Fortran library.
I want to emphasize I am not looking for external resources, recommendations, or a tutorial, only a minimal code snippet in golang, and the corresponding format in Fortran.
There are plenty of examples on this site of:
A Go -> Fortran example would be in line with these and useful for other developers.
This question has an answer and the one linked to as this being a duplicate of does not. Closing and redirecting this question as a duplicate that is likely to be closed with -5 votes would not be useful to stackoverflow users, though both present a reasonable question.
cgo (https://golang.org/cmd/cgo/) seems to provide a functionality for calling C. So I've tried using it for calling Fortran (with go-1.11 + gfortran-8.2 on OSX10.11), which seems to be working for this simple program...
main.go:
package main
// #cgo LDFLAGS: mylib.o -L/usr/local/Cellar/gcc/8.2.0/lib/gcc/8 -lgfortran
// void hello();
// int fort_mult( int );
// void array_test1 ( double*, int* );
// void array_test2_( double*, int* );
import "C"
import "fmt"
func main() {
// print a message
C.hello()
// pass a value
fmt.Println( "val = ", C.fort_mult( 10 ) )
k := C.int( 777 )
fmt.Println( "val = ", C.fort_mult( k ) )
// pass an array
a := []C.double {1, 2, 3, 4, 5.5555}
n := C.int( len(a) )
C.array_test1( &a[0], &n ) // pass addresses
fmt.Println( a )
C.array_test2_( &a[0], &n ) // no use of iso_c_binding
fmt.Println( a )
}
mylib.f90:
subroutine hello() bind(C)
print *, "Hello from Fortran"
end subroutine
function mult( x ) result( y ) bind(C,name="fort_mult") ! can use a different name
use iso_c_binding, only: c_int
integer(c_int), value :: x
integer(c_int) :: y
y = x * 10
end function
subroutine array_test1( arr, n ) bind(C) ! use iso_c_binding
use iso_c_binding, only: c_int, c_double
integer(c_int) :: n
real(c_double) :: arr( n )
arr(:) = arr(:) * 100.0d0
end subroutine
subroutine array_test2( arr, n ) ! no use of iso_c_binding (e.g. for legacy codes)
integer :: n
double precision :: arr( n ) ! or real(8) etc
arr(:) = arr(:) * 2.0d0
end subroutine
Compile:
gfortran -c mylib.f90
go build main.go
./main
Result:
Hello from Fortran
val = 100
val = 7770
[100 200 300 400 555.5500000000001]
[200 400 600 800 1111.1000000000001]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With