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

BIND C or !DEC$ ATTRIBUTES C

Martin__Paul
New Contributor I
2,922 Views

I have been using BIND(C,NAME='SubName') within an interface block to call functions declared in a C++ library. The Fortran project calling convention is set to CVF (Properties > Fortran > External Procedures) and the equivalent C++ project setting is cdecl.

Does the use of BIND(C,...) force the use of cdecl? Or is it still necessary to explicitly specify the calling convention with the use of !DEC$ ATTRIBUTES C in the interface where the project settings do not match as above? I understand this is the case for stdcall, but was under the impression BIND(C,...) assumed cdecl. My program exhibits behaviour typical of stack corruption when I use BIND(C,...) with the settings mentioned above, but behaves correctly when I omit the BIND construct and include !DEC$ ATTRIBUTES C, DECORATE, ALIAS: 'SubName' ::SubName in the interface block.

0 Kudos
12 Replies
Steven_L_Intel1
Employee
2,922 Views
BIND(C) forces the CDECL calling convention but does not have the side-effect of changing passing mechanism to "by value", which ATTRIBUTES C does. Use the VALUE attribute (Fiortran 2003 attribute, not !DEC$ ATTRIBUTES) if you want pass-by-value.
0 Kudos
Martin__Paul
New Contributor I
2,922 Views

Thanks. My program is crashing due to access violation whenever I call a C++ subroutine with arguments from Fortran (the crash behaviour is not reproducible if functions with no arguments are called). I have a few static variables declared in the C++ module although am not if this is likely to be the cause.

Fortran interface:

[fortran]INTERFACE
SUBROUTINE MySub (retVal, var1, var1, var3) BIND(C,NAME='MySub') INTEGER retVal INTEGER var1 [VALUE] INTEGER var2 [VALUE] INTEGER var3 [VALUE] END

!other subroutines...

END INTERFACE

(var2 is a dummy argument of type INTEGER) INTEGER :: retVal = 0 INTEGER :: var1 = 0
INTEGER :: var3 = 1 CALL MySub (retVal, var1, var2, var3) [/fortran]

C++ callee:

[cpp]//Static vars
vector clsV(20,NULL);

//Declaration:
extern "C"
{
	void MySub (int *retVal, const int var1, const int var2, const int var3);
}

//Implementation:
void MySub (int *retVal, const int var1, const int var2, const int var3)
{
...

}[/cpp]

The problem is likely to do with argument passing/stack cleanup, since the call succeeds when the arguments are removed.

0 Kudos
Steven_L_Intel1
Employee
2,922 Views
Can you construct a complete example and attach a ZIP of the solution/project folders?

Also, please use "INTEGER, VALUE ::" instead of [VALUE], which is an undocumented Microsoft extension.
0 Kudos
Martin__Paul
New Contributor I
2,922 Views
Steve,

Please find attached a zip of a cut-down project that reproduces the access violation - please see the comments in test1.for. The call succeeds when the C++ function is exported as stdcall, or when no arguments are passed, implying stack corruption.

Note that this is only reproducible in release mode. I have set debug info /debug:minimal in Console1.vfproj - if set to /debug:full the issue is not reproducible.

I am using compiler version 11.1.046 and Visual C++ 9.0.30729.1 (Visual Studio 2008 SP).

Thanks for your help.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,922 Views
It is not clear from you post as if you are on 32-bit or 64-bit system.

On 64-bit all function calls are fastcall (pass first few values via registers)

On 32-bit platform fastcall/ nofastcall is controlled by option switches, declspec, ATTRIBUTES etc.

Check to make sure fastcall is consistent

And, check to make sure int size is the same.

Alternate way to check:

Make a call to MySub from within the C++ side. Then compile both the Fortran and C++ modules making this call but add the option switch to produce the assembler output. Comparing the calling sequence might point you to the problem.

Jim Dempsey
0 Kudos
Martin__Paul
New Contributor I
2,922 Views

I'm using a 32-bit system, and all integer types line up (4-bytes signed). I've also tried setting the value types to pointers and removing const in the function name but this didn't work.

I'll take a look at the assembler output and see if it reveals anything.

Thanks

0 Kudos
Steven_L_Intel1
Employee
2,922 Views
I tried this with 11.1.060 and saw no error. Can you try that?
0 Kudos
Martin__Paul
New Contributor I
2,922 Views

I rebuilt using 11.1.060 and it runs fine on several machines. I have tested the "broken" version (11.1.046) on the same machines (both running in debugger and from command line) and get the same access violation issue. Is there any chance you could also test with 11.1.046 as a sanity check, in case some environment setting is causing the problem?

If this is a compiler issue, it possible to request a patch for compiler version 11.1.046? I don't think moving to a later compiler release is an option for us right now as we are gearing up for a release and would need to extensively re-test everything if using a newer compiler.

Many thanks.

0 Kudos
Steven_L_Intel1
Employee
2,922 Views
Yes, I can reproduce it using 11.1.048. We don't do "patches" - we fix issues by releasing an update that installs a new compiler. I verified that indeed version 048 does not pop the stack after the call and version 060 does. However, I am unable to identify which problem report in our database led to this fix, not that knowing this would help you.
0 Kudos
Martin__Paul
New Contributor I
2,922 Views

I still can't quite understand why this problem occurs in the attached project but not in other parts of my program where I am essentially doing the same thing: in the working cases I am passing in parameters of various types, including the first element of an assumed-shape array of reals, as well as single-byte and 4-byte ints. In fact, when I run the cut-down example with exactly the code that works in the project proper, it still fails. This had me thinking that I had not initialised something correctly, or that it was a calling convention issue, but doesn't explain why some examples succeed and others don't where all environment/project settings match.

In the release notes there is a reference to DPD200148942 Fortran Internal Compiler Error on Function returning pointer with BIND(C) which may be the fix.

0 Kudos
Steven_L_Intel1
Employee
2,922 Views
No, that issue is not related. The thing with the stack corruption is that you don't always see a symptom.
0 Kudos
Martin__Paul
New Contributor I
2,922 Views

As it's a compiler bug I think our only option is to move to version 060 when possible - sooner rather than later if it's only luck that we've not witnessed stack corruption until now!

Note that the problem is only evident when passing pointer variables to C, not value types.

Thanks for your help.

0 Kudos
Reply