Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Calling FORTRAN from Microsoft Visual C++ (2005)

111 views
Skip to first unread message

Mark

unread,
Apr 25, 2012, 8:37:00 AM4/25/12
to
Hi,

I'm trying to do a trivial test of a C++ main calling a FORTRAN static
liband I am getting a linker error I cannot get around. Here's the
source code and linker error:

extern "C"
{
void __stdcall tfort_ (int&, float&);
}


int _tmain(int argc, _TCHAR* argv[])
{
int a=5;
float b=1.2345f;
tfort_(a,b);
return 0;
}

C TEST FORTRAN
SUBROUTINE TFORT(A, B)
INTEGER A
REAL B
WRITE(UNIT=*, FMT=*)'A = ', A, ' B = ',B
RETURN
END

1>Compiling...
1>TestC.cpp
1>Linking...
1>TestC.obj : error LNK2019: unresolved external symbol _tfort_@8
referenced in function _wmain
1>C:\Mainframe\MainframePort\Debug\TestC.exe : fatal error LNK1120: 1
unresolved externals
1>Build log was saved at "file://c:\Mainframe\MainframePort\TestC\Debug
\BuildLog.htm"
1>TestC - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
==========

I have tried different variations of the underscore placement and
capitilization of the TFORT routine in the C++ code to no avail. Is
there a compiler option I need? (I am using the Intel FORTRAN
compiler).

Any help would be greatly appreciated!

simon

unread,
Apr 25, 2012, 9:11:06 AM4/25/12
to
On 25/04/2012 13:37, Mark wrote:
> extern "C"
> {
> void __stdcall tfort_ (int&, float&);
> }
>
>
> int _tmain(int argc, _TCHAR* argv[])
> {
> int a=5;
> float b=1.2345f;
> tfort_(a,b);
> return 0;
> }
>
> C TEST FORTRAN
> SUBROUTINE TFORT(A, B)
> INTEGER A
> REAL B
> WRITE(UNIT=*, FMT=*)'A = ', A, ' B = ',B
> RETURN
> END

It's sometime since I used VS 2005, but with 2010 and Intel Fortran 12.1
the following works:

extern "C"
{
void tfort(int, float);
}


int _tmain(int argc, char* argv[])
{
int a=5;
float b=1.2345f;
tfort(a,b);
return 0;
}

! TEST FORTRAN
SUBROUTINE TFORT(A, B) bind(c,name='tfort')
use iso_c_binding
INTEGER, intent(in), value :: A
REAL, intent(in), value :: B
WRITE(UNIT=*, FMT=*)'A = ', A, ' B = ',B
RETURN
END

Simon

Mark

unread,
Apr 25, 2012, 9:54:39 AM4/25/12
to
> Simon- Hide quoted text -
>
> - Show quoted text -

I did get further since my post and have a new problem. I built the
fortran code as a static lib and changed the properties of the fortran
project as follows: configuration properties->fortran->external
procedures->calling convention->STDCALL/REFERENCE. I also added the
path of all the INTEL compiler fortran libs to the Visual Studio VC++
directories. I also took off the underscore at the end of the tfort
call in the c++ main. Now, I get the following linker errors:

1>------ Build started: Project: TestC, Configuration: Debug Win32
------
1>Compiling...
1>TestC.cpp
1>Linking...
1>LIBCMTD.lib(dbgheap.obj) : error LNK2005: __CrtSetCheckCount already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(invarg.obj) : error LNK2005: __invoke_watson already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: _exit already defined in
MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __exit already defined in
MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __cexit already defined in
MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __amsg_exit already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __initterm_e already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(tidtable.obj) : error LNK2005: __encode_pointer already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(tidtable.obj) : error LNK2005: __decode_pointer already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(setlocal.obj) : error LNK2005: __configthreadlocale
already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(dbghook.obj) : error LNK2005: __crt_debugger_hook
already defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(winxfltr.obj) : error LNK2005: __XcptFilter already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(mlock.obj) : error LNK2005: __lock already defined in
MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(mlock.obj) : error LNK2005: __unlock already defined in
MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xi_a already defined
in MSVCRTD.lib(cinitexe.obj)
1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xi_z already defined
in MSVCRTD.lib(cinitexe.obj)
1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xc_a already defined
in MSVCRTD.lib(cinitexe.obj)
1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xc_z already defined
in MSVCRTD.lib(cinitexe.obj)
1>LIBCMTD.lib(errmode.obj) : error LNK2005: ___set_app_type already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>LIBCMTD.lib(dbgrptw.obj) : error LNK2005: __CrtDbgReportW already
defined in MSVCRTD.lib(MSVCR80D.dll)
1>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)
1>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)
1>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of
other libs; use /NODEFAULTLIB:library
1>LINK : warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of
other libs; use /NODEFAULTLIB:library
1>libifcoremt.lib(for_main.obj) : error LNK2019: unresolved external
symbol _MAIN__ referenced in function _main
1>C:\Mainframe\MainframePort\Debug\TestC.exe : fatal error LNK1120: 1
unresolved externals
1>Build log was saved at "file://c:\Mainframe\MainframePort\TestC\Debug
\BuildLog.htm"
1>TestC - 24 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
==========

