Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
186 Views

Fortran and C++ compilation

Hi Steve, hi all,

 

I am trying to compile a mixed Fortran/C++ project on Visual Studio 2017 and with Parallel Studio XE 2017 but when I try to run the compilation I have link errors (LNK2001 and LNK2019) which abort the compilation. The code I am trying to compile works because I was able to compile it with another compiler on UNIX but for my work I have to compile it with Visual Studio.

I also checked if the extern "C" was correctly defined and everything seems ok on this point.

I tried to modify a lot of options of MVS2017 but nothing happened.

I tried to add a static C++ project and to make the Fortran one dependent of the C++ project but it still doesn't work.

I was able to generate the C++ static lib, so I add it to the linker input of the Fortran project but the same errors were still there.

 

Finally, I tried to remove all the C++ file from the solution and I got exactly the same errors. So it seems that the link between Fortran and C++ is not correctly made or something on this king.

 

Is there someone who already has this issue and solved it ? If not, do you have any idea for solving this ?

 

Thank you a lot in advance,

Nicolas

0 Kudos
12 Replies
Highlighted
Honored Contributor I
186 Views

@Nicholas:

See this thread, Quote #6 with an example as well as a zip file attachment that I know to work alright on several Windows environments:

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/699941

You can try it out; if you run into issues, check your installation with the following info: https://software.intel.com/en-us/articles/intel-visual-fortran-composer-xe-information-and-frequently-asked-questions

 

0 Kudos
Highlighted
Beginner
186 Views

Hi FortranFan,

 

First thank you a lot for your answer. Unfortunatly, I already test the solutions presented in the links you gave to me. Moreover, as I told before, I was able to compile the application on UNIX with gcc/g++ and pgf90 which meens there is no need to modify the source code to compile it.

Actually, I found an option in the Fortran properties which allows to modify the way that external procedures are read. So I put the convention that is used (C,REFERENCE with Lower case and Append underscore option on) in my code.

 

But now I have another LINK2019 error (unresolved symbol) with iargc_ etime_ signal_ and getenv_ . These functions are defined as external in the Fortran file but are not defined in my c++ files. I guess they are commun functions of Fortran.

So I am wondering if I need to use the option "Append undersocre" or not. If yes do you have any oidea to solve the link error ?

 

Thank you a lot in advance,

Nicolas

 

0 Kudos
Highlighted
Black Belt
186 Views

