7

我希望能够在我的 Fortran 应用程序中调用网络功能。我的老板希望我用 Fortran 做所有事情,而不是使用 C 和 Fortran。我们已经在 Windows 上使用 PGI 的 Fortran 编译器完成了该应用程序的一个版本。我们正在将它转移到 Linux 上,我们可能会在其中使用他们的编译器。现在,我正在使用 gfortran。

我为这些网络调用创建了一个接口,并且一切都编译和链接。下面的代码与我正在做的类似,除了接口和常量在一个模块中。

PROGRAM MAIN

    INTEGER,PARAMETER  ::AF_INET = 2
    INTEGER,PARAMETER  ::SOCK_STREAM = 1
    INTEGER,PARAMETER  ::IPPROTO_TCP = 6

    INTERFACE
      FUNCTION socket(domain,type,protocol)
        INTEGER  ::socket,domain,type,protocol
      END FUNCTION
    END INTERFACE

    sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)
    WRTIE(*,*)"Socket returned: ",sock

END PROGRAM

当我运行程序时,套接字函数返回 -1 失败。我真的不知道发生了什么事。我没有在命令行上添加任何库,所以我猜它与默认库正确链接。我编译使用

gfortran -o MAIN_PROGRAM MAIN_PROGRAM.f90 -fno-underscoring
4

2 回答 2

10

您可以利用 Fortran 2003 中引入的 ISO_C_Binding 来访问 C 库功能,这是您拥有的最简洁和最便携的选项。与任何其他供应商手册一样,Gfortran 文档有一些详细信息。还有一些项目旨在为 Fortran 90 实现 POSIX 接口:fortranposixposix90。但正如我所说,使用 F2003 功能的适当 C-Binding 接口可能是最干净的选项,另请参见fortranwiki

编辑: 这是添加了 ISO-C-Binding 胶水的代码(使用 gfortran 4.4.5 测试):

program testsocket
  use, intrinsic ::  iso_c_binding

  implicit none

  interface
    function socket(domain, type, protocol) bind(c, name="socket")
      use, intrinsic :: iso_c_binding
      integer(kind=c_int) :: socket
      integer(kind=c_int), value :: domain, type, protocol
    end function socket
  end interface

  integer :: sock

  sock = socket(2_c_int, 1_c_int, 6_c_int)

  write(*,*) "Socket returned: ", sock

end program testsocket
于 2012-04-24T22:16:15.300 回答
0

这是一个猜测。你是科学或工程专业的研究生(但不是计算机科学或计算机工程),你的老板出生于 1950 年之前。如果是这样,我站在你的立场上(除了在我的情况下要求使用 Fortran 77) . 我感觉到你的痛苦。

您可能知道,Fortran 不像 C 那样使用头文件来原型化函数调用。当不检查参数的类型时,您可以调用不带标头的 Fortran 函数。

但是,有这个麻烦——或者曾经有这个麻烦,因为我最近的经验已经过时了好几年。与 C 相比,GNU Fortran 在每个函数的名称前添加一个隐藏的下划线。它还将函数名称小写。

readelf -a程序可以在这里为您提供帮助。在 Fortran 编译器发出的目标文件上使用它。在输出中查找socket符号。如果我没记错的话,你会_socket在里面看到一个。

如果你真的,真的根本不能使用任何 C —— 甚至用 C 名称创建一个包装函数_socket()—— 那么我承认我不知道你接下来应该做什么。在这种情况下,您可能会陷入困境。不管怎样,祝你好运。

更新: 我在下面推荐@MSB 的评论。

于 2012-04-24T21:05:19.370 回答