Ch.9 SML# feature: direct interface to C

§ 9.4. Using dynamically linked libraries

The declaration

val id = _import "symbol" : type

is statically resolved to a C function having the name symbol. When SML# compiles a source file containing this declaration, the compiler generates an object file containing symbol 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.

exp : _import type

exp is a SML# expression of type codeptr. type specifies the type of C function as in _import declaration.

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