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

Linking C code with fortran library

wrm1090
Beginner
2,970 Views
Hi Iam having a hard time linking c code with a fortran library that is compiled with intel visual fortran. I believe the function names arent the same for some reason. I have c++ code with a c wrapper around the fortran library. However the extern c is not sufficient for preventing all of the naming conventions that are happening. Does the intel visual fortran compiler append an underscore after the function name? THe basic problem is I have in c code


extern "C"{
function a_
function b_ //These underscores are added assuming the fortran compiler will add them after the function
}

then naming convention__cdecl (/Gd) adds an underscore to the beggining of the c function like so

_a_
_b_

I cant figure out how to look at the object (.obj) or library (.lib) and analyze the contents, atleast the function names and how they have been mangled. Does anyone know what might be happening here or what the command is for looking at the functions in the obj files or lib file? Thanks.

W-
0 Kudos
13 Replies
Steven_L_Intel1
Employee
2,970 Views
No, Intel Visual Fortran does not add a trailing underscore - that is a Linux/Unix convention. I will also note that the Windows compiler upcases routine names, so if you have a Fortran function named A the external name will be _A. (You should not specify the leading underscore in your C code, the compiler adds that automatically.)

I can tell you how to fix this in C++ or in Fortran - which would you prefer?
0 Kudos
anthonyrichards
New Contributor III
2,970 Views
You can use the DUMPBIN utility on the library (.LIB or .DLL) to view the symbols used in a library.
0 Kudos
wrm1090
Beginner
2,970 Views
Steve,

Thanks. Can you tell me both? Which would be easier to implement? Thank you very much. I appreciate your help.

W-
0 Kudos
TimP
Honored Contributor III
2,970 Views
If it works for you, the standard solution is to use extern "C" on the C++ side and iso_c_binding on the Fortran side, as Steve says in the next reply. Then you have no problem switching between Windows and other OS, nor between brands of compilers.
0 Kudos
Steven_L_Intel1
Employee
2,970 Views
It is probably easier to change the Fortran than the C++. The simplest way, I guess, is to change in your Fortran code:

SUBROUTINE A (arg, arg, arg)

to:

SUBROUTINE A (arg, arg, arg) BIND(C,NAME="a_")

where you specify the string for NAME= as the lowercase routine name followed by an underscore.

A way that is even simpler but may have side-effects and I do NOT recommend it, is to add the options:

/iface:cref /assume:underscore

to the Fortran compile options.

On the C++ side, you would need to change the names of the routines to be "A" instead of "a_", etc.
0 Kudos
wrm1090
Beginner
2,970 Views
Thanks fellas. All this was good and helped me progress. Now I am having trouble linking in whatever library has the trig functions (i.e. cos(), sin(), etc.). Any ideas on how to configure the projects to make this work. Keep in mind I have a C++ project with a C wrapper calling a Fortran static library. When I compile I get linker errors saying unresolved externals forsqrt, tan, asin, atan, sin, cos, etc. inside the fortran object files. These functions are in the fortran source and not the c source. Thanks for all your help.

W-
0 Kudos
Steven_L_Intel1
Employee
2,970 Views
0 Kudos
wrm1090
Beginner
2,970 Views

Hi Steve,

Thanks for the response. This is still not working. I noticed on here that it was refering to a couple of different .net versions as well as a couple of different intel VF versions. It only mentions intel version 10 or 11. Currently I am using version 9. Would this create a problem? Thanks.

W-

0 Kudos
wrm1090
Beginner
2,970 Views
Hi Steve I just got it to work. Thanks for all your help.

W-
0 Kudos
wrm1090
Beginner
2,970 Views

While that worked I have encoutered another problem that I guess falls under the same topic so I wont start a new thread.

The functions are now linked but I have data that I need to use in both sets of code. For instance I have structures defined in .hpp in the c++/c code and an equivalentcommon block in the fortran code. For instance

.hpp file in c++/c code .h file in fortran code

struct abc{ common ABC, var 1, var 2

var 1

var 2

}

then in a cpp file I have

extern abc abc_

All fortran is uppercase and all c\c++ is lowercase. I tried to match case in case the same thing happens here that it does with the functions. That didnt work. In this case should we have more of the same that we have with the functions that I wasnt able to resolve yet or is there another issue with this case?

in the end the C/C++ will call the fortran functions but I have some initialization code that inits data into the c/c++ structures and I need to get from the c\c++ structures to the fortran code through the fortran common structureif that makes any sense. Thanks for any help!

By the way this is leading to an unresolved external struct abc abc_.


W-

0 Kudos
anthonyrichards
New Contributor III
2,970 Views
TAken from the CVF help "Mixed-language programming, using common external data in":

Using Common External Data in Mixed-Language Programming

Accessing Common Blocks and C Structures Directly

You can access Fortran common blocks directly from C by defining an external C structure with the appropriate fields, and making sure that alignment and padding between Fortran and C are compatible. The C and ALIAS ATTRIBUTES options can be used with a common block to allow mixed-case names.

As an example, suppose your Fortran code has a common block named Really, as shown:

   !DEC$ ATTRIBUTES ALIAS:'Really' :: Really
REAL(4) x, y, z(6)
REAL(8) ydbl
COMMON / Really / x, y, z(6), ydbl

(my edit: The Fortran-forced upper-case name REALLY is aliased to 'Really' to match what the C-side uses)

You can access this data structure from your C code with the following external data structure:

 #pragma pack(2)
extern struct {
float x, y, z[6];
double ydbl;
} Really;
#pragma pack()

You can also access C structures from Fortran by creating common blocks that correspond to those structures. This is the reverse case from that just described. However, the implementation is the same because after common blocks and structures have been defined and given a common address (name), and assuming the alignment in memory has been dealt with, both languages share the same memory locations for the variables.

P.S. I think that the above assumes that the Fortran and C-code are eventually linked together, or the Fortran is in a static library that is linked to/from. If the Fortran is in a DLL, you will need to add a DLLEXPORT directive for the common block name in teh Fortran and an import directive on the C side.

0 Kudos
wrm1090
Beginner
2,970 Views
In case anyone cares the solution was to wrap

extern abc abc_ in an extern "C" and change the capitalization to what was described above. Thanks Steve.
0 Kudos
wrm1090
Beginner
2,970 Views
Thanks Anthony I didnt see your response until after I just posted my last post. Ill look into what you said to see if it works also. Thanks again.

W-
0 Kudos
Reply