class jnc.DynamicLib

Overview

This class provides direct access to functions in dynamic libraries (also known as shared libraries). More…

class DynamicLib {
    // fields

    void thin* readonly m_handle;

    // properties

    bool const property m_isOpen;

    // construction

    destruct();

    // methods

    bool errorcode open(string_t fileName);
    void close();
    void thin* errorcode getFunction(string_t name);

    // aliases

    alias dispose = close;
};

Detailed Documentation

This class provides direct access to functions in dynamic libraries (also known as shared libraries).

You can use jnc.DynamicLib in one of the two ways.

One way is to explicitly load a dynamic library by file name, resolve function names to pointers, (unsafely)cast these pointers to appropriate function pointer types, and then call these function pointers:

void foo() {
    jnc.DynamicLib lib;
    lib.open("libname"); // load library
    void thin* p = lib.getFunction("foo"); // resolve function by name

    typedef void stdcall FooFunc(int); // specify function type

    unsafe {
        FooFunc thin* foo = (FooFunc thin*)p; // cast to the proper type
    }

    foo(100); // call this function

catch:
    // handle error...
}

Alternatively, you can declare a pseudo-interface using dylib keyword, and then simply call methods of this interface. Eventually it will result in the same sequence of steps, and even the base implementation class will be the same, jnc.DynamicLib. But all the above steps will be done behind the scene – Jancy compiler will generate necessary calls automatically. Moreover, once the resolve completes, the result is cached, so the next time you call the same functions, cached pointer will be used and no repetitive resolve-by-name is going to happen.

Needless to say, this is the preferred approach:

dylib MyLib { // will use jnc.DynamicLib behind the scene
    void stdcall foo(int);
}

void foo() {
    MyLib myLib;
    myLib.open("libname"); // load library
    myLib.lib.foo(100); // resolve, cache and call

catch:
    // handle error...
}

Please note that when accessing functions from the dynamic library(foo in the example above), you need to prefix it with lib. qualifier – this design was chosen to avoid conflicts between library functions and jnc.DynamicLib members.

Fields

void thin* readonly m_handle

This field holds the native handle of the dynamic library(HMODULE returned by LoadLibraryW on Windows, void* returned by dlopen on POSIX)

Usually, you should ignore this field – unless you plan to do some platform-dependent low-level magic.

Properties

bool const property m_isOpen

Holds the open status for the dynamic library, i.e. true if opened; false otherwise.

Methods

bool errorcode open(string_t fileName)

Opens (loads) a dynamic library.

The function accepts a single fileName argument, which specifies the name of the library-containing file.

Returns true on success. If the dynamic library could not be loaded, IO error supplied by the dynamic loader of the operating system is set and then the function returns false [1].

void close()

Closes (releases) a previously loaded dynamic library, does nothing if no library is loaded. This function always succeeds.

Sometimes it may be convenient to use disposable pattern to ensure timely invokation of close [2].

void thin* errorcode getFunction(string_t name)

Resolves a function name in the previously loaded dynamic library.

The function accepts a single name argument, which specifies the name of the function. Note that if this is a C++ function, name should be properly mangled. On the other hand, C functions do not have to be prefixed with underscore character _.

Returns abstract pointer(void thin*), which then has to be cast to a thin function pointer of the proper type(e.g., void thin function* (int).

If the function name could not be resolved, IO error supplied by the dynamic loader of the operating system is set and then the function returns null [1].

Aliases

alias dispose = close

Effectively makes jnc.DynamicLib a disposable class [2].


Footnotes