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

Linking a C++ static library (VC++ 2015) in Fortran (IVF 11.1.070)

Leopoldo_M_
Beginner
734 Views

Embedding a C++ function into a Fortran code turned out to be a real deal...

Inside my Fortran code I have to create some output files in JSON. To do that I found a C++ JSON parser that exploits some C++11 libraries. I work with VS2008 Professional integrated with IVF 11.1.070 and VC++ 2008 therefore I first tried to compile the parser with VC++ 2008 but it doesn't support C++11. So I installed VS 2015 community which includes VC++ 2015 and this allowed me to correctly compile the parser as a static library.

Since this is my first experience with mixed programming languages and I don't know exactly how to link all the necessary stuff, I started with a more rookie approach instead of directly linking the JSON parser library: I created a very simple C++ function "addition" and tried to call it from Fortran. That's the beginning of my problems...

Compiling this simple test as a static library with VC++ 2008 and mixing it with Fortran code was easy, I think that this is probably due to the same IDE. When I create the "addition" library in VS 2015 I can compile it with VC++ 2015 but when I add the file .lib to the Fortran source I got the error

"Error 1 error LNK2019: unresolved external symbol addition referenced in function MAIN_".

Does anyone have an idea how to solve this problem?

0 Kudos
12 Replies
Steven_L_Intel1
Employee
734 Views

The main program is in Fortran? I note that "addition" is in lowercase and has no decoration. How is it declared in Fortran, what compiler options did you use and is this 32-bit or 64-bit? I'll also note that the Fortran 11.1 run-time-library probably won't link with the MSVC 2015 run-time library due to Microsoft incompatibility.

0 Kudos
Leopoldo_M_
Beginner
734 Views

Yes, the main program is in Fortran and the projects are built in 64x. This is how the function is declared and used in the main program:

#################################

      USE, INTRINSIC :: iso_c_binding

      INTERFACE c_subs

        INTEGER(C_INT) FUNCTION addition(a,b) BIND(C,name='addition')
          USE, INTRINSIC :: iso_c_binding
          IMPLICIT NONE
          INTEGER(C_INT) :: a, b
        END FUNCTION addition

      END INTERFACE c_subs

      integer :: a,b,c

      a=1
      b=2
      c=addition(a,b)

#################################

This is the C++ function, compiled as a static library:

#################################

#include <stdio.h>
#include <stdlib.h>
int addition(int *a, int *b)
{
  int i,j,c;
  i=*a;
  j=*b;
  c=i+j;
  //printf("\n In addition.c : the value of c is %i\n",c);
  return i+j;
}

#################################

To include the library in the Fortran solution I just added the file lib to the project files. When the file lib is created by VC++ 2015 something goes wrong and the function is not recognized when compiling the Fortran code.

0 Kudos
mecej4
Honored Contributor III
734 Views

What is the output of running dumpbin /symbols on the .OBJ or .LIB file compiled from the C source? If that listing shows "addition" in a fashion similar to

008 00000000 SECT3  notype ()    External     | addition

check the VS build-log file to see whether the linker line is correct. If not, resolve this problem before attempting to link with Fortran code.

0 Kudos
Leopoldo_M_
Beginner
734 Views

Running dumpbin/symbols for the file .lib I see

011 00000000 SECT4  notype ()    External     | ?addition@@YAHPEAH0@Z (int __cdecl addition(int *,int *))

Sorry but I don't understand exaclty what you mean for "see whether the linker line is correct" in the log file...the log file of the static library in "detailed" mode doesn't report any "linking" word.

0 Kudos
mecej4
Honored Contributor III
734 Views

The dumpbin output tells us what we need to know: the C function name that you wanted has been given C++ decoration. You have to tell the C/C++ compiler to compile the code as C source code, not C++. 

0 Kudos
Steven_L_Intel1
Employee
734 Views

Either that or preface the function definition with:

extern "C"

0 Kudos
Leopoldo_M_
Beginner
734 Views

