- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Linker error while calling fortran subroutine from VC++ when executing the following program
The Fortran code is as follows
SUBROUTINE MULTIDRAIN ( IERR )
IMPLICIT NONE
INCLUDE 'in2.inc'
INCLUDE 'calc.inc'
INCLUDE 'coeff.inc'
INCLUDE 'fore.inc'
INCLUDE 'in1.inc'
INCLUDE 'inphor.inc'
INCLUDE 'print.inc'
INCLUDE 'prop.inc'
INCLUDE 'respm.inc'
INCLUDE 'unitconv.inc'
INTEGER COUNT
INTEGER I
INTEGER ICUM
INTEGER, INTENT (OUT) :: IERR
...
RETURN
END
I am calling this subroutine MULTIDRAIN in VC++ 8.0 as follows
//Declaration in header file
extern "C" { int _stdcall MULTIDRAIN(); }
//calling in .cpp file
UINT ThreadCtrlFunc(LPVOID pParam)
{
MULTIDRAIN();
ThreadExitCode = TRUE;
return 1;
}
I couldn't find which goes wrong. I repeatedly getting this Linker error. Please do help. Thanks in advance.
Error 60 error LNK2019: unresolved external symbol _MULTIDRAIN@0 referenced in function "unsigned int __cdecl ThreadCtrlFunc(void *)" (?ThreadCtrlFunc@@YAIPAX@Z) MainFrm.obj
Error 61 fatal error LNK1120: 1 unresolved externals c:\Program Files\MultiLateral 02 04\MultiLateral\Multilateral\Release\MultiLateral.exe 1
The Fortran code is as follows
SUBROUTINE MULTIDRAIN ( IERR )
IMPLICIT NONE
INCLUDE 'in2.inc'
INCLUDE 'calc.inc'
INCLUDE 'coeff.inc'
INCLUDE 'fore.inc'
INCLUDE 'in1.inc'
INCLUDE 'inphor.inc'
INCLUDE 'print.inc'
INCLUDE 'prop.inc'
INCLUDE 'respm.inc'
INCLUDE 'unitconv.inc'
INTEGER COUNT
INTEGER I
INTEGER ICUM
INTEGER, INTENT (OUT) :: IERR
...
RETURN
END
I am calling this subroutine MULTIDRAIN in VC++ 8.0 as follows
//Declaration in header file
extern "C" { int _stdcall MULTIDRAIN(); }
//calling in .cpp file
UINT ThreadCtrlFunc(LPVOID pParam)
{
MULTIDRAIN();
ThreadExitCode = TRUE;
return 1;
}
I couldn't find which goes wrong. I repeatedly getting this Linker error. Please do help. Thanks in advance.
Error 60 error LNK2019: unresolved external symbol _MULTIDRAIN@0 referenced in function "unsigned int __cdecl ThreadCtrlFunc(void *)" (?ThreadCtrlFunc@@YAIPAX@Z) MainFrm.obj
Error 61 fatal error LNK1120: 1 unresolved externals c:\Program Files\MultiLateral 02 04\MultiLateral\Multilateral\Release\MultiLateral.exe 1
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Did you consult the documentation on C interoperability of your compiler? I'm guessing that you followed (partly) a recommendation for a Fortran compiler of 10 years ago or so, but your Fortran compiler may not be that old. Fortran compilers of the last year or so support iso_c_interop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - tim18
Did you consult the documentation on C interoperability of your compiler? I'm guessing that you followed (partly) a recommendation for a Fortran compiler of 10 years ago or so, but your Fortran compiler may not be that old. Fortran compilers of the last year or so support iso_c_interop.
For a start, in your C++ code, you declare MULTIDRAIN as if it were an Integer FUNCTION with no arguments, whereas you reference it as Void function with no arguments which assumes a SUBROUTINE on the Fortran side. On top ofthis your Fortran defines a SUBROUTINE taking one argument. Things are never going to match up in this situation. I think you should either change the C++ to match the Fortran Subroutine declaration, adding an argumentor declare the Fortran as a FUNCTION with no argument to match the C++.(Check the following C++ for correctness - I am not a regular C++ programmer)
extern "C" {_stdcall void MULTIDRAIN(int ERR); }
//calling in .cpp file
UINT ThreadCtrlFunc(LPVOID pParam)
{
int err;
MULTIDRAIN(err);
There remains the question of whether the Fortran code is compiled and linked into a .LIB or a .DLL. Ifthe latter it will need a DLLEXPORT directive on the Fortran side and on the C++ side you willto add __declspec(dllimport) to the extern declaration, as well as specifying the Library's location. Otherwise you should also add compiler directives to ensure the correct calling convention is used on the Fortran sideand that the argument is to be called by value to match the C++ 'int ERR'. If you use 'int* ERR' in the C++, then the argument is to be called by reference.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Are you using CVF or Intel Fortran?
If you are using CVF, there's one more small change you need to make:
extern "C" {_stdcall void MULTIDRAIN(int *ERR); }
You MUST pass the integer by reference. Otherwise, this should work for you because the calling standard for CVF was very close to C's _stdcall
However. If you are using Intel Fortran, then you should change your declaration to this:
extern "C" {void MULTIDRAIN(int *ERR); }
Again, you MUST pass the integer by reference, but you don't need to put in the _stdcall directive
Both CVF and Intel Fortran have extensive documentation onmixed-language programming, especially with C.
- Lorri
If you are using CVF, there's one more small change you need to make:
extern "C" {_stdcall void MULTIDRAIN(int *ERR); }
You MUST pass the integer by reference. Otherwise, this should work for you because the calling standard for CVF was very close to C's _stdcall
However. If you are using Intel Fortran, then you should change your declaration to this:
extern "C" {void MULTIDRAIN(int *ERR); }
Again, you MUST pass the integer by reference, but you don't need to put in the _stdcall directive
Both CVF and Intel Fortran have extensive documentation onmixed-language programming, especially with C.
- Lorri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - lorri_menard
Are you using CVF or Intel Fortran?
If you are using CVF, there's one more small change you need to make:
extern "C" {_stdcall void MULTIDRAIN(int *ERR); }
You MUST pass the integer by reference. Otherwise, this should work for you because the calling standard for CVF was very close to C's _stdcall
However. If you are using Intel Fortran, then you should change your declaration to this:
extern "C" {void MULTIDRAIN(int *ERR); }
Again, you MUST pass the integer by reference, but you don't need to put in the _stdcall directive
Both CVF and Intel Fortran have extensive documentation onmixed-language programming, especially with C.
- Lorri
If you are using CVF, there's one more small change you need to make:
extern "C" {_stdcall void MULTIDRAIN(int *ERR); }
You MUST pass the integer by reference. Otherwise, this should work for you because the calling standard for CVF was very close to C's _stdcall
However. If you are using Intel Fortran, then you should change your declaration to this:
extern "C" {void MULTIDRAIN(int *ERR); }
Again, you MUST pass the integer by reference, but you don't need to put in the _stdcall directive
Both CVF and Intel Fortran have extensive documentation onmixed-language programming, especially with C.
- Lorri
Hi Lorri,
Thanks for the reply. Iam using Intel Fortran. I have changed the declaration to
extern "C" { int _cdecl MULTIDRAIN(); }
and now the problem has gone.
Thank you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - anthonyrichards
For a start, in your C++ code, you declare MULTIDRAIN as if it were an Integer FUNCTION with no arguments, whereas you reference it as Void function with no arguments which assumes a SUBROUTINE on the Fortran side. On top ofthis your Fortran defines a SUBROUTINE taking one argument. Things are never going to match up in this situation. I think you should either change the C++ to match the Fortran Subroutine declaration, adding an argumentor declare the Fortran as a FUNCTION with no argument to match the C++.(Check the following C++ for correctness - I am not a regular C++ programmer)
extern "C" {_stdcall void MULTIDRAIN(int ERR); }
//calling in .cpp file
UINT ThreadCtrlFunc(LPVOID pParam)
{
int err;
MULTIDRAIN(err);
There remains the question of whether the Fortran code is compiled and linked into a .LIB or a .DLL. Ifthe latter it will need a DLLEXPORT directive on the Fortran side and on the C++ side you willto add __declspec(dllimport) to the extern declaration, as well as specifying the Library's location. Otherwise you should also add compiler directives to ensure the correct calling convention is used on the Fortran sideand that the argument is to be called by value to match the C++ 'int ERR'. If you use 'int* ERR' in the C++, then the argument is to be called by reference.
Hi,
Thanks for the reply. I have changed the declaration so that it returns int, as follows
extern "C" { int _cdecl MULTIDRAIN(); }
and now the problem has gone. Also, my Fortran code is compiled and linked as .lib file.
Thank you.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page