caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: John Whitington <john@coherentgraphics.co.uk>
To: David MENTRE <dmentre@linux-france.org>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Coherent Graphics Product Updates
Date: Thu, 12 Jul 2012 17:27:59 +0100	[thread overview]
Message-ID: <4FFEFB0F.5080506@coherentgraphics.co.uk> (raw)
In-Reply-To: <CAC3Lx=Yjj83wDicWjBGBeMbwJS3CsHCfgi4Ttj1FkZjnLCj0rQ@mail.gmail.com>

Hi,

David MENTRE wrote:
> Hello,
>
> 2012/7/12 John Whitington<john@coherentgraphics.co.uk>:
>> 1. A new version of our PDF editor for OS X (PDF manipulation in OCaml,
>> interface in Objective C):
>
> An architectural question: how your backend OCaml part and your
> Objective C GUI are communicating between each other?

It's entirely one-way. Objective C calls OCaml. OCaml never calls 
Objective C.

Here's the makefile for the library - this method is straight out of the 
OCaml manual.

mklib:
	ocamlc.opt cpdfstrftime.mli;
	ocamlopt.opt -c -I . unix.cmxa str.cmxa bigarray.cmxa cgutil.cmxa 
camlpdf.cmxa cpdfstrftime.ml;
	ocamlc.opt cpdf.mli;
	ocamlopt.opt -c -I . unix.cmxa str.cmxa bigarray.cmxa cgutil.cmxa 
camlpdf.cmxa cpdf.ml;
	ocamlc.opt cpdflib.mli;
	ocamlopt.opt -c -I . unix.cmxa str.cmxa bigarray.cmxa cgutil.cmxa 
camlpdf.cmxa cpdf.cmx cpdflib.ml;
	ocamlc.opt cpdflibwrapper.c;
	ocamlopt.opt -output-obj -o cpdflib.o unix.cmxa bigarray.cmxa 
cgutil.cmxa camlpdf.cmxa cpdfstrftime.cmx cpdf.cmx cpdflib.cmx;
	cp /usr/local/lib/ocaml/libasmrun.a cpdflib.a;
	ar r cpdflib.a cpdflib.o cpdflibwrapper.o

test:   zlibstubs.o cpdflib.a cpdflibc-test.c
  	cc -c cpdflibc-test.c -o cpdflibc-test.o; \
         cc -L'/usr/local/lib/ocaml' -lunix -lbigarray -lz -o test 
cpdflibc-test.o zlibstubs.o cpdflib.a


For example, for a single function 'fromFile' to load a PDF from disc:

cpdflib.ml (Wraps up functionality from our command line tools imperatively)
==============================================================

(* Read a file, no attempt at decryption, unless it's the blank user 
password. *)
let fromFile filename =
   try
     new_pdf (Pdfread.pdf_of_file (Some "") None filename)
   with
     e -> handle_error "fromFile" e; err_int

let _ = Callback.register "fromFile" fromFile



cpdflibwrapper.c (the foreign function interface)
=================================================

int fromFile(char* filename)
{
   CAMLparam0 ();
   CAMLlocal3(fromfile_v, filename_v, result_v);
   fromfile_v = *caml_named_value("fromFile");
   filename_v = caml_copy_string(filename);
   result_v = caml_callback(fromfile_v, filename_v);
   updateLastError ();
   CAMLreturnT(int, Int_val(result_v));
}



PDFDocument.m (Objective C)
===========================

...
clearError ();
const char* in_c = [[[self fileURL] path] UTF8String];
int pdf = fromFile((char*) in_c);
if (lastError != 0) return NO;
...



Functions like handle_error, updateLastError(), clearError() etc. 
provide a simple flat system for dealing with errors without exceptions 
crossing the C/OCaml boundary. This is very old fashioned, but seems to 
work. C code checks the error code after each callback to Ocaml, and can 
extract extra information about the error.

Similarly, no complicated OCaml data structures cross the boundary - 
it's all direct ints, floats, strings, and the occasional void*. The 
possibility for programmer error in building big OCaml data structures 
directly in C seems to outweigh the annoyance of a slightly flat 
interface, at least for this particular application. FFI Masters may 
disagree :-)

The multiple PDF files representing different undo/redo states of a 
document are held in memory in OCaml (with most of the data shared 
between them automatically, of course). When the PDF is updated or 
undone/redone, it's flattened to disk, and the PDFKit component in Cocoa 
picks it up and renders it - surprisingly, this is quick enough - it's 
all in the memory cache rather than the actual disk usually, of course.

PDFKit (The cocoa PDF component) is only used for rendering - almost 
every other piece of functionality is dealt with by CamlPDF via the FFI.

Thanks,

-- 
John Whitington
Director, Coherent Graphics Ltd
http://www.coherentpdf.com/


  reply	other threads:[~2012-07-12 16:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-12 13:04 John Whitington
2012-07-12 15:51 ` David MENTRE
2012-07-12 16:27   ` John Whitington [this message]
2012-07-12 16:44     ` David MENTRE
2012-07-13  0:27       ` Francois Berenger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4FFEFB0F.5080506@coherentgraphics.co.uk \
    --to=john@coherentgraphics.co.uk \
    --cc=caml-list@inria.fr \
    --cc=dmentre@linux-france.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).