I'm trying to modify this code (gist as back up) to become gfortran-gcc compatible.
- I removed the
[VALUE]
tags - used
POINTER
with-fcray-pointer
flag for gfortran, instead of the[REFERENCE]
tag - removed the
__stdcall
, because tried the#define __stdcall __attribute__((stdcall))
which causedwarning: ‘stdcall’ attribute ignored [-Wattributes]
now this is what I have:
C code CMAIN.C
:
#include <stdio.h>
extern int FACT_(int n);
extern void PYTHAGORAS_(float a, float b, float *c);
main()
{
float c;
printf("Factorial of 7 is: %d\n", FACT_(7));
PYTHAGORAS_(30, 40, &c);
printf("Hypotenuse if sides 30, 40 is: %f\n", c);
}
the FORTRAN code FORSUBS.FOR
:
INTEGER*4 FUNCTION Fact (n)
INTEGER*4 n
INTEGER*4 i, amt
amt = 1
DO i = 1, n
amt = amt * i
END DO
Fact = amt
END
SUBROUTINE Pythagoras (a, b, cp)
REAL*4 a
REAL*4 b
POINTER (cp, c)
REAL*4 c
c = SQRT (a * a + b * b)
END
the Makefile
:
all:
gfortran -c FORSUBS.FOR -fcray-pointer
gcc -c CMAIN.C
gfortran -o result.out FORSUBS.o CMAIN.o
rm -rf *.o
clean :
rm -rf *.out *~ *.bak *.o
However I still get the error:
CMAIN.o: In function `main':
CMAIN.C:(.text+0x1d): undefined reference to `FACT_(int)'
CMAIN.C:(.text+0x4c): undefined reference to `PYTHAGORAS_(float, float, float*)'
I would appreciate if you could help me know:
- What is the issue and how can I resolve it?
- what is the best method to modify the original code to become gcc-gfortran compatible with minimum change.
P.S.1. also shared on Reddit. P.S.2. operating system and compiler specifications are same as this question.
In addition to my top comments, Fortran passes by reference, so you have to modify the
.c
and the.for
files.The code below works. There may be a simpler way to declare things, but this should [at least] get you further along. Caveat: I haven't done much fortran since Fortran IV days, so I'm a bit rusty. I'd defer to Vladimir's
VALUE
solution as a better way to go.Here is the program output:
UPDATE:
Aha!
One thing I didn't mention [because I didn't think it would make a difference] is that I changed the source file names to use all lowercase letters (e.g.
CMAIN.C --> cmain.c
andFORSUBS.FOR --> forsubs.for
)With that, the output of
nm *.o
produces:The change in the fortran source filename doesn't matter too much. But, the C source filename does!
More to the point it's the filename suffix (i.e.
.C
changed to.c
).This is because
gcc
will [try to be smart and] look at the suffix to determine which language the file is written in and compile accordingly. For example,gcc -c foo.cpp
will compile the file as if it is written inc++
and notc
, just as if the command were:g++ -c foo.cpp
Although
.cpp
is the [more] usual suffix for ac++
filename, an alternate suffix forc++
files is:.C
That is, most projects use the
.cpp
convention, but some use the.C
convention. One of the reasons for preferring.cpp
over.C
is that Windows filesystems are case insensitive. So,.C
and.c
would appear the same. However, POSIX systems (e.g. linux, macOSX, iOS, android, etc.) have case sensitive filenames so either convention can be used.So,
gcc -c CMAIN.C
will compile asc++
. This doesc++
style "name mangling" of symbols--not what we want. Inc++
, the mangling is done to allow "overloading" of function names. That is, two [or more] different functions can have the same name, as long as they use different arguments. For example:Here is the output of
nm *.o
if we useCMAIN.C
:Running that file through
c++filt
to "demangle" thec++
names we get:So, try to use lowercase filenames if possible [that is recommended best practice]. But, at a minimum, don't use
.C