SML# - Resources/ProgrammingExamples/CallBack Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

Many C libraries such as Tcl_Tk require callback functions to be passed
as their arguments.
In SML#, you can just pass your own SML# functions directly.
Moreover, argument functions can be higher-order.

[[This file|smlsharp:examples/callback/callback.c]]
contains (somewhat artificial) example C functions that take
higher-order function and return higher-order functions.
Among them are the following:
void f1(void(*f)(void(*)(void(*)(void(*)(void(*)(void(*)(void)))))))
void (*(*(*g1(void))(void))(void))(void)
In SML# type system, they corresponds restectively below:
f1 : (((((unit -> unit) -> unit) -> unit) -> unit) -> unit) -> unit
g1 : unit-> unit -> unit -> unit -> unit
So, you can simply call them by writing the following simple SML# code:
  val lib = DynamicLink.dlopen "./callback.so"
  val sym1 = DynamicLink.dlsym (lib, "f1")
  val sym2 = DynamicLink.dlsym (lib, "g1")
  val f1 = sym1 : _import (((((()->unit)->unit)->unit)->unit)->unit)->unit
  val g1 = sym2 : _import ()->()->()->()->unit
  
  val () =
      f1 (fn h1 =>
             (print "h1\n";
              h1 (fn h2 =>
                     (print "h2\n";
                      h2 (fn h3 =>
                             print "h3\n")))))
  
  val g2 = g1 ()
  val g3 = g2 ()
  val g4 = g3 ()
  val () = g4 ()
The following is the result of evaluation.
  $ gcc -shared -o callback.so callback.c
  $ smlsharp
  SML# 0.10 (2007-03-17 11:39:26)
  use "callback.sml";
  # val lib = 0x083e11d0 : unit ptr
  val sym1 = 0x4515489c : unit ptr
  val sym2 = 0x45154916 : unit ptr
  val f1 =
      fn : (((((unit  -> unit)  -> unit)  -> unit)  -> unit)  -> unit)  -> unit
  val g1 = fn : unit  -> unit  -> unit  -> unit  -> unit
  f1
  h1
  f2
  h2
  f3
  h3
  g1
  val g2 = fn : unit  -> unit  -> unit  -> unit
  g2
  val g3 = fn : unit  -> unit  -> unit
  g3
  val g4 = fn : unit  -> unit
  g4
  #