xppcbk.exe generate a OBJ from a simple syntax script allowing your Xbase++ functions act as true callbacks in any API that require a callback pointer.
In this example we will use the winapi function EnumWindows() that require a pointer to a custom __stdcall function with the following prototype.
BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam);
Because Xbase++ functions cannot be called directly like a C function we will need a intermediate function that fulfill the required prototype and act as a proxy between the caller function and our Xbase++ function.
And this is just the task of our callback compiler so as the first we will create a cbk script file that will produce a .obj with the callback proxy function.
// --------- CALLBACKS.CBK ---------
BEGIN CALLBACK MyEnumWndProc AS BOOL
PARAM HANDLE // hWnd
PARAM DWORD // dwCargo
END CALLBACK
// -------------------------------
Then in our build.bat or from the command line we call the callback compiler to get callbacks.obj from callbacks.cbk ready to be linked or included in our project.
C:\sample>XPPCBK CALLBACKS.CBK
Callback Compiler for Xbase++ Ver 1.0
(c) Pablo Botella Navarro. (2006) http://www.xbwin.com
Compiling CALLBACKS.CBK ...
flat assembler version 1.64
3 passes, 1216 bytes.
C:\sample>
Now we can start writing our PRG
// ------------ TEST.PRG ------------
#include "ot4xb.ch"
// ------------------------------------
function Main()
? EnumWindows( _callback_MyEnumWndProc() , 0 )
The function _callback_MyEnumWndProc() will return a pointer to our proxy function.
inkey(0)
return NIL
// ------------------------------------
DLL USER32 IMPORT BOOL EnumWindows( POINTER32 fpEnum, LPARAM lp)
// ------------------------------------
DLL USER32 IMPORT int GetWindowText( HWND hWnd,LPSTR pStr, int nSize) ;
SYMBOL GetWindowTextA
// ------------------------------------
The next step will be to create our Xbase++ called function.
function MyEnumWndProc( hWnd , nCargo )
local cBuffer := ChrR(0,256)
local nLen := GetWindowText(hWnd,@cBuffer,256)
local cStr := Left(cBuffer,nLen)
if !Empty( cStr )
? ConvToOemCP( cStr)
end
return .T.
// ------------------------------------
The proxy function will call our MyEnumWndProc() providing the 2 parameters and will pass back the return value of MyEnumWndProc() as the result of the proxy callback.
Now our project file will be something like this:
// ------------ TEST.XPJ ------------
[PROJECT]
COMPILE = xpp
COMPILE_FLAGS = /n/m/w
GUI = yes
LINKER = alink
PROJECT.XPJ
[PROJECT.XPJ]
Test.exe
[Test.exe]
Test.prg
callbacks.obj