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 :

DLL Fortran appellée du C : problème tableau 2 dimensions


Sujet :

Fortran

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 20
    Points : 10
    Points
    10
    Par défaut DLL Fortran appellée du C : problème tableau 2 dimensions
    Bonjour,

    je cherche actuellement à utiliser une DLL Fortran dans un programme écrit en C.

    Je parviens à charger ma DLL, à l'appeler et à récupérer une des deux variables qui m'intéressent. Cependant, dès que j'accède à ma 2eme variable (matrice 13 x 5), une erreur apparait (je pense qu'il s'agit d'un segmentation fault).

    D'après ce que j'ai pu lire/entendre, le passage de tablueax multi-dimensionnels entre le fortran et le c peut poser problème.

    Est-ce que quelqu'un sait si le problème vient effectivement de la, sinon d'où vient-il et comment le résoudre.

    Ma routine Fortran est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    AMINEMeOH(TC, Namine, NumAmine, wAmine, wMeoH, k, alpha, PP, mat)
    où TC est un double de taille 1 x 1
    Namine un entier de taille 1 x 1
    NumAmine un entier de taille 9 x 1 
    wAmine un double de taille 9 x 1
    wMeOH un double de taille 1 x 1 
    k un entier de taille 2 x 1
    alpha un double de taille 2 x 1
    PP un double de taille 2 x 1 
    mat un double de taille 13 x 5
    Les valeurs de PP que je récupère sont bonnes.
    Celles de mat des que j'essaie de les afficher ou de les utiliser, le problème intervient.

    mon 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
    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
     
    #include <stdio.h> 
    #include <windows.h> 
    #include <stdlib.h>
     
    typedef int (*MYPROC)(double* ,short int* , short int* , double* , double* , short int*, double*, double* , double**);
     
    void call_dll(double* T_in, int* Namine_in ,  int* NumAmine_in, double* w_amine_in, double* wMeOH_in,  int* k_in, double* alpha_in, double* PP_in, double** Mat_in)
    {
        short int* Namine = (short int*) malloc(1*sizeof(short int)) ;
        short int* NumAmine = (short int*) malloc(9*sizeof(short int)) ;
        short int* k = (short int*) malloc(2*sizeof(short int)) ;
        int i,j;
     
        *Namine = (short int) *Namine_in ;
        k[0] = (short int) k_in[0] ; 
        k[1] = (short int) k_in[1] ; 
     
        for(i=0;i<9;i++) {
            NumAmine[i] = (short int) NumAmine_in[i] ;
        }    
        HINSTANCE hinstLib; 
        MYPROC ProcAdd; 
        BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
        // Get a handle to the DLL module.
     
        hinstLib = LoadLibrary(TEXT("LibrairieAmineMeOH.dll")); 
     
        // If the handle is valid, try to get the function address.
        if (hinstLib != NULL) 
        { 
            ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("AMINEMeOH")); 
     
     
     
            // If the function address is valid, call the function.
            if (NULL != ProcAdd) 
            {
                fRunTimeLinkSuccess = TRUE;
              ProcAdd(T_in, Namine, NumAmine, w_amine_in, wMeOH_in, k, alpha_in, PP_in, Mat_in); 
            } 
            // Free the DLL module.
            fFreeResult = FreeLibrary(hinstLib); 
        } 
        // If unable to call the DLL function, use an alternative.
     
        if (! fRunTimeLinkSuccess) {
            printf("Message via alternative method\n"); 
        }    
    }
     
     
     
    int main() {
     
        int i, j;
        double* T = (double*) malloc(1*sizeof(double)) ;
        int* Namine = (int*) malloc(1*sizeof(int)) ;
        int* NumAmine = (int*) malloc(9*sizeof(int)) ;
        double* wAmine = (double*) malloc(9*sizeof(double)) ;
        double* wMeOH = (double*) malloc(1*sizeof(double)) ;
        int* k = (int*) malloc(2*sizeof(int)) ;
        double* alpha = (double*) malloc(2*sizeof(double)) ;
        double* PP = (double*) malloc(2*sizeof(double)) ;
        double** Mat = (double**) malloc(13*sizeof(double*)) ;
    for(i=0;i<13;i++) {
        Mat[i] = (double*) malloc(5*sizeof(double)) ;
    } 
     
    for(i=0;i<9;i++) {
        NumAmine[i] = 0 ;
        wAmine[i] = 0 ;
    }    
    wAmine[0] = 30 ; 
    NumAmine[0] = 1 ;
    for(i=0;i<2;i++) {
        k[i] = 0 ;
        alpha[i] = 0 ;
        PP[i] = 0 ;
    }
    *Namine = 1 ;
     
     
    for(i=0;i<13;i++) {
        for(j=0;j<5;j++) {
            Mat[i][j] = 0 ;
        }
    }           
     
    T[0] = 30 ;
     
     
    wMeOH[0] = 0.000000001 ;
    k[0] = 1 ;
    k[1] = 1 ;
    alpha[0] = 0.5 ;
    alpha[1] = 0.5 ;
    PP[0] = 0 ;
    PP[1] = 0 ;
     
     
    call_dll(T, Namine, NumAmine, wAmine, wMeOH, k, alpha, PP, Mat);
     
    printf("T : %f\n\n",*T);
    printf("Namine : %d\n\n",*Namine);
    printf("wMeOH : %f\n\n",*wMeOH);
     
    printf("k \t\t alpha \t\t PP \n");
    for(i=0;i<2;i++) {
        printf("%d \t\t %0.4f \t\t %0.4f \n", k[i], alpha[i], PP[i]) ;
    }    
     
    printf("Num \t\t wAmine \n") ;
    for(i=0;i<9;i++) {
        printf("%d \t\t %0.4f \n", NumAmine[i], wAmine[i]) ;
    }    
    /*
    printf("Mat \n");
    for(i=0;i<13;i++) {
        for(j=0;j<5;j++) {
            printf("%0.4f \t", Mat[i][j]) ;
        }
        printf("\n");
    } 
    */
        return 0;
    }
    Ah oui aussi, je ne rencontre pas de problème sur d'autre routines où je n'ai que des scalaires et des tableaux uni-dimensionnel. Ce qui me conforte dans l'idée que le probème vient de la matrice.

    Merci d'avance
    Kokocha

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 20
    Points : 10
    Points
    10
    Par défaut
    je m'auto-réponds lol

    Bon j'ai trouvé quelquechose en appelant ma routine comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ProcAdd(T_in, Namine, NumAmine, w_amine_in, wMeOH_in, k, alpha_in, PP_in, &Mat_in[0][0]);
    et en remplacant forcément le typedef par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef int (*MYPROC)(double* ,short int* , short int* , double* , double* , short int*, double*, double* , double*);
    j'arrive à avoir des résultats, cependant il y a des valeurs "parasites", cad à des endroits ou ma matrice devrait être nulle, il y a des valeurs (qui correspondent à celles d'autres cases).
    Si quelqu'un sait pourquoi/comment résoudre ce (nouveau) problème, je suis preneur.

    Merci
    Kokocha

  3. #3
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Le Fortran classe les tableaux multi-dimensionnels en ordre "column-major" (dimension la plus a gauche varie le plus vite) alors que le C classe en ordre "row-major" (dimension la plus a droite varie le plus vite). Cela sans compter que les indices de tableau commencent par defaut a 1 en Fortran et a 0 en C.
    En clair, en Fortran, array(0,0) sera suivi de array(1,0) alors qu'en C array[0][0] est suivi de array[0][1]. Il te faut donc recalculer les indices a chaque fois, ou n'utiliser que des tableaux a une dimension.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    Complément de réponse.

    Une matrice C[13][5] est équivalente à une matrice Fortran (0:4,0:12) et peut être passée tel quel entre les 2.

    Si ta matrice est (13,5) en Fortran, tu reçois une matrice [5][13] en C. L'élément Fortran (m,n) correspond à l'élément C [n-1][m-1].

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 20
    Points : 10
    Points
    10
    Par défaut
    Merci pour ces explications

    Malheuresement ca ne fait pas avancer mon problème :s

    En fait mon code C va être exporter en tant que DLL (après les modification nécéssaires bien sur), en fait il s'agit d'un wrapper, afin de pouvoir appeler la DLL fortran depuis Scilab (ou matlab).

    Et ces problèmes de matrices me posent toujours des problèmes de segmentation fault :s

    Y a-t-il une possibilité de faire le même appel mais sans mettre &Mat[0][0] ?


    Edit : Sylvain, moi quand je passe directement ma matrice telle quelle, j'obtient un seg fault ...
    Edit2 : je devrais peut être exposer mon problème dans le forum C non ?

    Merci
    Kokocha

  6. #6
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Si tu as une segfault, c'est que tu depasses les dimensions de tes tableaux quelque part. Il va falloir trouver le bug...
    Pour cette histoire d'indice, cf les posts
    http://www.developpez.net/forums/sho...hlight=fortran
    et http://www.developpez.net/forums/sho...hlight=fortran qui abordent a peu pres le meme sujet.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 20
    Points : 10
    Points
    10
    Par défaut
    Si je comprends bien ce qui est écrit dans le 2eme post que tu as cité, je peux transmettre ma matrice par un tableau cad :
    au lieu d'envoyer une matrice 13 x 5 je peux envoyer un tableau de taille 65 et après, avecle jeu d'indice, pouvoir reconstituer ma matrice.

    C'est bien ca ?

    Merci
    Kokocha

  8. #8
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Citation Envoyé par Kokocha
    au lieu d'envoyer une matrice 13 x 5 je peux envoyer un tableau de taille 65 et après, avecle jeu d'indice, pouvoir reconstituer ma matrice.
    C'est ca. Ca simplifie pas mal la vie.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 20
    Points : 10
    Points
    10
    Par défaut
    effectivement, cela simplifie carrément le problème. En ce qui me concerne ca a même réussit a faire fonctionner tout mon bazar

    Merci DaZumba
    et merci a ceux qui m'ont aider

    Le code final (pour ceux que ca pourrait intéresser) :
    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
     
    #include <stdio.h> 
    #include <windows.h> 
    #include <stdlib.h>
     
    typedef int (*MYPROC)(double* , int* , short int* , double* , double* , short int*, double*, double* , double*);
     
    void call_dll(double* T_in, int* Namine_in ,  int* NumAmine_in, double* w_amine_in, double* wMeOH_in,  int* k_in, double* alpha_in, double* PP_in, double* Mat_in)
    {
        short int* Namine = (short int*) malloc(1*sizeof(short int)) ;
        short int* NumAmine = (short int*) malloc(9*sizeof(short int)) ;
        short int* k = (short int*) malloc(2*sizeof(short int)) ;
        int i,j;
     
        k[0] = (short int) k_in[0] ; 
        k[1] = (short int) k_in[1] ; 
     
        for(i=0;i<9;i++) {
            NumAmine[i] = (short int) NumAmine_in[i] ;
        }    
        HINSTANCE hinstLib; 
        MYPROC ProcAdd; 
        BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
        // Get a handle to the DLL module.
     
        hinstLib = LoadLibrary(TEXT("LibrairieAmineMeOH.dll")); 
     
        // If the handle is valid, try to get the function address.
        if (hinstLib != NULL) 
        { 
            ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("AMINEMeOH")); 
     
     
     
            // If the function address is valid, call the function.
            if (NULL != ProcAdd) 
            {
                fRunTimeLinkSuccess = TRUE;
              ProcAdd(T_in, Namine_in, NumAmine, w_amine_in, wMeOH_in, k, alpha_in, PP_in, Mat_in);
     
            // Free the DLL module.
            fFreeResult = FreeLibrary(hinstLib); 
        } 
        // If unable to call the DLL function, use an alternative.
     
        if (! fRunTimeLinkSuccess) {
            printf("Message via alternative method\n"); 
        }    
    }
     
     
    }
     
     
     
    int main() {
     
        int i, j;
        double* T = (double*) malloc(1*sizeof(double)) ;
        int* Namine = (int*) malloc(1*sizeof(int)) ;
        int* NumAmine = (int*) malloc(9*sizeof(int)) ;
        double* wAmine = (double*) malloc(9*sizeof(double)) ;
        double* wMeOH = (double*) malloc(1*sizeof(double)) ;
        int* k = (int*) malloc(2*sizeof(int)) ;
        double* alpha = (double*) malloc(2*sizeof(double)) ;
        double* PP = (double*) malloc(2*sizeof(double)) ;
        double* Mat = (double*) malloc(65*sizeof(double)) ;
     
    for(i=0;i<65;i++) {
        Mat[i] = 0 ;
    }    
    for(i=0;i<9;i++) {
        NumAmine[i] = 0 ;
        wAmine[i] = 0 ;
    }    
    wAmine[0] = 30 ; 
    NumAmine[0] = 1 ;
    for(i=0;i<2;i++) {
        k[i] = 0 ;
        alpha[i] = 0 ;
        PP[i] = 0 ;
    }
    Namine[0] = 1 ;
     
    T[0] = 30 ;
     
     
    wMeOH[0] = 0.000000001 ;
    k[0] = 1 ;
    k[1] = 1 ;
    alpha[0] = 0.5 ;
    alpha[1] = 0.5 ;
    PP[0] = 0 ;
    PP[1] = 0 ;
     
     
    call_dll(T, Namine, NumAmine, wAmine, wMeOH, k, alpha, PP, Mat);
     
    printf("T : %f\n\n",*T);
    printf("Namine : %d\n\n",*Namine);
    printf("wMeOH : %f\n\n",*wMeOH);
     
    printf("k \t\t alpha \t\t PP \n");
    for(i=0;i<2;i++) {
        printf("%d \t\t %0.4f \t\t %0.4f \n", k[i], alpha[i], PP[i]) ;
    }    
     
    printf("Num \t\t wAmine \n") ;
    for(i=0;i<9;i++) {
        printf("%d \t\t %0.4f \n", NumAmine[i], wAmine[i]) ;
    }    
     
     
    printf("Mat \n");
    for(i=0;i<13;i++) {
        for(j=0;j<5;j++) {
            printf("%0.4f \t", Mat[(j*13)+i]) ;
        }
        printf("\n");
    } 
        return 0;
    }
    Encore merci
    Kokocha

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

Discussions similaires

  1. [2.x] [Symfony2] Problème tableau 2 dimensions
    Par hjoumane dans le forum Symfony
    Réponses: 1
    Dernier message: 22/04/2014, 20h01
  2. Problème tableau 2 dimensions dynamique
    Par Beaudelicius dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 22/08/2011, 14h24
  3. [Fortran 90] Ecriture d'un tableau à 2 dimensions
    Par freetryall dans le forum Fortran
    Réponses: 4
    Dernier message: 27/12/2008, 09h52
  4. probléme tableau 1 dimension
    Par kamnouz dans le forum Débuter
    Réponses: 4
    Dernier message: 12/12/2007, 20h55
  5. Problème tableau 2 Dimensions
    Par kiouz dans le forum Flash
    Réponses: 3
    Dernier message: 08/01/2007, 22h06

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