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 mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id EFF5D820A1 for ; Thu, 15 Aug 2013 09:33:59 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of dra-news@metastack.com) identity=pra; client-ip=81.103.221.52; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="dra-news@metastack.com"; x-sender="dra-news@metastack.com"; x-conformance=sidf_compatible Received-SPF: Neutral (mail2-smtp-roc.national.inria.fr: domain of dra-news@metastack.com does not assert whether or not 81.103.221.52 is permitted sender) identity=mailfrom; client-ip=81.103.221.52; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="dra-news@metastack.com"; x-sender="dra-news@metastack.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mtaout04-winn.ispmail.ntl.com) identity=helo; client-ip=81.103.221.52; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="dra-news@metastack.com"; x-sender="postmaster@mtaout04-winn.ispmail.ntl.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AsUCAEWDDFJRZ900nGdsb2JhbABSCYJlgSa/C4EfFg4BAQEBAQYNCQkUIQeCJAEBAQEDJxMzHAIBCBgKFBAyJQIEG4gJA7l8jwqBFTiDG3cDlA2DV5Rtgio X-IPAS-Result: AsUCAEWDDFJRZ900nGdsb2JhbABSCYJlgSa/C4EfFg4BAQEBAQYNCQkUIQeCJAEBAQEDJxMzHAIBCBgKFBAyJQIEG4gJA7l8jwqBFTiDG3cDlA2DV5Rtgio X-IronPort-AV: E=Sophos;i="4.89,883,1367964000"; d="scan'208";a="29414957" Received: from mtaout04-winn.ispmail.ntl.com ([81.103.221.52]) by mail2-smtp-roc.national.inria.fr with ESMTP; 15 Aug 2013 09:33:58 +0200 Received: from aamtaout04-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout04-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20130815073358.SNEZ22777.mtaout04-winn.ispmail.ntl.com@aamtaout04-winn.ispmail.ntl.com> for ; Thu, 15 Aug 2013 08:33:58 +0100 Received: from romulus.metastack.com ([81.98.252.242]) by aamtaout04-winn.ispmail.ntl.com (InterMail vG.3.00.04.00 201-2196-133-20080908) with ESMTP id <20130815073358.MUJX21648.aamtaout04-winn.ispmail.ntl.com@romulus.metastack.com> for ; Thu, 15 Aug 2013 08:33:58 +0100 Received: from remus.metastack.local (remus.metastack.com [172.16.0.1]) by romulus.metastack.com (8.14.2/8.14.2) with ESMTP id r7F7XtIJ024700 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL) for ; Thu, 15 Aug 2013 08:33:55 +0100 Received: from Remus.metastack.local ([fe80::547c:3c42:e1da:eda2]) by Remus.metastack.local ([fe80::547c:3c42:e1da:eda2%10]) with mapi id 14.03.0158.001; Thu, 15 Aug 2013 08:33:55 +0100 From: David Allsopp To: "caml-list@inria.fr" Thread-Topic: [Caml-list] Callback.register equivalent before runtime is initialized? Thread-Index: AQHOmYW3hREtOhIngk+091Yvm3Hs0ZmV3eCw Date: Thu, 15 Aug 2013 07:33:53 +0000 Message-ID: References: <20130815070432.GA31041@jade.home.test> In-Reply-To: <20130815070432.GA31041@jade.home.test> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.16.0.18] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Organization: MetaStack Solutions Ltd. X-Scanned-By: MIMEDefang 2.65 on 172.16.0.20 X-Cloudmark-Analysis: v=1.1 cv=AUhbpHVS+xhHrj9wLCYAQoYnFLYUZdbP8UM0GmH2jwk= c=1 sm=0 a=IXlcok0kcmcA:10 a=XpAq_mXIRIsA:10 a=cTs9vV391PwA:10 a=kj9zAlcOel0A:10 a=xqWC_Br6kY4A:10 a=vaFUolhbxO8tLyV4lLAA:9 a=CjuIK1q_8ugA:10 a=9s889Sdci64LZ2Ds:21 a=ExpYwqe-H94vJiB5:21 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117 Subject: RE: [Caml-list] Callback.register equivalent before runtime is initialized? Evgeny Roubinchtein wrote: > Hello, everyone, >=20 > I am learning about run-time compilation, and using OCaml as a base for my > experiments. So far, I have a really simple C primitive that just calls > back into a simple OCaml wrapper around Toplevel.load_lambda (it passes a > Lambda.lambda that has been marshalled to a string constant). > Since the C primitive is in the run-time (libcamlrun) library, and the > wrapper is in the Toplevel, I am using Callback.register to pass the > address of the wrapper to the C primitive. That set-up works pretty well > in the toplevel because I can call Callback.register when the toplevel is > being initialized, i.e., before any code is read from the user. >=20 > However, I am now trying to move to producing bytecode executables, so, if > I stay with my current set-up I would need to do the equivalent of > Callback.register (i.e., put the address of the wrapper into the hash > table maintained by caml_callback_register) before any of the "user code" > in the executable starts to run. I have been looking at the > (bytecode) linker and also the caml_startup function to understand how the > running of bytecode "gets started", and I have also modified tools/objinfo > to print the contens of the SYMB section in bytecode executables and the > relocations table in .cmo's to see if inspiration strikes ;-) -- but so > far I am not quite seeing "how things work." >=20 > I'll keep looking, but I though I'd ask for advice here in case someone > has some advice to offer. Exposing the primitives directly is in general a bad idea - and the "proble= m" you're looking at here is one reason why it's bad. Wrap the primitive in= a module and instruct your users (even if that's just you!) to use the mod= ule - link order then takes care of your problem. So if your primitive is m= y_first_primitive then you could have: MyPrimitives.mli: external first_primitive : foo -> bar =3D "my_first_primitive" MyPrimitives.ml: external first_primitive : foo -> bar =3D "my_first_primitive" let _ =3D Callback.register ... Now when you compile a program using your primitive, you should link MyPrim= itives.cmo (or MyPrimitives.cmx in native) and your initialisation code is = guaranteed to be called before MyPrimitives.first_primitive is ever called = by a user. This also ensures that your primitive is used with the correct O= Caml type (although bear in mind that C primitives can be written to be leg= itimately used with multiple types - e.g. %identity). Yes, your primitive could still be called directly - but that's now an "uns= upported" route and a user doing that gets all that's coming to them! Incid= entally, you don't have to use the "external" declaration in the .mli, but = the manual chapter on C linking explains that there is a small benefit to d= oing that, if you don't mind revealing that the function is a C stub. HTH, David