Enhancing your Xbase++ applications
Home Contact Info
 
©2006. Pablo Botella
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.
xppcbk.exe uses and include the free asm compiler FASM.EXE to create the resulting OBJ make sure FASM.EXE is in the same folder as xppcbk.exe or in a folder pointed by your path environment var. Read the FASM_LICENSE.TXT file inside the xppcbk.zip package or visit the flat assembler main page www.flatassembler.net for more info about the FASM license.

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 fullfill the required prototype and act as a proxi betwen 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 proxi 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 writting our PRG

// ------------  TEST.PRG  ------------ 
#include  "dll.ch"
// ------------------------------------ 
function Main()
? (EnumWindows( _callback_MyEnumWndProc() , 0 ) != 0)

The function _callback_MyEnumWndProc() will return a pointer to our proxi function.

inkey(0)
return NIL
// ------------------------------------ 
DLLFUNCTION EnumWindows(pProc,nParam) USING STDCALL FROM User32.DLL
DLLFUNCTION GetWindowTextA(hWnd,@cBuffer,nSize) USING STDCALL FROM User32.DLL
// ------------------------------------ 

The next step will be to create our Xbase++ called function.

function MyEnumWndProc( hWnd , nCargo )
local cBuffer := Space(256)
local nLen    := GetWindowTextA(hWnd,@cBuffer,256)
local cStr    := Left(cBuffer,nLen)
if !Empty( cStr ) 
   ? ConvToOemCP( cStr)
end
return .T.
// ------------------------------------ 

The proxi function will call our MyEnumWndProc() providing the 2 parameters and will pass back the return value of MyEnumWndProc() as the result of the proxi 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