<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta name="robots" content="index,nofollow">



<title>CallingFromSMLToCFunctionPointer - MLton Standard ML Compiler (SML Compiler)</title>
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="all" href="common.css">
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="screen" href="screen.css">
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="print" href="print.css">


<link rel="Start" href="Home">


</head>

<body lang="en" dir="ltr">

<table bgcolor = lightblue cellspacing = 0 style = "border: 0px;" width = 100%>
  <tr>
    <td style = "
		border: 0px;
		color: darkblue; 
		font-size: 150%;
		text-align: left;">
      <a class = mltona href="Home">MLton 20051202</a>
    <td style = "
		border: 0px;
		font-size: 150%;
		text-align: center;
		width: 50%;">
      CallingFromSMLToCFunctionPointer
    <td style = "
		border: 0px;
		text-align: right;">
      <table cellspacing = 0 style = "border: 0px">
        <tr style = "vertical-align: middle;">
      </table>
  <tr style = "background-color: white;">
    <td colspan = 3
	style = "
		border: 0px;
		font-size:70%;
		text-align: right;">
      <a href = "Home">Home</a>
      &nbsp;<a href = "Index">Index</a>
      &nbsp;
</table>
<div id="content" lang="en" dir="ltr">
Just as MLton can <a href="CallingFromSMLToC">directly call C functions</a>, it is possible to make indirect function calls; that is, function calls through a function pointer.  MLton extends the syntax of SML to allow expressions like the following: 
<pre>_import * : MLton.Pointer.t -&gt; real * char -&gt; int;
</pre><p>
This expression denotes a function of type 
<pre>MLton.Pointer.t -&gt; real * char -&gt; int</pre>whose behavior is implemented by calling the C function at the address denoted by the <tt>MLton.Pointer.t</tt> argument, and supplying the C function two arguments, a <tt>double</tt> and an <tt>int</tt>.  The C function pointer may be obtained, for example, by the dynamic linking loader (<tt>dlopen</tt>, <tt>dlsym</tt>, ...). 
</p>
<p>
The general form of an indirect <tt>_import</tt> expression is: 
</p>

<pre>_import * attr... : cPtrTy -&gt; cFuncTy;
</pre><p>
The type and the semicolon are not optional. 
</p>
<h2 id="head-0f01ed56a1e32a05e5ef96e4d779f34784af9a96">Example</h2>
<p>
This example uses <tt>dlopen</tt> and friends (imported using normal <tt>_import</tt>) to dynamically load the math library (<tt>libm</tt>) and call the <tt>cos</tt> function. Suppose <tt>iimport.sml</tt> contains the following. 
</p>
<p>
<pre class=code><B><FONT COLOR="#0000FF">signature</FONT></B> DYN_LINK =
   <B><FONT COLOR="#0000FF">sig</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> hndl
      </FONT></B><B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> mode
      </FONT></B><B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> fptr

      </FONT></B><B><FONT COLOR="#A020F0">val</FONT></B> dlopen : string * mode -&gt; hndl
      <B><FONT COLOR="#A020F0">val</FONT></B> dlsym : hndl * string -&gt; fptr
      <B><FONT COLOR="#A020F0">val</FONT></B> dlclose : hndl -&gt; unit

      <B><FONT COLOR="#A020F0">val</FONT></B> RTLD_LAZY : mode
      <B><FONT COLOR="#A020F0">val</FONT></B> RTLD_NOW : mode
   <B><FONT COLOR="#0000FF">end</FONT></B>