A number of functions/subroutines in the category (3f) in Unix/Linux (for example, see https://docs.oracle.com/cd/E37069_01/html/E54439/getenv-3f.html ) are not standard Fortran routines, but are wrappers for similar (and similarly named) routines in the C library or the OS utilities. When porting Fortran code from one OS to another, you have to use a "portability" library, if provided, replace some of the calls to other routines with similar functionality, if available, or contend with unavailability.

As far as such routines are concerned, it is incorrect to believe that  "I was able to compile the application on UNIX with gcc/g++ and pgf90 which means there is no need to modify the source code to compile it".

Such inconveniences are not peculiar to Fortran. For instance, note that the C library functions radixsort() and mergesort() (see https://linux.die.net/man/3/mergesort ) may not be available on some platforms (e.g., GCC on Cygwin).

0 Kudos
Highlighted
Black Belt
186 Views

You may have checked this by now, but you must actually look at the link errors to see if they are the result of name mangling in your procedures which will differ between linux and windows.  The preferred way to fix those is to decorate with bind(C,NAME='what your C expects')  as well as extern "C" (what your Fortran expects).  If you introduce stdcall (or the CVF version of it) on either side, you must deal with those issues.  Viewing object file linkages will be necessary if you don't use bind(c).

0 Kudos
Highlighted
Honored Contributor I
186 Views

Dray, Nicolas wrote:

..as I told before, I was able to compile the application on UNIX with gcc/g++ and pgf90 which meens there is no need to modify the source code to compile it.

.. I put the convention that is used (C,REFERENCE with Lower case and Append underscore option on) in my code.

 

But now I have another LINK2019 error (unresolved symbol) with iargc_ etime_ signal_ and getenv_ . These functions are defined as external in the Fortran file but are not defined in my c++ files. I guess they are commun functions of Fortran.

So I am wondering if I need to use the option "Append undersocre" or not. If yes do you have any oidea to solve the link error ? ..

@Nicholas,

One of the points you should take note from Quote #6 of that thread (https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/699941) is illustration, in that quote you are shown the exact C++ and Fortran code. how the Fortran code makes use of standard facilities to avoid the problems and issues with name-mangling (prefix or suffix underscore(s), etc.), how one can setup Microsoft Visual Studio IDE with C++ and Fortran solutions, and so forth.

Whereas you do not show any relevant details of your issue, saying it works on Unix means little.  If you can share a reproducer with code and Visual Studio details, other more knowledgeable readers might be able to help.

0 Kudos
Highlighted
186 Views

Sometimes to shed light on the issue of naming difference (if you avoid following the guidelines as referenced in FortranFan's post #6) is to, on both the Fortran compilation and C/C++ compilation, is to generate assembler code with source listing, Then look at the names used by the call-er and the call-ee.

It might also help for you to build the example in the illustration in FortranFan's post #6 with the  generate assembler code with source listing to compare the symbols use by the call-er and call-ee. This may give you a better understanding of what is happening.

Jim Dempsey

0 Kudos
Highlighted
Beginner
186 Views

Hi all,

 

First of all, thank you for all your answers.

Mecej4 and FortranFan, now I understand that compiling on UNIX is not meaningful in this context.

FortranFan I understand that the quote #6 is an illustration but I prefere not to modify the code I am trying to compile because first I don't know the Fortran programming (and don't have enough time to learn it). Moreover, I can't show you the source code due to confidentiality of this program but I can tell you that it is concived in such way that it is compatible with both UNIX and Windows. Actually, I am able to compile it with the script which is provided with the sources on Windows but it only create an .exe file and I need to have a compiling project in order to modify some part of the code.

 

Tim P. and FortranFan, I don't know if this is due to binding in name but I tried all the options which are available in Visual Studio for Calling Convention (cref, stdref, stdcall and cvf). I put the name case interpretation as Lower case as the name of my methods are lower case.

In the source code, I have this kind of line "!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'_mymethod_' :: mymethod" , so I assumed the cref option with append underscore option on too. Anyway, in all the cases of calling convention the code doesn't compile.

With the option cref and append underscore I have four LNK2019 error that says "external symbol not resolved mymethod_ in the function myfunction_ "

With the option cref and no append underscore I have a LNK2019 error that says "external symbol not resolved mymethod in the function myfunction " and also a LNK2001 error that says "external symbol not resolved mymethod".

In the second case, I have more error than in the first case but I think it doesn't mean a lot.

 

Finally, jimdempseyatthecove I tried to do what you suggested but there are a lot of source files in this code and I was not able to understand all the output files that were created.

 

I hope the details I gave to you will explain more the issue I am encountering and will allow you to give me more precise advices. In any case I thank all of you a lot for your help so far.

 

Best regards,

Nicolas

0 Kudos
Highlighted
Honored Contributor I
186 Views

Dray, Nicolas wrote:

..

In the source code, I have this kind of line "!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'_mymethod_' :: mymethod" , so I assumed the cref option with append underscore option on too. Anyway, in all the cases of calling convention the code doesn't compile.

With the option cref and append underscore I have four LNK2019 error that says "external symbol not resolved mymethod_ in the function myfunction_ "

With the option cref and no append underscore I have a LNK2019 error that says "external symbol not resolved mymethod in the function myfunction " and also a LNK2001 error that says "external symbol not resolved mymethod".

In the second case, I have more error than in the first case but I think it doesn't mean a lot. ..

@Nicholas,

Is it possible for you to share some basic details re: your program?

  1. Which language is the main program?  Fortran?  There is a C++ (static) library, correct?
  2. Is there a function in C++ called by Fortran?  Or a FUNCTION/SUBROUTINE in Fortran called by C++?  Or both?
  3. One would presume there is 'extern C' declaration coming into play in C++  code toward interoperation with Fortran stuff - can you confirm?
  4. With respect to question 2 above and with the function(s) coming into play in the two language environments, can you indicate the nature of function parameters (dummy arguments per Fortran terminology)?  That is, are they floating point (double/float per C++) and/or integer (int/long ?) and/or string/character and or void *?  Are there arrays?  Any general information you can share will help.
  5. And with function parameters, can you indicate what happens in C++?  That is, are some 'const' qualified meaning not changed in C++ but are there other which get defined in C++?
0 Kudos
Highlighted
Beginner
186 Views

Dear FortranFan,

 

Yes the the main program is in Fortran an I both created a c++ lib and a project which the Fortran application is dependent on.

Only the C++ function are called by the Fortran.

Yes the call is made with an extern "C" command.

The arguments are int and double in C++ and real and integer in Fortran. There are no const in the C++ part.

 

Thank you a lot in advance,

Best regards,

Nicolas

 

0 Kudos
Highlighted
Honored Contributor I
186 Views

Dray, Nicolas wrote:

.. the main program is in Fortran an I both created a c++ lib and a project which the Fortran application is dependent on.

Only the C++ function are called by the Fortran.

Yes the call is made with an extern "C" command.

The arguments are int and double in C++ and real and integer in Fortran. There are no const in the C++ part. ..

@Nicholas,

Based on your descriptions in your latest comment as well as the original post, one can only venture a guess your code is along the following lines:

C++ example:

#include <iostream>
using namespace std;

extern "C" {

   // Prototype for a function with extern attribute 
   void mymethod(int& i, double& d);

}

void mymethod(int&i, double& d)
{

   cout << "In C++: mymethod" << endl;
   cout << "i = " << i << endl;
   cout << "d = " << d << endl;

   i++;
   d = d + 2.0;
}

Fortran main program:

   implicit none
   
   interface
   
      subroutine mymethod(i, d)
      !DEC$ ATTRIBUTES C, REFERENCE :: mymethod
      
         implicit none
         
         !.. Argument list
         integer, intent(inout) :: i
         real(8), intent(inout) :: d
      
      end subroutine mymethod
         
   end interface

   integer :: i
   real(8) :: d
   
   i = 0
   d = 0D0

   call mymethod(i, d)
   print *, "In Fortran main: after call to mymethod"
   print *, "i = ", i
   print *, "d = ", d

   stop

end

With above, see the command line steps below - try them out exactly as shown and see if you get the same response.  If you do, you can apply the same in your actual project and see if that works.  Note the $DEC$ ATTRIBUTES line where no ALIAS is brought into play i.e., it is left at the default given the 'C, REFERENCE' option.  For your convenience, attached is a zip file with Visual Studio projects and a solution: note the 'External Procedures' section in the Fortran project in Visual IDE: it's left at default as well.  Basically, the !DEC$ compiler directive is setup to do the work.

C:\Temp>type c++.cpp
#include <iostream>
using namespace std;

extern "C" {

   // Prototype for a function with extern attribute
   void mymethod(int& i, double& d);

}

void mymethod(int&i, double& d)
{

   cout << "In C++: mymethod" << endl;
   cout << "i = " << i << endl;
   cout << "d = " << d << endl;

   i++;
   d = d + 2.0;
}

C:\Temp>cl /c /EHsc /W3 /MT c++.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

c++.cpp

C:\Temp>lib c++.obj /OUT:libcpp.lib
Microsoft (R) Library Manager Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>type p.f90
   implicit none

   interface

      subroutine mymethod(i, d)
      !DEC$ ATTRIBUTES C, REFERENCE :: mymethod

         implicit none

         !.. Argument list
         integer, intent(inout) :: i
         real(8), intent(inout) :: d

      end subroutine mymethod

   end interface

   integer :: i
   real(8) :: d

   i = 0
   d = 0D0

   call mymethod(i, d)
   print *, "In Fortran main: after call to mymethod"
   print *, "i = ", i
   print *, "d = ", d

   stop

end

C:\Temp>ifort /c /warn:all p.f90
Intel(R) Visual Fortran Compiler for applications running on IA-32, Version 17.0.4.210 Build 20170411
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>link p.obj libcpp.lib /subsystem:console /out:p.exe
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>p.exe
In C++: mymethod
i = 0
d = 0
 In Fortran main: after call to mymethod
 i =            1
 d =    2.00000000000000

C:\Temp>

 

0 Kudos
Highlighted
New Contributor II
186 Views

That's a useful example, FortranFan.

Why the "stop" statement?

0 Kudos
Highlighted
Honored Contributor I
186 Views

gib wrote:

.. Why the "stop" statement?

STOP is optional, as you may know.  The above example includes it as a "left-over" instruction from another case I had which included a couple of ERROR STOP statements with non-zero codes and a STOP with zero value for the stop-code.

0 Kudos