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

How to make a basic mixed C++ / Fortran program

bruppel1
Beginner
1,392 Views
Hello,
I am trying to put together a proof of concept example of a mixed C++ and Fortran program. I am trying to demonstrate the ability of C++ to call a Fortran subroutine. I feel like a deer staring into headlights.

I am running Visual Fortran 11.1 and Visual C++ Express 2010.
The provided documentation in the Intel Fortran help file is pretty extensive, but I haven't found a simple step-by-step solution. I don't know C++ and the help file does not provide a complete C++ calling program in its examples.

I would really appreciate it if someone could point me to a single source of information that goes through all the required steps and settings to get a basic program running, so I can work from there.

I have the following C++ code (all of this is based on the sample but simplified or expanded as needed):


void simulation(long alpha, double *beta, long *gamma, double delta[]);

int main(int argc, char **argv)

{

long alpha; // input

double beta; // output

long gamma; // input AND output

double delta[3]; // input

// These need starting values

alpha = 0;

beta = 0.0;

gamma = 0;

delta[0] = 0.0;

delta[1] = 0.0;

delta[2] = 0.0;

simulation(alpha, β, γ, delta);

return 0;

}

And here is my Fortran:

SUBROUTINE SIMULATION(ALPHA, BETA, GAMMA, DELTA) BIND(C)

USE, INTRINSIC :: ISO_C_BINDING

IMPLICIT NONE

INTEGER (C_LONG), VALUE :: ALPHA

REAL (C_DOUBLE), INTENT(INOUT) :: BETA

INTEGER (C_LONG), INTENT(OUT) :: GAMMA

REAL (C_DOUBLE),DIMENSION(*),INTENT(IN) :: DELTA

alpha = 1

beta = 2.0

gamma = 3

!delta(1) = 1.1

!delta(2) = 2.2

!delta(3) = 3.3

END SUBROUTINE SIMULATION


I compile the C++ code in the IDE and copy the result (main.obj)into the fortran directory, as this is what the help file recommends.
Then I run:
ifort main.obj simulation.f90

I get the following result:

Intel Visual Fortran Compiler Professional for applications running on IA-32,

Version 11.1 Build 20100414 Package ID: w_cprof_p_11.1.065

Copyright (C) 1985-2010 Intel Corporation. All rights reserved.

Microsoft Incremental Linker Version 9.00.21022.08 Copyright (C) Microsoft Corporation. All rights reserved.

-out:main.exe

-subsystem:console

main.obj

simulation.obj

main.obj : warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/OPT:ICF' specification LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library main.obj : error LNK2019: unresolved external symbol "void __cdecl simulation(long,double *,long *,double * const)" (?simulation@@YAXJPANPAJQAN@Z) referenced in function _main main.exe : fatal error LNK1120: 1 unresolved externals

0 Kudos
7 Replies
Steven_L_Intel1
Employee
1,391 Views
You need 'extern "C"' before the 'void simulation' in the C++ code to prevent name mangling.

Have you looked at the two mixed Fortran-C++ samples provided with the product? See also Configuring for Mixed Languages.
0 Kudos
bruppel1
Beginner
1,391 Views
Hi Steve,
Do you mean the samples in the help files accessed through the visual studio help system? The two I found were one for when fortran is the caller, and one for when c++ is the caller. I was complaining about how the second one doesn't give a complete c++ program. The code I have posted is a simplified version of one of the samples I found in the help system.
If there are other samples somewhere, maybe those would help. A lot of what I see in the help system (and in the link you provided) seems to be for when one has both languages running in the same IDE, which I am not. The command line instructions seem to be rather simple, but I think I'm missing something since the code is not linking. I think I must have to dig into my compiling preferences, and I'm not familiar with static vs. dynamic run times, console vs library applications, and stuff like that, so instead I was hoping for a simple walkthrough somewhere.
Thanks,
Ben
0 Kudos
mecej4
Honored Contributor III
1,391 Views
My comments are restricted to building your project from the command line (with the IDE, there are so many configuration parameters that I do not want to go there).

If your C code is in cmain.c and your Fortran in fsub.f90, do

cl /MT /c cmain.c

ifort /MT fsub.f90 cmain.obj /Fecmain

