Ch.6 SML# feature: direct interface to C

§ 6.4. Using dynamically linked libraries

The declaration

val id = _import string : type

is statically resolved to a C function having the name string. When SML# compiles a source file containing this declaration, the compiler generates an object file containing string 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 =
struct
     type lib (= ptr)
     datatype scope = LOCAL | GLOBAL
     datatype mode = LAZY | NOW
     val dlopen : string -> lib
     val dlopen' : string * scope * mode -> lib
     val dlsym : lib * string -> unit ptr
     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.

exp : _import type

type specifies the type of C function as in _import declaration.

Figure 6.3 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
Figure 6.3. Using dynamic link library