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

C/Fortran Mixed-language Environment in Visual Studio 2015

Martin__Jonathan
Beginner
1,265 Views

I'm working with some legacy code to try and compile it in an updated development environment. This project contains C code which calls on the subroutines of Fortran code in the same project. I'm using the following:

  • Visual Studio 2015 with Update 3
  • Parallel Studio 2016 with Update 3

I've verified that the Intel Compilers are recognized by Visual Studio and followed the steps described here ( https://software.intel.com/en-us/articles/configuring-visual-studio-for-mixed-language-applications/ ) to configure it for a mixed-language environment but it appears that the Fortran subroutines are not visible to the C code. For example, a .c file with the line:

extern void SETUP(void);

is in reference to a subroutine in a .f90 file in the same project:

SUBROUTINE SETUP

but Visual Studio indicates that the subroutine is not found with the message: "Function definition for 'SETUP' not found"

What is the best approach to verify Visual Studio is configured properly for mixed-language compilation and how to get the C code to recognize the Fortran?

0 Kudos
15 Replies
Steve_Lionel
Honored Contributor III
1,265 Views

Do you have both the Fortran and C code in the same project? That hasn't been supported since VS98.

If the main program is C, you'll need to do the following:

  • Add a new Fortran Static Library project to the solution with your Fortran code.
  • Right click on the C project, select Build Dependencies > Project Dependencies
  • Check the "Depends on" box for your Fortran project, click OK
  • In the C project properties, linker, Additional Dependencies, add the path to where the Fortran .lib will be placed

This last part wasn't needed in older VS versions, but Visual C++ no longer pulls in non-C++ dependent projects.

0 Kudos
Martin__Jonathan
Beginner
1,265 Views

Thanks for the guidance, the Fortran static library is being properly recognized by the C project. This resolved the errors I was experiencing for the project I was working on. However, I've moved to a similar, albeit slightly more complex, C project and have encountered a different error.

I extracted the Fortran code into its own static library project and successfully built the .lib file. After linking I build the C project and get several of the following error:

LNK2019 unresolved external symbol __imp__ELEVATION_DATA_mp_RD_ELEV_DATA referenced in function _RD_ELEV_DATA

The error indicates that the problem lies within the Fortran .lib file. Here's a snippet of one of the subroutines in question:

SUBROUTINE RD_ELEV_DATA(<parameters>)

    !DEC$ ATTRIBUTES DLLEXPORT :: RD_ELEV_DATA
    !DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'_RD_ELEV_DATA' :: RD_ELEV_DATA

    USE ELEVATION_DATA, ONLY: M_RD_ELEV_DATA => RD_ELEV_DATA

    <initialize parameters>
    CALL M_RD_ELEV_DATA (<parameters>)

END SUBROUTINE RD_ELEV_DATA

I believe the LNK2019 error is related to the 'USE ELEVATION_DATA' portion of this subroutine. There is a module named ELEVATION_DATA that exists in a separate file which contains the subroutine that is being wrapped:

MODULE ELEVATION_DATA
    ...
    PUBLIC:RD_ELEV_DATA
    ...
    SUBROUTINE RD_ELEV_DATA(<parameters>)

        CDEC$ ATTRIBUTES DLLEXPORT :: RD_ELEV_DATA
        ...
    END SUBROUTINE RD_ELEV_DATA

Why would this error appear when building the C project and not during the compilation of the Fortran library?

0 Kudos
Steve_Lionel
Honored Contributor III
1,265 Views

This is a link-time error. When you build the library, there is no linking.

Is the object file containing module ELEVATION_DATA included in the linking for the C project? I'll also note that because you DLLEXPORT the module procedure, that turns into a DLLIMPORT of the procedure where it is USEd. Normally if the linker sees a local definition of a DLLIMPORTed procedure it gives a warning but continues. The error message here suggests that the object for the module is not being seen at link time.

0 Kudos
Martin__Jonathan
Beginner
1,265 Views

Is the object file containing module ELEVATION_DATA included in the linking for the C project?

I only included the Fortran .lib file in the 'Linker -> Input -> Additional Dependencies' of the C project, no object files were explicitly linked.

 

So the problem appears to be the linking of the Fortran static library with the C project, not the building of the static library, correct?

