[Mixed F77/C++] Worked in VS2008 + IVF 10.1, doesn't work in VS2012 + IVF 13. Why?

[Mixed F77/C++] Worked in VS2008 + IVF 10.1, doesn't work in VS2012 + IVF 13. Why?

Hello,

I have this code:

C++ (file main.cpp):

#include <iostream>

#include <vector>

#include <string>

#pragma pack(2)

using namespace std;

extern "C"

{

   struct { double d1; int i1; float f1; double vector[666]; double matrix[4*5]; } THE_COMMON;

   void WRITE_FROM_COMMON();

}

int main(int argc, char* argv[])

{

   THE_COMMON.d1 = 666.666;

   THE_COMMON.i1 = 666;

   THE_COMMON.f1 = 0.666;

   for (size_t i = 0; i < THE_COMMON.i1; ++i)

      THE_COMMON.vector[i] = (double)(i + 1);

  

   for (size_t j = 0; j < 5; ++j)

   {

      for (size_t i = 0; i < 4; ++i)

         THE_COMMON.matrix[j*4 + i] = i*j;

   }

  

   WRITE_FROM_COMMON();

   return 0;

}

F77 (file Source1.FOR):

      subroutine WRITE_FROM_COMMON

C

      implicit none

      real*8 d1

      integer*4 i1

      real*4 f1

      real*8 vector(666)

      real*8 matrix(4,5)

      common /the_common/ d1, i1, f1, vector, matrix

C

      write(*,*) 'Double d1 = ', d1

      write(*,*) 'Integer i1 = ', i1

      write(*,*) 'Float f1 = ', f1

      write(*,*) 'vector = ', vector

      write(*,*) 'matrix = ', matrix

      return

      end

Now, this compiles (and works) fine in VS2008 Pro + IVF 10.1 I have at work.

Then I tried to do the same in VS2012 Pro with the trial version of Intel Fortran Composer XE 2013 (or however it is called), and I get the following link time error:

error LNK2001: unresolved external symbol _WRITE_FROM_COMMON in main.obj

I disassembled the .obj files generated by the compilers, and in both (Source1.obj and main.obj) there is a function called _WRITE_FROM_COMMON, declared as external in the C++ obj file. Then why can't the linker resolve the call? And why did it work in previous versions?? I didn't change the compiler options (Default calling convention for F77, which results in appending an underscore just like __cdecl does for C++; and the function doesn't take any argument so it couldn't be any simpler). Of course I have set the dependency of my C++ project onto the F77 project (of type static library).

Thanks in advance,

Andrea

6 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

I think you need to do more than just set the project dependencies with the newer versions of Visual Studio, you need to also explicitly list the Fortran library that you build in the linker properties for the C++ project.  This is discussed in the release notes for the current compiler versions under section 3.6.2. 

You can get the release notes from http://software.intel.com/en-us/articles/intel-fortran-composer-xe-2013-....

If you do stick with the newer compiler, you should familiarise yourself with Fortran 2003's C interoperability feature.

Quote:

IanH wrote:

I think you need to do more than just set the project dependencies with the newer versions of Visual Studio, you need to also explicitly list the Fortran library that you build in the linker properties for the C++ project.  This is discussed in the release notes for the current compiler versions under section 3.6.2. 

You can get the release notes from http://software.intel.com/en-us/articles/intel-fortran-composer-xe-2013-....

If you do stick with the newer compiler, you should familiarise yourself with Fortran 2003's C interoperability feature.

Thanks, I'll have a read at that.

And I knew someone would come up with the BIND(C) stuff :D I read about it but I don't feel like it's very much needed in my small projects, so I don't think studying that new syntax is worth the time. I've been learning a lot about mixing F and C++ lately, and I've learnt about calling conventions, compiler options and stuff...I think that will suffice for me, for the moment.

Quote:

Andrea B. wrote:

...

And I knew someone would come up with the BIND(C) stuff :D I read about it but I don't feel like it's very much needed in my small projects, so I don't think studying that new syntax is worth the time. I've been learning a lot about mixing F and C++ lately, and I've learnt about calling conventions, compiler options and stuff...I think that will suffice for me, for the moment.

Each to their own.  But to me the cost of learning the additional syntax and associated language rules is a trivial inconvenience relative to the robustness and portability benefits associated with the feature, even for small projects.

Andrea,

I built your example code using the Intel compilers from the command line and, as expected, the code gets built and runs fine when targeting IA-32 as well as X64 on Windows 8. Therefore, any linker errors that you encountered are caused by incorrect/incomplete project settings in Visual Studio. You can look at the linking command that VS shows you and/or attach the build log file to a post in this forum to help establish why the linking failed.

Though your test program may now work, there is an additional factor for you to keep in mind when building your finished application.

In your test C++ code you had #pragma pack(2) in effect when the struct for the FORTRAN COMMON was declared. Had you had any odd byte numbered variables/fields you may or may not have had issues depending on how the packing preference was used in the FORTRAN program. It is your responsibility to assure these rules for both C++ anf FORTRAN procuce the same memory layouts. See !DEC$ PACK... and/or SEQUENCE and/or -align command line option.

Jim Dempsey

www.quickthreadprogramming.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today