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

Linking problems on project converted from CVF

chris-sn
Beginner
1,050 Views
I've converted an oldmixed-language (C++ and FORTRAN) project to two projectsusing the "Extract Compaq visual fortran project items tool". The FORTRAN builds to a static library, referenced by the C++ project which yields a dll callable by other C++ code.

There were very few compilation problems which was very pleasing, and the static library is building ok. However when I try and link the C++ dll I get a lot of errors,see belowfrom the debug build (the release build has a different set)

Any ideas?
-----------------------------------------------------------

1>stdspr_lib.lib(PSVCHK.obj) : error LNK2019: unresolved external symbol _SLEEPQQ@4 referenced in function _PSVCHK

1>stdspr_lib.lib(GDATE.obj) : error LNK2019: unresolved external symbol _GETDAT@12 referenced in function _GDATE

1>stdspr_lib.lib(GDATE.obj) : error LNK2019: unresolved external symbol _GETTIM@16 referenced in function _GTIME

1>libifcoremt.lib(for_diags_intel.obj) : error LNK2019: unresolved external symbol __iob referenced in function _for__io_return

1>libifcoremt.lib(for_nt_open_proc.obj) : error LNK2001: unresolved external symbol __iob

1>libmmt.lib(libm_error.obj) : error LNK2001: unresolved external symbol __iob

1>libifcoremt.lib(for_init.obj) : error LNK2019: unresolved external symbol ___argv referenced in function _for_rtl_init_wrap_

1>libifcoremt.lib(for_init.obj) : error LNK2019: unresolved external symbol ___argc referenced in function _for_rtl_init_wrap_

-----------------------------------------------------------

My C++ project has additional library directories
C:\\Program Files\\Intel\\Compiler\\11.1\\060\\lib\\ia32
C:\\Program Files\\Microsoft Visual Studio 9.0\\VC\\lib

odbc32.lib, odbccp32.lib as additional dependencies

libcmtd,libcd,libc,dfor,msvcrt as specific libraries to be ignored.

0 Kudos
1 Solution
Steven_L_Intel1
Employee
1,050 Views
Ok, I understand this better now.

Right click on the Fortran project, select Properties, and make the following change:

