Call methods of a dynamic library

exec_dll_method()

Execute any exported method in a dynamic library

Version >= 6.2.0


SYNTAX

exec_dll_method(calling_convention, library, method_name [, ret, arg1, arg2,…])

This function permits execution of exported methods in a dynamic library (*.dll on Windows or *.so on *nix). Making it possible to execute methods writen in “C” or other languages or execute Windows WIN32 API functions (see example below). The dll should be 32 or 64 bits to match the 32/64 bit Sculptor interpeter.

calling_convention

See the possible CC_ definitions as defined in <sculptor.h>

library

The dynamic library that contains the method to be called. Normal OS rules apply to locate the library (it is not always needed to specify the absolute path).

method_name

The method to execute from the dynamic library.

ret

This parameter,if defined and different from NULL, must be a !temp, a field (inside !record/!file) or a !record/!file. That object will receive the method_name execution return value. Sculptor uses the object or field type to work out the return value type of the method, see the equivalences below

arg*

A variable number of method arguments may follow the return value. When an argument is a literal value or a field/!temp the value is passed to the method by value (long, long long, double, char*…). When an argument is a !record/!file the value is passed by reference. For example when passing a !record with only an i4 inside it is like passing an “int*”. In this latter case values changed by the method are copied back to the sculptor object. The dll method must then declare its arguments appropriately as pointers or specific data types.

When dealing with literal or field/!temp values it is not possible to determine what type of integer (char, short, long or long long) or double (float or double) the argument is. Therefore we pass always a double (32 and 64 bit platforms), a long long (64 bit platforms) and long (32 bits platforms). An exception is if the integer is greater than MAXI4 or less than MINI4 then a long long is used even on 32 bit platforms.

A successful call of the method results in exec_dll_method() returning zero. Otherwise the return value is an error code , such as EXEC_DLL_LOAD which would be returned if ,for example, the dll could not be found. This return value should not be confused with the ret parameter above. See the EXEC_DLL_ return values as defined in <sculptor.h>.

These are the equivalences when converting between Sculptor the C code:

Sculptor object type

Library C type

Field i1/u1

char/unsigned char

Field i2/u2

short/unsigned short

Field i4/u4

int/unsigned int

Field i8/u8

long long/unsigned long long

Field a#

char *

Field r4/r8

float/double

!record/!file

struct *

Not defined or NULL

void (no return value)

Important: In the case of setting ret to be a !record or !file, the method’s returned value should to point to a structure equivalent to the Sculptor one (we can even define subrecords). So care must be taken to replicate the structure members in the dll with the correct types (taking into account the equivalences above ), without skipping a field and maintaining the same order.

In Windows, where there are ASCII and Unicode versions to choose from, the ASCII version must be chosen. For example in kernel32.dll the GetVersionEx method has two options GetVersionExA and GetVersionExW. The GetVersionExA has to be chosen.

Note: To provide this functionally Sculptor makes use of the dyncall library (External ink)


EXAMPLES

!include <sculptor.h>

!record verInfoRec {
    dwOSVersionInfoSize,,u4
    dwMajorVersion,,u4
    dwMinorVersion,,u4
    dwBuildNumber,,u4
    dwPlatformId,,u4
    szCSDVersion,,a128
}

!temp exec_dll_res,,i4
!temp get_vers_res,,i4

/*********************************************************************************/

/* Exec GetVersionExA to get the Windows version information */
clear verInfoRec
verInfoRec.dwOSVersionInfoSize = 148 /* (5 x 4) + 128 */

exec_dll_res = exec_dll_method(CC_X86_WIN32_STD, "Kernel32.dll", "GetVersionExA", get_vers_res, verInfoRec)

if (exec_dll_res != EXEC_DLL_OK) {
    error "exec_dll_method error: " + tostr(exec_dll_res)
    exit 1
}

if (get_vers_res = 0) {
    error "GetVersionExA error"
    exit 1
}

prompt "Major=" + tostr(verInfoRec.dwMajorVersion) + " Minor=" + tostr(verInfoRec.dwMinorVersion)
exit 0

In the example above the args are passed by reference. The following skelton example shows args passed by value:

!include <sculptor.h>

!temp TestInt,,i4
!temp TestChar,,a32

!temp exec_dll_res,,i4
!temp get_res,,i4

/*********************************************************************************/

exec_dll_res = exec_dll_method(CC_X86_WIN32_STD, "TestDll.dll", "TestMethod", get_res, TestInt, TestChar)

if (exec_dll_res != EXEC_DLL_OK) {
    error "exec_dll_method error: " + tostr(exec_dll_res)
    exit 1
}

RELATED TOPICS

execute()

exec