Bonjour à tous.

Voici mon problème :

Je dois, à partir d'un programme principal en fortran, appeler une fonction c++, qui elle-même appelle une subroutine fortran du programme principal.

Je code sous linux et après quelques tours sur des forums sur le sujet j'ai cru comprendre que le plus simple était de passer par du C.

Mon architecture est donc la suivante :
le programme fortran appelle une fonction C, qui elle-même appelle une fonction c++, qui elle-même appelle une subroutine fortran.

Et y'a un soucis à la compilation.

Voici les squelettes de mes codes :

Fortran (fonction.f) :
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
program fortran
 
end
 
recursive &
   subroutine solveur (fcn, x, tolerance, code_sortie)
 
     ! arguments
     interface
       subroutine fcn (n, m,  x, fvec, iflag)
         integer   :: n
         integer   :: m
         real, dimension (1:3) :: x(n)
         real, dimension (1:3) :: fvec(m)
         integer   :: iflag
       end subroutine fcn
     end interface
 
     real, dimension (1:3) :: x(:)
     real, dimension (1:3) :: tolerance
     integer,   intent(out)   :: code_sortie
 
     ! appel
     call interface_n(n, m, x, tolerance, code_sortie)
 
   end subroutine solveur
Le C (module.c):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
#include <stdlib.h>
#include <stdio.h>
 
extern void n_cpp(int, int, float*, int, int);
 
void interface_n(int n, int m, float *x, int tolerance, int code_sortie)
{
	nomad_cpp(n, m, x, tolerance, code_sortie);
}
Et le c++ (n_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
#include <iostream>
#include <fstream>
 
using namespace std;
 
extern "C"
{
void n_cpp(int, int, float*, int, int);
void fcn_(int*, int*,  float*, float*, int*);
}
 
void n_cpp(int n, int m, float *x, int tolerance, int code_sortie)
{
	float fvec[m];
	int iflag = -1;
	fcn_(&n, &m, x, fvec, &iflag);
}
Bien sûr ces codes sont bidons, c'est juste pour essayer de faire fonctionner ces "appels croisés".

Je compile tout ça avec :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
% gfortran -c -ffree-form fonction.f
% gcc -c module.c
% g++ -c n_cpp.cpp
% gfortran -o fonction.o module.o n_cpp.o
Et voici l'erreur :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
n_cpp.o: In function `__static_initialization_and_destruction_0(int, int)':
n_cpp.cpp:(.text+0x1d): undefined reference to `std::ios_base::Init::Init()'
n_cpp.cpp:(.text+0x22): undefined reference to `std::ios_base::Init::~Init()'
n_cpp.o: In function `nomad_cpp':
n_cpp.cpp:(.text+0x185): undefined reference to `fcn_'
n_cpp.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
/usr/lib/gcc/i586-suse-linux/4.3/libgfortranbegin.a(fmain.o): In function `main':
(.text+0x35): undefined reference to `MAIN__'
collect2: ld a retourné 1 code d'état d'exécution
En tapant ces erreurs dans Google (qui est mon ami) j'ai trouvé comme raison des programmes c++ compilés avec gcc au lieu de g++.
J'ai donc essayé de compiler mon code c avec g++, modulo une toute petite modif au niveau de la déclaration de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
extern void n_cpp(int, int, float*, int, int);
qui devient
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
extern "C"
{ void n_cpp(int, int, float*, int, int);}
mais les erreurs restent les mêmes...

Et je bloque...

Est-ce que quelqu'un pourrait m'aider sioupl ?

Est-ce que les appels croisés que je fais sont tout simplement impossibles ?
Ou est-ce que je fais une erreur lors de l'éditions des liens ?
Ou autre chose encore ?

Merci beaucoup.