wb_call_function

Special warning about wb_call_function()

This function provides access to the Windows API and should be used with great care. This function can easily generate a runtime exception or freeze the PHP application if you omit or mismatch a parameter, or if you add an extra parameter to the array. Worse, if you are using Windows 98 or Me, it is not unlikely to crash the whole system when calling this function. For this reason Windows 98 or Windows Me are not recommended for developing WinBinder applications. Always be careful and double-check your source code before running it when using this function.

int wb_call_function (int address [, array args])

Calls the DLL function pointed by address. args is an optional array of parameters that must match those of the function being called. Returns an integer that may be a valid value or a pointer to one object, according to the library function called.

NOTE: Function arguments are limited to a maximum of 20.

Extending WinBinder with foreign functions

You must perform the following steps to use a foreign function with WinBinder:

  1. Load a DLL that contains the function using wb_load_library().
  2. Get function address with wb_get_function_address().
  3. Declare constants for all structures, if any (detailed below).
  4. Create a PHP function that uses the foreign function using pack() and unpack() to pass and retrieve any structures.
  5. Call the newly declared PHP function as any other regular PHP function. 

Passing and retrieving structures

The pack() function should be used to pass a structure to a foreign function. Similarly, the unpack() function can retrieve structure fields as an associative array. Some common Windows types and their corresponding format characters for pack() / unpack() are listed in the table below.

Windows

ANSI C

pack()

bytes

BYTE

unsigned char

C

1

DWORD

unsigned long

V

4

HANDLE¹

void *

V

4

LONG

long

l

4

LPARAM

long

l

4

LPTSTR, LPCTSTR

unsigned short *

V

4

LRESULT

long

l

4

UINT

unsigned int

I

4

WORD

unsigned short

v

2

WPARAM

unsigned int

I

4


¹ Note: Most Windows and GDI handles, like HINSTANCE, HWND, HACCEL, HBITMAP, HICON etc. are 32-bit handles and should be packed identically.

Defining constants

Up to three constants are needed for each structure. The best way is to define them in advance to improve code readability. For example, the Windows API documentation defines a MEMORYSTATUS structure that is passed to the GlobalMemoryStatus() function to retrieve information about the system memory. The definition is as follows:

typedef struct _MEMORYSTATUS {
    DWORD dwLength;        // sizeof(MEMORYSTATUS)
    DWORD dwMemoryLoad;    // percent of memory in use
    DWORD dwTotalPhys;     // bytes of physical memory
    DWORD dwAvailPhys;     // free physical memory bytes
    DWORD dwTotalPageFile; // bytes of paging file
    DWORD dwAvailPageFile; // free bytes of paging file
    DWORD dwTotalVirtual;  // user bytes of address space
    DWORD dwAvailVirtual;  // free user bytes
} MEMORYSTATUS;

Because the structure consists of eight DWORDs, we can create a constant to format the structure like this:

define("MEMORYSTATUS_RAW",    "VVVVVVVV");

or

define("MEMORYSTATUS_RAW",    "V8");

This is enough to pass the structure to the function. To retrieve the structure, however, we need a different structure so that unpack() function can return an associative array with the field names:

define("MEMORYSTATUS",        "Vlen/Vmemload/Vphys/Vavailphys/Vpagefile/Vavailpagefile/Vvirtual/Vavailvirtual")

Finally, because we must also pass the size of the structure, we define another constant:

define("MEMORYSTATUS_SIZE",   8 * 4);

Examples

The example below shows how to create a new PHP function that calls a Windows function.

<?
include "../include/winbinder.php";                         // Location of WinBinder library

// STEP 1: Load the DLL that contains the function

$KERNEL = wb_load_library("KERNEL");

// STEP 2: Get function address

$fgms = wb_get_function_address("GlobalMemoryStatus", $KERNEL);

// STEP 3: Declare constants for all structures

define("MEMORYSTATUS",        "Vlen/Vmemload/Vphys/Vavailphys/Vpagefile/Vavailpagefile/Vvirtual/Vavailvirtual");
define("MEMORYSTATUS_RAW",    "V8");
define("MEMORYSTATUS_SIZE",   8 * 4);

// STEP 4: Create function that uses foreign function

function GlobalMemoryStatus()
{
    global $KERNEL, $fgms;
 
    $val = pack(MEMORYSTATUS_RAW, MEMORYSTATUS_SIZE,0,0,0,0,0,0,0);
    wb_call_function($fgms, array($val));
    return unpack(MEMORYSTATUS, $val);
}
 
// STEP 5: Use the newly declared PHP function as any other regular PHP function.
 
$mem = GlobalMemoryStatus();
$report =  "Total RAM is " . sprintf("%.2f", ($mem["phys"] / (1024 * 1024))) . " MB, " . $mem["memload"] . "% used";
wb_message_box(null, $report);

?>

The mini-program below shows how to call a Windows function in a single PHP line.

<?
// Shows the current ANSI code-page identifier for the operating system.

include "../include/winbinder.php";

wb_message_box(0, "ANSI code-page identifier: " . wb_call_function(wb_get_function_address("GetACP", wb_load_library("KERNEL"))));

?>

See also

wb_get_function_address
wb_load_library
Low-level functions