Native function calling (NFC)
V1 can call native functions of dynamic libraries (.dll, .so).
Load dynamic link library
// 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
// Call the function "zlibVersion" with no parameters and return const char* (string)
version = call (module, "zlibVersion", ":s");
Function/Arguments | Return | Description |
---|---|---|
dlsym (number module, string symbol) | number | Get pointer address of symbol in module loaded with dl() function. On success pointer address is returned. If symbol is not found false is returned. |
call (number module, mixed function, mixed paramDef [, mixed arg1 ... ]) | mixed | Call a native function of a module loaded with dl() function. The function can also be a memory pointer (number) returned from dlsym(). The array or string 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. See list of types below. |
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 functions. Enough buffer must be allocated with resize() or binformat() function. |
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));
// Call the native function which is defined as:
// int compress (void *dstBuf, int *dstLen, const char* srcBuf, int srcLen);
// 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);
resize (dst, len);
print ("Compressed string: ", dst);
}
Example 2
// 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 11 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*
s = memat (arg1);
print (s);
// Cast the argument to int (signed)
i = binparse (binformat (arg1), 7, 0, 1);
print (i);
// Cast the argument to float
d = binparse (binformat (arg1), 5);
print (d);
return 0;
}
// Give a native function the callback pointer
call (hDLL, "nativeFunction", [["p", "s"], "i"], dlsym (null, "callbackA1"), "Argument");
// Following callback functions are possible to call with __cdecl calling convention
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 convention
// __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: Binary functions and example X11 Window.
V1 Version 0.96 - Documentation generated Sun, 05 May 2024 07:59