В дополнение к моим лучшим комментариям, Fortran передает по ссылке, поэтому вам нужно изменить файлы .c
и .for
.
Код ниже работает.Может быть более простой способ объявить вещи, но это должно [по крайней мере] продвинуть вас дальше. Предостережение : Я не делал много фортранов со времен Фортрана IV, поэтому я немного заржавел.Я бы предпочел решение Владимира VALUE
как лучший путь.
#include <stdio.h>
#if 0
extern int fact_(int n);
extern void pythagoras_(float a, float b, float *c);
#else
extern int fact_(int *n);
extern void pythagoras_(float *a, float *b, float *c);
#endif
int
main(void)
{
float c;
#if 0
printf("Factorial of 7 is: %d\n", fact_(7));
#else
int n = 7;
printf("Factorial of 7 is: %d\n", fact_(&n));
#endif
#if 0
pythagoras_(30, 40, &c);
#else
float a = 30;
float b = 40;
pythagoras_(&a, &b, &c);
#endif
printf("Hypotenuse if sides 30, 40 is: %f\n", c);
return 0;
}
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, c)
REAL*4 a
REAL*4 b
REAL*4 c
c = SQRT (a * a + b * b)
END
Вот вывод программы:
Factorial of 7 is: 5040
Hypotenuse if sides 30, 40 is: 50.000000
ОБНОВЛЕНИЕ:
Я получаю ту же ошибку undefined reference
из вашего кода!
Ага!
Одна вещь, которую я не упомянул [потому что я не думал, что это будет иметь значение], заключается в том, что я изменил имена исходных файлов, чтобы использовать все строчные буквы (например, CMAIN.C --> cmain.c
и FORSUBS.FOR --> forsubs.for
)
При этом вывод nm *.o
дает:
cmain.o:
U fact_
0000000000000000 T main
U printf
U pythagoras_
forsubs.o:
0000000000000000 T fact_
0000000000000045 T pythagoras_
Изменение имени файла с исходным кодом на фортране не имеет большого значения.Но имя файла источника C имеет значение!
Более того, это имя файла суффикс (то есть .C
изменено на .c
).
Это потому, что gcc
[попытается быть умным и] посмотрит на суффикс, чтобы определить, на каком языке записан файл, и соответственно скомпилирует.Например, gcc -c foo.cpp
скомпилирует файл, как если бы он был написан в c++
, а не c
, как если бы команда была: g++ -c foo.cpp
Хотя .cpp
это [более] обычный суффикс для c++
имени файла, альтернативный суффикс для c++
файлов: .C
То есть большинство проектов используют соглашение .cpp
, но некоторые используют.C
конвенция.Одна из причин предпочтения .cpp
над .C
заключается в том, что файловые системы Windows не чувствительны к регистру.Итак, .C
и .c
будут выглядеть одинаково.Однако системы POSIX (например, linux, macOSX, iOS, android и т. Д.) Имеют имена файлов с учетом регистра, поэтому можно использовать любое соглашение.
Таким образом, gcc -c CMAIN.C
будет компилироваться как c++
.Это делает c++
стиль «искажения имени» символов - не то, что мы хотим.В c++
искажение сделано, чтобы разрешить «перегрузку» имен функций.То есть две [или более] разные функции могут иметь одно и то же имя, если они используют разные аргументы.Например:
void calc(int val);
void calc(int val1,int val2);
void calc(double fval);
Вот вывод nm *.o
, если мы используем CMAIN.C
:
CMAIN.o:
0000000000000000 T main
U printf
U _Z11pythagoras_PfS_S_
U _Z5fact_Pi
FORSUBS.o:
0000000000000000 T fact_
0000000000000045 T pythagoras_
Запуск , что файл через c++filt
для"разобрать" c++
имен, которые мы получаем:
CMAIN.o:
0000000000000000 T main
U printf
U pythagoras_(float*, float*, float*)
U fact_(int*)
FORSUBS.o:
0000000000000000 T fact_
0000000000000045 T pythagoras_
Итак, попробуйте использовать имена файлов в нижнем регистре, если это возможно [это рекомендуется наилучшей практикой].Но, как минимум, не используйте .C