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

Troubles linking with mixed language in Visual Studio 2008

patkins
Beginner
636 Views

I am trying to compile a project with C++ and Fortran codes using the Intel C++ and Fortran compilers (10.01.025) in Visual Studio 2008. I have been able to compile and run this code in Linux using the Intel Linux compilers and I had previously compiled this code in Visual Studio 6.0 with CVF. When I try to compile my code, the linker returns the error messages:

2>Compiling with Intel C++ 10.1.025 [IA-32]... (Intel C++ Environment)
2>FunctionValues.cpp
2>timer.cpp
2>GenLayGreenMain.cpp
2>GenLayeredGreens.cpp
2>Linking... (Intel C++ Environment)
2>xilink: executing 'link'
2>GenLayeredGreens.obj : error LNK2019: unresolved external symbol _cbesselj_dblwrap_ referenced in function "public: void __thiscall GenLayeredGreens::Bess0(class std::complex)" (?Bess0@GenLayeredGreens@@QAEXV?$complex@N@std@@@Z)
2>GenLayeredGreens.obj : error LNK2019: unresolved external symbol _cbesselh_dblwrap_ referenced in function "public: void __thiscall GenLayeredGreens::Hankl0(class std::complex)" (?Hankl0@GenLayeredGreens@@QAEXV?$complex@N@std@@@Z)
2>GenLayeredGreens.obj : error LNK2019: unresolved external symbol _d1mach_ referenced in function "public: void __thiscall GenLayeredGreens::Qk21(class std::complex (__thiscall GenLayeredGreens::*)(class FunctionValues *,class std::complex),class std::complex,class std::complex,class std::complex &,double &,double &,double &)" (?Qk21@GenLayeredGreens@@QAEXP81@AE?AV?$complex@N@std@@PAVFunctionValues@@V23@@Z11AAV23@AAN44@Z)
2>C:\Code\InterpretGreen\Debug/InterpretGreen.exe : fatal error LNK1120: 3 unresolved externals
2>Build log was saved at "file://C:\Code\InterpretGreen\InterpretGreen\Debug\BuildLog.htm"
2>InterpretGreen - 4 error(s), 0 warning(s)

Per my searches of the forums I have created an empty C++ project where I placed my C++ files and I added to this solution a Static Library Fortran project where I placed the Fortran files. I set the project dependencies such that the C++ was dependent upon the Fortran project with the Fortran project compiling first. Judging by the command line text, it looks like the Fortran library is being referenced to the linker. I did extern C the relevant Fortran subroutines in my C++ code using:

#ifdef WIN32
#define cbesselj_dblwrap_ CBESSELJ_DBLWRAP
#define cbesselh_dblwrap_ CBESSELH_DBLWRAP
#define d1mach_ D1MACH
extern "C" {
void __stdcall cbesselj_dblwrap_(Dcmplx *cX, int *NOrder, Dcmplx *Ret);
void __stdcall cbesselh_dblwrap_(Dcmplx *cX, int *NOrder, Dcmplx *Ret);
double __stdcall d1mach_(int *I);
}
#else
extern "C" {
void cbesselj_dblwrap_(Dcmplx *cX, int *NOrder, Dcmplx *Ret);
void cbesselh_dblwrap_(Dcmplx *cX, int *NOrder, Dcmplx *Ret);
double d1mach_(int *I);
}
#endif

0 Kudos
1 Solution
Steven_L_Intel1
Employee
636 Views

Ok, progress. You need to do the following:

1. From Control Panel > Add or Remove Programs, select Microsoft Visual Studio 2005 (or 2008) > Change/Remove. The Visual Studio Maintenance Mode window will appear. Click Next.

2. Click Add or Remove Features

3. Under Select features to install, expand Language Tools > Visual C++

4. If the box X64 Compiler and Tools is not checked, check it, then click Update. If the box is already checked, click Cancel.

5. In Tools > Options > Projects > VC++ Directories, select Platform x64. Then for Library files, add the line:

$(IFORT_COMPILER10)em64tlib

6. You have to set the run-time library type of the C++ and Fortran projects to be consistent. C++ defaults to "debug multithreaded DLL" whereas Fortran defaults to "debug multithreaded" (static). Choose one to change to match the other. In C++, this is under Code Generation, in Fortran under Libraries.

View solution in original post

0 Kudos
9 Replies
TimP
Honored Contributor III
636 Views

I suppose you are using 32-bit Windows, so you could use ifort /iface:cvf. If you have no reason to use that option, you would omit the __stdcall in the C definitions.

0 Kudos
patkins
Beginner
636 Views
Quoting - tim18

I suppose you are using 32-bit Windows, so you could use ifort /iface:cvf. If you have no reason to use that option, you would omit the __stdcall in the C definitions.


