Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / examples / ffi / iimport.sml
CommitLineData
7f918cf1
CE
1signature DYN_LINK =
2 sig
3 type hndl
4 type mode
5 type fptr
6
7 val dlopen : string * mode -> hndl
8 val dlsym : hndl * string -> fptr
9 val dlclose : hndl -> unit
10
11 val RTLD_LAZY : mode
12 val RTLD_NOW : mode
13 end
14
15structure DynLink :> DYN_LINK =
16 struct
17 type hndl = MLton.Pointer.t
18 type mode = Word32.word
19 type fptr = MLton.Pointer.t
20
21 (* These symbols come from a system libray, so the default import scope
22 * of external is correct.
23 *)
24 val dlopen =
25 _import "dlopen" : string * mode -> hndl;
26 val dlerror =
27 _import "dlerror": unit -> MLton.Pointer.t;
28 val dlsym =
29 _import "dlsym" : hndl * string -> fptr;
30 val dlclose =
31 _import "dlclose" : hndl -> Int32.int;
32
33 val RTLD_LAZY = 0wx00001 (* Lazy function call binding. *)
34 val RTLD_NOW = 0wx00002 (* Immediate function call binding. *)
35
36 val dlerror = fn () =>
37 let
38 val addr = dlerror ()
39 in
40 if addr = MLton.Pointer.null
41 then NONE
42 else let
43 fun loop (index, cs) =
44 let
45 val w = MLton.Pointer.getWord8 (addr, index)
46 val c = Byte.byteToChar w
47 in
48 if c = #"\000"
49 then SOME (implode (rev cs))
50 else loop (index + 1, c::cs)
51 end
52 in
53 loop (0, [])
54 end
55 end
56
57 val dlopen = fn (filename, mode) =>
58 let
59 val filename = filename ^ "\000"
60 val hndl = dlopen (filename, mode)
61 in
62 if hndl = MLton.Pointer.null
63 then raise Fail (case dlerror () of
64 NONE => "???"
65 | SOME s => s)
66 else hndl
67 end
68
69 val dlsym = fn (hndl, symbol) =>
70 let
71 val symbol = symbol ^ "\000"
72 val fptr = dlsym (hndl, symbol)
73 in
74 case dlerror () of
75 NONE => fptr
76 | SOME s => raise Fail s
77 end
78
79 val dlclose = fn hndl =>
80 if MLton.Platform.OS.host = MLton.Platform.OS.Darwin
81 then () (* Darwin reports the following error message if you
82 * try to close a dynamic library.
83 * "dynamic libraries cannot be closed"
84 * So, we disable dlclose on Darwin.
85 *)
86 else
87 let
88 val res = dlclose hndl
89 in
90 if res = 0
91 then ()
92 else raise Fail (case dlerror () of
93 NONE => "???"
94 | SOME s => s)
95 end
96 end
97
98val dll =
99 let
100 open MLton.Platform.OS
101 in
102 case host of
103 Cygwin => "cygwin1.dll"
104 | Darwin => "libm.dylib"
105 | _ => "libm.so"
106 end
107
108val hndl = DynLink.dlopen (dll, DynLink.RTLD_LAZY)
109
110local
111 val double_to_double =
112 _import * : DynLink.fptr -> real -> real;
113 val cos_fptr = DynLink.dlsym (hndl, "cos")
114in
115 val cos = double_to_double cos_fptr
116end
117
118val _ = print (concat [" Math.cos(2.0) = ", Real.toString (Math.cos 2.0), "\n",
119 "libm.so::cos(2.0) = ", Real.toString (cos 2.0), "\n"])
120
121val _ = DynLink.dlclose hndl