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

Problem with Fotran-C mixed language dll.

Edward_Stanley
Beginner
898 Views
My Fortran-C mixed language dll compiles and links without any errors. I have a Fortran executable that calls functions in this dll and during execution when it comes to the second PRINT statement in the code below, I get the following error:

Unhandled exception at 0x00404e05 in Driver.exe: 0xC0000005: Access violation writing location 0xa4858d14.

Here is the relevant code from the executable:

PROGRAM DRIVER

IB = 1
CALL RGKNPATCH( IB, NPATCH)
PRINT *, " NPATCH = ", NPATCH

CALL RGKNPAN( IB, NPANC, NPAND, NPANP)
PRINT *, " NPANC = ",NPANC, "NPAND = ",NPAND, "NPANP = ",NPANP
.
.
.

In one Fortran source file from the dll, I have:

!============================================================
subroutine RGKNPATCH ( ib, npatch)

! Expose subroutine RGKNPATCH to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::RGKNPATCH
USE CPROC

! Variables
INTEGER(4), INTENT(IN) :: ib
INTEGER(4), INTENT(OUT) :: npatch

! Body of RGKNPATCH
CALL RGKNPATCHX( ib, npatch)

end subroutine RGKNPATCH

!============================================================
subroutine RGKNPAN ( ib, npanc, npand, npanp)

! Expose subroutine RGKNPAN to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::RGKNPAN
USE CPROC

! Variables
INTEGER(4), INTENT(IN) :: ib
INTEGER(4), INTENT(OUT) :: npanc
INTEGER(4), INTENT(OUT) :: npand
INTEGER(4), INTENT(OUT) :: npanp

! Body of RGKNPAN
CALL RGKNPANX( ib, npanc, npand, npanp)

end subroutine RGKNPAN

!============================================================

In a second Fortran source file from the dll, I have:

MODULE CPROC
INTERFACE
SUBROUTINE RGKNPATCHX ( ib, npatch)
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'cRGKnpatch' :: RGKNPATCHX
!DEC$ ATTRIBUTES VALUE :: ib
!DEC$ ATTRIBUTES REFERENCE :: npatch

INTEGER(4) ib
INTEGER(4) npatch

END SUBROUTINE

SUBROUTINE RGKNPANX ( ib, npanc, npand, npanp)
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'cRGKnpan' :: RGKNPANX
!DEC$ ATTRIBUTES VALUE :: ib
!DEC$ ATTRIBUTES REFERENCE :: npanc
!DEC$ ATTRIBUTES REFERENCE :: npand
!DEC$ ATTRIBUTES REFERENCE :: npanp

INTEGER(4) ib
INTEGER(4) npanc
INTEGER(4) npand
INTEGER(4) npanp

END SUBROUTINE
END INTERFACE
END MODULE

And in the c source file, I have:

/*-------------------------------------------------------------------*/

void cRGKnpatch( int ib, int* npatch)
{
int np = -1;

if( 1 <= ib && ib <= nbody
&& Bodies[ib] && Bodies[ib]->pPaneMaps)
{
np = Bodies[ib]->pPaneMaps->npanes;
}

*npatch = np;
}
/*-------------------------------------------------------------------*/

void cRGKnpan( int ib, int* npanc, int* npand, int* npanp)
{
int npc = -1;
int npd = -1;
int npp = -1;

if( 0 <= ib && ib <= nbody
&& Bodies[ib] && (Bodies[ib]->qualify & 1))
{
npc = Bodies[ib]->npan[0];
npd = Bodies[ib]->npan[1];
npp = Bodies[ib]->npan[2];
}

*npanc = npc;
*npand = npd;
*npanp = npp;
}
/*-------------------------------------------------------------------*/

These all worked without any problems several years ago when cRGKnpan had just one less argument and it was likely compiled using an old Compaq Visual Fortran. What seems odd to me is that the call to RGKNPATCH and the following PRINT statement are executed without any problem.

I have stepped through the whole execution of the call to RGKNPAN using the debugger and npanc, npand and npanp return with the correct values. Yet as soon as it tries to execute that second PRINT statement, I get the error mentioned above.
0 Kudos
1 Solution
IanH
Honored Contributor II
898 Views
Command line options for Fortran calling app:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c

Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c

You have /iface:cvf on the DLL but not on the main program. When compiling the main program how does the compiler know that the Fortran entry points in the DLL are not using the ifort default calling convention? Are the Fortran DLL routines in a module? If not, do you have an interface block for the routines that has all the !DEC$ ATTRIBUTES stuff required for the CVF calling convention? If neither, then there's your problem.

View solution in original post

0 Kudos
7 Replies
IanH
Honored Contributor II
898 Views
Ramblings only...

- Exploding print statements make it sound like stack corruption.

- What ifort version? Which C compiler, what C compiler version? What command line options for both?

- Some of the the lines with compiler directives are getting pretty long. 12.1 docs say you can't go past column 72 even in free form (which might be an error in the docs - but it doesn't take much to get a directive treated as a comment and ignored). No warnings or other informational messages in the build log?

