2
votes

Des blocs d'interface sont-ils nécessaires pour compiler Fortran?

J'essaie de m'apprendre Fortran et je me suis amusé à lier plusieurs fichiers ensemble. Les exemples suivants, j'ai écrit des programmes dans un fichier, des fonctions dans un autre, et j'ai utilisé des blocs d'interface dans mon programme principal pour faire référence à la fonction externe.

Je testais la quantité d'informations nécessaires dans le bloc d'interface et je me suis rendu compte que je peut le supprimer entièrement.

Mon programme:

    subroutine func(x,y)
        implicit none
        real :: x,y
        y = x**3
    end subroutine func

Et le fichier de fonction:

    function func(x)
        implicit none
        real :: x, func
        func = x**3
    end function func

Je le compile ensuite en utilisant gfortran -o test test.f90 func.f90 et le code fonctionne comme prévu. Ma question est la suivante: pourquoi n'ai-je pas besoin d'inclure un bloc d'interface dans mon fichier programme? Est-ce simplement une question de bonne pratique, ou est-ce que définir func comme une variable réelle sert de raccourci? Je suis sous Windows, ayant installé gfortran via minGW.

En tant que question secondaire / connexe, si j'utilise à la place un sous-programme:

    program test
        implicit none
        real :: x, y, func

        x = 3
        y = func(x)
        print *, y
    end program test

Et changez le ligne y = func (x) à appel func (x, y) alors le code fonctionnera correctement sans aucun bloc d'interface ni déclaration. Pourquoi est-ce?


0 commentaires

3 Réponses :


1
votes

Pourquoi n'ai-je pas besoin d'inclure un bloc d'interface dans mon fichier programme?

Depuis Fortran 90, la manière recommandée pour définir des fonctions et des sous-programmes réutilisables est d'utiliser des modules.

module func_m
contains
    function func(x)
        implicit none
        real :: x, func
        func = x**3
    end function func
end module func_m

Ensuite, écrivez use func_m dans le main programme, avant implicite aucun : gfortran -c func_m.f90 , gfortran -c test.f90 et gfortran -o test test. o func_m.o .

Lorsque vous utilisez des modules, le compilateur vérifiera le type des arguments des fonctions. Vous n'avez pas non plus besoin de déclarer real :: func car les déclarations sont extraites du module.

Lorsque vous compilez comme un fichier objet "simple", le compilateur appellera simplement quelle que soit la fonction nommée func sans vérification, tant qu'une telle fonction est donnée dans un fichier objet.

Le bloc d'interface est une sorte de "entre les deux". Dans votre cas, vous pouvez en ajouter un dans le fichier programme. Cela vous obligerait à suivre cette déclaration dans le programme. Mais cela n'empêchera pas la connexion à de mauvaises fonctions au moment de la liaison: il n'y a aucune garantie que l'interface est correcte. C'est surtout utile si vous devez appeler du code C ou FORTRAN 77 de quelqu'un d'autre, pour lequel vous ne pouvez pas utiliser de modules.

Et changez la ligne y = func (x) pour appeler func (x, y) alors le code sera fonctionne bien sans aucun bloc d'interface ni déclaration. Pourquoi est-ce?

Le problème d'interface est orthogonal au problème de fonction vs sous-programme.


0 commentaires

2
votes

La déclaration real :: func dans le programme principal ici déclare que func est une fonction avec un résultat réel (par défaut). Cette fonction a une interface dans le programme principal en conséquence, il est donc légitime de référencer cette fonction avec y = func (x) .

Dans ce cas, l'interface est implicite . De cette façon, le programme principal sait exactement trois choses sur func :

  • c'est une fonction (avec ce nom);
  • il a l'attribut external ;
  • il a un résultat réel.

La référence à la fonction est compatible avec cette connaissance. De plus, la façon dont vous faites référence à la fonction correspond précisément aux propriétés de la fonction elle-même.

De même, dans le cas du sous-programme, un call func (x, y) indique exactement trois choses au programme principal, toujours avec l'interface implicite:

  • c'est un sous-programme (avec ce nom);
  • il a l'attribut external ;
  • cela prend deux arguments réels.

Ces trois choses correspondent à nouveau à la définition du sous-programme, donc tout va bien.

En gros, vous n'avez donc pas besoin d'un bloc d'interface dans ces cas car les interfaces implicites sont assez bonnes.

Il y a des moments où une interface explicite est requise et dans la plupart (presque tous) cas une interface explicite est meilleure. Comme vous pouvez le voir dans d'autres questions et réponses, il existe généralement de meilleures façons de fournir une interface explicite que d'utiliser un bloc d'interface.


0 commentaires

0
votes

Dans certains cas, des blocs d'interface sont nécessaires. Par exemple si le sous-programme appelé utilise un pointeur, des tableaux de forme allouables ou supposés (cette liste n'est pas complète, voir le standard pour plus):

integer, pointer :: x(:,:)  ! pointer attribute
integer, allocatable :: x(:,:)  ! pointer attribute
integer :: a(:,:)           ! assumed shape array

Le pointeur / attribuable a l'avantage que l'appelé le sous-programme peut l'allouer pour la fonction appelante. Les tableaux de formes supposées transfèrent automatiquement les dimensions vers le sous-programme appelé.

Si vous utilisez l'un de ces éléments, votre programme plantera sans interface explicite. La solution la plus simple est comme indiqué dans l'autre réponse: utilisez des modules pour que l'interface soit automatiquement correcte. Nous utilisons un script perl extrayant automatiquement les interfaces pour vérifier l'interface sans réécrire le code dans les modules (et éviter les longs temps de compilation jusqu'à ce que tous les compilateurs prennent en charge de manière fiable les sous-modules Fortran 2008 ...)


2 commentaires

Même avec ceux-ci, les blocs d'interface ne sont toujours pas nécessaires.


les tableaux de formes supposées nécessitent une interface