I have a small C program that I would like to link to a small Fortran program, but get the linker error undefined reference to fibonacci_array.

The Fortran code:

module fibonacci_number
  implicit none
  integer, parameter :: LongInt = selected_int_kind (38)
contains
  integer (kind=LongInt) elemental function fibonacci(ordinal)
    implicit none
    ! Declare variables
    integer, intent(in) :: ordinal
    integer :: count
    integer (kind=LongInt), dimension(2,2) :: matrix, initial
    matrix=reshape((/ 1, 1, 1, 0 /), shape(matrix))
    initial=reshape((/ 1, 0, 0, 1 /), shape(initial))
    count = ordinal

    ! Do actual computations
    do while (count > 0)
       ! If the exponent is odd, then the output matrix
       ! should be multiplied by the current base
       if (mod(count,2) == 1) then
          initial = matmul(matrix, initial)
       end if
       ! This is the squaring step
       matrix = matmul(matrix, matrix)
       count = count/2
    end do
    fibonacci = initial(1,2)
  end function fibonacci

  subroutine fibonacci_array (input, len) bind(C)
    use, intrinsic :: ISO_C_BINDING
    implicit none
    integer (kind=c_int), intent(in), value :: len
    integer (kind=c_int), dimension(len), intent(in) :: input
    ! integer, allocatable, target :: input(:)
    integer (kind=LongInt), allocatable :: array(:)
    allocate (array(len))
    array = fibonacci(input)
    write(*,*) array    
  end subroutine fibonacci_array
end module fibonacci_number

The C code:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

void fibonacci_array(int *ptr, int len);

int main(int argc, char *argv[])
{
  if (argc < 2) {
    fputs("This program calculates Fibonacci numbers corresponding to its arguments. You must enter at least one argument.\n", stderr);
    return 1;
  }
  int i;
  int *input = malloc(((size_t)argc - 1)*(sizeof(int)));
  for (i = 0; i < argc - 1; i++) {
    char *test = argv[i];
    input[i-1] = strtoll(argv[i], &test, 10);
    if (*test != '\0') {
      fprintf(stderr, "You must enter an integer, not '%s'\n", argv[i]);
      return 1;
    }

    if (input[i-1] < 0) {
      fputs("You must enter a positive number!\n", stderr);
      return 1;
    }

    if (errno != 0 || input[i-1] > 184) {
      fprintf(stderr, "%s is too large \n", argv[i]);
      return 1;
    }
  }

  fibonacci_array (input, argc - 1);
  return 0;
}

The makefile:

# This macro contains the source files
# D sources not included because of rdmd
sources := $(wildcard *.c *.f08)
include FFLAGS
include CFLAGS
objects := $(sources:%.c=%.o)
objects := $(objects:%.f08=%.o)
.SUFFIXES:
.SUFFIXES: .f08 .c .o
.SILENT:
all: combined

clean:
    $(RM) $(objects) combined

combined: call.o fibonacci_function.o
    echo "Linking combined executable"
    gcc $< -o $@ -L/usr/local/lib64 

.c.o:
    echo "Building $@ from $<"
    gcc $(CFLAGS) $< -c -o $@

.f08.o:
    echo "Building $@ from $<"
    gfortran $(FFLAGS) $< -c -o $@

The error message:

Linking combined executable
call.o: In function `main':
call.c:(.text.startup+0x25c): undefined reference to `fibonacci_array'
collect2: error: ld returned 1 exit status
make: *** [combined] Error 1
make: Target `all' not remade because of errors.
有帮助吗?

解决方案

In make, $< is the name of the first requisite only. You'll need $^, the names of all requisites, in your link command in order to link both call.o and fibonacci.o to combine. (See Automatic variables in make.)

(Corrected wrong representation of $^ and $< with at sign instead of dollar sign in an earlier version of my answer.)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top