2012-05-31 2 views
1

У меня есть код FORTRAN, который вызывает процедуру C для вычисления меры. Код FORTRAN является:Клавиатура FORTRAN и C с помощью изменения файла makefile

program fortran 
implicit none 
interface 
double precision function fpli_hv(A, d, n) 
real :: A(5,3) 
integer :: d, n 
end function fpli_hv 
end interface 
real :: A(5,3) 
double precision :: HV 
integer :: i, j 
A(1,:) = (/1.1,3.2,2.0/) 
A(2,:) = (/6.3,5.2,7.2/) 
A(3,:) = (/3.3,4.4,9.1/) 
A(4,:) = (/3.3,5.2,2.1/) 
A(5,:) = (/7.6,1.7,4.3/) 
HV = fpli_hv(A, 3, 5) 
end program fortran 

с функция выглядит следующим образом:

double fpli_hv(double *front, int d, int n, double *ref); 

Для того, чтобы клуб с и Fortran, мне нужно включить Makefil.lib в моем Makefile. Я так и сделал, и подготовил свой Makefile следующим образом:

# The makefile should contain a set of suffix rules. All suffixes must 
# be defined. In this case we will have .o for object files, .c for 
# C files, and .f for Fortran files. 
.SUFFIXES: .o .c .f90 

# LIBRARY: 
LIBHV = /gpfs0/home/shafiiha/programs/hv-2.0rc1-src/fpli_hv.a 
#include Makefile.lib 

# Define the C and Fortran compilers to be used in this makefile: 
CC= 
FC=gfortran -ffree-form -c 

# Define flags to be used by the C and Fortran compilers: 
CFLAGS =  
FFLAGS = 

# Define include to be used by the C and Fortran compilers: 
C_INCLUDES =  
F_INCLUDES = fortran.f90 

# The linker executable in this case must be the MPI Fortran compiler 
# to build a mixed C and Fortran MPI code: 
LINK = gfortran 

# Define values of parameters that appear in the source codes: 
DEFINES = 

# Define the list of object files for the linker. The linker will use 
# those files to build the executable. 
OBJECTS = fortran.o 

# The rule that makes the drv executable (note that libraries have 
# been specified by the mpif90 linker): 
fortran: $(OBJECTS) 
    $(LINK) -o fortran $(OBJECTS) $(LIBHV) 

# The rule that makes all object files from C sources: 
.c.o: 
    $(CC) $(CFLAGS) $(C_INCLUDES) $(DEFINES) $< 

# The rule that makes all object files from Fortran sources: 
.f90.o: 
    $(FC) $(FFLAGS) $(F_INCLUDES) $^ $(LIBHV) 

# The rule for deleting object files no longer needed after using 
# make for drv: 
clean: 
    rm *.o 

Но когда я делаю это, я получаю сообщение:

gfortran -o fortran fortran.o /gpfs0/home/shafiiha/programs/hv-2.0rc1-src/fpli_hv.a 
fortran.o: In function `MAIN__': 
fortran.f90:(.text+0x548): undefined reference to `fpli_hv_' 
collect2: ld returned 1 exit status 
make: *** [fortran] Error 1 

Не могли бы вы помочь мне, почему я получаю эту ошибку? Большое спасибо.

+4

Если вы собираетесь использовать привычку смешивать Fortran и C (и нет причин, по которым вы не должны этого делать), тогда стоит похвастаться «совместимостью с функциями C» последних стандартов Fortran. Эти функции обеспечивают, среди прочего, стандартный подход к разрешению различий в способах, с помощью которых компиляторы C и Fortran традиционно искажают имена. Больше не нужно выяснять, сколько подчеркиваний добавить к именам C, чтобы сделать их понятными для Fortran и многое другое. –

+0

Файл makefile, который вы показываете нам, не определяет значение для компилятора C 'CC' и имеет строку, содержащую' Makefile.lib', закомментированную. – eriktous

ответ

0

Wrap

double fpli_hv(double *front, int d, int n, double *ref); 

с

void FPLI_HV_(double *front, int* d, int* n, double *ref, double* returnvalue); 

Фортрана объектов понимают только то, оканчивающиеся на _ и все функциональные проходы по указателю.

(Редактировать для нижеследующего комментария).

+0

На самом деле это 'void fpli_hv_ (double * out, double * front, int * d, int * n, double * ref)'. Процедуры Fortran передают адрес последнего значения возвращаемого значения в стек. Что касается подчеркивания, YMMV, и вам, возможно, придется указывать имя во всех кешках: 'FPLI_HV' или' FPLI_HV_', в зависимости от реализации. –

+0

'gfortran', конечно, не помещает имена символов во все кепки. –

+0

У меня все еще такая же проблема! Собственно, есть также заголовочный файл, и соединение между заголовком и источником определено в makefile.lib, которое я включил в свой файл makefile. Почему я все еще получаю такое же сообщение об ошибке? – Matt

5

В эту эпоху лучший способ позвонить C из Fortran - использовать привязку ISO C. Ваша проблема связана с именем, которое Fortran делает по умолчанию, чтобы избежать столкновений с подпрограммами C или стандартных библиотек, обычно добавляя символы подчеркивания. С помощью связывания ISO C вы можете указать точное имя вызываемой процедуры, переопределение имени и легко достичь согласованности Fortran-C в аргументах. На стороне Fortran вы пишете интерфейс, описывающий процедуру C. Там были ответы на предыдущие ответы, и в руководстве gfortran есть примеры. Примеры не уникальны для gfortran, поскольку ISO C Binding является частью стандарта языка Fortran 2003.

+0

Да, действительно, я согласен. –

+0

+1; бах, ты избил меня минутой :) –

+0

Соглашение об именах - не единственная проблема - на самом деле конвенция о вызове больше. Все (должно быть) связано с привязкой ISO C. –

4

Если вы уже делаете интерфейсы (это здорово!), Вы можете также использовать модуль iso_c_binding, который должен содержать новейшие версии большинства fortran-компиляторов, чтобы не беспокоиться о символах подчеркивания и письма и что у вас есть:

interface 
    function fpli_hv(A, d, n) bind(C) 
    use iso_c_binding 
    implicit none 

    real(kind=c_double) :: fpli_hv 
    integer(kind=c_int), value :: d, n 
    real(kind=c_float) :: A(5,3) 

    end function fpli_hv 
end interface 
+0

+1 вам тоже, за предоставление кода тоже. –

+0

Моя проблема все еще не решена, даже после вложения C Binding. Дело в том, что есть файл .h, связанный с подпрограммой c, и я думаю, что это должно быть обработано через «include makefile.lib». Но я все равно получаю такое же сообщение об ошибке. В чем проблема с моим make-файлом? – Matt

+1

Для управления изменением имени это должно быть: bind (C, name = "fpli_hv") –

Смежные вопросы