I am running 64-bit Vista. The fact that VS is using the 32 bit compilers as opposed to the 64 bit compilers is a point of minor concern but I have not figured out how to change that yet. For the most part it is not necessary since there is nothing in the code that would benefit from the larger address space. So compiling using the four combinations of including and/or excluding the __stdcall in the C definitions and the /iface:cvf in the Fortran compiler command line does not solve or change the compiler error. I am not familiar with Fortran and so I have based the C definitions on the few examples of multi language code that I found on the web. What __stdcall does I do not know but it was always in the examples that I found.

0 Kudos
Steven_L_Intel1
Employee
636 Views

The examples you found assumed use of Compaq Visual Fortran (or Microsoft Fortran PowerStation of a decade ago) which defaulted to the STDCALL mechanism.

I am somewhat confused here as I would have expected the undefined names to be uppercase and with an @n suffix. Perhaps the ifdef is not being honored or WIN32 is not defined? I agree with the suggestion to remove the __stdcall.

If you want to use the 64-bit compilers, select Build > Configuration Manager. Create a new configuration "x64" copied from Win32.

0 Kudos
patkins
Beginner
636 Views

The examples you found assumed use of Compaq Visual Fortran (or Microsoft Fortran PowerStation of a decade ago) which defaulted to the STDCALL mechanism.

I am somewhat confused here as I would have expected the undefined names to be uppercase and with an @n suffix. Perhaps the ifdef is not being honored or WIN32 is not defined? I agree with the suggestion to remove the __stdcall.

If you want to use the 64-bit compilers, select Build > Configuration Manager. Create a new configuration "x64" copied from Win32.

I think that did something. I had removed the ifdef statement before, thinking the same thing, but not knowing to remove the __stdcall it did not work at the time. The new error messages that I get from the linker are:

2>Linking... (Intel C++ Environment)
2>xilink: executing 'link'
2>LIBCMTD.lib(dbgheap.obj) : error LNK2005: __CrtSetCheckCount already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(crt0dat.obj) : error LNK2005: _exit already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __exit already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __cexit already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __amsg_exit already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __initterm_e already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(invarg.obj) : error LNK2005: __invoke_watson already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(tidtable.obj) : error LNK2005: __encode_pointer already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(tidtable.obj) : error LNK2005: __decode_pointer already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(setlocal.obj) : error LNK2005: __configthreadlocale already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(dbghook.obj) : error LNK2005: __crt_debugger_hook already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(winxfltr.obj) : error LNK2005: __XcptFilter already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xi_a already defined in MSVCRTD.lib(cinitexe.obj)
2>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xi_z already defined in MSVCRTD.lib(cinitexe.obj)
2>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xc_a already defined in MSVCRTD.lib(cinitexe.obj)
2>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xc_z already defined in MSVCRTD.lib(cinitexe.obj)
2>LIBCMTD.lib(hooks.obj) : error LNK2005: "void __cdecl terminate(void)" (?terminate@@YAXXZ) already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(mlock.obj) : error LNK2005: __lock already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(mlock.obj) : error LNK2005: __unlock already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(crt0.obj) : error LNK2005: _mainCRTStartup already defined in MSVCRTD.lib(crtexe.obj)
2>LIBCMTD.lib(errmode.obj) : error LNK2005: ___set_app_type already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(_trnsctrl_.obj) : error LNK2005: ___CxxFrameHandler already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(atox.obj) : error LNK2005: _atoi already defined in MSVCRTD.lib(MSVCR90D.dll)
2>LIBCMTD.lib(dbgrptw.obj) : error LNK2005: __CrtDbgReportW already defined in MSVCRTD.lib(MSVCR90D.dll)
2>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
2>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
2>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
2>LINK : warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of other libs; use /NODEFAULTLIB:library
2>besselfunct.lib(zbinu.obj) : error LNK2019: unresolved external symbol _ZMLRI referenced in function _ZBINU
2>besselfunct.lib(zacai.obj) : error LNK2001: unresolved external symbol _ZMLRI

The last two I know are due to the fact that I did not compile the zmlri.f, I get the compiler error in that one saying:

Error: The type of the function reference does not match the type of the function definition. [ZZABS]

For the line in zmlri.f, AZ = ZZABS(ZR,ZI), in:

DOUBLE PRECISION ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI,
* CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, FNU, PTI, PTR, P1I,
* P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI,
* SUMR, TFNF, TOL, TST, YI, YR, ZEROI, ZEROR, ZI, ZR, DGAMLN,
* D1MACH, ZABS
INTEGER I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, KODE, M, N, NZ
DIMENSION YR(N), YI(N)
DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 /
SCLE = D1MACH(1)/TOL
NZ=0
AZ = ZZABS(ZR,ZI)

