Appel à une fonction C++ à partir du fortran

Appel à une fonction C++ à partir du fortran - Divers - Programmation

Marsh Posté le 13-09-2004 à 15:29:01    

Bonjour,
 
Je souhaiterais pouvoir appeler une fonction écrite en C++ à partir d'un programme fortran. Je pensais savoir comment faire et, d'habitude, cela marchait mais là, je ne vois pas ce qui pose problème. Pour simplifier, mon programme fortran principal est :
 
principal.f :
 
      program principal
 
      integer carre
 
      integer a
 
      a=3
 
      print *,"carre=",carre(a)
       
      end program
 
et la fonction " carre " écrite en C++ est dans le fichier Carre.C :
 
#include <fstream.h>
 
extern "C" int carre_(int*);
 
int carre_(int* b)
{
  int c;
   
  c = (*b)*(*b);
   
  cout << "c = " << c << endl;
 
  return (c);  
}
 
Je compile succsessivement par :
 
g77 -c principal.f
g++ -c Carre.C
g77 -o principal principal.o Carre.o
 
A l'édition de lien, j'ai un message d'erreur m'indiquant que les opérateurs cout, << et endl ne sont pas connus (alors que la bibliothèque fstream.h est la pourt ça). Apparemment, c'est le seul problème car, lorsque j'évite de faire une sortie écran de la valeur de c, le programme fonctionne. Qu'est ce qui cloche ? Comment obliger le programme à faire ces sorties écran ?
 
D'avance merci de votre aide  
 
Nathan G
 

Reply

Marsh Posté le 13-09-2004 à 15:29:01   

Reply

Marsh Posté le 13-09-2004 à 16:04:57    

Essaye de rajouter libstdc++.a à ta ligne de link (la dernière donc), ou au pire, le paramètre "-lstdc++".
 
Sinon, 2 remarques :  
1. c'est du vieux c++ que tu nous fais là. La norme a un peu changé depuis 99, on y reviendra plus tard.
 
2. fstream.h n'est pas une bibliothèque mais un fichier de déclarations : tu déclares les fonctions (leurs signatures), mais tu ne les définis pas (tu ne donnes pas leurs implémentations). Tout ça se trouve dans ... libstdc++, tu l'avais deviné. :)
 
 
Edit: non, comme d'hab, je dis plein de conneries. En fait, utilise plutot "g++" pour faire le link, plutôt que "g77". Ca devrait peut-être mieux marcher :-)


Message édité par Lam's le 13-09-2004 à 16:06:02
Reply

Marsh Posté le 13-09-2004 à 16:18:09    

Merci bcp, ca fonctionne maintenant !
 
Juste quelques explications supplémentaires. Si les définitions des opérateurs posant problème (cout,endl,<< ...) se trouvent dans le fichier libstdc++.a, pourquoi faut-il rajouter ce fichier dans la ligne de compilation avec g77, c'est à dire le compiler en plus de mes propres fichiers *.o, alors que cela est inutile si j'utilise g++. Est ce justement parce que cette librarie est standard en c++ et donc inutile à indiquer lors s'une compilation purement en c++ ?

Reply

Marsh Posté le 13-09-2004 à 16:28:11    

nathan_g a écrit :

Est ce justement parce que cette librarie est standard en c++ et donc inutile à indiquer lors s'une compilation purement en c++ ?


 
Oui, c'est la "Standard Library" définie par le standard C++. Pour g++, elle s'appelle libstdc++. Pour Forte sous Solaris, elle s'appelle libC.  
Et donc, bien sûr, le compilateur sait généralement qu'il faut l'inclure.  
 
Maintenant, tu vas me faire plaisir, et remplacer
#include "fstream.h" par #include <fstream>
 
Et juste après la dernière ligne d'include, tu écris:
   using namespace std;
 
Ca te fera rééllement basculer dans le C++ du 3ème millénaire ;-)

Reply

Marsh Posté le 13-09-2004 à 16:47:26    

