C_PTR and VALUE not respected on v17

C_PTR and VALUE not respected on v17

I have the following "C" call back declaration;

typedef void (*ProgCallBackType2)(size_t, int, int, float);

I am trying to call that from Fortran but I get garbage coming through. It works perfectly on GFortran (under linux and macOS). Here are the relevant Fortran bits:

! similar callback routine, with two integer arguments
ABSTRACT INTERFACE
SUBROUTINE ProgressCallBack2(objAddress, loopCompleted, totalLoops, bseYield)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(c_size_t),INTENT(IN), VALUE :: objAddress
INTEGER(KIND=4), INTENT(IN), VALUE :: loopCompleted
INTEGER(KIND=4), INTENT(IN), VALUE :: totalLoops
REAL(KIND=4),INTENT(IN), VALUE :: bseYield
END SUBROUTINE ProgressCallBack2
END INTERFACE

Then down in the actual Fortran function we make the call:
!--------------------------------------------------------------------------
recursive subroutine EMsoftCgetMCOpenCL(ipar, fpar, atompos, atomtypes, latparm, accum_e, accum_z, cproc, objAddress, cancel) &
bind(c, name='EMsoftCgetMCOpenCL') ! this routine is callable from a C/C++ program
!DEC$ ATTRIBUTES DLLEXPORT :: EMsoftCgetMCOpenCL

TYPE(C_FUNPTR), INTENT(IN), VALUE :: cproc
integer(c_size_t),INTENT(IN), VALUE :: objAddress
character(len=1),INTENT(IN) :: cancel
integer(kind=irg) :: cn, dn, totn
real(kind=sgl),target :: bseyield

......

call proc(objAddress, cn, totn, bseyield)

Back on the C++ side of things I have the following as my Callback function:
void MonteCarloSimulationControllerProgress(size_t instance, int loopCompleted, int totalLoops, float bseYield)
{
std::cout << "MonteCarloSimulationControllerProgress: " << instance << "\t"
<< loopCompleted << "\t" << totalLoops << "\t" << bseYield << std::endl;
}

When I run the program I get utter garbage as the variables. They are not pointers, the actual values are not correct and they are not pointers to pointers (that I can tell). I'm very much a beginner at Fortran (I am working to call this Fortran module from C++) but looking around on Google seems to indicate that we have setup our Fortran code correctly (as evidenced by it working from GFortran).

While trying to figure out what was going on I acted on a hunch and changed the "C" side of things to be the following:

typedef void (*ProgCallBackType2)(size_t*, int*, int*, float*);

void MonteCarloSimulationControllerProgress(size_t* instance, int* loopCompleted, int* totalLoops, float* bseYield)
{
std::cout << "MonteCarloSimulationControllerProgress: " << *instance << "\t"
<< *loopCompleted << "\t" << *totalLoops << "\t" << *bseYield << std::endl;
}

And now I get all the proper values passed through. It seems like Fortran is still passing by reference even though we told it by value? If I leave these changes then GFortran segfaults when running?

This is with version 17.0.4.210 with a build on JULY 2016. Is this a known bug? I can't move to a newer compiler because our fortran code will ICE the next revision of the IFORT so we stuck with this version.

Help. I'm lost.

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

The Fortran standard says that VALUE, by itself, passes a writeable copy by reference. If the procedure declaration includes BIND(C), then it does mean pass-by-value. Earlier versions of Intel Fortran didn't get this right, treating VALUE as always meaning pass-by-value. I think it was version 16 that changed this. /assume:nostd_value reverts to the old behavior.

I haven't quite sorted out all you wrote, but I note that the abstract interface ProgressCallback2 doesn't include BIND(C).

If this doesn't help, please attach a small but complete test case that demonstrates the problem.

Steve (aka "Doctor Fortran") - Retired from Intel

Thank You so much. The bind(c) solved the problem.

Quick question to the OP --- did you (or your company) report the ICE in your sources?    That way, we can fix it and you'll be able to move on if necessary.

            thanks -

                         --Lorri

Unfortunately we did not. Which as a software developer is NOT what I would want to hear but it boiled down to time. I would either have had to reduce the issue down to something small that I could give you or give you access to our entire project. I'm not a regular Fortran developer as my main language is C++. I am working with a collaborator who writes the Fortran and I access the Fortran from our C++ Gui so reducing the issue down to something small and reproducible would be beyond my capabilities. Looks like Update 4 is working correctly for us so that is the solution for us. What ever you updated/fixed between update 2 and update 4 seems to have fixed our issue. My collaborator also only develops on macOS and Linux where they use GFortran and I am keeping the cross platform going by running nightly builds on our Windows 10 machine. Such are academic research projects on shoestring budgets.

I do appreciate the followup.

Leave a Comment

Please sign in to add a comment. Not a member? Join today