Минимальный пример вызова библиотеки Fortran из Go - PullRequest
0 голосов
/ 18 ноября 2018

Я ищу минимальный пример FFI между этими двумя языками, очень простой привет программе Go, вызывающей библиотеку Fortran.

Хочу подчеркнуть, что я не ищу внешних ресурсов, рекомендаций или учебника, только минимальный фрагмент кода в golang и соответствующий формат в Фортране.

Есть множество примеровна этом сайте:

Пример Go -> Fortran будет соответствовать этим и будет полезен для других разработчиков.

Правка для устранения дублированияпретензия

На этот вопрос есть ответ, а на тот, на который он ссылается, дубликата - нет.Закрытие и перенаправление этого вопроса как дубликата, который, вероятно, будет закрыт с -5 голосами, не будет полезным для пользователей stackoverflow, хотя оба представляют разумный вопрос.

1 Ответ

0 голосов
/ 18 ноября 2018

cgo (https://golang.org/cmd/cgo/), кажется, обеспечивает функциональность для вызова C. Поэтому я попытался использовать его для вызова Fortran (с go-1.11 + gfortran-8.2 на OSX10.11), который, кажется, работаетдля этой простой программы ...

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

Компиляция:

gfortran -c mylib.f90
go build main.go
./main

Результат:

 Hello from Fortran
val =  100
val =  7770
[100 200 300 400 555.5500000000001]
[200 400 600 800 1111.1000000000001]
...