从go调用fortran库的最小例子

Mit*_*ops 4 fortran ffi go

我正在寻找这两种语言之间FFI的最小例子,这是一个非常简单的Go程序调用Fortran库的hello世界.

我想强调一点,我不是在寻找外部资源,建议或教程,只是golang中的最小代码片段,以及Fortran中的相应格式.

这个网站上有很多例子:

Go - > Fortran示例符合这些并且对其他开发人员有用.

编辑以解决重复声明

这个问题有一个答案和一个链接的问题,因为这是一个副本而不是.关闭并重定向此问题作为可能以-5票结束的副本对stackoverflow用户没有用,尽管两者都提出了一个合理的问题.

roy*_*vib 5

cgo(https://golang.org/cmd/cgo/)似乎提供了一个调用C的功能.所以我尝试用它来调用Fortran(在OSX10.11上使用go-1.11 + gfortran-8.2),似乎正在为这个简单的程序工作......

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 )
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

编译:

gfortran -c mylib.f90
go build main.go
./main
Run Code Online (Sandbox Code Playgroud)

结果:

 Hello from Fortran
val =  100
val =  7770
[100 200 300 400 555.5500000000001]
[200 400 600 800 1111.1000000000001]
Run Code Online (Sandbox Code Playgroud)

  • 否 - 使用ISO_C_BINDING使事物可互操作是一种常见的误解.Fortran中的关键是语言绑定属性BIND(C).当在过程,变量或类型声明中指定它时,它会强加与"伴随C处理器"兼容的规则和行为.例如,在一个过程中,它意味着没有隐藏的参数,以及传递值的能力.在类型上,它表示C编译器不会执行填充.当然,ISO_C_BINDING是一种帮助,但它本身没有任何帮助. (3认同)
  • 我通常的回答是:"如果你可以用语言<x>打电话给C,你可以打电话给Fortran." (这不会扩展到C++.)Fortran具有广泛的C互操作性功能.最大的障碍,尤其是非编译语言,正在寻找绑定到已编译代码的机制.一旦你有了,其余的都很简单(你必须坚持C互操作性功能,否则你可能会产生麻烦.) (2认同)
  • 您当然需要考虑数组排序,但这对进行调用没有影响. (2认同)