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

Use of a COMMON Fortran in C++

sphost
Beginner
812 Views

Iremark a strange behavior using COMMON in a C++ :

 

C++ Code :

extern "C" struct {int c, e, f;} com;

Fortran Code :

COMMON/COM/ C, E

integer(C_INT):: C

integer(C_INT):: E

bind(C, NAME="com"):: /COM/

When I compile and execute this, I've got no error even if the structure is not the same. Is there any reason ? Can I give a special option to ifort (or g++ for link) to raise an error if I have this kind of difference ?

0 Kudos
8 Replies
TimP
Honored Contributor III
812 Views
If you're talking about making the object smaller in one function than another, don't count on it always "working," even if there is no warning from the linker. For example, Intel OpenMP will give you fits when you make threadprivate objects out of this, particularly if the first time it is accessed is not the largest one.
0 Kudos
sphost
Beginner
812 Views

Thanks for your response.

Maybe my question was not very clear. As you see the structure defined in C++ and the one defined in Fortran are not the same. I understand that it will not always working. My question was to know if there is any option to forbid this.

0 Kudos
jimdempseyatthecove
Honored Contributor III
812 Views

You are only specifing a common name "com". You would have the same problem in C++ if each source used a different deffinition for the structure declared with the name of "com".

You might consider having both the C++ and F90 program use the same #include file (will require FPP) where the include file conditionally expandson languagebut is easire to maintain.

#ifdef _CPP
// com.inc
#pragma pack(1)
extern "C" struct {int c, e, f;} com;
#else
C COM.INC
COMMON/COM/ C, E, F
integer(C_INT):: C
integer(C_INT):: E
integer(C_INT):: F
bind(C, NAME="com"):: /COM/
#endif

This way the structure declarations are in one file.

I would also using modules and user defined types

 #ifdef _CPP
// com.inc
#pragma pack(1)
struct MyCom {int c, e, f;};
#else
C COM.INC
type MyCom
sequence
integer(C_INT) :: C
integer(C_INT) :: E
integer(C_INT) :: F
end type MyCom
#endif
Your C++ app
 #include "com.inc"
extern "C" struct MyCom com;
Your F90 module
module YourModule
#include "com.inc"
type(MyCom) :: COM
bind(C, NAME="com") :: COM
...
end module YourModule
Your F90 application
program YourProgram
use YourModule
...
COM%C = COM%E + COM%F

Jim Dempsey

0 Kudos
sphost
Beginner
812 Views

Thanks for your answer.

So if I understand well, I have to check everytime if my structure declared in C++ is the same as in Fortran. There's no way to check this automaticly during compiling or linking.

0 Kudos
Steven_L_Intel1
Employee
812 Views
There's no way to do it automatically. However, if you have both in the same include file, that can reduce the chance of error. (Back when I was at DEC, we had a tool called SDL that allowed you to declare data structures in a language-independent manner and then generate language-specific code in a dozen or more languages.)

Let me suggest the following modification to the Fortran type:

 type, bind(C) :: MyCom
integer(C_INT) :: C
integer(C_INT) :: E
integer(C_INT) :: F
end type MyCom
This creates an "interoperable" type which is guaranteed by the language to be the same as what the "companion C processor" would use.
0 Kudos
sphost
Beginner
812 Views
Ok, but if I declare it as a "type" instead of a "COMMON", I will lose the value inside it from one call to another due to the fact that this "type" will be a local variable, won't it ?
0 Kudos
Steven_L_Intel1
Employee
812 Views
No, a COMMON variable can be a derived type. It's your choice as to how you want to do this - COMMON with individual variables or as a single variable with derived type.
0 Kudos
sphost
Beginner
812 Views
Ok I understand now what you mean. So it's better to choose a derived type instead of individual variables for the COMMON.

Thanks for this tips.
0 Kudos
Reply