Dernière question (je sais j'insite).
 
J'ai un peu regardé sur le forum pour comprendre l'intérêt du "using namespace std".
 
En fait les commandes cout , endl ... devraient s'écrire std::cout et std::endl. La ligne "using namespace std" permet de raccourcir ces commandes en signifiant qu'elles sont du même type. C'est ça ?
 
Néanmoins, comme tu le vois, je l'oublie systématiquement. Ce n'est pas grave car, par défaut, il est rajouté ?
 
Mais, si j'ai d'autres commandes faisant parties du même contexte (par ex toto), je peut aussi utiliser une seconde commande using namespace toto ? Dans ce cas, on peut aussi surcharger les commandes cout, endl (je sais, ce serait pousser le bouchon). En fait, il n'y pas de risuqe de confusion ? Le programme sait dans quel namespace se situe chaque commande ?

Reply

Marsh Posté le 13-09-2004 à 17:16:22    

nathan_g a écrit :


En fait les commandes cout , endl ... devraient s'écrire std::cout et std::endl. La ligne "using namespace std" permet de raccourcir ces commandes en signifiant qu'elles sont du même type. C'est ça ?


 
En C++, tu as des namespaces (package/librairies/nom de domaine, enfin tu vois le genre).  
 
Le fichier <fstream> est défini comme:  
 
namespace std {
#include <fstream.h>
}
 
Donc, si tu utilises fstream (ce qui est largement recommandé), plutôt que fstream.h (qui est là pour la compatibilité ascendante), alors tes variables/types/méthodes seront définies dans le namespace std uniquement.
 
Pour t'en servir, tu as alors 3 choix possibles:
 
1. incorporer tout std, avec la ligne:
using namespace std;
 
2. incorporer uniquement cout avec:
using std::cout;
 
3: préciser à chaque fois que tu veux spécifiquement le cout de std:
std::cout << "Hello" << std::endl;
 
Ton code actuel fonctionne parce que tu utilises le vieux header, et donc tu n'as pas besoin d'incorporer std. Quand je dis incorporer std, cela signifie que tu indiques au compilo que tout ce qui se trouve dans std doit désormais être accessible depuis le namespace global (celui par défaut).
 
 
Enfin, pour n'utiliser que cout, etc. Pas besoin de <fstream> : tu devrais en fait inclure <iostream>
 
Et pour finir, ce que tu disais est globalement vrai:
 

Code :
  1. #include <iostream>
  2. // par défaut, on est dans le namespace global
  3. std::string endl = "GlobalEndl";
  4. namespace toto {
  5.   std::string endl = "TotoEndl";
  6. }
  7. int main() {
  8.   std::cout << endl << " " << toto::endl << std::endl;
  9.   return 0;
  10. }


 
Ceci devrait fonctionner et afficher "GlobalEndl TotoEndl".
 

Reply

Marsh Posté le 13-09-2004 à 17:26:08    

Malheureusement, à la compilation, j'ai :
 
g++ -c main.C
 
main.C:4: syntax error before `='
main.C:7: syntax error before `='
main.C: In function `int main()':
main.C:11: `endl' undeclared in namespace `toto'
 
Mais, j'ai, je crois un compilateur assez ancien. En plus, les fichiers de déclaration sont bizarrement positionné sur ma machine (par ex include <time> n'est pas accepté à la compilation mais include "time.h" l'est).
 
Enfin, je pense quand même avoir compris pas mal de chose sur le C++ grace à toi. Si je cherche d'autres précisions, j'essaierais de me plonger dans un bouquin sur le C++.
 
Merci pour tout !

Reply

Marsh Posté le 13-09-2004 à 17:31:58    

nathan_g a écrit :


main.C:4: syntax error before `='
main.C:7: syntax error before `='
main.C: In function `int main()':
main.C:11: `endl' undeclared in namespace `toto'


 
Aaaargh.
J'ai oublié un #include <string> bien sûr !!!!
 
Mais bon, tu vois l'esprit. C'est juste pour que tu ne sois pas surpris si tu vois que ton code se marrie "mal" avec des programmes qui utilisent la norme C++ plutôt que la vieille façon de faire...

Reply

Marsh Posté le 13-09-2004 à 18:14:29    

nathan_g a écrit :


Mais, j'ai, je crois un compilateur assez ancien. En plus, les fichiers de déclaration sont bizarrement positionné sur ma machine (par ex include <time> n'est pas accepté à la compilation mais include "time.h" l'est).


 
ben c'est #include <ctime> comme pour les autres headers C (<cstdio> etc...)

Reply

Marsh Posté le 14-09-2004 à 09:00:58    

Ah, OK, je vais essayer. Je ne savais pas. Merci !

Reply

Sujets relatifs:

Leave a Replay

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