The relevant header to ZZABS is:

DOUBLE PRECISION FUNCTION ZZABS(ZR, ZI)
C***BEGIN PROLOGUE ZABS
C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY
C
C ZABS COMPUTES THE ABSOLUTE VALUE OR MAGNITUDE OF A DOUBLE
C PRECISION COMPLEX VARIABLE CMPLX(ZR,ZI)
C
C***ROUTINES CALLED (NONE)
C***END PROLOGUE ZABS
DOUBLE PRECISION ZR, ZI, U, V, Q, S

As far as I can tell everything there is kosher (compiles with the Linux ifort). The other new errors I am not sure on. In the VC++ Directories I added the path for the IA32 Fortran libraries in the Library Files, I recall seeing that as a common answer in similar threads. That produces the aforementioned errors. Removing that reference creates the lnking error:

2>LINK : fatal error LNK1104: cannot open file 'ifconsol.lib'

So I assume that including the path was the correct thing to do. In regards to the 64-bit. I have tried adding the "x64" platform in the Configuration Manager. I can add the x86 Platform, copying Win32, but I get an error saying that the "Intel Fortran COmpiler for 'x64' not installed. I cannot find the option for "x64" for the C++ platfom. The Intell 64 bit C++ compiler is installed because I can see an EM64T directory in the Intel compiler folders. I also double checked that I had grabbed the "w_fc_p_10.1.025_novsppe.exe" version of the Fortran compiler and I have tried reinstalling it without effect.

0 Kudos
TimP
Honored Contributor III
636 Views

You can't mix 32- and 64-bit compilation and libraries. In order for the 64-bit ifort installation to work, you must first have installed the x64 option under the c++ option in Visual Studio installation. The fact that ifort 64-bit is present in the em64t directory doesn't bear on the presence or absence of the required amd64 components in the VC installation.

0 Kudos
Steven_L_Intel1
Employee
637 Views

Ok, progress. You need to do the following:

1. From Control Panel > Add or Remove Programs, select Microsoft Visual Studio 2005 (or 2008) > Change/Remove. The Visual Studio Maintenance Mode window will appear. Click Next.

2. Click Add or Remove Features

3. Under Select features to install, expand Language Tools > Visual C++

4. If the box X64 Compiler and Tools is not checked, check it, then click Update. If the box is already checked, click Cancel.

5. In Tools > Options > Projects > VC++ Directories, select Platform x64. Then for Library files, add the line:

$(IFORT_COMPILER10)em64tlib

6. You have to set the run-time library type of the C++ and Fortran projects to be consistent. C++ defaults to "debug multithreaded DLL" whereas Fortran defaults to "debug multithreaded" (static). Choose one to change to match the other. In C++, this is under Code Generation, in Fortran under Libraries.

0 Kudos
Steve_Nuchia
New Contributor I
636 Views
The examples that ship with the Intel compiler are quite helpful here. See for instance

C:Program Files (x86)IntelCompilerFortran10.1.025samplesMixedLanguageC_calls_Fortran
It's in the form of a complet Visual Studio solution. Even if it doesn't quite match your needs you can start out from a working setup and chnage one thing at a time and maybe get where you need to be, then use it as a guide with your own code.
I'm just wrapping up a similar legacy porting task so I know what you're goint through. There is a light at the end of this tunnel, it can be made to work. Hang in there.
0 Kudos
Steve_Nuchia
New Contributor I
636 Views

And I gotta start using a spell checker. Having a bad finger day here.

0 Kudos
patkins
Beginner
636 Views

Ok, progress. You need to do the following:

1. From Control Panel > Add or Remove Programs, select Microsoft Visual Studio 2005 (or 2008) > Change/Remove. The Visual Studio Maintenance Mode window will appear. Click Next.

2. Click Add or Remove Features

3. Under Select features to install, expand Language Tools > Visual C++

4. If the box X64 Compiler and Tools is not checked, check it, then click Update. If the box is already checked, click Cancel.

5. In Tools > Options > Projects > VC++ Directories, select Platform x64. Then for Library files, add the line:

$(IFORT_COMPILER10)em64tlib

6. You have to set the run-time library type of the C++ and Fortran projects to be consistent. C++ defaults to "debug multithreaded DLL" whereas Fortran defaults to "debug multithreaded" (static). Choose one to change to match the other. In C++, this is under Code Generation, in Fortran under Libraries.

Right, that finally did it. The last problem I had was the fact that the Fortran and C++ run-time libraries were inconsistent. Once I fixed the Fortran code (funny Linux Intel Fortran did not recognize these errors, but that may be why the resulting Fortran code is not producing correct results) I was able to compile and run everything. Thanks.

0 Kudos
Reply