| 1 | CallingFromCToSML |
| 2 | ================= |
| 3 | |
| 4 | MLton's <:ForeignFunctionInterface:> allows programs to _export_ SML |
| 5 | functions to be called from C. Suppose you would like export from SML |
| 6 | a function of type `real * char -> int` as the C function `foo`. |
| 7 | MLton extends the syntax of SML to allow expressions like the |
| 8 | following: |
| 9 | ---- |
| 10 | _export "foo": (real * char -> int) -> unit; |
| 11 | ---- |
| 12 | The above expression exports a C function named `foo`, with |
| 13 | prototype |
| 14 | [source,c] |
| 15 | ---- |
| 16 | Int32 foo (Real64 x0, Char x1); |
| 17 | ---- |
| 18 | The `_export` expression denotes a function of type |
| 19 | `(real * char -> int) -> unit` that when called with a function |
| 20 | `f`, arranges for the exported `foo` function to call `f` |
| 21 | when `foo` is called. So, for example, the following exports and |
| 22 | defines `foo`. |
| 23 | [source,sml] |
| 24 | ---- |
| 25 | val e = _export "foo": (real * char -> int) -> unit; |
| 26 | val _ = e (fn (x, c) => 13 + Real.floor x + Char.ord c) |
| 27 | ---- |
| 28 | |
| 29 | The general form of an `_export` expression is |
| 30 | ---- |
| 31 | _export "C function name" attr... : cFuncTy -> unit; |
| 32 | ---- |
| 33 | The type and the semicolon are not optional. As with `_import`, a |
| 34 | sequence of attributes may follow the function name. |
| 35 | |
| 36 | MLton's `-export-header` option generates a C header file with |
| 37 | prototypes for all of the functions exported from SML. Include this |
| 38 | header file in your C files to type check calls to functions exported |
| 39 | from SML. This header file includes ++typedef++s for the |
| 40 | <:ForeignFunctionInterfaceTypes: types that can be passed between SML and C>. |
| 41 | |
| 42 | |
| 43 | == Example == |
| 44 | |
| 45 | Suppose that `export.sml` is |
| 46 | |
| 47 | [source,sml] |
| 48 | ---- |
| 49 | sys::[./bin/InclGitFile.py mlton master doc/examples/ffi/export.sml] |
| 50 | ---- |
| 51 | |
| 52 | Note that the the `reentrant` attribute is used for `_import`-ing the |
| 53 | C functions that will call the `_export`-ed SML functions. |
| 54 | |
| 55 | Create the header file with `-export-header`. |
| 56 | ---- |
| 57 | % mlton -default-ann 'allowFFI true' \ |
| 58 | -export-header export.h \ |
| 59 | -stop tc \ |
| 60 | export.sml |
| 61 | ---- |
| 62 | |
| 63 | `export.h` now contains the following C prototypes. |
| 64 | ---- |
| 65 | Int8 f (Int32 x0, Real64 x1, Int8 x2); |
| 66 | Pointer f2 (Word8 x0); |
| 67 | void f3 (); |
| 68 | void f4 (Int32 x0); |
| 69 | extern Int32 zzz; |
| 70 | ---- |
| 71 | |
| 72 | Use `export.h` in a C program, `ffi-export.c`, as follows. |
| 73 | |
| 74 | [source,c] |
| 75 | ---- |
| 76 | sys::[./bin/InclGitFile.py mlton master doc/examples/ffi/ffi-export.c] |
| 77 | ---- |
| 78 | |
| 79 | Compile `ffi-export.c` and `export.sml`. |
| 80 | ---- |
| 81 | % gcc -c ffi-export.c |
| 82 | % mlton -default-ann 'allowFFI true' \ |
| 83 | export.sml ffi-export.o |
| 84 | ---- |
| 85 | |
| 86 | Finally, run `export`. |
| 87 | ---- |
| 88 | % ./export |
| 89 | g starting |
| 90 | ... |
| 91 | g4 (0) |
| 92 | success |
| 93 | ---- |
| 94 | |
| 95 | |
| 96 | == Download == |
| 97 | * <!RawGitFile(mlton,master,doc/examples/ffi/export.sml)> |
| 98 | * <!RawGitFile(mlton,master,doc/examples/ffi/ffi-export.c)> |