Software Archive
Read-only legacy content
17061 Diskussionen

Function Pointers

Intel_C_Intel
Mitarbeiter
673Aufrufe
Several Windows API's require the address of a function (MyFunc, say) as input. As far as I can make out, the rules-of-behavior of CVF's (%)Loc extension in conjunction with use of integer (Cray-style) pointers prohibit passing the address of MyFunc. The only way around that I can conjur up is that if MyFunc is in a MyDLL then its address is GetProcAddress(LoadLibrary('MyDLL'C),'MyFunc'C) assuming MyFunc is an export. But if I don't want to export MyFunc, what's my alternative? Does F2K's interoperability-with-C impact on what I'm trying to do?

Thanks,
Gerry T.
0 Kudos
6 Antworten
Jugoslav_Dujic
Geschätzter Beitragender II
673Aufrufe
Not 100% sure to me what you're trying to do. Nothing prohibits
you from using LOC() on an existing function, for example
when subclassing a window:

 
lpfnOldWindowProc=SetWindowLong(hWnd, GWL_WNDPROC, LOC(MyWindowProc)) 


If your function is pointee of an integer-pointer, simply pass
the integer pointer once it receives a valid value. Thus, you don't
need mesing with DLLs.


Or am I missing something?

Jugoslav
Steven_L_Intel1
Mitarbeiter
673Aufrufe
Right - as long as CVF knows it's a procedure (either there's an INTERFACE or an EXTERNAL declaration), you can pass LOC(routine), if the argument is declared as an integer. If the Fortran INTERFACE declared the argument as a procedure, then pass the procedure name directly (not an issue with Win32 API routines).

Steve
Intel_C_Intel
Mitarbeiter
673Aufrufe
Did you try this? Surely LOC(MyWindowProc) is the name of an internal procedure which (%)LOC doesn't allow?

--
Gerry T.
Intel_C_Intel
Mitarbeiter
673Aufrufe
I want to call SetConsoleCtrlHandler as interfaced in kernel32.


the code snippet

:  
interface   
subroutine SetCtrlHandler(hConOut)  
integer hConOut  
end subroutine SetCtrlHandler  
end interface  
call SetCtrlHandler(hwnd)  
:  
:  
logical(4) function handler(dwCtrlType)  
:  
!Success  
handler = 1  
return  
end function handler  
  
subroutine SetCtrlHandler(hConOut)  
  
use dfwinty  
use kernel32, only: SetConsoleCtrlHandler  
  
implicit none  
  
interface  
logical(4) function MyHandler(hConOut)  
integer hConOut  
end function MyHandler  
end interface  
  
external handler  
pointer(ptr_handler,MyHandler)  
integer hConOut  
logical(4) status  
integer, external :: MyHandler  
ptr_handler = Loc(handler)  
status = SetConsoleCtrlHandler(Myhandler,.true.)  
  
end subroutine SetCtrlHandler  



the equivalent code snippet is

:  
interface   
subroutine SetCtrlHandler[C,ALIAS:'_SetCtrlHandler'] (hConOut)  
integer hConOut  
end subroutine SetCtrlHandler  
end interface  
call SetCtrlHandler(hwnd)  
:  
:  
#include   
#include   
#include   
  
BOOL WINAPI handler(DWORD dwCtrlType)  
{  
:  
	return(TRUE);  
}  
  
void SetCtrlHandler(HANDLE hConOut)  
{  
  BOOL status;  
  
  //Set custom handler for process  
  status = SetConsoleCtrlHandler(handler, TRUE);  
      
  return;  
}  


This Fortran/C version works (and so does the handler) but the all Fortran version doesn't even compile due to 1 or 2 errors, viz:
1. at the statement
integer, external :: MyHandler
Error: This name has already been used as an external procedure name. [MYHANDLER]
2. at the statement
status = SetConsoleCtrlHandler(Myhandler,.true.)
Error: This actual argument must not be the name of a procedure. [MYHANDLER]

If I remove the interface to MyHandler, the first error goes away and the secord error changes to
Error: This actual argument must not be the name of a procedure. [MYHANDLER]

Can someone kindly tell me what's wrong with the all Fortran version?

Thanks,
Gerry T.
Steven_L_Intel1
Mitarbeiter
673Aufrufe
The interface block defines MyHandler, so your EXTERNAL declaration is redundant. Remove it. Use loc(MyHandler) in the call to SetConsoleCtrlHandler.

Warning - this code may not work correctly unless you compile with /fpscomp:logicals. CVF LOGICAL is not the same as C BOOLEAN, which is what the Win32 API uses. I suggest making MyHandler INTEGER instead of LOGICAL and passing TRUE (from DFWINTY) instead of .TRUE. - these are different values.

Steve
Intel_C_Intel
Mitarbeiter
673Aufrufe
Excellent. Thanks Steve and Jugoslav. Now the all Fortran version works and so does the handler.

Ciao,
Gerry T.
Antworten