This file is indexed.

/usr/share/doc/libperl4caml-ocaml-doc/writing-a-wrapper.html is in libperl4caml-ocaml-doc 0.9.5-4build10.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Writing a high-level wrapper around a Perl library</title>
    <link rel="stylesheet" href="http://www.merjis.com/css/default.css"
      type="text/css">
  </head>

  <body bgcolor="#ffffff">
    <h1>Writing a high-level wrapper around a Perl library</h1>

    <p>
      This document discusses the theory and practice behind writing
      a wrapper around a typical object-oriented Perl library. We
      use <a href="../html/Pl_LWP_UserAgent.html">Pl_LWP_UserAgent</a>
      as an example. (This is the high-level wrapper around the
      <a href="http://search.cpan.org/dist/libwww-perl/lib/LWP/UserAgent.pm">LWP::UserAgent</a>
      library).
    </p>

    <p>
      Don't worry - writing wrappers is really not very hard at all. I
      hope that you, the reader, will write some wrappers around your
      favorite Perl libraries and contribute them back to
      <a href="http://www.merjis.com/developers/perl4caml/">perl4caml</a>
      development.
    </p>

    <h2>First steps</h2>

    <p>
      I'm going to use <a href="http://search.cpan.org/dist/libwww-perl/lib/LWP/UserAgent.pm">LWP::UserAgent</a>
      as my example throughout this document. Substitute that for whatever
      library you want to wrap up and call from OCaml.
      First of all make sure you have the library installed and working
      under Perl, and make sure you have the manual page for that
      library in front of you:
    </p>

<pre>
perldoc LWP::UserAgent
</pre>

    <p>
      or <a href="http://search.cpan.org/dist/libwww-perl/lib/LWP/UserAgent.pm">follow
	this link</a>.
    </p>

    <h2>Understanding what we're doing</h2>

    <p>
      The low-level <a href="../html/Perl.html">Perl</a> module offers
      two useful functions and a useful datatype which we'll be using
      extensively. The useful functions are:
    </p>

    <table class="table">
	<tr>
	  <th> Function name </th>
	  <th> Perl equivalent </th>
	  <th> Description </th>
	</tr>

	<tr>
	  <td> <code>call_class_method</code> </td>
	  <td> <code>$obj&nbsp;=&nbsp;LWP::UserAgent-&gt;new&nbsp;(args...)</code> </td>
	  <td>
	    <p> Calls a static method or constructor on a class. </p>
	  </td>
	</tr>

	<tr>
	  <td> <code>call_method</code> </td>
	  <td> <code>$obj-&gt;some_method&nbsp;(args...)</code> </td>
	  <td>
	    <p> Calls an instance method on an object. </p>
	  </td>
	</tr>
    </table>

    <p>
      The useful datatype is called the <code>Perl.sv</code> (an
      abstract type), which represents a scalar value in Perl (anything
      you would normally write in Perl with a <code>$</code>, including
      numbers, strings, references and blessed objects). To find out
      more about "SVs" see <a href="http://www.perldoc.com/perl5.8.0/pod/perlguts.html">the perlguts(3) man page</a>.
    </p>

    <p>
      To see how these three things interact, let's create an
      <code>LWP::UserAgent</code> object and call a method on it:
    </p>

<pre>
# #load "perl4caml.cma";;
# open Perl;;
# let sv = call_class_method "LWP::UserAgent" "new" [];;
<i>val sv : Perl.sv = &lt;abstr&gt;</i>
# let agent = call_method sv "agent" [];;
<i>val agent : Perl.sv = &lt;abstr&gt;</i>
# string_of_sv agent;;
<i>- : string = "libwww-perl/5.69"</i>
</pre>

    <p>
      Note how the variable <code>sv</code> contains the actual Perl
      object (an instance of <code>LWP::UserAgent</code>).  To be
      quite clear, this is the equivalent of the following Perl code:
    </p>

