linker — Ошибка при связывании подпрограммы fortran с программой на c ++

Я нахожусь в процессе преобразования программы из Фортрана в C ++. Однако для обеспечения совместимости ввода я использую подпрограммы и функциональность списка имен Fortran, следуя инструкциям в этом вопросе. Поскольку это устаревший код, список имен, над которым я работаю, несколько более нелепый, с более чем 30 переменными. Все работает до связывания, когда я получаю ошибку:

main.cpp:(.text+0x2732): undefined reference to `readDatainMesh(double*, int*, int*, double*, char*, double*, char*, int*, int*, int*, double*, int*, int*, int*, double*, double*, double*, int*, int*, int*, int*, double*, double*, double*, double*, int*, int*, double*, int*, int*, double*, char*, double*, double*, double*, int*, double*, double*, double*, int*, int*, int*, char*, char*, double*, double*)'

У меня есть следующие входные файлы:

readNamelists.f90:

 subroutine readDatainMesh(...) &
bind(c, name='readDatainMesh')
use,intrinsic :: iso_c_binding,only:c_double,c_int,c_char
implicit none

real(kind=c_double),    intent(inout) :: realVars
integer(kind=c_int),    intent(inout) :: intVars
character(kind=c_char), intent(inout) :: charVars
.
.
.

namelist/datain_mesh/...

open(unit = 100, file = 'input.nam', status = 'old')
read(unit = 100, nml = datain_mesh)
close(unit = 100)

endsubroutine readDatainMesh

с которым я собираю gfortran -Wall -o readNamelists.o -c readNamelists.f90, Это выдает предупреждения о неиспользуемых фиктивных переменных, но это все.

У меня есть заголовок C для функции, который я проверил как по вызываемой функции в main.cpp, так и по реализации на языке fortran. Это выглядит как:

#ifndef READNAMELISTS_H
#define READNAMELISTS_H

void readDatainMesh(...);

#endif

Я звоню gcc -Wall -o main.o -c main.cpp который не дает никаких предупреждений. Потом наконец gcc -Wall -o main main.o readNamelists.o -lstdc++ -lgfortran который выбрасывает вышеуказанную ошибку. Я подумал, что, возможно, символы не совпадают, поэтому я побежал nm как на объектных файлах, так и на интересующих линиях:

0000000000000000 T readDatainMesh

а также

             U _Z14readDatainMeshPdPiS0_S_PcS_S1_S0_S0_S0_S_S0_S0_S0_S_S_S_S0_S0_S0_S0_S_S_S_S_S0_S0_S_S0_S0_S_S1_S_S_S_S0_S_S_S_S0_S0_S0_S1_S1_S_S_

которые явно не совпадают. Мой вопрос, как мне решить эту проблему?

0

Решение

_Z14readDatainMeshPdPiS0_S_PcS_S1_S0_S0_S0_S_S0_S0_S0_S_S_S_S0_S0_S0_S0_S_S_S_S_S0_S0_S_S0_S0_S_S1_S_S_S_S0_S_S_S_S0_S0_S0_S1_S1_S_S_ является искаженным именем C ++, включая типы параметров. Таким образом, компилятор C ++ может давать перегруженным функциям разные символы и различать их.

Можно разобрать его из командной строки:

$ echo _Z14readDatainMeshPdPiS0_S_PcS_S1_S0_S0_S0_S_S0_S0_S0_S_S_S_S0_S0_S0_S0_S_S_S_S_S0_S0_S_S0_S0_S_S1_S_S_S_S0_S_S_S_S0_S0_S0_S1_S1_S_S_ | demangle
readDatainMesh(double*, int*, int*, double*, char*, double*, char*, int*, int*, int*, double*, int*, int*, int*, double*, double*, double*, int*, int*, int*, int*, double*, double*, double*, double*, int*, int*, double*, int*, int*, double*, char*, double*, double*, double*, int*, double*, double*, double*, int*, int*, int*, char*, char*, double*, double*)

Поэтому вы должны указать компилятору C ++, чтобы он воспринимал это как функцию C без перегрузки. Это можно сделать с помощью extern "C", Если из кода C и C ++ используется один и тот же заголовок, вам также потребуется защита, так как extern "C" не действует в C.

полностью заголовок может выглядеть так:

#ifndef READNAMELISTS_H
#define READNAMELISTS_H

#ifdef  __cplusplus
extern "C" {
#endif
void readDatainMesh(...);
#ifdef  __cplusplus
}
#endif

#endif

Если вы используете только C ++ и это единственная функция, вы можете сократить ее до

#ifndef READNAMELISTS_H
#define READNAMELISTS_H

extern "C" void readDatainMesh(...);

#endif
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]