You do not have to use LIBCMT.lib (the /MT option pulls in LIBCMT.lib) but, if you choose another, you need to use it for both the C and Fortran parts. Not being consistent in this regard results in Linker errors such as those that you encountered.
0 Kudos
Steven_L_Intel1
Employee
1,391 Views
Ben,

There is a Samples folder in the Intel Visual Fortran installation folder. For example, C:\Program Files\Intel\Compiler\11.1\065\Samples. Under that is an EN_US\Fortran folder for English. There you'll find a samples.htm file that lists the samples. Each set is provided as a ZIP file which you must unpack to a writable folder on your system.

In the MixedLanguage.zip are solutions C_Calls_Fortran and Fortran_Calls_C. Both are extensively commented.
0 Kudos
bruppel1
Beginner
1,391 Views

Thank you mecej4, this is exactly what I was looking for. I take it that the /MT switches tell both compilers to use compatible runtime libaries. I think this is what they are getting at in the help topic "Building Intel Fortran/C Mixed-Language Programs on Windows* Systems"

With the switch /Fecmain, the purpose is to name the output executable "cmain", right?

0 Kudos
bruppel1
Beginner
1,391 Views
Thank you Steve. It looks like the example code in that zip file takes a bit of a different approach from the example in the help files under "Interoperability with C". Perhaps this ISO_C_BINDING module is newer than the samples?

Adding "extern "C"" to the front of the function definition definitely got rid of one problem I was having, and this definitely isn't included in the sample code under "Interoperability with C", subheader "Example of C Calling Fortran", so maybe that is worth adding to the help file?

In fact, now that I have extern "C" I think the rest of everything is working. I thought I needed the /MT switches as recommended by mecej4 but it looks like the defaults work, I must have been missing a step. It looks like if I had had that "extern "C"" statement all along I wouldn't have had to panic about all the runtime library stuff, which I was having trouble understanding while on a short deadline :)
0 Kudos
IanH
Honored Contributor III
1,391 Views
If you go back to doing this through the VS environment, then note that:

  • In a VS Intel Fortran project, /MT is equivalent to having Configuration properties > Fortran > Libraries > Runtime Library set to Multithreaded.
  • In a VS2005 Microsoft cpp project, /MT is equivalent to have Configuration properties > C/C++ > Code Generation > Runtime Library set to Multi-threaded.
These are the two properties that need to be consistent (though not in hyphenation). There are two aspects - debug versus release, and statically linked versus dynamically linked, both aspects should be consistent.

Unfortunately the default value for the two languages (in the VS environment at least) is different - MS prefer to direct you towards the DLL version of the runtime library while the Fortran default is the static linked runtime library.

If you were in a debug configuration, you'd set these both to be a debug runtime library (either both debug-static or both debug-dll, /MTd or /MDd if you prefer the command line).

If you were building a DLL or an EXE that is going to be using non-"system" DLL's, then the recommendation is generally to use the DLL runtimes, to avoid problems with the executable "modules" (i.e. EXE's/DLL's, not the fortran language concept) having their own instances of the runtime library, which, if you are not careful, can cause much crisis, confusion and chaos when it comes to things like I/O and memory allocation. If you are just building a classic stand-alone application, then the decision is usually driven more by deployment considerations. (This decision, on its own, is independent of the number of languages that you are trying to glue together.)

Once you are happy that you've got things working, back in VS consider making the fortran project a static library project (ie the output of the compilation and linking of the fortran files is a lib file) and then link that static library with your C files. If the dependencies in your VS projects are set up appropriately, then VS will do this linking automatically for you. This saves you from having to separately copy/reference obj files.

Yes, /Fexxx just names the exe file. ifort /? tells you this after about 506 pages of optimisation options.

While they share much, C and C++ are different languages. One of the important areas of difference is in how they generate/treat/mangle/link with external symbols. Fortran C-interoperability (BIND(C), etal) is with C and that interoperability has a lot to do with making the external symbols line up. You said your original code was C++ (as presented it could have been compiled either way), the extern "C" is the C++ specific feature that's needed to tell the C++ compiler to treat the routine like it was a C routine (and hence be interoperable with Fortran). Having a bare "extern "C" ..." in a C source file is a syntax error.
0 Kudos
Reply