<!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">

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-833377-1";
urchinTracker();
</script>
<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 20061025</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="#5F9EA0">signature</FONT></B> DYN_LINK <B><FONT COLOR="#5F9EA0">=</FONT></B>
   <B><FONT COLOR="#5F9EA0">sig</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B> hndl
      <B><FONT COLOR="#A020F0">type</FONT></B> mode
      <B><FONT COLOR="#A020F0">type</FONT></B> fptr

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

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

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

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

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

      <B><FONT COLOR="#A020F0">val</FONT></B> dlerror <B><FONT COLOR="#5F9EA0">=</FONT></B> <B><FONT COLOR="#A020F0">fn</FONT></B> () <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> addr <B><FONT COLOR="#5F9EA0">=</FONT></B> dlerror ()
         <B><FONT COLOR="#A020F0">in</FONT></B>
            <B><FONT COLOR="#A020F0">if</FONT></B> addr <B><FONT COLOR="#5F9EA0">=</FONT></B> MLton.Pointer.null
               <B><FONT COLOR="#A020F0">then</FONT></B> <B><FONT COLOR="#5F9EA0">NONE</FONT></B>
               <B><FONT COLOR="#A020F0">else</FONT></B> <B><FONT COLOR="#A020F0">let</FONT></B>
<B><FONT COLOR="#A020F0">                       fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">loop</FONT></I></B></FONT></B> (index, cs) <B><FONT COLOR="#5F9EA0">=</FONT></B>
                          <B><FONT COLOR="#A020F0">let</FONT></B>
                             <B><FONT COLOR="#A020F0">val</FONT></B> w <B><FONT COLOR="#5F9EA0">=</FONT></B> MLton.Pointer.getWord8 (addr, index)
                             <B><FONT COLOR="#A020F0">val</FONT></B> c <B><FONT COLOR="#5F9EA0">=</FONT></B> Byte.byteToChar w
                          <B><FONT COLOR="#A020F0">in</FONT></B>
                             <B><FONT COLOR="#A020F0">if</FONT></B> c <B><FONT COLOR="#5F9EA0">=</FONT></B> #<B><FONT COLOR="#BC8F8F">&quot;\000&quot;</FONT></B>
                                <B><FONT COLOR="#A020F0">then</FONT></B> <B><FONT COLOR="#5F9EA0">SOME</FONT></B> (implode (rev cs))
                                <B><FONT COLOR="#A020F0">else</FONT></B> loop (index <B><FONT COLOR="#5F9EA0">+</FONT></B> 1, c<B><FONT COLOR="#5F9EA0">::</FONT></B>cs)
                          <B><FONT COLOR="#A020F0">end</FONT></B>
                    <B><FONT COLOR="#A020F0">in</FONT></B>
                       loop (0, [])
                    <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="#5F9EA0">=</FONT></B> <B><FONT COLOR="#A020F0">fn</FONT></B> (filename, mode) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> filename <B><FONT COLOR="#5F9EA0">=</FONT></B> filename <B><FONT COLOR="#5F9EA0">^</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;\000&quot;</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> hndl <B><FONT COLOR="#5F9EA0">=</FONT></B> dlopen (filename, mode)
         <B><FONT COLOR="#A020F0">in</FONT></B>
            <B><FONT COLOR="#A020F0">if</FONT></B> hndl <B><FONT COLOR="#5F9EA0">=</FONT></B> 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>
                                   <B><FONT COLOR="#5F9EA0">NONE</FONT></B> <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;???&quot;</FONT></B>
                                 <B><FONT COLOR="#5F9EA0">|</FONT></B> <B><FONT COLOR="#5F9EA0">SOME</FONT></B> s <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> 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="#5F9EA0">=</FONT></B> <B><FONT COLOR="#A020F0">fn</FONT></B> (hndl, symbol) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> symbol <B><FONT COLOR="#5F9EA0">=</FONT></B> symbol <B><FONT COLOR="#5F9EA0">^</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;\000&quot;</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> fptr <B><FONT COLOR="#5F9EA0">=</FONT></B> 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>
               <B><FONT COLOR="#5F9EA0">NONE</FONT></B> <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> fptr
             <B><FONT COLOR="#5F9EA0">|</FONT></B> <B><FONT COLOR="#5F9EA0">SOME</FONT></B> s <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <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="#5F9EA0">=</FONT></B> <B><FONT COLOR="#A020F0">fn</FONT></B> hndl <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
         <B><FONT COLOR="#A020F0">if</FONT></B> MLton.Platform.OS.host <B><FONT COLOR="#5F9EA0">=</FONT></B> 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 <B><FONT COLOR="#5F9EA0">=</FONT></B> dlclose hndl
            <B><FONT COLOR="#A020F0">in</FONT></B>
               <B><FONT COLOR="#A020F0">if</FONT></B> res <B><FONT COLOR="#5F9EA0">=</FONT></B> 0
                  <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>
                                   <B><FONT COLOR="#5F9EA0">NONE</FONT></B> <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;???&quot;</FONT></B>
                                 <B><FONT COLOR="#5F9EA0">|</FONT></B> <B><FONT COLOR="#5F9EA0">SOME</FONT></B> s <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> s)
            <B><FONT COLOR="#A020F0">end</FONT></B>
   <B><FONT COLOR="#A020F0">end</FONT></B>

<B><FONT COLOR="#A020F0">val</FONT></B> dll <B><FONT COLOR="#5F9EA0">=</FONT></B>
   <B><FONT COLOR="#A020F0">let</FONT></B>
      <B><FONT COLOR="#A020F0">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 <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;cygwin1.dll&quot;</FONT></B>
       <B><FONT COLOR="#5F9EA0">|</FONT></B> Darwin <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;libm.dylib&quot;</FONT></B>
       <B><FONT COLOR="#5F9EA0">|</FONT></B> _ <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;libm.so&quot;</FONT></B>
   <B><FONT COLOR="#A020F0">end</FONT></B>

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

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

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

<B><FONT COLOR="#A020F0">val</FONT></B> _ <B><FONT COLOR="#5F9EA0">=</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-20061025-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>
