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


Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.