Множественное определение main: связывание фортрана с C++

Я хотел бы написать программу на C++, которая вызывает подпрограмму mvndst_() из

http://www.math.wsu.edu/faculty/genz/software/fort77/mvndstpack.f

В Linux, если я создам test.cc:

extern "C" {
    int mvndst_(int *, double *, double *, int *, double *, int *,
                double *, double *, double *, double *, int *);
};
int main() {
    return 0;
}

и скомпилировать через

g++ -c -o test.o test.cc
gfortran -c -o mvndstpack.o mvndstpack.f
gfortran -Mnomain -o test test.o mvndstpack.o

тогда я получаю

mvndstpack.o: In function `main':
mvndstpack.f:(.text+0x4a2a): multiple definition of `main'
test.o:test.cc:(.text+0x0): first defined here
collect2: ld returned 1 exit status

Однако, если я запускаю strip -N main mvndstpack.o до связывания, то связывание завершается успешно. Может кто-нибудь объяснить, почему здесь не работает флаг -Mnomain? Я также хотел бы избежать решения, использующего «strip», так как поведение «strip» в Mac OS X отличается (т. е. опция -N недоступна, и я не уверен в другом способе получить правильное поведение). Я также хотел бы избежать редактирования исходного кода Fortran, если это возможно.

Подробности: - GNU Fortran (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 - g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 - GNU Strip (GNU Binutils для Ubuntu) 2.21.53.20110810 - Strip на Mac OS X 10.6 Снежный барс


person cbd    schedule 17.10.2011    source источник


Ответы (2)


Я не могу найти никакой документации для опции -Mnomain, но gfortran не жалуется на это (кажется, передает это компоновщику). Но он также не жаловался, когда я бежал

gfortran -Mnoplatypus -o test test.o mvndstpack.o

Итак, я предполагаю, что он не поддерживает -Mnomain и молча игнорируется. (Либо так, либо есть вариант -Mnoplatypus, но это маловероятно.)

Что сработало для меня, так это закомментировать строки PROGRAM TSTNRM .. END в mvndstpack.f (строки с 15 по 62).

В любом случае, это, вероятно, самый разумный подход; вы не хотите использовать основную программу Fortran, так что вы можете не компилировать ее, а не пытаться обмануть компоновщика, чтобы он ее игнорировал.

(Если хотите, можете использовать #if ... #endif или #ifdef ... #endif.)

ИЗМЕНИТЬ:

Поскольку ваша основная программа написана на C++, вам, вероятно, потребуется использовать g++, а не gfortran, для создания исполняемого файла:

g++ -c -o test.o test.cc
gfortran -c -o mvndstpack.o mvndstpack.f
g++ -o test test.o mvndstpack.o

(И в какой-то момент вы действительно захотите вызвать функцию.)

person Keith Thompson    schedule 17.10.2011
comment
Спасибо, имеет смысл! Я почему-то думал, что должен быть способ сделать это без редактирования исходного кода на Фортране... но я думаю, что, возможно, нет. - person cbd; 17.10.2011

Ваша проблема в том, что ваш код FORTRAN также включает main, просто в этом мире он известен как PROGRAM. Из mvndstpack.f:

      PROGRAM TSTNRM
*
*     Test program for MVNDST
*

Вам нужно выбрать, на какой стороне забора будет проходить вечеринка первой!

В этом случае вы хотите, чтобы C++ вызывал FORTRAN, поэтому вам просто нужно выбросить верхнюю часть файла FORTRAN, которая содержит программу TSTNRM, или поместить ее в раздел условной компиляции:

#if TEST
      PROGRAM TSTNRM
...
      END
#endif

Затем вы можете переименовать файл в (регистр имеет значение) mvndstpack.F или mvndstpack.FPP или использовать -cpp в параметрах командной строки для gfortran.

person user7116    schedule 17.10.2011