<pre>
$sv = LWP::UserAgent-&gt;new ();
$agent = $sv-&gt;agent ();
print $agent;
</pre>

    <p>
      You could actually just continue to use the low-level interface
      to access Perl objects directly, but there are three problems with
      this: firstly it's cumbersome because you have to continually
      convert to and from SVs; secondly it's not type safe
      (eg. calling <code>string_of_sv</code> might fail if the SV
      isn't actually a string); thirdly there are more pleasant ways
      to present this interface.
    </p>

    <p>
      Writing a high-level wrapper around these low-level operations
      is what is described in the rest of this document ...
    </p>

    <h2>Classes and constructors</h2>

    <p>
      Our general plan, therefore, will be to create an OCaml class
      corresponding to <code>LWP::UserAgent</code>, which hides the
      implementation (the <code>sv</code>, the calls to
      <code>call_method</code>, and the conversion of arguments
      to and from SVs). We will also need to write one or more constructor
      function.
    </p>

    <p>
      We will write at least one method for every method exported by
      the Perl interface. Sometimes we'll write two methods for each
      Perl method, as in the case where a Perl method is a "getter/setter":
    </p>

<pre>
$ua-&gt;agent([$product_id])
   Get/set the product token that is used to identify the user agent
   on the network.  The agent value is sent as the "User-Agent" header
   in the requests.
</pre>

    <p>
      becomes two methods in the OCaml version:
    </p>

<pre>
class lwp_useragent sv = object (self)
  (* ... *)
  method agent : string
  method set_agent : string -&gt; unit
end
</pre>

    <p>
      We will also write at least one function for every
      constructor or static function exported from Perl.
    </p>

    <p>
      The OCaml object itself contains the <code>sv</code> which
      corresponds to the Perl SV (ie. the actual Perl object).
    </p>

    <p>
      Here is the shape of our class:
    </p>

<pre>
(** Wrapper around Perl [LWP::UserAgent] class.
  *
  * Copyright (C) 20xx <i>your_organisation</i>
  *
  * $ Id $
  *)

open Perl

let _ = eval "use LWP::UserAgent"

class lwp_useragent sv = object (self)

  <i>The methods will go here ...</i>

end

(* The "new" constructor. Note that "new" is a reserved word in OCaml. *)
let new_ ... =
  ...
  let sv = call_class_method "LWP::UserAgent" "new" [<i>args ...</i>] in
  new lwp_useragent sv

<i>Any other static functions will go here ...</i>
</pre>

    <p>
      Notice a few things here:
    </p>

    <ol>
      <li> There is some ocamldoc describing the class.
      <li> We "open Perl" to avoid having to prefix everything with
	<code>Perl.</code>.
      <li> We <code>eval "use LWP::UserAgent"</code> when the module
	is loaded. This is required by Perl.
      <li> The <code>sv</code> (scalar value representing the actual
	object) is passed as a parameter to the class.
    </ol>

    <h2>Writing methods</h2>

    <h3>Getters and setters</h3>

    <p>
      Of all types of methods, getters and setters are the easiest
      to write. First of all, check the manual page to find out what
      type the slot is. You'll need to write one get method and
      one set method. (Rarely you'll find getters and setters which
      are quasi-polymorphic, for instance they can take a string or
      an arrayref. You'll need to think more deeply about these,
      because they require one set method for each type, and the
      get method can be complicated).
    </p>

    <p>
      Here's our getter and setter for the agent slot, described above.
      The agent is a string:
    </p>

<pre>
  method agent =
    string_of_sv (call_method sv "agent" [])
  method set_agent v =
    call_method_void sv "agent" [sv_of_string v]
</pre>

    <p>
      Note:
    </p>

    <ol>
      <li> The get method is just called <code>agent</code> (not
	"get_agent"). This is the standard for OCaml code.
      <li> We use <code>string_of_sv</code> and <code>sv_of_string</code>
	to convert to and from SVs. This will ensure that the
	class interface will have the correct type (string), and
	thus be type safe as far as the calling code is concerned,
	and also means the caller doesn't need to worry about
	SVs.
      <li> The set method called <code>call_method_void</code> which
	we haven't seen before. This is exactly the same as
	<code>call_method</code> except that the method is called
	in a "void context" - in other words, any return value is
	thrown away. This is slightly more efficient than ignoring
	the return value.
    </ol>

    <p>
      Here's another example, with a boolean slot:
    </p>

<pre>
  method parse_head =
    bool_of_sv (call_method sv "parse_head" [])
  method set_parse_head v =
    call_method_void sv "parse_head" [sv_of_bool v]
</pre>

    <h3>Ordinary methods</h3>

    <p>
      Other methods are perhaps simpler to wrap than getters and
      setters. <code>LWP::UserAgent</code> contains an interesting
      method called <code>request</code> (which actually runs the
      request).
    </p>

    <p>
      What's particularly interesting about this method are the
      parameter and return value. It takes an <code>HTTP::Request</code>
      object and returns an <code>HTTP::Response</code>.
    </p>

    <p>
      I have already wrapped <code>HTTP::Request</code> and
      <code>HTTP::Response</code> as modules
      <a href="../html/Pl_HTTP_Request.html">Pl_HTTP_Request</a> and
      <a href="../html/Pl_HTTP_Response.html">Pl_HTTP_Response</a>
      respectively. You should go and look at the code in those
      modules now.
    </p>

    <p>
      If <code>request</code> requires a parameter, what should that
      parameter be? Naturally it should be the SV corresponding to
      the <code>HTTP::Request</code> object. To get this, I provided
      an <code>#sv</code> method on the <code>http_request</code> class.
    </p>

    <p>
      And what will <code>request</code> return? Naturally it will
      return an SV which corresponds to the (newly created inside
      Perl) <code>HTTP::Response</code> object. We need to wrap
      this up and create a new OCaml <code>http_response</code> object,
      <em>containing that SV</em>.
    </p>

    <p>
      This is what the final method looks like:
    </p>

<pre>
  method request (request : http_request) =
    let sv = call_method sv "request" [request#sv] in
    new http_response sv
</pre>

    <p>
      It's actually not so complicated.
    </p>

    <h2>Writing constructors and static functions</h2>

    <p>
      Constructors are fairly simple, although the <code>new_</code>
      function inside <code>Pl_LWP_UserAgent</code> is complicated
      by the many optional arguments which <code>LWP::UserAgent-&gt;new</code>
      can take.
    </p>

    <p>
      Here is the guts, omitting all but one of the optional args:
    </p>

<pre>
let new_ ?agent (* ... *) () =
  let args = ref [] in
  let may f = function None -&gt; () | Some v -&gt; f v in
  may (fun v -&gt;
	 args := sv_of_string "agent" :: sv_of_string v :: !args) agent;
(* ... *)
  let sv = call_class_method "LWP::UserAgent" "new" !args in
  new lwp_useragent sv
</pre>

    <p>
      It works simply enough, first building up a list of <code>sv</code>s
      corresponding to the arguments, then calling
      <code>call_class_method</code> to create the Perl object, then
      returning a constructed OCaml <code>lwp_useragent</code> object
      containing that <code>sv</code>.
    </p>

    <h2>Contributing wrappers back to perl4caml</h2>

    <p>
      If you write a wrapper for a Perl class, particularly one from
      <a href="http://www.cpan.org/">CPAN</a>, I urge you to
      contribute it back to the <a
      href="http://www.merjis.com/developers/perl4caml/">perl4caml</a>
      development effort. Your contribution enriches the project
      as a whole, and makes OCaml more useful too.
    </p>

    <hr>
    <address><a href="mailto:rich@annexia.org">Richard W.M. Jones</a></address>
<!-- Created: Thu Oct 16 13:36:59 BST 2003 -->
<!-- hhmts start -->
Last modified: Thu Oct 16 14:39:02 BST 2003
<!-- hhmts end -->
  </body>
</html>