Вызов функции/подпрограммы C в коде Fortran

Я пытаюсь скомпилировать и связать код Fortran, вызывающий подпрограмму c:

Код Фортрана:

program adder
integer a,b
a=1
b=2
call addnums(a,b)
stop    
end program

C-код:

void addnums( int* a, int* b ) 
{
    int c = (*a) + (*b);  /* convert pointers to values, then add them */
    printf("sum of %i and %i is %i\n", (*a), (*b), c );
}

Я использовал следующие команды для компиляции и компоновки в среде Windows.

ifort -c adder.f
cl -c addnums.c
ifort -o add adder.obj addnums.obj

Я получаю следующую ошибку:

Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.
-out:add.exe 
-subsystem:console 
adder.obj 
addnums.obj 
adder.obj : error LNK2019: unresolved external symbol ADDNUMS referenced in function MAIN__
add.exe : fatal error LNK1120: 1 unresolved externals

Пожалуйста, помогите мне решить эту проблему? Спасибо.


person momba    schedule 24.07.2013    source источник
comment
Вы пытались сопоставить это имя функции (т. е. все заглавные буквы)?   -  person Carl Norum    schedule 25.07.2013


Ответы (2)


Вам нужно предоставить тело интерфейса для функции C внутри части спецификации основной программы Fortran, которая сообщает компилятору Fortran, что имя addnums является функцией C. Что-то типа:

INTERFACE
  SUBROUTINE addnums(a, b) BIND(C)
    USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT
    IMPLICIT NONE
    INTEGER(C_INT) :: a, b
  END SUBROUTINE addnums
END INTERFACE

(Для этих компиляторов на этой платформе без специальных параметров тип целого числа по умолчанию такой же, как C_INT, но явное указание целочисленного типа помогает защитить вас, если параметры компилятора/платформы или компиляции изменятся.)

person IanH    schedule 24.07.2013
comment
Спасибо. Ваш совет помог. - person momba; 25.07.2013

Вот две вещи, которые я вижу сразу (я работаю в основном с FORTRAN77, поэтому это может быть не самый новый или лучший способ сделать это):

  1. Поскольку ваша функция C является функцией (а не подпрограммой), вам нужно объявить «дополнения» как EXTERNAL. Добавьте это в свой код в разделе объявлений.

    EXTERNAL addnums
  2. Добавьте подчеркивание к имени функции в коде C. FORTRAN делает это автоматически со своими собственными функциями, но не с функциями на других языках. Таким образом, сигнатура функции будет

    void addnums_( int* a, int* b )

На этой странице есть неплохой обзор смешивания C и FORTRAN. Надеюсь, это помогло!

person c.anna    schedule 24.07.2013
comment
Современный способ соединения Fortran и C заключается в использовании файла Fortran ISO_C_Binding. Являясь частью языка Fortran, он не зависит от компилятора и платформы. Это позволяет избежать необходимости знать о внутренних компонентах компилятора. Связанная страница устарела. - person M. S. B.; 25.07.2013
comment
Если вы не можете использовать привязку ISO_C, объявите подпрограмму C как __stdcall, иначе по умолчанию она будет __cdecl. Он вызовет вашу процедуру и вылетит при выходе. - person cup; 25.07.2013
comment
Ссылка на эту страницу не работает. - person Wauzl; 23.01.2015
comment
Другим источником для этой страницы является docs.oracle. com/cd/E19059-01/stud.8/817-5066/11_cfort.html Oracle, вероятно, (непреднамеренно) сломает ссылку, как только я опубликую ее, поэтому Google-fu, чтобы найти ее позже, должен искать для документации Sun/Oracle для их компилятора Fortran - person arclight; 02.01.2016