Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28630 Discussions

Using Interface Statements to call C from Fortran

mhovers
Beginner
281 Views

Here is a simple test program of 3 files (below) when I try to compile and link in Visual Fortran (VS) I get:

1>------ Build started: Project: test, Configuration: Debug Win32 ------

1>Compiling with Intel Fortran 11.0.061 [IA-32]...

1>test3.f90

1>Linking...

1>test3.obj : error LNK2019: unresolved external symbol _c_code referenced in function _MAIN__

1>Debug\\test.exe : fatal error LNK1120: 1 unresolved externals

1>

1>Build log written to "file://C:\\Users\\hovg\\test\\Debug\\BuildLog.htm"

1>test - 2 error(s), 0 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

What am I missing??

FILE 1:

program test

use int_mod

real*4 a(50)

integer*4 n

call c_code(n,a)

write(*,*) (a(i),i=1,n)

stop

end

FILE 2:

module int_mod

interface

subroutine c_code(nn,a)

!DEC$ ATTRIBUTES C, ALIAS:'_c_code' :: c_code

!DEC$ ATTRIBUTES REFERENCE :: nn

!DEC$ ATTRIBUTES REFERENCE :: a

integer*4 nn

real*4, dimension (*) :: a

end subroutine c_code

end interface

end module

FILE 3:

void c_code(n,a)

int n;

float *a;

{

int i;

n =10;

for (i=0;i

a = (float) i;

}

return;

}

0 Kudos
1 Reply
IanH
Honored Contributor II
281 Views

Are you linking in the object file produced from compilation of the c file? The build log would help us diagnose. Within Visual Studio you probably need to make the Fortran project depend on the C project. Details depend on the version of Visual Studio, but right click on the fortran project and look for a Project dependencies item or similar in the resulting menu.

A better (compliant with Fortran standards and therefore more portable and robust) way of writing the interface is:

[fortran]module int_mod
IMPLICIT NONE
interface subroutine c_code(nn,a) BIND(C, NAME='c_code') USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT, C_FLOAT IMPLICIT NONE INTEGER(C_INT), INTENT(OUT) :: nn REAL(C_FLOAT), INTENT(OUT) :: a(*) end subroutine c_code end interface end module int_mod[/fortran]

Note the use of the standard INTEGER(xx) style declarations, rather than the INTEGER*xx form, the latter is a language extension. You could apply similar changes to your main program too. (If you see a red coloured REAL in the code above then that is just due to a problem with the forum software - please ignore it)

More importantly, the first argument in your c function as presented above is being taken by value, not by reference. The form of the declarations for the function arguments are also a relic of a bygone era. Consider:

[cpp]void c_code(int *n, float *a)
{
   int i;
   *n = 10;
   for (i = 0; i < *n; i ++) {
      a = (float) i;
   }
   return;
}
[/cpp]

0 Kudos
Reply