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

How to avoid prepend underscore when linking a fortran lib from C++?

Christer
Beginner
3,347 Views

I have a problem when using a fortran lib (actually a dll) from C++

I have created a fortran-dll andI want touse this fortran-dll in a C++ project.

But when linking my c++ project I receieve the error message :
unresolved external symbol _pt_h_gas

A short description of my project:

  • In my fortran dll I am using the following attributes:
  • Real*8 Function pt_h_gas(p , t, y1, y2, y3, y4, y5, y6, y7,unit)

    C Dll directives
    !dec$ attributes dllexport :: pt_h_gas
    !dec$ attributes alias:'pt_h_gas' :: pt_h_gas
    !dec$ attributes value:: p,t,y1,y2,y3,y4,y5,y6,y7,unit

    In the C++ project I have added the library from the fortran project and used the following code to use the function (this is just the test code)

extern "C"

double __stdcall pt_h_gas(double p ,double t,float SO2,float H2O,float CO2,float N2,float O2,
float Ar,float He,float unit);

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
float SO2 , H2O, CO2, N2, O2,Ar,He, unit;
double enthalpy;
double p,t;
enthalpy = PT_H_GAS(p ,t,SO2,H2O,CO2,N2,O2,Ar, He,unit);
}

(I can use __cdecl and I get the samme message)

The main problem is C++, it will add an underscore as prefix to function names when linking but the fortran lib/dll does not have any prefix.
I want to avoid this prefix and my question is there any settings/options pragmaor any other way to avoid the prefix?
I am using Visual Studio 2005 for C++

I know I can avoid this problemby deleting the line !dec$ attributes alias: and use function name PT_H_GAS instead in the c++ code (I have tested) but I really want to avoid this.
The reason for this is that the fortran dll/lib is used in other applications (functions for Excel etc) and isdistributed to many users. Then I have to change these programs as they work without any underscore prefix. The solution to have different fortran dll:s/libs is not acceptablefor quality reason it is said.

Maybe it is impossible to solve but to avoid a lot of work I try help from you!

0 Kudos
6 Replies
TimP
Honored Contributor III
3,347 Views
If you have matching C (or C++) and Fortran compilers, there will not be a discrepancy on account of leading underscores. However, ifort for Windows will default to upper case linkage identifiers without underscore conflicts with Windows C. You could correct the case in a standard compliant manner by specifying an iso_c_binding Fortran interface, and removing the _stdcall on the C side. Microsoft dropped full support for stdcall about 7 years ago, and so the cases where it could be used are limited. If you are still using CVF, of course, you have to deal with stdcall.
0 Kudos
Steven_L_Intel1
Employee
3,347 Views
At least two problems here. 1) You have __stdcall in the C++ declaration but Intel Fortran uses the C mechanism. Remove it. 2) You spell the routine name in lowercase in the C++ declaration but call it with the uppercase name. As far as C++ is concerned, these are two separate routines.

To fix. Take out the __stdcall and change the case of the declaration to be uppercase. Remove the ALIAS directive in the Fortran code.

Alternative. This for the C++:

[cpp]extern "C"

double pt_h_gas(double p ,double t,float SO2,float H2O,float CO2,float N2,float O2,
float Ar,float He,float unit);

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
float SO2 , H2O, CO2, N2, O2,Ar,He, unit;
double enthalpy;
double p,t;
enthalpy = pt_h_gas (p ,t,SO2,H2O,CO2,N2,O2,Ar, He,unit);
}[/cpp]


and this for the Fortran:

[plain]Function pt_h_gas(p , t, y1, y2, y3, y4, y5, y6, y7,unit) bind(C)

use iso_c_binding

real(C_DOUBLE) :: pt_h_gas
real(C_FLOAT), value:: y1, y2, y3, y4, y5, y6, y7, unit
real(C_DOUBLE) :: p, t[/plain]


0 Kudos
Christer
Beginner
3,347 Views
At least two problems here. 1) You have __stdcall in the C++ declaration but Intel Fortran uses the C mechanism. Remove it. 2) You spell the routine name in lowercase in the C++ declaration but call it with the uppercase name. As far as C++ is concerned, these are two separate routines.

To fix. Take out the __stdcall and change the case of the declaration to be uppercase. Remove the ALIAS directive in the Fortran code.

Alternative. This for the C++:

[cpp]extern "C"

double pt_h_gas(double p ,double t,float SO2,float H2O,float CO2,float N2,float O2,
float Ar,float He,float unit);

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
float SO2 , H2O, CO2, N2, O2,Ar,He, unit;
double enthalpy;
double p,t;
enthalpy = pt_h_gas (p ,t,SO2,H2O,CO2,N2,O2,Ar, He,unit);
}[/cpp]


and this for the Fortran:

[plain]Function pt_h_gas(p , t, y1, y2, y3, y4, y5, y6, y7,unit) bind(C)

use iso_c_binding

real(C_DOUBLE) :: pt_h_gas
real(C_FLOAT), value:: y1, y2, y3, y4, y5, y6, y7, unit
real(C_DOUBLE) :: p, t[/plain]




Many thanks for your answers!

Well, I used cdecl but as I got more "desparate" I tested everything including stdcall so the code I sent was just one in many examples. (Actually the libaray/dll was created in CVF and I did not know if CVF was created with cdecl or stdcall)
Uppercase was was just an editing mistake; it was from me testing without alias when it did work with linking problem.

iso_c_binding was something new, thanks for the tip!

Butis thereany flag for C++ to stop adding the underscore prefix? (Maybe wrong forum butI can always try!)
0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,347 Views
Quoting - Christer
Butis thereany flag for C++ to stop adding the underscore prefix? (Maybe wrong forum butI can always try!)

I think not (I might be wrong though), but why does it bother you at all? Just go with the defaults. You can always use:

!DEC$ATTRIBUTES DECORATE, ALIAS: "whatever"

and the Fortran compiler will add whatever underscores and other decoration is required to match the calling convention.
0 Kudos
Steven_L_Intel1
Employee
3,347 Views
I agree with Jugoslav that it makes more sense to let the compilers do their thing. Rather than use DECORATE I'd suggest the BIND(C,NAME="MixedCaseString") specification on the Fortran routine, as long as you aren't using STDCALL. This tells Fortran to create the same global name that the "companion" C compiler would use. You'll only get into trouble if you try to hard-code name decoration rules, especially if you move to a 64-bit platform where the decorations are different.
0 Kudos
Christer
Beginner
3,347 Views
I agree with Jugoslav that it makes more sense to let the compilers do their thing. Rather than use DECORATE I'd suggest the BIND(C,NAME="MixedCaseString") specification on the Fortran routine, as long as you aren't using STDCALL. This tells Fortran to create the same global name that the "companion" C compiler would use. You'll only get into trouble if you try to hard-code name decoration rules, especially if you move to a 64-bit platform where the decorations are different.

Thanks Steve and Jugoslav, I have learneda lotwhen reading your comments about mixed language!

The reason I was asking about avoiding prefix underscore was that my program is calling functions in an "official" dll/lib used for other programs. If I change the dll/lib (it is possible as I am the owner of that dll) I have to changethe other programs function calls and it will be a lot of work I do not have at the moment.

But with your tips Igot new ideas !
0 Kudos
Reply