Вызов подпрограммы FORTRAN из C
Я пытаюсь вызвать функцию FORTRAN из C
Мои вопросы:
Если
fortRoutine
это имя моей подпрограммы Fortran, то я называю это из C какfortRoutine_
, ЕслиfortRoutine
содержит только один аргумент массива символов, тогда я могу передать так:fortRoutine_("I am in fortran");
Когда я вызываю подпрограммы FORTRAN, когда я должен использовать передачу по значению и когда передача по ссылке?
Поскольку я новичок в C, я понятия не имею об этом. Если возможно, предложите также несколько хороших обучающих ссылок.
3 ответа
Способ сделать это сейчас - использовать связывание Fortran ISO C на стороне Fortran. Это является частью стандарта языка Fortran 2003 и доступно во многих компиляторах; это не специфично для gcc. Это было описано во многих ответах на этом сайте. Как часть языкового стандарта, он не зависит от компилятора и платформы. И вам не нужно знать о внутренних условных обозначениях компилятора. Привязка ISO C, когда она используется в объявлении подпрограммы или функции Fortran, заставляет компилятор Fortran использовать соглашения о вызовах C, чтобы эту процедуру можно было напрямую вызывать из C. Вам не нужно добавлять скрытые аргументы или имя Название фортрановой подпрограммы, т.е. без подчеркивания. Имя, используемое компоновщиком, происходит из опции "bind".
Строки - сложный случай, потому что технически в Си они являются массивами символов, и вы должны соответствовать этому в Фортране. Вы также должны иметь дело с различными определениями строк: C завершен нулем, Fortran фиксированной длины и дополнен пробелами. Пример показывает, как это работает. Числа проще. Единственная проблема, связанная с массивами, заключается в том, что C является мажорной строкой и Fortran-майорной колонкой, так что многомерные массивы транспонируются.
int main ( void ) {
char test [10] = "abcd";
myfortsub (test);
return 0;
}
а также
subroutine myfortsub ( input_string ) bind ( C, name="myfortsub" )
use iso_c_binding, only: C_CHAR, c_null_char
implicit none
character (kind=c_char, len=1), dimension (10), intent (in) :: input_string
character (len=10) :: regular_string
integer :: i
regular_string = " "
loop_string: do i=1, 10
if ( input_string (i) == c_null_char ) then
exit loop_string
else
regular_string (i:i) = input_string (i)
end if
end do loop_string
write (*, *) ">", trim (regular_string), "<", len_trim (regular_string)
return
end subroutine myfortsub
Вы компилируете C в объектный файл и используете gfortran для компиляции фортрана и связываете оба:
gcc-mp-4.6 \
-c \
test_fortsub.c
gfortran-mp-4.6 \
test_fortsub.o \
myfortsub.f90 \
-o test_fortsub.exe
Выход:
>abcd< 4
Конечно, все зависит от вашего компилятора FORTRAN, но в целом:
Нет, вам нужно передать скрытый аргумент длины для вашей строки. Некоторые компиляторы чередуют их с другими параметрами непосредственно после строки. Другие группируют все аргументы длины строки в конце списка аргументов.
char str[11] = {0}; fortranFunc_(str, sizeof(str) - 1); // remember that 'str' will need to be null terminated // and will be padding with spaces to fit the length // so for C passing strings to Fortran specify the length // less 1 so you can add a nul terminator, and on all strings // being filled in by FORTRAN, trim-end all spaces.
Почти всегда это передача по ссылке, но вы можете переключать это поведение, используя атрибуты на фиктивных аргументах на стороне FORTRAN.
int value = 10; fortranFunc_(&value); // INTEGER I
Вот несколько ссылок, которые применимы на основе различных компиляторов:
Ответ зависит от компилятора и системы (технически, ее ABI). Для GCC (который является компилятором C, C++, Ada и Fortran) прочитайте главу по смешанному программированию на Fortran.