15

I am attempting to compile and link a Fortran code calling c subroutine:

Fortran code:

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

C code:

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 );
}

I used the following commands to compile and link in windows environment.

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

I get the following error:

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

Please help me resolve this issue? Thanks.

Kara
  • 6,115
  • 16
  • 50
  • 57
momba
  • 185
  • 1
  • 2
  • 8

2 Answers2

19

You need to provide an interface body for the C function inside the specification part of the Fortran main program that tells the Fortran compiler that the name addnums is a C function. Something like:

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

(With those compilers on that platform without special options the default kind of integer is the same as C_INT - but being explicit about the integer KIND helps protect you if compiler/platform or compile options change.)

IanH
  • 21,026
  • 2
  • 37
  • 59
3

Here's two things I can see right off the bat (I work mainly with FORTRAN77 so this may not be the newest or best way to do this):

  1. Since your C function is, well, a function (and not a subroutine), you'll need to declare 'addnums' as EXTERNAL. Add this to your code in your declarations section.

    EXTERNAL addnums
  2. Add an underscore to the name of the function in your C code. FORTRAN does this automatically to its own functions, but not to functions in other languages. So, the function's signature would be

    void addnums_( int* a, int* b )

This page has a pretty good rundown on mixing C and FORTRAN. Hope this helped!

modrobert
  • 19
  • 6
c.maclean
  • 401
  • 2
  • 9
  • 1
    The modern way of connecting Fortran and C is to use the Fortran ISO_C_Binding. As part of the Fortran language, it is compiler and platform independent. It avoids needing to know about compiler internals. The linked page is obsolete. – M. S. B. Jul 25 '13 at 01:44
  • If you are unable to use ISO_C binding, declare the C routine as __stdcall otherwise it defaults to __cdecl. It will call your routine and crash on exit. – cup Jul 25 '13 at 04:35
  • The link to "This page" is broken. – Wauzl Jan 23 '15 at 10:43
  • Another source for that page is https://docs.oracle.com/cd/E19059-01/stud.8/817-5066/11_cfort.html Oracle will probably (inadvertently) break the link as soon as I post it so the Google-fu to find it later is to search for Sun/Oracle documentation for their Fortran compiler – arclight Jan 02 '16 at 20:51