Thank you, now the Fortran code links correctly to the library built with VC++2015 but there is another problem; when I uncomment the printf command in "addition", build the library with VC++2015 and compile the Fortran code, such error messages appear:

Error    8     error LNK2005: _vfprintf_l already defined in addition.lib(Source.obj)    LIBCMTD.lib(vfprintf.obj)    
Error    9     error LNK2005: printf already defined in addition.lib(Source.obj)    LIBCMTD.lib(printf.obj)    
Error    10     error LNK2019: unresolved external symbol __imp___acrt_iob_func referenced in function printf    addition.lib(Source.obj)    
Error    11     error LNK2019: unresolved external symbol __imp___stdio_common_vfprintf referenced in function _vfprintf_l    addition.lib(Source.obj)

If I create the library with VC++2008 the main program is compiled without issues.

0 Kudos
mecej4
Honored Contributor III
734 Views

The error messages that you displayed are from the linker, not the compiler. Make sure that you select compatible library options when you compile the C and Fortran parts: for example, specify /libs:dll and /debug:none in both compilations.

0 Kudos
Steven_L_Intel1
Employee
734 Views

The first two errors are what mecej4 said. But the next two are almost certainly due to changes Microsoft made in Visual C++ for VS2015 - I referred to this earlier.  My guess is that you are linking this in VS2008 against the MSVC 2008 libraries. That won't work.

First thing to try is to add the paths to the VS2015 C++ libraries as "Additional library directories" in your Fortran project. You may need any and all of the following:

$(VCInstallDir)atlmfc\lib\amd64
$(VCInstallDir)lib\amd64
$(WindowsSdkDir)lib\winv6.3\um\x64
$(UniversalCRTSdkDir)lib\winv10.0\ucrt\x64
$(UniversalCRTSdkDir)Lib\$(UCRTVersion)\ucrt\x64

You will probably have to replace the $(...) with the actual path for all of these.

0 Kudos
Leopoldo_M_
Beginner
734 Views

Ok mecej4, but which are the compatible library options you said? The project properties between the Fortran and C++ codes are quite different and don't always correspond...for example when you mention "/debug:none" you mean the property that in the VS 2008 is under Configuration Properties -> Fortran -> General -> Debug Information Format -> None, and in VS 2015 for the C++ project is under Configuration Properties -> C/C++ -> General -> Debug Information Format -> None? To which property refers "/libs:dll"?

Steve, I tried to do what you suggest by adding the following additional libraries both in the intrinsic form with macros and by specifying the actual folders but it doesn't seems to have the rigth effect.

Sorry for my ignorance in this field but this is the first time I get myself into such mixed languages things!

0 Kudos
Steven_L_Intel1
Employee
734 Views

Mixed language isn't really the problem here - it's mixed versions. It most likely wouldn't even be a problem there hadn't Microsoft decided to deliberately introduce a breaking change with VS2015. (They had good reasons for this, but it is still painful.) You'd be fine if you were using the version of Intel Fortran that supports VS2015, as we've made adjustments for the Microsoft change.

When mecej4 mentioned /debug he really meant /dbglibs. This is the option that selects the "debug" version of the run-time libraries. However, you really don't need this even when debugging - what's important is that all parts of the program agree on which set of libraries are being used.

The VS2015-compiled C code MUST link to the VS2015 C run-time libraries. No way around that. However, the Fortran 11.1 static libraries won't link to the VS2015 C libraries. Here's some options:

  • Upgrade Fortran 11.0 to 16.0 (Parallel Studio XE 2016) and do everything in VS2015. This would be my first choice.
  • Change both the Fortran and C builds to specify the Multithreaded DLL non-debug libraries. Install the Intel Compiler 2016 redistributables. Link the executable against the VS2015 C libraries. (It's ok to link to the 11.1 Fortran libraries here but when you run you'll get the newer Fortran run-time DLLs that know about VS2015.)
0 Kudos
Jacob_Williams
New Contributor I
733 Views

Shameless plug: you don't need C++ to read/write JSON files from Fortran: https://github.com/jacobwilliams/json-fortran

0 Kudos
Reply