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