1(* mosml/src/dynlibs/interface/smlside.sml -- foreign function interface.
2   How to pass SML values to C functions, and how to pass them back.
3   The SML side of things.                 sestoft@dina.kvl.dk 1998-05-05 *)
4
5(* Load the Dynlib and FileSys structures from the Moscow ML library: *)
6
7app load ["Dynlib", "FileSys"];
8
9open Dynlib;
10
11(* Obtain a handle pointing to the library defining the C functions: *)
12
13val dlh = dlopen { lib = "libdside.so",
14                   flag = RTLD_LAZY,
15                   global = false }
16
17(* Define SML functions using this handle.  The type ascriptions are
18   necessary for SML type safety:
19 *)
20
21(* Passing and returning base types: unit, int, char, real, string, bool: *)
22
23val fu : unit   -> unit   = app1 (dlsym dlh "cfu")
24val fi : int    -> int    = app1 (dlsym dlh "cfi")
25val fc : char   -> char   = app1 (dlsym dlh "cfc")
26val fr : real   -> real   = app1 (dlsym dlh "cfr")
27val fs : string -> string = app1 (dlsym dlh "cfs")
28val fb : bool   -> bool   = app1 (dlsym dlh "cfb")
29
30(* Passing several curried arguments: *)
31
32val fcur : int -> char -> real -> string -> bool -> int =
33    app5 (dlsym dlh "cfcur")
34
35(* Passing a tuple: *)
36
37val ftup : int * char * real -> int =
38    app1 (dlsym dlh "cftup")
39
40(* Passing a record: *)
41
42val frec : { surname : string, givenname : string, age : int } -> bool =
43    app1 (dlsym dlh "cfrec")
44
45(* Passing a constructed value belonging to a datatype:
46   It is advisable to declare the constructors in alphabetical order
47   since Moscow ML 2.00 and later sorts them anyway, and the C side
48   must use the tags (0, 1, ...) of the sorted constructors.
49*)
50
51datatype t =
52    Br of int * t * t
53  | Brs of t list
54  | Lf
55
56val fdat : t -> int =
57    app1 (dlsym dlh "cfdat")
58
59(* Passing an ML function (a closure): *)
60
61val ffun : (int -> real) -> int -> string =
62    app2 (dlsym dlh "cffun");
63
64(* Returning a tuple *)
65
66val frtup : int -> int * bool =
67    app1 (dlsym dlh "cfrtup");
68
69(* Returning a record *)
70
71val frrec : int -> { half : int, odd : bool } =
72    app1 (dlsym dlh "cfrrec");
73
74(* Illustration of heap allocation trickiness *)
75
76val fconcat : string -> string -> string =
77    app2 (dlsym dlh "cfconcat");
78
79(* Exercising the C functions: *)
80
81val test1 = () = fu ();
82
83val test2 = 5667 = fi 5666;
84
85val test3 = #"T" = fc #"t";
86
87val test4 = 56.0 = fr 28.0;
88
89val test5 = "TEST NUMBER +1" = fs "Test number +1";
90
91val test6 = fb false;
92
93val test7 = 85 = fcur 5 #"A" 10.0 "blah" true;
94
95val test8 = 80 = ftup(5, #"A", 10.0);
96
97val test9 = not (frec {surname = "Jensen", givenname = "Karin", age = 28 });
98
99local
100    val tree = Brs[Lf,
101                   Br(12, Br(10, Lf, Lf), Br(20, Lf, Lf)),
102                   Brs[Br(15, Lf, Lf)]]
103in
104
105    val test10 = 57 = fdat tree
106end
107
108val test11 = ("Just right" = ffun (fn x => real x + 7.0) 100000);
109
110val test12 = (8, true) = frtup 17;
111
112val test13 = {half = 8, odd = true} = frrec 17;
113
114val test14 = "abcdef" = fconcat "abc" "def";
115
116val _ = quit();
117