Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > bd5c3d824c3db63ffd9226c15941e6ad > files > 105

mozart-1.4.0-1mdv2010.0.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>15 Global Counter Library</TITLE><LINK href="ozdoc.css" rel="stylesheet" type="text/css"></HEAD><BODY><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node19.html">- Up -</A></TD><TD><A href="node21.html#chapter.counter.object">Next &gt;&gt;</A></TD></TR></TABLE><DIV id="chapter.counter.global"><H1><A name="chapter.counter.global">15 Global Counter Library</A></H1><P>Oz can be very simply extended with new functionality and datatypes implemented in C or C++. This capability is often used to interface Oz to existing libraries: for example, the <SPAN class="library">regex</SPAN> and <SPAN class="library">gdbm</SPAN> modules are implemented in this fashion.</P><P>Every extension is presented to the system in the form of a <EM>native functor</EM><A name="label50"></A>, i.&nbsp;e. a functor which happens to be implemented in C or C++ rather than in Oz.</P><P>In this chapter, we define a native functor that exports a <SPAN class="ignore"><CODE>&nbsp;</CODE></SPAN><CODE>next</CODE> function which returns the next value of a global counter each time it is called.</P><H2><A name="label51">15.1 Implementation</A></H2><P></P><DL class="anonymous"><DD class="code"><CODE>#include&nbsp;<SPAN class="string">&quot;mozart.h&quot;</SPAN>&nbsp;<BR>&nbsp;<BR><SPAN class="keyword">static</SPAN>&nbsp;<SPAN class="type">long</SPAN>&nbsp;<SPAN class="variablename">n</SPAN>;<BR>&nbsp;<BR><SPAN class="functionname">OZ_BI_define</SPAN>(counter_next,0,1)<BR>{<BR>&nbsp;&nbsp;OZ_RETURN_INT(n++);<BR>}<BR>OZ_BI_end<BR>&nbsp;<BR><SPAN class="type">OZ_C_proc_interface</SPAN>&nbsp;*&nbsp;<SPAN class="functionname">oz_init_module</SPAN>(<SPAN class="type">void</SPAN>)<BR>{<BR>&nbsp;&nbsp;<SPAN class="keyword">static</SPAN>&nbsp;<SPAN class="type">OZ_C_proc_interface</SPAN>&nbsp;<SPAN class="variablename">table</SPAN>[]&nbsp;=&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<SPAN class="string">&quot;next&quot;</SPAN>,0,1,counter_next},<BR>&nbsp;&nbsp;&nbsp;&nbsp;{0,0,0,0}<BR>&nbsp;&nbsp;};<BR>&nbsp;&nbsp;n&nbsp;=&nbsp;1;<BR>&nbsp;&nbsp;<SPAN class="keyword">return</SPAN>&nbsp;table;<BR>}</CODE></DD></DL><P> <CODE>OZ_BI_define(counter_next,0,1)</CODE> indicates that we are defining a procedure <SPAN class="ignore"><CODE>&nbsp;</CODE></SPAN><CODE>counter_next</CODE> that implements a new builtin which takes 0 input arguments and returns 1 output value. <CODE>OZ_BI_end</CODE> is required to finish this definition.</P><P><SPAN class="ignore"><CODE>&nbsp;</CODE></SPAN><CODE>OZ_RETURN_INT(</CODE><I>d</I><CODE>)</CODE> is a macro that causes the builtin to return integer <I>d</I> as an Oz integer. This should only be used when the builtin has one unique output value; and it is essentially equivalent to the code sequence: </P><BLOCKQUOTE class="code"><CODE>OZ_out(0)=OZ_int(d);<BR><SPAN class="keyword">return</SPAN>&nbsp;PROCEED;</CODE></BLOCKQUOTE><P></P><P>Finally procedure <SPAN class="ignore"><CODE>&nbsp;</CODE></SPAN><CODE>oz_init_module</CODE> implements the native functor: it performs arbitrary initializations and then returns a table of builtins. Each entry in this table consists of (1) the name of the export, (2) the input arity, (3) the output arity, (4) the procedure implementing the builtin. The table must be terminated by an entry whose fields are all zero.</P><P>Note that global variable <CODE>n</CODE> is explicitly initialized by <SPAN class="ignore"><CODE>&nbsp;</CODE></SPAN><CODE>oz_init_module</CODE> rather than with a static initializer. Here, it probably makes no difference, but you cannot in general rely on the fact that constructors for global objects will be properly invoked when the native functor is loaded. What actually happens varies from one system to another. The only reliable technique is to perform all initializations in <SPAN class="ignore"><CODE>&nbsp;</CODE></SPAN><CODE>oz_init_module</CODE>.</P><P>You may also define the variable <SPAN class="ignore"><CODE>&nbsp;</CODE></SPAN><CODE>oz_module_name</CODE> to give your native module a name that can be used when printing the builtins which it exports. This is particularly useful for debugging and for interactively looking at values. For example, you could give it the name <CODE><SPAN class="string">&quot;GlobalCounter&quot;</SPAN></CODE>: </P><BLOCKQUOTE class="code"><CODE><SPAN class="type">char</SPAN>&nbsp;<SPAN class="variablename">oz_module_name</SPAN>[]&nbsp;=&nbsp;<SPAN class="string">&quot;GlobalCounter&quot;</SPAN>;</CODE></BLOCKQUOTE><P> </P><DIV id="section.counter.global.compilation"><H2><A name="section.counter.global.compilation">15.2 Compilation</A></H2><P>We must now make this native module available as a <EM>shared object library</EM>. First we must compile it and create <CODE>counter.o</CODE>: </P><BLOCKQUOTE class="code"><CODE>oztool&nbsp;c++&nbsp;-c&nbsp;counter.cc</CODE></BLOCKQUOTE><P> Then we must produce a platform specific shared object library: </P><BLOCKQUOTE class="code"><CODE>oztool&nbsp;ld&nbsp;counter.o&nbsp;-o&nbsp;counter.so-`oztool&nbsp;platform`</CODE></BLOCKQUOTE><P> You may find it useful to create a <CODE>Makefile</CODE> of the form: </P><BLOCKQUOTE><PRE><SPAN class="variablename">PLATFORM</SPAN>&nbsp;=&nbsp;$(shell&nbsp;oztool&nbsp;platform)<BR><SPAN class="variablename">NATIVES</SPAN>&nbsp;&nbsp;=&nbsp;counter<BR><SPAN class="variablename">TARGETS</SPAN>&nbsp;&nbsp;=&nbsp;$(addsuffix&nbsp;.so-$(PLATFORM),$(NATIVES))<BR>all:&nbsp;$(TARGETS)<BR>%.so-$(PLATFORM):&nbsp;%.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oztool&nbsp;ld&nbsp;$&lt;&nbsp;-o&nbsp;$@&nbsp;<BR>%.o:&nbsp;%.cc<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oztool&nbsp;c++&nbsp;-c&nbsp;$&lt;&nbsp;-o&nbsp;$@&nbsp;<BR></PRE></BLOCKQUOTE><P></P><P><CODE>oztool</CODE><A name="label52"></A> is a program that invokes the facility named as its first argument with appropriate options. For example, it is essential to invoke the same C++ compiler and with the same e.&nbsp;g. code generation options as were used for building the Oz emulator; otherwise it will not be possible to dynamically link your library into a running Oz process. Normally, the Oz emulator is compiled without <EM>run time information</EM> (option <CODE>-fno-rtti</CODE> for g++) and without support for C++ exceptions (option <CODE>-fno-exceptions</CODE> for g++). <CODE>oztool&nbsp;c++</CODE> automatically invokes the right compiler with the right options. <CODE>oztool</CODE> is documented in <A href="../tools/node14.html#chapter.oztool">Chapter&nbsp;6 of ``Oz Shell Utilities''</A>.</P><P>Even more complicated is how to create a DLL from a compiled object file: it varies depending on the system, compiler and linker used. Under Windows, the sequence of necessary incantations is so arcane and highly magical, it could well endanger your sanity. Fortunately <CODE>oztool&nbsp;ld</CODE> automatically takes care of the details.</P></DIV><DIV id="section.counter.global.compilation.deployment"><H2><A name="section.counter.global.compilation.deployment">15.3 Deployment</A></H2><P>Normally, you will then place the resulting shared object file, e.g. <CODE>counter.so-linux-i486</CODE> on a Linux system, in an installation directory; let's call it <I>install</I>. If your site has several platforms sharing one file system, then you can place all platform specific shared object libraries that you create from <CODE>counter.cc</CODE> in the same <I>install</I> directory. They all have distinct names since the platform name is appended.</P><P>In an Oz functor, you then write an import of the form: </P><BLOCKQUOTE class="code"><CODE>Cnt&nbsp;<SPAN class="keyword">at</SPAN>&nbsp;<SPAN class="string">'</SPAN></CODE><I>install</I><CODE><SPAN class="string">/counter.so{native}'</SPAN></CODE></BLOCKQUOTE><P> The <SPAN class="ignore"><CODE><SPAN class="string">'</SPAN></CODE></SPAN><CODE><SPAN class="string">{native}</SPAN></CODE><SPAN class="ignore"><CODE><SPAN class="string">'</SPAN></CODE></SPAN> suffix indicates to the system that this denotes a native functor whose platform independent basename is <CODE><I>install</I>/counter.so</CODE>. The module manager dynamically links the appropriate platform specific shared object library (by appending the platform specific extension to the basename) and makes available the module it defines as the value of <CODE>Cnt</CODE>. The body of your functor can invoke <CODE>{Cnt<SPAN class="keyword">.</SPAN>next}</CODE> to get the next value of the global counter.</P><P>In the emacs OPI, you can try this out immediately: </P><BLOCKQUOTE class="code"><CODE><SPAN class="keyword">declare</SPAN>&nbsp;[M]&nbsp;=&nbsp;{Module<SPAN class="keyword">.</SPAN>link&nbsp;[<SPAN class="string">'</SPAN></CODE><I>install</I><CODE><SPAN class="string">/counter.so{native}'</SPAN>]}</CODE></BLOCKQUOTE><P></P></DIV></DIV><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node19.html">- Up -</A></TD><TD><A href="node21.html#chapter.counter.object">Next &gt;&gt;</A></TD></TR></TABLE><HR><ADDRESS><A href="http://www.ps.uni-sb.de/~duchier/">Denys&nbsp;Duchier</A>, <A href="http://www.ps.uni-sb.de/~kornstae/">Leif&nbsp;Kornstaedt</A> and&nbsp;<A href="http://www.ps.uni-sb.de/~schulte/">Christian&nbsp;Schulte</A><BR><SPAN class="version">Version 1.4.0 (20090610)</SPAN></ADDRESS></BODY></HTML>