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

Calling a Fortran function from C in VS 2019

Latorre__Vittorio
1,501 Views

Dear all,

I am trying to create a program that calls from C a function written in Fortran in visual studio 2019 using the fortran compiler included in intel parallel studio 2019.

I am trying the simplest program: just a main function in C that calls the "Hello World" function in Fortran:

// main.cpp

int main(){
   hellof();
}

where hellof() is the only function in a fortran library added to the solution:

!source.f90

subroutine hellof()
    
    write(*,*) "Hello World!!!"
    
end subroutine hellof

I have compiled the Fortran code and added the path of the .lib file to the C project properties > linker > Additional Dependencies.

I have also checked the box for the Fortran library in the Build Dependencies > Project Dependencies.

Howerver I get the identifier not found error during the building of the entire solution.

I also tried the procedure on the page:

https://software.intel.com/en-us/articles/configuring-visual-studio-for-mixed-language-applications/

however there is no configuration instructions for VS 2019, so I am not sure if the problem lies here.

Do you have any suggestions/solutions?

 

0 Kudos
10 Replies
gib
New Contributor II
1,501 Views

What C compiler are you using?

0 Kudos
mecej4
Honored Contributor III
1,501 Views

External names are decorated differently in C and Fortran. If you give your C file to have a .c suffix, and change hellof to HELLOF, the decorated names will match (on Windows, x64 target, using the Intel or MS C compiler).

If you want the interoperability to be portable, you may use the Fortran intrinsic module ISO_C_BINDING . See Chapter 15 of the Fortran 2018 Standard.

0 Kudos
Steve_Lionel
Honored Contributor III
1,501 Views

The partial correct solution is to add BIND(C) after the subroutine declaration. For example:

subroutine hellof() bind(C)

This will make the name match what your C code is looking for. (mecej4's mention of the ISO_C_BINDING is not directly relevant, though it has definitions you may find useful as you progress.)

However... since you have named the file with a .cpp file type, C++ rules apply and the name will be "mangled". The easiest solution to this is to rename the file to be main.c. If you don't want to do that, you will need to add a prototype for hellof preceded by 'extern "C"'

The instructions for configuring VS2019 are the same as for VS2017. You also need to make sure that the object library created by the Fortran project is included when the C project is linked. Unfortunately, setting the dependent project is no longer sufficient for that, due to changes on the Microsoft Visual C++ side. Instead you will need to either add the Fortran .lib as a "source file" to the C project, or use the Linker property page to specify the path to the .LIB and name the .LIB in External Dependencies.

0 Kudos
Latorre__Vittorio
1,501 Views

gib wrote:

What C compiler are you using?

The standard compiler for Visual studio 2019

 

0 Kudos
Latorre__Vittorio
1,501 Views

Steve Lionel (Ret.) (Blackbelt) wrote:

The partial correct solution is to add BIND(C) after the subroutine declaration. For example:

subroutine hellof() bind(C)

This will make the name match what your C code is looking for. (mecej4's mention of the ISO_C_BINDING is not directly relevant, though it has definitions you may find useful as you progress.)

However... since you have named the file with a .cpp file type, C++ rules apply and the name will be "mangled". The easiest solution to this is to rename the file to be main.c. If you don't want to do that, you will need to add a prototype for hellof preceded by 'extern "C"'

The instructions for configuring VS2019 are the same as for VS2017. You also need to make sure that the object library created by the Fortran project is included when the C project is linked. Unfortunately, setting the dependent project is no longer sufficient for that, due to changes on the Microsoft Visual C++ side. Instead you will need to either add the Fortran .lib as a "source file" to the C project, or use the Linker property page to specify the path to the .LIB and name the .LIB in External Dependencies.

I made the following changes:

.f90
subroutine HELLOF() bind(C)
    write(*,*) "Hello World!!!"    
end subroutine HELLOF 

Changed the .cpp file into a .c file and wrote:

int main(){
	HELLOF();
}

So no "mangling" from c++.

I  checked several times:

1) The VC++ directory under the property manager for the include directories and library directories;

2) The building proprieties for the main_c project, checking that it would depend on the fortran_library.

