2017-07-15 3 views
0

J'ai cette question précise et sur le sujet qui a été fermé, en essayant d'appeler C de l'API simple libcurl de Fortran: https://stackoverflow.com/questions/44891188/calling-libcurl-from-fortran-2008Fortran 2008 C Interop Erreur: Plus réel que des arguments formels en appel de procédure à (1)

En suivant les conseils des commentaires, je reçois toujours des erreurs sur la façon d'appeler correctement les pointeurs C et les fonctions C de Fortran.

Pas beaucoup de code, mais les problèmes principaux sont les avertissements:

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: 

et erreurs:

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: 

Voici mon exemple minimal:

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 

aussi mentionné ceci:

+3

Vous devez spécifier les composants du type 'de CURL', ainsi que des arguments à la fonctions de boucle. Ceux-ci vous devez obtenir à partir des en-têtes curl. –

Répondre

3

Je veux apporter une précision somethings sur C inter-portabilité:

  1. Pour faire un type inter-portable, vous devez retaper sa définition dans Fortran avec le keywork bind(c) , Exemple:

    Le type type_c défini dans C comme:

    struct { 
        int i; 
        double d 
    } type_c; 
    

    en Fortran, nous devons l'écrire comme:

    type ,bind(c) :: type_c 
        integer(c_int) :: i 
        real(c_double) :: d 
    end type 
    
  2. En Fortran, il existe deux types de procédures: fonctions et sous-routines. l'équivalent des sous-routines en C sont des fonctions déclarées avec void (en C: cela signifie une fonction qui ne retourne pas de valeur). Donc, pour rendre les procédures C inter-portables, vous devez d'abord regarder leurs définitions et décider si elles sont équivalentes à une fonction Fortran ou un sous-programme.
  3. Pour rendre les procédures C inter-portable avec Fortran, vous devez les définir avec leurs arguments, par exemple:

    Les fonctions de la fun1 »et 'fun2' sont définis en C comme:

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

    en Fortran nous devons les écrire comme:

    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