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

a strange problem in call C/C++ function in Fortran

hjh2008
Beginner
408 Views
I encountered a strange problem when i call C/C++ function in Fortran,the Code as follows:

function RXDProcess(inArray,rows,cols,ProgressFunc) BIND(c,name='RXDProcess')
use,intrinsic :: ISO_C_BINDING
use mkl95_lapack, only: sytrf,sytri
implicit none
!DEC$ IF DEFINED (_DLL)
!DEC$ ATTRIBUTES DLLEXPORT :: RXDProcess
!DEC$ END IF
interface
function ProgressFunc(num)
use,intrinsic :: ISO_C_BINDING
implicit none
integer(c_int) :: num
logical :: ProgressFunc
end function
end interface
...
do r=1,10 !! r=1,5 is ok
...
bb=ProgressFunc
end do
call sytrf(covArray,'U',ipiv,info) !! error!
...
return
end function


the ProgressFunc is the callback function to show the Algorithm's progress,the problem is:
when i call ProgressFunc 5 times then call sytrf(), the function runs ok. But when i call ProgressFunc more than 5 times then call sytrf(), the function will occurred an error,the runtime error message is:
Unhandled exception at 0x00000005 in FortranDllTest.exe: 0xC0000005: Access violation reading location 0x00000005.

and i must call the callback function more than 5 times, How can i do? thanks advance!
0 Kudos
1 Solution
IanH
Honored Contributor II
408 Views
Your C prototype (that statement doesn't "invoke" the function, it just declares what its interface looks like to the C compiler) for RXDProcess has more arguments that your Fortran declaration! What is supposed to happen to bands and outArray?

What does the actual invocation of RXDProcess look like?

What are the Fortran declarations for the other arguments in RXDProcess?

What is CE_DLLCALL defined as? Does that make the calling convention for the callback function stdcall? (If so, you have a calling convention mismatch that will corrupt your programs stack. In that case you need to adjust the interface block to include the STDCALL attribute and add the REFERENCE attribute to the argument. Typically the ProgressFunc argument in RXDProcess would be of type C_FUNPTR, passed by value. You then use the C_F_PROCPOINTER procedure to associate that C function pointer with a fortran procedure pointer. I'm not sure how stdcall might interact with this.)

Which C compiler are you using, what C and Fortran compile options are you using, etc, etc, etc...

At the moment I'm a bit surprised that you were able to make one call, let alone five!

(Are you compiling C or C++? C++'s bool is not necessarily interoperable with Fortran's logical. Consider making the return type of that function int and return a zero, then adjust the Fortran interface accordingly.)

View solution in original post

0 Kudos
4 Replies
IanH
Honored Contributor II
408 Views
Please show the definition (if it is a C function then show its prototype) of ProgressFunc.

If ProgressFunc is a C function then you are missing the BIND(C) suffix on the function statement in the interface block. Similarly if ProgressFunc really does return something of type _Bool then its return type should be declared LOGICAL(C_BOOL).

0 Kudos
hjh2008
Beginner
408 Views
thanks for your reply!
the definition of ProgressFunc is :
typedef bool (CE_DLLCALL * ProgressFunc)(int*);

and the implement is:
bool CE_DLLCALL PrintProgress(int *i)
{
printf("progress=%d\n",*i);
return false;
}


the invoke statement
int RXDProcess(float *inArray,int rows,int cols,int bands,float *outArray,ProgressFunc pf);

the question is: why can call the ProgressFunc only less than 5 times?
0 Kudos
IanH
Honored Contributor II
409 Views
Your C prototype (that statement doesn't "invoke" the function, it just declares what its interface looks like to the C compiler) for RXDProcess has more arguments that your Fortran declaration! What is supposed to happen to bands and outArray?

What does the actual invocation of RXDProcess look like?

What are the Fortran declarations for the other arguments in RXDProcess?

What is CE_DLLCALL defined as? Does that make the calling convention for the callback function stdcall? (If so, you have a calling convention mismatch that will corrupt your programs stack. In that case you need to adjust the interface block to include the STDCALL attribute and add the REFERENCE attribute to the argument. Typically the ProgressFunc argument in RXDProcess would be of type C_FUNPTR, passed by value. You then use the C_F_PROCPOINTER procedure to associate that C function pointer with a fortran procedure pointer. I'm not sure how stdcall might interact with this.)

Which C compiler are you using, what C and Fortran compile options are you using, etc, etc, etc...

At the moment I'm a bit surprised that you were able to make one call, let alone five!

(Are you compiling C or C++? C++'s bool is not necessarily interoperable with Fortran's logical. Consider making the return type of that function int and return a zero, then adjust the Fortran interface accordingly.)
0 Kudos
hjh2008
Beginner
408 Views
thanks for your reply, I solved this problem.

You are right! we must use __cdecl for callback function ,not __stdcall
0 Kudos
Reply