0

我有这个已关闭的特定主题问题,试图从 Fortran 的 libcurl 简单 API 调用 C: https ://stackoverflow.com/questions/44891188/calling-libcurl-from-fortran-2008

根据评论的建议,我仍然收到有关如何从 Fortran 正确调用 C 指针和 C 函数的错误。

这里的代码不多,但主要问题是警告:

dl2.f08:11.23:

  type, bind(C) :: CURL
                       1
Warning: Derived type 'curl' with BIND(C) attribute at (1) is empty, and may be inaccessible by the C companion processor
dl2.f08:14.27:

和错误:

  call curl_easy_setopt(curl, CURLOPT_URL_VAL, "http://example.com")
                                                                    1
Error: More actual than formal arguments in procedure call at (1)
dl2.f08:48.35:

这是我的最小示例:

module fcurl
! This is the simple C code I am trying to call from Fortran
!
! CURL *curl = curl_easy_init();
! if(curl) {
!   CURLcode res;
!   curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
!   res = curl_easy_perform(curl);
!   curl_easy_cleanup(curl);
! }
  use, intrinsic ::  iso_c_binding
  implicit none
  type, bind(C) :: CURL
  end type CURL

  type, bind(C) :: CURLcode
  end type CURLcode

  type, bind(C) :: CURLOPT_URL
  end type CURLOPT_URL

  interface
     subroutine curl_easy_init()  bind(C, name="curl_easy_init")
     end subroutine curl_easy_init
  end interface

  interface
     subroutine curl_easy_setopt()  bind(C, name="curl_easy_setopt")  
     end subroutine curl_easy_setopt
  end interface

  interface
     subroutine curl_easy_perform()  bind(C, name="curl_easy_perform")  
     end subroutine curl_easy_perform
  end interface

  interface
     subroutine curl_easy_cleanup()  bind(C, name="curl_easy_cleanup")  
     end subroutine curl_easy_cleanup
  end interface  

end module fcurl

program mycurl
  use fcurl
  type(CURL) :: curl
  type(CURLcode) :: res
  type(CURLOPT_URL) :: CURLOPT_URL_VAL
  call curl_easy_init(curl)
  call curl_easy_setopt(curl, CURLOPT_URL_VAL, "http://example.com")
  call curl_easy_perform(res, curl)
  print *, res  
  call curl_easy_cleanup(curl)

end program mycurl

还引用了这个:

4

1 回答 1

3

我只想澄清一些关于 C 互移植性的事情:

  1. 要使类型可移植,您应该在 Fortran 中使用 keywork 重新键入其定义bind(c),例如:

    type_cC中定义的类型为:

    struct {
      int i;
      double d
    } type_c;
    

    在 Fortran 中,我们应该这样写:

    type ,bind(c) :: type_c
      integer(c_int) :: i
      real(c_double) :: d
    end type
    
  2. 在 Fortran 中有两种类型的过程:函数和子例程。C 中子程序的等价物是用void( 在 C 中:它表示不返回值的函数) 声明的函数。因此,要使 C 程序具有可移植性,您应该首先查看它们的定义并确定它是否等效于Fortran 函数或子例程。
  3. 要使 C 过程与 Fortran 可互移植,您应该使用它们的参数定义它们,例如:

    函数 'fun1' 和 'fun2' 在 C 中定义为:

    float fun1(int i);
    void fun2(double a, int *l);
    

    在 Fortran 中,我们应该将它们写为:

    interface
      function fun1(i) bind(c)
        real(c_float) :: fun1
        integer(c_int), value :: i
      end function fun1
    end interface
    
    interface
      subroutine fun2(a,l) bind(c)
        real(c_double), value :: a
        integer(c_int) :: l
      end subroutine fun2
    end interface
    
于 2017-07-16T05:06:47.707 回答