Menu

Native function calling

Kalle

Native function calling

V1 can call native functions of dynamic libraries (.dll, .so).

** Load dynamic link library **

<?v1
/* Load the libZ library and return module number
Parameter true means, that libz is a native dynamic link library and no V1 module! */
module = dl ('libz.so', true);
if (!module) {
  print ("Module not found.");
  exit ();
}
?>

** Call a function **

<?v1
/* Call the function "zlibVersion" with no parameters and return const char* (string) */
version = call (module, "zlibVersion", [[], 's']);
?>
Function/Arguments Return Description
call (number module, string function, array paramDef [, mixed arg1 ... ]) mixed Call a native function of a module loaded with dl() function. The array paramDef defines the parameters and return code of native funtion:
[[ 'type of param1' ... 'type of param N' ], 'type of return' ]
For better performance it is recommended to give the parameter definition as string in following format: 'abc:x' where a, b, c are parameter types and x is the return type.

Types and corresponding C datatypes:

Parameter / Return Type Native C datatype V1 datatype Description
i int number Signed integer number
f float number Low precision floting point number (32 Bit)
d double number High precision floting point number (64 Bit)
s const char* or
void*
string 0 terminated string or buffer
p void* or
unsigned int
number Memory pointer or unsigned integer. Memory pointers can be used with memat() to read or memset() to write memory data. memref() return a reference pointer to the memory buffer of a V1 string.
To navigate through the memory, the offset in constant _ALIGN can be used where the default byte align is defined (4 on 32 Bit, 8 on 64 Bit versions of V1).
r void* &string Reference to V1 string which can be written by native function.
Enough buffer must be allocated with resize() or binformat() function.
<?v1
src = "String to compress with ZLib native function.";

/* Make enough destination buffer */
dst = ""; 
resize (dst, strlen (src));

/* The length of the desination buffer as binary string */
len = binformat (strlen (src),7);

/* Call the native function which is defined as:
 int compress (void *destBuf, int *destLen, const char* srcBuf, int sourceLen);
 dst and len are reference parameters and filled with binary data by native function. */
ret = call (module, "compress", "rrsi:i", dst, len, src, strlen(src));
if (ret===0) {
  /* Parse the binary length and truncate destination string */
  len = binparse (len,7);
  resize (dst, len);

  print ("Compressed string: ", dst);
}
?>

**Example 2 **

<?v1
/* Show a multibyte message box on Windows by calling two native functions */
hDLLUser32 = dl ('user32.dll', true);
hDLLKernel32 = dl ('kernel32.dll', true);

function MultiByteToWideChar (src) {
  global hDLLKernel32;
  dst = "";
  resize (dst, strlen(src)*2+2); // Make enough buffer for wide char string
  size = call (hDLLKernel32, "MultiByteToWideChar", "iisiri:i",  65001, 0, src, -1, dst, strlen(src)+1);
  if (size>0)
    resize (dst, size*2);  // Resize to correct length (byte aligned)
  return dst;
}

function MessageBox (text, topic="Info") {
    global hDLLUser32;
    call (hDLLUser32, "MessageBoxW", "pssi:i", null, MultiByteToWideChar(text), MultiByteToWideChar (topic), 0|0x00000030);
}

if (hDLLKernel32) {
    MessageBox ("специальный символ");
}
?>

** Working with callbacks**

There are 8 callback functions, which can be referenced by dlsym() to get the pointer address for a native function.

/* 
 This function is called from a native function as a callback with one argument.
 The pointer address of the callback function is given to a native function with dl (null, "callbackXX");
 Note:
 All arguments are V1 unsigned numbers which can be interpreted as C types void* or unsigned int with length of _ALIGN. 
 You have to cast the V1 number according different C types in the callback function.
 The return type is always C type int.
*/

function callbackA1 (arg1) {
  /* Cast the argument to const char* and V1 string */
  s = memat (binformat (param1));
  print (s);

  /* Cast the argument to int and V1 number */
  i = binparse (binformat (arg1), 7, 0, 1);  
  print (i);

  /* Cast the argument to double and V1 number */
  d = binparse (binformat (arg1), 6);  
  print (d);

  return 0;
}

/* Give a native function the callback pointer */
call (hDLL, "nativeFunction", "ps:i", dlsym (null, "callbackA1"), "Argument");

/* Following callback functions are possible to call with __cdecl calling conversion */
function callbackA1 (arg1) {
}

function callbackA2 (arg1, arg2) {
}

function callbackA3 (arg1, arg2, arg3) {
}

function callbackA4 (arg1, arg2, arg3, arg4) {
}

function callbackB1 (arg1) {
}

function callbackB2 (arg1, arg2) {
}

function callbackB3 (arg1, arg2, arg3) {
}

function callbackB4 (arg1, arg2, arg3, arg4) {
}

/* Following callback functions are possible to call with __stdcall calling conversion
 __stdcall will be used only by WIN32 Callback functions, thats why the 
 following callback functions are not available on Linux */

function std_callbackA2 (arg1, arg2) {
}

function std_callbackA3 (arg1, arg2, arg3) {
}

function std_callbackA4 (arg1, arg2, arg3, arg4) {
}

See also enhanced example: Connect to MySQL database

back to Home