IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Fortran Discussion :

Interface C++ / Fortran


Sujet :

Fortran

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 21
    Par défaut Interface C++ / Fortran
    Bonjour à tous,

    Je vous expose mon problème, je cherche à interfacer un programme en C++ avec des subroutines Fortran que j'ai crée.
    L'interface marche bien pour les entier, réel, double, etc... mais pour les vecteurs (sous forme de tableau à une seul dimension...), ca ne marche pas.

    Comment faire cette interfaçage ?

    Merci beaucoup

  2. #2
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 21
    Par défaut
    (Re)Bonjour,

    Le problème ce précise, mon fichier Fortran est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    	SUBROUTINE resolution(tab_est,alpha,q0,Qr0,eps,eta,indice)
     
    	IMPLICIT NONE
    	INTERFACE
    		DOUBLE PRECISION FUNCTION maxi(tab)
    			DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: tab
    		END FUNCTION maxi
    		DOUBLE PRECISION FUNCTION mini(tab)
    			DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: tab
    		END FUNCTION mini
    		DOUBLE PRECISION FUNCTION rms_error(tab_measured,tab_est)
    			DOUBLE PRECISION, DIMENSION(:),INTENT(IN) :: tab_measured, tab_est
    		END FUNCTION rms_error
    		SUBROUTINE rms_expo(n,tab_est,tab_measured,tab_jour,error,rms_exp,nvl_donnees,i,alpha,Qr0)
    			DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: tab_est,tab_measured,tab_jour,rms_exp, nvl_donnees
    			LOGICAL, INTENT(INOUT) :: error
    			INTEGER, INTENT(IN) :: n,i
    			DOUBLE PRECISION, INTENT(INOUT) :: alpha, Qr0
    		END SUBROUTINE rms_expo
    		SUBROUTINE rms_homog(n,tab_est,tab_measured,tab_jour,error,rms_homo,i,eta,eps,q0)
    			DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: tab_est,tab_measured,tab_jour,rms_homo
    			LOGICAL, INTENT(INOUT) :: error
    			INTEGER, INTENT(INOUT) :: n,i
    			DOUBLE PRECISION, INTENT(INOUT) :: eta,eps, q0
    		END SUBROUTINE rms_homog
    	END INTERFACE
    	DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: tab_est!, tab_measured, tab_jour
    	!LOGICAL, INTENT(INOUT) :: error
    	LOGICAL :: error
    	INTEGER, INTENT(INOUT) :: indice
    	INTEGER :: i, j, k, alloc,n
    	INTEGER, PARAMETER :: p=67
    	DOUBLE PRECISION, DIMENSION(p) :: tab_measured, tab_jour
    	DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: exp_est, homo_est, rms_exp, rms_homo, nvl_donnees,rms_total
    	DOUBLE PRECISION, INTENT(INOUT) :: alpha,q0,Qr0,eps,eta
    	DOUBLE PRECISION :: minimum
    	!tab_est=0
    	n=p
    	DO i=1,n
    		tab_jour(i)=i-1
    	END DO
    	tab_measured=(/1.055,1.011,0.937,0.877,0.826,0.792,0.770,0.756,0.739, &
    	& 0.720,0.701,0.688,0.685,0.683,0.674,0.658,0.644,0.636,0.625,0.608,&
    	& 0.594,0.588,0.584,0.591,0.585,0.578,0.573,0.567,0.559,0.554,0.554, &
    	& 0.551,0.547,0.546,0.541,0.532,0.523,0.517,0.512,0.509,0.504,0.499, &
    	& 0.495,0.493,0.492,0.489,0.486,0.485,0.482,0.478,0.474,0.473,0.471,&
    	& 0.469,0.468,0.467,0.464,0.463,0.462,0.459,0.453,0.452,0.450,0.449,&
    	&0.447,0.447,0.446/)
    	ALLOCATE(exp_est(n),stat=alloc)
    	IF (alloc.NE.0) THEN
    		error=.TRUE.
    		STOP
    	END IF
    	ALLOCATE(homo_est(n),stat=alloc)
    	IF (alloc.NE.0) THEN
    		error=.TRUE.
    		STOP
    	END IF
    	ALLOCATE(rms_exp(n),stat=alloc)
    	IF (alloc.NE.0) THEN
    		error=.TRUE.
    		STOP
    	END IF
    	ALLOCATE(rms_homo(n),stat=alloc)
    	IF (alloc.NE.0) THEN
    		error=.TRUE.
    		STOP
    	END IF
    	ALLOCATE(nvl_donnees(n),stat=alloc)
    	IF (alloc.NE.0) THEN
    		error=.TRUE.
    		STOP
    	END IF
    	ALLOCATE(rms_total(n-3),stat=alloc)
    	IF (alloc.NE.0) THEN
    		error=.TRUE.
    		STOP
    	END IF
     
    	rms_exp=0
    	rms_homo=0
    	exp_est=0
    	homo_est=0
    	DO i=2,n-1
    	!i=42
    		CALL rms_expo(n,exp_est,tab_measured,tab_jour,error,rms_exp,nvl_donnees,i,alpha,Qr0)
    		DO j=1,n
    			nvl_donnees(j)=tab_measured(j)-exp_est(j)
    		END DO
    		eta=(1./i)
    		eps=0.001
    		q0=nvl_donnees(1)
    		CALL rms_homog(n,homo_est,nvl_donnees,tab_jour,error,rms_homo,i,eta,eps,q0)
    	END DO
     
    	DO i=2,n-2
    		rms_total(i-1)=(rms_homo(i)+rms_exp(i))/2
    	END DO
    	minimum = mini(rms_total)
    	DO i=1,n
    		IF (rms_total(i).EQ.minimum) THEN
    			indice=i
    		END IF
    	END DO
     
    	CALL rms_expo(n,exp_est,tab_measured,tab_jour,error,rms_exp,nvl_donnees,indice,alpha,Qr0)
    	DO j=1,n
    		nvl_donnees(j)=tab_measured(j)-exp_est(j)
    	END DO
    	eta=(1./i)
    	eps=0.001
    	q0=nvl_donnees(1)
    	CALL rms_homog(n,homo_est,nvl_donnees,tab_jour,error,rms_homo,indice,eta,eps,q0)
    	DO i=1,n
    		IF(i.LE.indice)THEN
    			tab_est(i)=exp_est(i)+homo_est(i)
    		ELSE
    			tab_est(i)=exp_est(i)
    		END IF
    	END DO
     
     
    	DEALLOCATE(exp_est)
    	DEALLOCATE(homo_est)
    	DEALLOCATE(rms_exp)
    	DEALLOCATE(rms_homo)
    	DEALLOCATE(nvl_donnees)
    	DEALLOCATE(rms_total)
     
    END SUBROUTINE resolution

    et fonctionne parfaitement avec un program Fortran.
    Cependant, j'appelle cette fonction à partir d'un programme en C++, donc j'utilise :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    extern "C"
    {
    void  resolution_(double *,double *,double *,double *,double *,double *,int*);
    }
    L'erreur que j'ai en retour est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Démarrage de C:\Users\user\GUI_beta-build-desktop-Qt_4_8_0_for_Desktop_-_MinGW__Qt_SDK__Release\release\GUI_beta.exe...Exception: Access Violation
    At line 120 of file tc.f90
    Traceback: (Innermost first)

    Avez-vous une idée sur comment corriger cette erreur ?

    Merci

  3. #3
    Membre éprouvé Avatar de rogue-spectre
    Homme Profil pro
    Inscrit en
    Juillet 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 104
    Par défaut
    Bonjour,

    C'est juste une idée… mais les tableaux en C ça commence à l'indice 0, et en Fortran à 1 par défaut. Je n'ai personnellement pas fait d'interface C/fortran, mais je me souvient qu'il fallait faire attention à ce point.

    Bonne soirée.

    PS : C'est quoi au juste ce i=42 en plein milieu du code, tu pensais que ça allait résoudre LA question

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 21
    Par défaut
    Bonsoir,

    J'y ai pensé, mais même en modifiant les indices des tableaux ça me renvoie une erreur.
    Du coup, j'ai fait un autre code assez simple pour "tester" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SUBROUTINE testf(tab,n)
    	IMPLICIT NONE
    	DOUBLE PRECISION,  DIMENSION(:) , INTENT(IN) :: tab
    	INTEGER, INTENT(OUT) :: n
     
    	n = size(tab)
     
    END SUBROUTINE testf
    Je l'appelle comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    extern "C"
    {
    void  testf_(double *, int*);
    }
    extern "C"

    et j'initialise mon tableau en C++ comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    double *vect_test = new double [65];
         for (int i=0;i<65;i++)
         {
             vect_test[i]=i+1.;
         }
     
         testf_(vect_test,&f);
    Et ceci ne marque pas, par contre, si je déclare ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SUBROUTINE testf(tab,n)
    	IMPLICIT NONE
    	DOUBLE PRECISION, , POINTER,, INTENT(IN) :: tab
    	INTEGER, INTENT(OUT) :: n
    	IF ( associated(tab) ) THEN
    		n = 8
    	ELSE
    		n=5
    	END IF
     
    END SUBROUTINE testf
    Alors le code C++ me renvoie 8 dans le terminal...
    Ainsi, je pense que l'on donne en fait au fortran des pointeurs, et non pas directement les variables. Don, je pense que je donne au fortran non pas un tableau de double mais un pointeur sur un tableau de double (peux-être que je me trompe), mais je ne sais pas comment récupérer ce tableau à partir de son adresse...

    Si quelqu'un à une idée ?

    Merci d'avance.


    (PS: oups, le i=42 était une valeur du i pour laquelle je connaissait les résultat de la subroutine, cet indice était là pour les tests, j'ai complètement oublié de l'enlever...)

  5. #5
    Membre éprouvé Avatar de rogue-spectre
    Homme Profil pro
    Inscrit en
    Juillet 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 104
    Par défaut
    une mini recherche plus tard avec un moteur de recherche…
    http://www.yolinux.com/TUTORIALS/Lin...rtranAndC.html

    Pour le mini test ça donne donc :

    testF.f :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
          SUBROUTINE testf(tab,n)
          IMPLICIT NONE
          DOUBLE PRECISION,  dimension(65):: tab
          INTEGER, INTENT(OUT) :: n
     
          write(*,*)tab
     
          write(*,*)n
          END SUBROUTINE testf
    testC.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #include <iostream>
     
    using namespace std;
     
    extern "C"
    {
    void  testf_(double*, int*);
    }
     
    main()
    {
      int f;
      f=1;
    double vect_test[65];
         for (int i=0;i<65;i++)
         {
             vect_test[i]=i+1.;
         }
     
         testf_(vect_test,&f);
    }
    Et compilé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    gfortran --free-form -c testF.f ; g++ -c testC.cpp ; g++ testF.o  testC.o  -o lala -lgfortran
    Par contre je ne rentrerais pas dans des explications techniques du pourquoi du comment car je risquerais de dire de la soupe…suivre le lien donné au début donc. Faudra donc adapter le premier code.

    Bonne soirée

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 21
    Par défaut
    Super, merci beaucoup, j'essaierai avec ta méthode.

    Si ça peut aider un prochain j'ai également trouvé ça :

    Le code de test en Fortran :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SUBROUTINE testf(tab,n)
    	IMPLICIT NONE
    	DOUBLE PRECISION tab(*)
    	INTEGER n
    	INTEGER i
    	n = 5
    	DO i = 1,67
    		tab(i)=i+1.
    	END DO
     
    END SUBROUTINE testf
    Le code C++ :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    #include <iostream>
     
    using namespace std;
     
    extern "C"
    {
    void  testf_(double*, int*);
    }
     
    main()
    {    int f;
         f=67;
         double *vect_test=new double[67];
         testf_(&vect_test[0],&f);
    }

    L'erreur venait peut-être aussi de QT (j'utilise ce code dans QT, pour réaliser une interface graphique à des routines Fortran).
    J'avoue que le comment du pourquoi méchape OO, mais bon, ça devrait le faire avec ça.

    Merci encore.

    Bonne nuit

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Interface graphique fortran
    Par gogo1741 dans le forum Fortran
    Réponses: 2
    Dernier message: 02/06/2012, 14h53
  2. interface graphique fortran
    Par taylasa dans le forum Fortran
    Réponses: 3
    Dernier message: 16/02/2012, 18h38
  3. Interface graphique en Fortran
    Par janviech dans le forum Fortran
    Réponses: 4
    Dernier message: 02/08/2006, 10h31
  4. Problème en interfacant C et Fortran
    Par karl3i dans le forum MFC
    Réponses: 6
    Dernier message: 23/05/2006, 16h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo