This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Building a program with C an FORTRAN code
- To: ramiro at labtie dot mmt dot upc dot es
- To: egcs at cygnus dot com
- Subject: Re: Building a program with C an FORTRAN code
- From: Luc dot Maisonobe at cnes dot fr (Luc Maisonobe)
- Date: Fri, 30 Oct 1998 09:41:48 +0100
- References: <36384199.C8FFB268@labtie.mmt.upc.es>
Ramiro> I am trying to buil a program writen in C wicth has some code in
Ramiro> FORTRAN. The compiling
Ramiro> phase has no problems but when linking the objets together, it finds
Ramiro> undefined references to
Ramiro> the functions writen in FORTRAN (witch are referenced from C), as if
Ramiro> there were not defined
Ramiro> anywhere.
I have used C/C++/fortran combinations for years without
problems. However there are two things to be aware of ; the compiler
can transform function names when building symbols, and the languages
conventions for parameters differ.
I think (I'm not sure) that HP does not transform names for C and
convert names to lowercase for fortran. So the C funtion int foobar ()
can be called from fortran by : N = FOOBAR ().
Another common approach (egcs for example) is to add an underscore
after fortran names. If you want to write N = FOOBAR (), the compiler
will use the name foobar_ and so your C function should be named
int foobar_ ().
Warning : if you want to call a C++ function from fortran, you should
declare it as extern "C" int foobar_ (), otherwise the C++ name
mangling will prevent you from calling it from fortran.
The nm command can be used to find the symbols names of your object
files and to understand the coding used. I think your problem is here,
did you add the underscore ?
Fortran uses references for all parameters, whereas C uses
values. references are generally implemented by addresses and C knows
about addresses.
The solution is to use addresses on the C side :
fortran side :
INTEGER I, N, FOOBAR
DOUBLE PRECISION X
N = FOOBAR (I, X)
C side :
int foobar_ (int *ptrI, double *ptrX)
{ return (*ptrX > 0.0) ? *ptrI : -*ptrI; }
You can use references if you call a C++ function :
extern "C" int foobar_ (int &i, double &x)
{ return (x > 0.0) ? i : -i; }
The last problem is with character strings, since there is no end of
string character in fortran. Fortran compilers generally add an extra
argument (the declared length) for each character string after all
explicit arguments. Those extra parameters are generally passed by
value, as in the following example :
fortran side :
CHARACTER*80 S1
CHARACTER*20 S2
INTEGER I, N, FOOBAR
DOUBLE PRECISION X
N = FOOBAR (S1, I, S2, X)
C side :
int foobar_ (char *s1, int *ptrI, char *s2, double *ptrX,
int l1, int l2)
C++ side :
extern "C" int foobar_ (char *s1, int &i, char *s2, double &x,
int l1, int l2)
In the preceding cases, the C and C++ functions would receive 80 for
the extra l1 parameter and 20 for the extra l2 parameter.
All those conventions vary accross systems and compilers, I think egcs
trys to follow the conventions of the native compilers if they are
known, thus allowing to mix egcs code with other compilers code. You
should try and possibly configure your C code with #ifdef if you
intend to port it to several architectures.
Luc
--
------------------------------------------------------------------------------
Luc Maisonobe - DTS/MPI/MS/AM | Tel : (33) 05-61-28-26-31
CNES | Fax : (33) 05-61-27-35-40
18 avenue E. Belin |
31401 Toulouse CEDEX 4 - FRANCE | Email: Luc.Maisonobe@cnes.fr
------------------------------------------------------------------------------