<B><FONT COLOR="#0000FF">structure</FONT></B> DynLink :&gt; DYN_LINK =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> hndl </FONT></B>=<FONT COLOR="#228B22"><B> MLton.Pointer.t
      </FONT></B><B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> mode </FONT></B>=<FONT COLOR="#228B22"><B> Word32.word
      </FONT></B><B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> fptr </FONT></B>=<FONT COLOR="#228B22"><B> MLton.Pointer.t

      </FONT></B><B><FONT COLOR="#A020F0">val</FONT></B> dlopen =
         _import <FONT COLOR="#BC8F8F"><B>&quot;dlopen&quot;</FONT></B> : string * mode -&gt; hndl;
      <B><FONT COLOR="#A020F0">val</FONT></B> dlerror =
         _import <FONT COLOR="#BC8F8F"><B>&quot;dlerror&quot;</FONT></B>: unit -&gt; MLton.Pointer.t;
      <B><FONT COLOR="#A020F0">val</FONT></B> dlsym =
         _import <FONT COLOR="#BC8F8F"><B>&quot;dlsym&quot;</FONT></B> : hndl * string -&gt; fptr;
      <B><FONT COLOR="#A020F0">val</FONT></B> dlclose =
         _import <FONT COLOR="#BC8F8F"><B>&quot;dlclose&quot;</FONT></B> : hndl -&gt; Int32.int;

      <B><FONT COLOR="#A020F0">val</FONT></B> RTLD_LAZY = <B><FONT COLOR="#5F9EA0">0wx00001</FONT></B> <I><FONT COLOR="#B22222">(* Lazy function call binding.  *)</FONT></I>
      <B><FONT COLOR="#A020F0">val</FONT></B> RTLD_NOW  = <B><FONT COLOR="#5F9EA0">0wx00002</FONT></B> <I><FONT COLOR="#B22222">(* Immediate function call binding.  *)</FONT></I>

      <B><FONT COLOR="#A020F0">val</FONT></B> dlerror = <B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt;
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> addr = dlerror ()
         <B><FONT COLOR="#A020F0">in</FONT></B>
            <B><FONT COLOR="#A020F0">if</FONT></B> addr = MLton.Pointer.null
               <B><FONT COLOR="#A020F0">then</FONT></B> NONE
               <B><FONT COLOR="#A020F0">else</FONT></B> <B><FONT COLOR="#A020F0">let</FONT></B>
                       <B><FONT COLOR="#A020F0">fun</FONT></B> loop (index, cs) =
                          <B><FONT COLOR="#A020F0">let</FONT></B>
                             <B><FONT COLOR="#A020F0">val</FONT></B> w = MLton.Pointer.getWord8 (addr, index)
                             <B><FONT COLOR="#A020F0">val</FONT></B> c = Byte.byteToChar w
                          <B><FONT COLOR="#A020F0">in</FONT></B>
                             <B><FONT COLOR="#A020F0">if</FONT></B> c = #<FONT COLOR="#BC8F8F"><B>&quot;\000&quot;</FONT></B>
                                <B><FONT COLOR="#A020F0">then</FONT></B> SOME (implode (rev cs))
                                <B><FONT COLOR="#A020F0">else</FONT></B> loop (index + <B><FONT COLOR="#5F9EA0">1</FONT></B>, c::cs)
                          <B><FONT COLOR="#A020F0">end</FONT></B>
                    <B><FONT COLOR="#A020F0">in</FONT></B>
                       loop (<B><FONT COLOR="#5F9EA0">0</FONT></B>, [])
                    <B><FONT COLOR="#A020F0">end</FONT></B>
         <B><FONT COLOR="#A020F0">end</FONT></B>

      <B><FONT COLOR="#A020F0">val</FONT></B> dlopen = <B><FONT COLOR="#A020F0">fn</FONT></B> (filename, mode) =&gt;
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> filename = filename ^ <FONT COLOR="#BC8F8F"><B>&quot;\000&quot;</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> hndl = dlopen (filename, mode)
         <B><FONT COLOR="#A020F0">in</FONT></B>
            <B><FONT COLOR="#A020F0">if</FONT></B> hndl = MLton.Pointer.null
               <B><FONT COLOR="#A020F0">then</FONT></B> <B><FONT COLOR="#A020F0">raise</FONT></B> Fail (<B><FONT COLOR="#A020F0">case</FONT></B> dlerror () <B><FONT COLOR="#A020F0">of</FONT></B>
                                   NONE =&gt; <FONT COLOR="#BC8F8F"><B>&quot;???&quot;</FONT></B>
                                 | SOME s =&gt; s)
               <B><FONT COLOR="#A020F0">else</FONT></B> hndl
         <B><FONT COLOR="#A020F0">end</FONT></B>

      <B><FONT COLOR="#A020F0">val</FONT></B> dlsym = <B><FONT COLOR="#A020F0">fn</FONT></B> (hndl, symbol) =&gt;
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> symbol = symbol ^ <FONT COLOR="#BC8F8F"><B>&quot;\000&quot;</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> fptr = dlsym (hndl, symbol)
         <B><FONT COLOR="#A020F0">in</FONT></B>
            <B><FONT COLOR="#A020F0">case</FONT></B> dlerror () <B><FONT COLOR="#A020F0">of</FONT></B>
               NONE =&gt; fptr
             | SOME s =&gt; <B><FONT COLOR="#A020F0">raise</FONT></B> Fail s
         <B><FONT COLOR="#A020F0">end</FONT></B>

      <B><FONT COLOR="#A020F0">val</FONT></B> dlclose = <B><FONT COLOR="#A020F0">fn</FONT></B> hndl =&gt;
         <B><FONT COLOR="#A020F0">if</FONT></B> MLton.Platform.OS.host = MLton.Platform.OS.Darwin
            <B><FONT COLOR="#A020F0">then</FONT></B> ()  <I><FONT COLOR="#B22222">(* Darwin reports the following error message if you
                      * try to close a dynamic library.
                      *   &quot;dynamic libraries cannot be closed&quot;
                      * So, we disable dlclose on Darwin.
                      *)</FONT></I>
         <B><FONT COLOR="#A020F0">else</FONT></B>
            <B><FONT COLOR="#A020F0">let</FONT></B>
               <B><FONT COLOR="#A020F0">val</FONT></B> res = dlclose hndl
            <B><FONT COLOR="#A020F0">in</FONT></B>
               <B><FONT COLOR="#A020F0">if</FONT></B> res = <B><FONT COLOR="#5F9EA0">0</FONT></B>
                  <B><FONT COLOR="#A020F0">then</FONT></B> ()
               <B><FONT COLOR="#A020F0">else</FONT></B> <B><FONT COLOR="#A020F0">raise</FONT></B> Fail (<B><FONT COLOR="#A020F0">case</FONT></B> dlerror () <B><FONT COLOR="#A020F0">of</FONT></B>
                                   NONE =&gt; <FONT COLOR="#BC8F8F"><B>&quot;???&quot;</FONT></B>
                                 | SOME s =&gt; s)
            <B><FONT COLOR="#A020F0">end</FONT></B>
   <B><FONT COLOR="#0000FF">end</FONT></B>

