Appeler une librairie dynamique écrite en C dans Fortran sous Linux

Appeler une librairie dynamique écrite en C dans Fortran sous Linux - Divers - Programmation

Marsh Posté le 23-11-2011 à 14:03:08    

Bonjour à tous, je demande votre aide car je n'arrive pas à lier une librairie dynamique (ma_dll.so) avec un programme Fortran sous Linux. Je débute en Fortran et je n'ai jamais utilisé de librairie dynamique. Je copie-colle ci joint mon programme info.f dont le but est d'afficher une chaine de caractère (en passant par une structure) présente dans la librairie.
 
info.f :
 
program test
use iso_c_binding
implicit none
 
INTERFACE
FUNCTION info() BIND(C) RESULT (pa)
use iso_c_binding
type(c_ptr):: pa
END FUNCTION info
END INTERFACE
 
type(c_ptr), target :: pa
character(1, c_char),pointer::fpa(:)
pa=info()
call c_f_pointer(pa, fpa, [50])
print*, fpa(1:50)
 
end program test
 
Pouvez-vous m'expliquer comment lier ma libraire avec ce code? Et les éventuelles options de compilation? Pour info je compile avec pgfortran.
 
Cordialement.

Reply

Marsh Posté le 23-11-2011 à 14:03:08   

Reply

Marsh Posté le 23-11-2011 à 17:50:47    

Si ta lib est dans un répertoire de ta variable d'environnement LD_LIBRARY_PATH, tu rajoutes juste -lma_dll et ça devrait marcher (si ton code fortran est bon)

Reply

Marsh Posté le 24-11-2011 à 15:37:33    

Ok merci beaucoup GrosBocdel! J'ai réussi à compiler mais hélas ça plante à l'exécution...segmentation fault. En fait j'aimerais ne pas utiliser de pointeurs dans ma dll afin d'avoir un code "simple" et surtout couplaple facilement avec d'autres langages (genre C++, VB, Python, Matlab...). Comment pourrais -je adapter mon programme fortran avec cette contrainte? Je n'y arrive pas, car en plus la fonction C appelée info() est de type structure:  
 
#ifndef _VERSION_H_
#define _VERSION_H_
typedef struct numeroversion{
 char *v;
}numeroversion;
#endif
 
static char *version="blabla";
 
export numeroversion call info_version();
 
numeroversion call info_version(){
 numeroversion retour;
 strcpy(retour.v,version);
 return retour;
}
 
Une idée?  :whistle:


Message édité par dr-xam le 24-11-2011 à 15:38:41
Reply

Marsh Posté le 24-11-2011 à 16:16:07    

ça segfault parce que retour.v n'est pas initialisé.
Pour utiliser strcpy il faut que la zone d'arrivée soit allouée.
donc char v[10] au lieu de char *v et ça devrait(?) fonctionner.
 
Je ne comprends pas le reste du code.
 

Reply

Marsh Posté le 25-11-2011 à 13:35:36    

Merci, en fait j'avais déjà testé avec char v[10] et pareil pour static char version[10] mais ça seg fault aussi. Ca plante après le strcpy de la fonction info(). Je ne comprends pas pourquoi, mais j'imagine qu'il y a un problème de lien avec la librairie? Est-il possible de faire appel à une fonction C sans pointeur qui retourne une structure, dans Fortran?
 
Pour info je compile avec : gfortran -Bdynamic -fPIC infoversion.f -L. -lma_dll -o test
 
A l'aide!

Reply

Marsh Posté le 25-11-2011 à 13:49:25    

Code :
  1. #ifndef _VERSION_H_
  2. #define _VERSION_H_
  3. typedef struct numeroversion{
  4. char *v;
  5. }numeroversion;
  6. #endif
  7. static char *version="blabla";
  8. export numeroversion call info_version();
  9. numeroversion call info_version(){
  10. numeroversion retour;
  11. strcpy(retour.v,version);
  12. return retour;
  13. }


Tu as aucun controle sur ce code, il vient de l'extérieur? Ou c'est toi qui code ça?
Parce que c'est pas terrible, la.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 25-11-2011 à 14:04:41    

La librairie m'a été fournie mais je dispose des fichiers sources donc je peux éventuellement les modifier. En fait, je cherche à faire appel à la fonction info(), qui est dans main.c. La structure numeroversion est quant à elle définie dans un fichier structure.h. Je (re)précise bien que les chaines de caractères sont maintenant initialisées avec une taille de 10 (plus char*). Toute aide sera la bienvenue concernant le code C, mais à mon avis c'est plutôt le Fortran (que je découvre) qui est mal codé, car je ne sais pas comment appeler correctement la fonction info() et c'est bien là que ça plante à l'exécution (j'ai vérifier avec des print).  
 
program test
use iso_c_binding
implicit none
 
INTERFACE
FUNCTION info() BIND(C) RESULT (pa)
use iso_c_binding
type(c_ptr):: pa
END FUNCTION info
END INTERFACE
 
type(c_ptr), target :: pa
character(1, c_char),pointer::fpa(:)
pa=info() => Appel correct?
call c_f_pointer(pa, fpa, [50])
print*, fpa(1:50)
 
end program test
 
Merci pour vos réponses rapides en tout cas!


Message édité par dr-xam le 25-11-2011 à 14:05:09
Reply

Marsh Posté le 25-11-2011 à 14:19:49    

Citation :

La librairie m'a été fournie mais je dispose des fichiers sources donc je peux éventuellement les modifier


 
Je serais toi, je tenterais avec un truc de la forme
int call info_version(char *ver) {
  if (!ver) return -1;
  strcpy(ver, version);
  return 0;
}
 
Bref, un truc ou la zone mémoire ou tu copies ta chaîne est dans le programme appelant.
Pour le reste, je connais pas assez les évolutions de fortran pour pouvoir t'aider la, j'en ai plus fait depuis 30 ans (sur cartes perforées à l'époque).
A+,


Message édité par gilou le 25-11-2011 à 14:26:13

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 25-11-2011 à 17:00:51    

Ok merci pour l'aide je vais me débrouiller avec ça :)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed