ICI Modules: dll


Modules by name : by type

Overview

This describes the use of the ICI dynamically loaded extention module dll. This module allows the calling of pre-existing functions defined in dynamic load libraries directly from ICI without any explicitly compiled linkage. For example, under Windows one may execute:

    dll.user32.MessageBox
    (
        "int",
        NULL,
        "Test of call to dll.user32.MessageBox(...)",
        "ICI DLL call test",
        0/*MB_OK*/
    );

    

In general this is a dangerous operation and there are several caveats. One must exercise as much care, or more, as one would when writing ordinary C.

Usage in brief

A function in a DLL can be called with:

	ret = dll.dll-name.func-name(ret-type, ...)

    
Where:
ret
Will be an object of the type declared by ret-type.
dll-name
Is the name of a DLL. Extensions will be added and paths searched as necessary to convert this name to a specific DLL (see below for details).
func-name
Is the name of a function to be found in that DLL. Compiler name decoration (such as leading underscores) will be added as necessary and callings conventions deduced as best as possible (see below).
ret-type
Is a string declaring the type returned by this function. Currently only "int" is supported, which should be used for all 32 (or less) bit integral quantities including pointers.
...
Represents arguments to be passed to the function.

Actual arguments to the DLL function are fabricated from the ICI arguments given in this call according to the following rules:

ICI argument Raw argument
an int A 32 bit integral value, generally suitable for smaller sizes too.
a string A pointer to the read-only chars. This will be '\0' terminated, although embedded '\0's will obviously cause problems. The string must not be modifiled.
NULL A 32 bit zero.
an pointer to an int A pointer to a 32 bit integral value. The integral value may be modified by the function, which will cause the ICI int to be updated accordingly.
a mem object A pointer to the read-write memory. Care must be exercised not to allow over-runs etc.

As long a DLLs and functions are referred to with the same names, repeated calls are efficient and do not cause repeated library loads or function lookups.

Detailed usage

Use of this extension requires that the ICI extension module

icidll.???
(where ??? is the local system dynamic load library suffix) be present in a suitable location. On first reference of the identifier
dll
the ICI interpreter will load the extention module in the normal fashion. The extenstion module will cause a single object of type dllmanager to be assigned to dll.

This object supports fields in the manner of a struct, except that reference to a previsously undefined field is interpreted as a request to load a DLL of that name, and if successful, assign it to that same field and return it. Subsequent lookups of that field merely return the previsouly assigned object.

When a name is resolved to a DLL, attempts are made to resolve it to a specific file by, possibly, adding extensions and searching for the file in various directories as is appropriate for the local system. (Under Windows the name is looked up as if by LoadLibrary()). It should be noted that refering to the same DLL by two different name will result in two independent loads of the DLL.

Each loaded DLL is represented by an object of type DLL. this also acts like a struct, with a similar side effect that references to undefined elements causes an attempt to resolve the name to a function of that name in the DLL.

###MORE TO FOLLOW###

A more complex example (Windows)


    static HKEY_CURRENT_CONFIG = 0x80000005;
    static KEY_QUERY_VALUE = 1;
    static value_type = 0;
    static valuez = 128;
    static value = alloc(valuez);
    static key_handle = 0;
    static ecode;

    ecode = dll.advapi32.RegOpenKeyEx
    (
        "int",
        HKEY_CURRENT_CONFIG,
        "Display\\Settings",
        0,
        KEY_QUERY_VALUE,
        &key_handle
    );
    if (ecode != 0)
        fail(sprintf("Failed to RegOpenKeyEx(), returned %d.", ecode));
    ecode = dll.advapi32.RegQueryValueEx
    (
        "int",
        key_handle,
        "Resolution",
        0,
        &value_type,
        value,
        &valuez
    );
    if (ecode != 0)
        fail(sprintf("Failed to RegQueryValueEx(), returned %d.", ecode));

    static
    cstring(m)
    {
        auto    a, c, i;
        auto    vargs = [array 0];

        a = array();
        for (i = 0 + vargs[0]; i < nels(m); ++i)
        {
            if ((c = m[i]) == 0)
                break;
            push(a, c);
        }
        return implode(a);
    }

    dll.user32.MessageBox
    (
        "int",
        NULL,
        sprintf("HKEY_CURRENT_CONFIG\\Display\\Settings\\Resolution = %s",
        cstring(value)),
        "ICI DLL call test",
        0/*MB_OK*/
    );