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