У меня есть основная программа на Фортране, в которой есть много подпрограмм. Одна из подпрограмм вызывает функцию c ++. Эта функция c ++ вызывает другую подпрограмму Fortran. Теперь мне нужно собрать их все вместе, чтобы получить результат.
Я попытался скомпилировать файл C ++ с ICL. Затем я использовал ifort в качестве компоновщика между файлом Fortran и объектным файлом, созданным для c ++. Но метод не работает. Это показывает нерешенный внешний символ.
Я ожидаю, что вы хотя бы видели это: https://software.intel.com/en-us/node/691954
То, что они там написали, в основном относится к C, хотя есть упоминания о библиотеках C ++. Если вы связываетесь с C ++ ocde, они вам нужны.
Вы должны прочитать об искажении имени символа в C ++. Потому что C ++ поддерживает перегруженные функции, но компоновщик требует уникальный символы, C ++ генерирует
что-то вроде _foo****@8
вместо foo
для функции foo (int i, float j), где * зависит от компилятора и типа аргументов.
Код Fortran генерирует символы в стиле C, если используется BIND (C), вы можете заставить C ++ генерировать символы для функции, используя extern "C"
в коде C ++ как для прототипов функций на языке Fortran, вызываемых из C ++, так и для функций, которые будут вызываться из языка Fortran.
Этот пример работает с компилятором C, но для C ++ вам нужно изменить сгенерированный символ (https://software.intel.com/en-us/node/691929#92BDCE7A-30FA-4A60-BCDB-7CE1521572EC). Обратите внимание, что совместимость C и Fortran не стандартизирована и обычно не переносима из одного набора компиляторов в другой. Мне пришлось столкнуться с проблемой, заключающейся в том, что компилятор Compaq также манипулировал именами функций, но не на языке C ++, или что PGI Fortran требовал соглашений stdcall.
Пример кода на Фортране
subroutine Simulation(alpha, beta, gamma, delta, arrays) BIND(C)
use, intrinsic :: ISO_C_BINDING
implicit none
integer (C_LONG), value :: alpha
real (C_DOUBLE), intent(inout) :: beta
integer (C_LONG), intent(out) :: gamma
real (C_DOUBLE),dimension(*),intent(in) :: delta
type, BIND(C) :: pass
integer (C_INT) :: lenc, lenf
type (C_PTR) :: c, f
end type pass
type (pass), intent(inout) :: arrays
real (C_FLOAT), ALLOCATABLE, target, save :: eta(:)
real (C_FLOAT), pointer :: c_array(:)
...
! Associate c_array with an array allocated in C
call C_F_POINTER (arrays%c, c_array, (/arrays%lenc/) )
...
! Allocate an array and make it available in C
arrays%lenf = 100
ALLOCATE (eta(arrays%lenf))
arrays%f = c_loc(eta)
...
end subroutine Simulation
Пример объявления C Struct
struct pass {int lenc, lenf; float *c, *f;};
Пример прототипа функции C
void simulation(long alpha, double *beta,
long *gamma, double delta[], struct pass *arrays);
C Пример вызывающей последовательности
simulation(alpha, &beta, &gamma, delta, &arrays);
Других решений пока нет …