<B><FONT COLOR="#A020F0">val</FONT></B> dll =
   <B><FONT COLOR="#A020F0">let</FONT></B>
      <B><FONT COLOR="#0000FF">open</FONT></B> MLton.Platform.OS
   <B><FONT COLOR="#A020F0">in</FONT></B>
      <B><FONT COLOR="#A020F0">case</FONT></B> host <B><FONT COLOR="#A020F0">of</FONT></B>
         Cygwin =&gt; <FONT COLOR="#BC8F8F"><B>&quot;cygwin1.dll&quot;</FONT></B>
       | Darwin =&gt; <FONT COLOR="#BC8F8F"><B>&quot;libm.dylib&quot;</FONT></B>
       | _ =&gt; <FONT COLOR="#BC8F8F"><B>&quot;libm.so&quot;</FONT></B>
   <B><FONT COLOR="#A020F0">end</FONT></B>

<B><FONT COLOR="#A020F0">val</FONT></B> hndl = DynLink.dlopen (dll, DynLink.RTLD_LAZY)

<B><FONT COLOR="#0000FF">local</FONT></B>
   <B><FONT COLOR="#A020F0">val</FONT></B> double_to_double =
      _import * : DynLink.fptr -&gt; real -&gt; real;
   <B><FONT COLOR="#A020F0">val</FONT></B> cos_fptr = DynLink.dlsym (hndl, <FONT COLOR="#BC8F8F"><B>&quot;cos&quot;</FONT></B>)
<B><FONT COLOR="#0000FF">in</FONT></B>
   <B><FONT COLOR="#A020F0">val</FONT></B> cos = double_to_double cos_fptr
<B><FONT COLOR="#0000FF">end</FONT></B>

<B><FONT COLOR="#A020F0">val</FONT></B> _ = print (concat [<FONT COLOR="#BC8F8F"><B>&quot;    Math.cos(2.0) = &quot;</FONT></B>, Real.toString (Math.cos <B><FONT COLOR="#5F9EA0">2.0</FONT></B>), <FONT COLOR="#BC8F8F"><B>&quot;\n&quot;</FONT></B>,
                       <FONT COLOR="#BC8F8F"><B>&quot;libm.so::cos(2.0) = &quot;</FONT></B>, Real.toString (cos <B><FONT COLOR="#5F9EA0">2.0</FONT></B>), <FONT COLOR="#BC8F8F"><B>&quot;\n&quot;</FONT></B>])

<B><FONT COLOR="#A020F0">val</FONT></B> _ = DynLink.dlclose hndl
</PRE>
 
</p>
<p>
Compile and run <tt>iimport.sml</tt>. 
<pre>% mlton -default-ann 'allowFFI true'    \
        -target-link-opt linux -ldl     \
        -target-link-opt solaris -ldl   \
         iimport.sml
% iimport
    Math.cos(2.0) = ~0.416146836547
libm.so::cos(2.0) = ~0.416146836547
</pre>
</p>
<p>
This example also shows the <tt>-target-link-opt</tt> option, which uses the switch when linking only when on the specified platform.  Compile with <tt>-verbose&nbsp;1</tt> to see in more detail what's being passed to <tt>gcc</tt>. 
</p>
<h2 id="head-a479c9c34e878d07b4d67a73a48f432ad7dc53c8">Download</h2>

    <ul>

    <li>
<p>
 
<a href = "http://mlton.org/cgi-bin/viewsvn.cgi/*checkout*/mlton/tags/on-20051202-release/doc/examples/ffi/iimport.sml"><img src="moin-www.png" alt="[WWW]" height="11" width="11">iimport.sml</a>
 
</p>
</li>
</ul>

</div>



<p>
<hr>
Last edited on 2005-11-30 23:18:27 by <span title="ppp-71-139-183-221.dsl.snfc21.pacbell.net"><a href="StephenWeeks">StephenWeeks</a></span>.
</body></html>