Fortran > Libraries > Runtime Libraries - change to Multithreaded DLL (for a Debug configuration: Debug Multithreaded DLL

In your Fortran sources that call SLEEPQQ, GETDAT and GETTIM, add after the SUBROUTINE or FUNCTION line:

USE IFPORT

This should resolve the problems.

In the longer term, you can investigate using the default calling convention instead of CVF. This will require your C++ sources to not use __stdcall and to move the string lengths to the end of the argument list.

In the longer term, look into the Fortran 2003 C Interoperability features, though character variables are a bit messy to handle if one is following the rules strictly.

View solution in original post

0 Kudos
9 Replies
TimP
Honored Contributor III
1,050 Views
The obvious idea is you are trying to mix the CVF modified stdcall linking with current Microsoft cdecl conventions. As Microsoft deprecated stdcall about 9 years ago, and all maintained Fortran compilers have supported iso_c_binding for 2 years, it's time to move on.
0 Kudos
chris-sn
Beginner
1,050 Views
Thanks Tim, this project is at least that old so I can believe there is some updating to do. I'll go educate myself, if you happen to know of any links to the necessary specs that would be useful if not I'm sure google will do the job.

0 Kudos
Steven_L_Intel1
Employee
1,050 Views
How are the C++ routines declared in the C++ code?

Is the main program Fortran or C++? Make sure that the Runtime Library setting is consistent between C++ and Fortran.
0 Kudos
chris-sn
Beginner
1,050 Views
Steve,

The main program is in C++, though I don't think that's relevant here - what I am trying to build is a dll used by the main program. The dll is essentially a FORTRAN calculation engine, with a thin C++ wrapper providing access to the principal FORTRAN"go calculate" subroutine and a couple of other things like "return your version number".

Here iswhat the principal C++ routine (in the dll project, with /MDd) looks like:


extern "C" { void _stdcall pcbat(const char* dataPath, int datlen, const char* filesPath, int fileslen, int* viewData, char* szFlag, int flaglen, char* warning, int warnlen, char* customer, int custlen); }

And its equivalent FORTRAN function (ina static library, multithreaded debug runtime, CVF calling convention,referenced by the C++ dll)

SUBROUTINE PCBAT(SPATH, DPATH, CALCFLAG, FLAG, MWARN, CUSTMR)
!DEC$ ATTRIBUTES STDCALL,REFERENCE :: PCBAT
CHARACTER*96 SPATH, DPATH
CHARACTER*64 CUSTMR
CHARACTER*1 FLAG, MWARN
INTEGER CALCFLAG

It would be very helpful to have an examplar on the current recommended way of passing character strings from C++ to FORTRAN - I found this article, it looks much more complicated than the code above?
http://software.intel.com/en-us/forums/showthread.php?t=66841

Just to complicate the issue, the FORTRAN calculation engine calls back out to the C++ code (for example to report progress or check for an interrupt). I may have to strip things down to atest projectand then build back up to see where the error is comign from.

TIA for any suggestions

Chris
0 Kudos
Steven_L_Intel1
Employee
1,051 Views
Ok, I understand this better now.

Right click on the Fortran project, select Properties, and make the following change:

Fortran > Libraries > Runtime Libraries - change to Multithreaded DLL (for a Debug configuration: Debug Multithreaded DLL

In your Fortran sources that call SLEEPQQ, GETDAT and GETTIM, add after the SUBROUTINE or FUNCTION line:

USE IFPORT

This should resolve the problems.

In the longer term, you can investigate using the default calling convention instead of CVF. This will require your C++ sources to not use __stdcall and to move the string lengths to the end of the argument list.

In the longer term, look into the Fortran 2003 C Interoperability features, though character variables are a bit messy to handle if one is following the rules strictly.
0 Kudos
IDZ_A_Intel
Employee
1,050 Views
Steve, that wasspot on thanks - now compiling and building happily in debug and release versions ;-)

UnfortunatelyI'm not out of the woods yet- when I run it in debug I get a runtime error message
"Dummy character variable SPATH has length 96 which is greater then(sic) actual variable length 38"
Simplifying a little the code is like this

SUBROUTINE PCBAT(SPATH, DPATH, CALCFLAG, FLAG, MWARN, CUSTMR)
!DEC$ ATTRIBUTES STDCALL,REFERENCE :: PCBAT
INCLUDE 'FILES.FI'
..
CHARACTER*96 SPATH, DUMMY
..
DUMMY= SPATH !Runtime error here

Any idea what might be happening here? Wheremight the reported actual length of 38 be coming from?

Have a great easter - I'm for a few days hopefully tofind some sunshine;-)

0 Kudos
Les_Neilson
Valued Contributor II
1,050 Views
Something is calling pcbat with a character string that is only 38 long.
The easiest thing would be to change the line
character*96 SPATH, DUMMYto

character(*) :: SPATH

character(96) :: DUMMY

Les

(As a matter of style I always separate the declaration ofdummy arguments from local variables. Also I prefer one declaration per line (where sensible)- makes changes much easier to do and IMHO code easier to read)
0 Kudos
chris-sn
Beginner
1,050 Views
Thank you Les, that didi the trick, though I'm slightly puzzled that the debugger reported that SPATH was the requisite 96 characters (space padded).

And must remember to ask only question per thread...makes it difficult to mark the best answer...
0 Kudos
Les_Neilson
Valued Contributor II
1,050 Views
Yes you told the compiler that SPATH in the subroutine was ALWAYS 96 characters long, but something was calling it with a string that was shorter.
Today I have been debugging exactly this kind of bug in some code here.

Les
0 Kudos
Reply