- What's the declaration (and perhaps initialisation and/or subsequent memory allocation) for Bodies? Is it indexable from zero through to and including nbody (in the context of an array(N) in C being indexed from zero through to N-1)? ib has a "valid" lower index of one in cRGKnpath, but zero in cRGKnpan, is that intentional?

- Perhaps they've been elided, butI don't see any implicit none statements inside the program units or interface bodies. Are the variables in the actual argument lists for the subroutine calls in the main program all INTEGER(4)? Are the subroutines external or in a module?

- Are you familiar with the C interoperability stuff from F2003? Because it is standard it lets you test this sort of stuff on different processors, which can help isolate bugs. I find its syntax much cleaner and more robust to mistakes that the !DEC$ business too.

- What you've presented is not far off being a compilable test case. Is it possible to provide or write a little bit more code to make something that can be examined in isolation? Will help cut down the signal to rambling ratio too...

0 Kudos
anthonyrichards
New Contributor III
898 Views
The debugger should be of assistance here. However, I would suggest using MessageBox inside the C-code to display exactly what the C-functions are sending and MessageBox inside the Fortran subroutines to display exactly what they think they are receiving and going on from there. It is possible to get a confusion between sending an address (pointer) which goes on the stack as a value which should be recovered as a value but the Fortran might recover it as an address to an address, or possibly vise versa!

Also, make sure that the calling conventions match between the C-code and the Fortran code calling it or else the stack is likely top get corrupted and that may eventually cause what you are seeing. Remember that IVF uses a default calling convention that is different from that of CVF.
0 Kudos
jimdempseyatthecove
Honored Contributor III
898 Views

Is this a C source file or CPP source file?

If CPP then you may need to declare your CPP functions as

extern "C" void cRGKnpatch( int ib, int* npatch);
extern "C" void cRGKnpan( int ib, int* npanc, int* npand, int* npanp);

Also, your code will have portability issues.

On your Fortran side, consider using

INTEGER(C_INT) ib
INTEGER(C_PTR) npanc
...

Jim Dempsey

0 Kudos
Edward_Stanley
Beginner
898 Views
- What ifort version? Which C compiler, what C compiler version? What command line options for both?

ifort version = 12.1.3514
C compiler = VS2005 version 2.0.50727 SP2

Command line options for Fortran calling app:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c

Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c

Command line options for c portion of dll:
/Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_VC80_UPGRADE=0x0600" /D "_MBCS" /Gm /EHsc /RTC1 /MTd /Fp".\Debug/RG2W.pch" /Fo".\Debug/" /Fd".\Debug/" /FR".\Debug\" /W3 /nologo /c /Zi /TC /errorReport:prompt


- Some of the the lines with compiler directives are getting pretty long. 12.1 docs say you can't go past column 72 even in free form (which might be an error in the docs - but it doesn't take much to get a directive treated as a comment and ignored). No warnings or other informational messages in the build log?

I don't get any warnings concerning line length.

- What's the declaration (and perhaps initialisation and/or subsequent memory allocation) for Bodies? Is it indexable from zero through to and including nbody (in the context of an array(N) in C being indexed from zero through to N-1)? ib has a "valid" lower index of one in cRGKnpath, but zero in cRGKnpan, is that intentional?

The zero in cRGKnpan was an oversight. Bodies is really immaterial to the problem. I can assign different values to npanc, npand and npanp directly and comment out that block of code referencing Bodies and still get the error.

- Perhaps they've been elided, butI don't see any implicit none statements inside the program units or interface bodies. Are the variables in the actual argument lists for the subroutine calls in the main program all INTEGER(4)? Are the subroutines external or in a module?

There are no IMPLICIT NONE statements anywhere. The variables are indeed INTEGER(4)'s.

- Are you familiar with the C interoperability stuff from F2003? Because it is standard it lets you test this sort of stuff on different processors, which can help isolate bugs. I find its syntax much cleaner and more robust to mistakes that the !DEC$ business too.

No, I am not familiar with this. I haven't done any significant Fortran coding in over twenty years.

- What you've presented is not far off being a compilable test case. Is it possible to provide or write a little bit more code to make something that can be examined in isolation? Will help cut down the signal to rambling ratio too...

I might try to do this if I can find the time.
0 Kudos
Edward_Stanley
Beginner
898 Views
Is this a C source file or CPP source file?

It's a c source file.

On your Fortran side, consider using

INTEGER(C_INT) ib
INTEGER(C_PTR) npanc
...

Thanks, I'll look into this.
0 Kudos
IanH
Honored Contributor II
899 Views
Command line options for Fortran calling app:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c

Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c

You have /iface:cvf on the DLL but not on the main program. When compiling the main program how does the compiler know that the Fortran entry points in the DLL are not using the ifort default calling convention? Are the Fortran DLL routines in a module? If not, do you have an interface block for the routines that has all the !DEC$ ATTRIBUTES stuff required for the CVF calling convention? If neither, then there's your problem.
0 Kudos
Edward_Stanley
Beginner
898 Views
Thanks for the help Ian! Everything worked fine after adding the /iface:cvf option to the main program.
0 Kudos
Reply