10.4 Using dynamically linked libraries
The declaration
val = _import "" :
is statically resolved to a C function having the name . When SML# compiles a source file containing this declaration, the compiler generates an object file containing as an external name. When an executable program is build from these objects files, the system linker links these object files with C functions. This is also true in interactive mode, which is implemented by a simple iteration that performs separate compilation, linking and loading.
However for a library that is only available at runtime, such static resolution is impossible. To cope with those situation, SML# provide dynamic linking through the following module.
structure DynamicLink : sig
type lib
type codeptr
datatype scope = LOCAL | GLOBAL
datatype mode = LAZY | NOW
val dlopen : string -> lib
val dlopen’ : string * scope * mode -> lib
val dlsym : lib * string -> codeptr
val dlclose : lib -> unit
end
These functions provide the system services of the same names provide in a Unix-family OS.
-
•
dlopen opens a shared library.
-
•
dlopen’ takes one of those parameters to control dlopen. RTLD_LOCAL, RTLD_GLOBAL and RTLD_LAZY, RTLD_NOW. For its details, consult OS manual on dlopen.
-
•
dlsym takes a library handle obtained by dlopen and a function name, and returns a C pointer to the function.
-
•
dlclose closes the shared library.
The C pointer returned by dlsym can be converted to SML# function by the following expression.
: _import
is a SML# expression of type codeptr. specifies the type of C function as in _import declaration.
Figure 10.2 shows an example.
samle.c file:
int f(int s) {
return(s * 2); } Execution: $ gcc -shared -o sample.so sample.c $ smlsharp SML# version 1.00 (2012-04-02 JST) for x86-linux # val lib = DynamicLink.dlopen "sample.so"; val lib = _ : lib # val fptr = DynamicLink.dlsym(lib, "f"); val fptr = ptr : unit ptr # val f = fptr : _import int -> int; val f = _ : int -> int # f 3; val it = 6 : int |