Повторяющийся символ при связывании C ++ и Fortran - PullRequest
0 голосов
/ 14 марта 2020

Я получаю повторяющуюся ошибку символа при связывании кода на языке Fortran и C ++, и я не понимаю, почему.

У меня есть следующий код Fortran, simple.f90:

module foo
    use iso_c_binding
    integer(kind=c_int) :: bar
end module foo

subroutine print()
    use foo
    write(*,*) bar
end subroutine print

и у меня есть следующий драйвер C ++, main. cpp


extern "C"
{
  int __foo_MOD_bar;
  void print();
}


int main()
{
  __foo_MOD_bar = 42;
  print();
  return 0;
}

Я хотел бы назначить переменной foo / bar модуля значение и распечатать его из Fortran. подпрограмма.

Однако, когда я компилирую и связываю

gfortran -std=f2003 -fno-underscoring -c simple.f90
g++ -c main.c
gfortran main.o gfortran.o -o out

Я получаю ошибку дублированного символа

[100%] Linking CXX executable out
duplicate symbol '___foo_MOD_bar' in:
    CMakeFiles/out.dir/main.cpp.o
    CMakeFiles/out.dir/simple.f90.o
ld: 1 duplicate symbol for architecture x86_64
 nm simple.f90.o
00000000000000f8 s EH_frame1
00000000000004cc S ___foo_MOD_bar
                 U __gfortran_st_write
                 U __gfortran_st_write_done
                 U __gfortran_transfer_integer_write
0000000000000000 T _print
0000000000000078 s lC0
nm main.cpp.o
0000000000000388 S ___foo_MOD_bar
0000000000000000 T _main
                 U _print

Я немного убыток

Ответы [ 2 ]

1 голос
/ 14 марта 2020

При использовании extern "C" с блоком определения переменных внутри блока не получают обработку класса внешнего хранилища. Для такого поведения есть довольно веская причина, а именно такие случаи, как

extern "C" {
#include <some_c_lib.h>
}

, чтобы сделать заголовочные файлы C пригодными для использования в C ++. Если extern "C" { ... } изменить все определения переменных во внешние объявления, могут произойти плохие вещи.

1 голос
/ 14 марта 2020

Ваш int __foo_MOD_bar; определяет переменную, а не просто объявляет ее (так как блок extern "C" изменяет только связь), и код Fortran, вероятно, делает то же самое. Попробуйте добавить явный спецификатор extern к самой переменной, например:

extern int __foo_MOD_bar;

(extern "C" int __foo_MOD_bar; также должно работать IIR C, внутри или снаружи блока extern "C").

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

...