- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
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!
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.)
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.)
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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).
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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.)
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
thanks for your reply, I solved this problem.
You are right! we must use __cdecl for callback function ,not __stdcall
You are right! we must use __cdecl for callback function ,not __stdcall
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page