Then I:

3) Added the build folder of the fortran_library to property> linker> additional library directory of the main_c project.

It did not work. Then I tried:

4)Remove the build folder of the fortran_library from property> linker> additional library directory of the main_c project and add the fortran_library.lib file in the source files of the main_c project.

It did not work. Then I tried both point 3) and 4) together and it did not work.

In all cases it gave me the LNK2019 unresolved external symbol problem.

5) Then I tried to use the command prompt from Visual Studio and used the "cl" command on the .c file and the .lib file together and got the LNK2019 error again.

Then I thought that maybe the HELLOF() method was not in the .lib file and used the "dumpbin /symbols" command on the library and obtained:

File Type: LIBRARY

COFF SYMBOL TABLE
000 00000000 SECT1  notype       Static       | .text
    Section length   84, #relocs    6, #linenums    0, checksum        0
002 00000000 SECT1  notype ()    External     | _hellof
003 00000000 SECT2  notype       Static       | .debug$S
    Section length  37C, #relocs    4, #linenums    0, checksum        0
005 00000000 SECT6  notype       Static       | .debug$T
    Section length   60, #relocs    0, #linenums    0, checksum        0
007 00000000 SECT3  notype       Static       | .rdata
    Section length   68, #relocs    4, #linenums    0, checksum        0
009 00000000 SECT3  notype       Static       | __STRLITPACK_1
00A 00000000 UNDEF  notype ()    External     | _for_write_seq_lis
00B 00000000 UNDEF  notype ()    External     | @_RTC_CheckStackVars@8
00C 00000000 UNDEF  notype ()    External     | __RTC_CheckEsp
00D 00000048 SECT3  notype       Static       | __STRLITPACK_3
00E 00000050 SECT3  notype       Static       | __STRLITPACK_0
00F 00000058 SECT3  notype       Static       | __STRLITPACK_2
010 00000000 SECT4  notype       Static       | .drectve
    Section length   BE, #relocs    0, #linenums    0, checksum        0
012 00000000 SECT5  notype       Static       | .trace
    Section length   70, #relocs    2, #linenums    0, checksum        0
014 00000001 ABS    notype       Static       | @feat.00

String Table Size = 0x79 bytes

  Summary

         37C .debug$S
          60 .debug$T
          BE .drectve
          68 .rdata
          84 .text
          70 .trace

As you can see, hellof() is there, but there is no way for the compiler to see it.

 

To be honest I do not know what to do at this point.

0 Kudos
Steve_Lionel
Honored Contributor III
1,501 Views

Change the name of the routine to hellof (at least in the C code, but it makes sense to do it in Fortran as well.) The BIND(C) downcases the routine name, as shown in the dump.

0 Kudos
Latorre__Vittorio
1,501 Views

Steve Lionel (Ret.) (Blackbelt) wrote:

Change the name of the routine to hellof (at least in the C code, but it makes sense to do it in Fortran as well.) The BIND(C) downcases the routine name, as shown in the dump.

I thought that C was not case sensitive.

Anyway, should I also add the underscore symbol "_" before the function name in the .c file?

0 Kudos
Steve_Lionel
Honored Contributor III
1,501 Views

C is case-sensitive, Fortran is not. Do not add the underscore - that's platform-specific decoration and the compilers will add it automatically.

0 Kudos
Latorre__Vittorio
1,501 Views

Steve Lionel (Ret.) (Blackbelt) wrote:

C is case-sensitive, Fortran is not. Do not add the underscore - that's platform-specific decoration and the compilers will add it automatically.

Ok, I probably got confused between C and Fortran.

Anyway, I changed to lower cases in the .c program and now it works, but only if I add the Fortran library in the source files. If I add the library folder in the additional libraries under the linker, it does not find the subroutine.

In any case now it works, so thank you very much for your suggestions.

 

V.

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,501 Views

It's not sufficient to add the folder, you also have to give the name of the .lib under Additional Dependencies.

0 Kudos
Reply