From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by sympa.inria.fr (Postfix) with ESMTPS id 6BA657ED34 for ; Thu, 12 Jul 2012 18:28:07 +0200 (CEST) Received-SPF: None (mail4-smtp-sop.national.inria.fr: no sender authenticity information available from domain of john@coherentgraphics.co.uk) identity=pra; client-ip=188.64.186.31; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="john@coherentgraphics.co.uk"; x-sender="john@coherentgraphics.co.uk"; x-conformance=sidf_compatible Received-SPF: None (mail4-smtp-sop.national.inria.fr: no sender authenticity information available from domain of john@coherentgraphics.co.uk) identity=mailfrom; client-ip=188.64.186.31; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="john@coherentgraphics.co.uk"; x-sender="john@coherentgraphics.co.uk"; x-conformance=sidf_compatible Received-SPF: None (mail4-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@bluemoon3.ukhost4u.com) identity=helo; client-ip=188.64.186.31; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="john@coherentgraphics.co.uk"; x-sender="postmaster@bluemoon3.ukhost4u.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Aj0FAGj5/k+8QLofVmdsb2JhbABFuAkYASEnJoIgAQEFJxFAARALBxEJDwQDBQoJAwIBAgExFAYOBYgRrnCPDo4igxoDlkyRVA X-IronPort-AV: E=Sophos;i="4.77,573,1336341600"; d="scan'208";a="150474278" Received: from bluemoon3.ukhost4u.com ([188.64.186.31]) by mail4-smtp-sop.national.inria.fr with ESMTP; 12 Jul 2012 18:28:06 +0200 Received: from 78-105-203-81.zone3.bethere.co.uk ([78.105.203.81]:58459 helo=feast.lan) by bluemoon3.ukhost4u.com with esmtpa (Exim 4.77) (envelope-from ) id 1SpMEv-0001xg-4H; Thu, 12 Jul 2012 17:27:42 +0100 Message-ID: <4FFEFB0F.5080506@coherentgraphics.co.uk> Date: Thu, 12 Jul 2012 17:27:59 +0100 From: John Whitington User-Agent: Postbox 3.0.4 (Macintosh/20120616) MIME-Version: 1.0 To: David MENTRE CC: caml-list@inria.fr References: <4FFECB57.9060900@coherentgraphics.co.uk> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - bluemoon3.ukhost4u.com X-AntiAbuse: Original Domain - inria.fr X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - coherentgraphics.co.uk X-Source: X-Source-Args: X-Source-Dir: Subject: Re: [Caml-list] Coherent Graphics Product Updates Hi, David MENTRE wrote: > Hello, > > 2012/7/12 John Whitington: >> 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/