Has anybody run into this one?

Tim Prince

unread,
Apr 25, 2012, 10:41:16 AM4/25/12
to
On 4/25/2012 9:54 AM, Mark wrote:
> On Apr 25, 9:11 am, simon<si...@whiteowl.co.uk> wrote:
>> On 25/04/2012 13:37, Mark wrote:
>>
>>
I built the
> fortran code as a static lib and changed the properties of the fortran
> project as follows: configuration properties->fortran->external
> procedures->calling convention->STDCALL/REFERENCE. I also added the
> path of all the INTEL compiler fortran libs to the Visual Studio VC++
> directories. I also took off the underscore at the end of the tfort

> 1>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of
> other libs; use /NODEFAULTLIB:library
> 1>LINK : warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of
> other libs; use /NODEFAULTLIB:library
> 1>libifcoremt.lib(for_main.obj) : error LNK2019: unresolved external
> symbol _MAIN__ referenced in function _main
> 1>C:\Mainframe\MainframePort\Debug\TestC.exe : fatal error LNK1120: 1
> unresolved externals
> 1>Build log was saved at "file://c:\Mainframe\MainframePort\TestC\Debug
> \BuildLog.htm"
> 1>TestC - 24 error(s), 2 warning(s)
> ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
> ==========
>
> Has anybody run into this one?
>
Yes, it's important to follow the advice, including (if at all possible)
the use of default ABI (not the stdcall which was obsoleted 12 years
ago), using the cmd prompt window shortcut off Windows Start menu to set
up your paths, making your C++ project use static libs so you don't run
into these static vs. dll run-time conflicts, and use of iso_c_binding.
If you are willing to follow advice, or give explanations of what you
are doing, the place to seek further advice on Intel compiler is on the
Intel forum
http://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/


--
Tim Prince

glen herrmannsfeldt

unread,
Apr 25, 2012, 11:15:30 AM4/25/12
to
Mark <mark...@yahoo.com> wrote:

> I'm trying to do a trivial test of a C++ main calling a FORTRAN static
> liband I am getting a linker error I cannot get around. Here's the
> source code and linker error:

> extern "C"
> {
> void __stdcall tfort_ (int&, float&);
> }

(snip)
> C TEST FORTRAN
> SUBROUTINE TFORT(A, B)

As far as I know, most Fortran compilers now are not using STDCALL.

(If no other reason, that not using it makes calls between C and
Fortran easier.)

Otherwise, if you use bind(C) in the Fortran program then it
should match the calling sequence of the appropriate C compiler,
including any underscores.

In general, C doesn't use STDCALL. STDCALL requires the called routine
to pop the arguments off the stack, which doesn't work with varargs
routines. C could use a different calling sequence for varargs, but
that is rarely done. (Probably too many C programs depend on varargs
working, even in the cases where it wasn't declared.)

It saves a few bytes to use VARARGS, but causes more problems than
it is worth.

-- glen

Terence

unread,
Apr 25, 2012, 10:30:38 PM4/25/12
to
You need a compiled Main program present if you proceed to link any object
modules.
Since you only have a subroutine, you can save the object code, but it
cannot by itself act as an executable.


Ian Harvey

unread,
Apr 26, 2012, 1:16:04 AM4/26/12
to
In this case (with the VS2005 C++ compiler), the _tmain C++ function is
"supposed" to be the equivalent of a Fortran main program. But that
requires appropriate #define's/#include's/project settings for the VC
compiler, which appear to be missing. Without them, the main C++
function should simply be the standard "main".

Other errors are because the projects have conflicting settings for
properties related to the runtime libraries. TimP has suggested that
both be set to static, alternatively both could be set to DLL.

I would also not recommend using stdcall - go with F2003's C
interoperability. A correction to the previous poster's use of
C-interop - ISO_C_BINDING was being USEd and then not being used, if you
get my drift.

! ifort /c /MD fortran.f90
SUBROUTINE TFORT(A, B) BIND(c,NAME='tfort')
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT, C_FLOAT
INTEGER(C_INT), INTENT(IN), VALUE :: A
REAL(C_FLOAT), INTENT(IN), VALUE :: B
WRITE (UNIT=*, FMT=*) 'A = ', A, ' B = ',B
RETURN
END SUBROUTINE TFORT

// cl /MD cpp.cpp fortran.obj /FeWinkyWonkyDonkey.exe
extern "C" void tfort(int, float);

int main(int argc, char* argv[])
{
int a=5;
float b=1.2345f;
tfort(a,b);
return 0;
}

Hee haw.
0 new messages