0 Kudos
Steve_Lionel
Honored Contributor III
1,265 Views

Correct. Is the module ELEVATION_DATA in that library? It looks as if it isn't, so the linker is looking for the DLL import library from building the DLL. Speaking of that, are you building a static library or a DLL from the Fortran code?

0 Kudos
Martin__Jonathan
Beginner
1,265 Views

Is the module ELEVATION_DATA in that library?

Yes. Also, the Fortran project contains both .for and .f90 files. The ELEVATION_DATA module is in a .for file and the subroutine that USEs it is in a .f90 file.

are you building a static library or a DLL from the Fortran code?

The project containing the Fortran code is configured to build a static library

0 Kudos
Steve_Lionel
Honored Contributor III
1,265 Views

In the C project properties, go to Linker > General. For "Show Progress" set it to "Show all progress messages" and then relink the project.  Create a zip of the Debug\XXX.tlog folder (or Release\) and attach it to a reply here.

0 Kudos
Martin__Jonathan
Beginner
1,265 Views

Attached zip.

On a side note, out of curiosity in the Linker > Input > Additional Dependencies of the C project I added the .obj files produced by the Fortran project (<absolute path to Fortran Debug directory>/*.obj) and the C project successfully built.

It should not be necessary to add the object files as dependencies for the project to build, correct?

0 Kudos
Steve_Lionel
Honored Contributor III
1,265 Views

I don't understand why the link-step logs are empty. But your adding the .obj files and it working tells me that you in fact did NOT add the Fortran .lib to the C project's dependencies.

0 Kudos
Martin__Jonathan
Beginner
1,265 Views

It's possible I incorrectly linked the Fortran lib. Just for clarification, here's how I added the dependency to the C project:

  • In Linker > General > Additional Library Directories, I added a relative path to the /Debug directory of the Fortran project
  • In Linker > Input > Additional Dependencies, I simply added the name of the lib file (Elevation_FOR.lib) which resides in the /Debug directory of the Fortran project
0 Kudos
Steve_Lionel
Honored Contributor III
1,265 Views

That should have worked - were there no messages about not finding a library? I'm very puzzled that the .tlog files don't have that info. I really don't like the way MSBUILD creates log files.

0 Kudos
Martin__Jonathan
Beginner
1,265 Views

Could the issue be related to having mixed Fortran standards in the static library project? In this case, a .f90 file contains a subroutine that USEs a module from a .for file (see above code samples):

  1. ElevData.for
    1. contains the ELEVATION_DATA module
  2. ElevWrapper.f90
    1. contains the subroutine that USEs the subroutine from ELEVATION_DATA

I'm not sure if this makes sense, but is it possible that the linker is able to see the .f90 subroutine but cannot interpret the .for module/subroutine that is being USEd?

0 Kudos
mecej4
Honored Contributor III
1,265 Views

No, and in fact the file suffixes ".for" and ".f90" simply mean that the former is fixed format source and the latter free format source. They are both compiled using the same default Fortran standard. The module files depend on the content of the file and not the source format. 

If you compiled the files separately, and specified (through compiler options, etc.) that different standards should be applied to each, the outcome could be different. The linker does not even look at the .mod files. It only reads .obj, .lib and other files that are completely oblivious to whether the source code was fixed or free format.

0 Kudos
Martin__Jonathan
Beginner
1,265 Views

I understand, that makes sense. I'm still trying to figure out why the C project fails when linking to the Fortran static library but succeeds when linking directly to the Fortran .obj files.

  • Although the Fortran static library builds, could there be a linking issue within the library between .obj files?
  • Note that the C project produces a DLL and the Fortran project builds a static library. Could this be an issue when linking?
0 Kudos
mecej4
Honored Contributor III
1,265 Views

A library file is simply a collection of OBJ files with, possibly, an extended directory/dictionary added. When you specify object files for linking, normally each of them is loaded, whether the code/data in the OBJ is needed or not.

When you specify a static library, instead, each OBJ in the LIB is loaded (into the EXE or DLL that is being built) only if that OBJ is needed to supply unsatisfied references in previously loaded objects.

Some linkers may provide further optimizations such as not loading code in each OBJ file if the code in that object is not referenced in one of the other objects.

0 Kudos
Reply