From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: weis Received: (from weis@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id UAA06821 for caml-redistribution; Tue, 27 Oct 1998 20:02:02 +0100 (MET) Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id VAA02531 for ; Mon, 26 Oct 1998 21:27:55 +0100 (MET) Received: from pauillac.inria.fr (pauillac.inria.fr [128.93.11.35]) by concorde.inria.fr (8.8.7/8.8.7) with ESMTP id VAA11088; Mon, 26 Oct 1998 21:27:53 +0100 (MET) Received: (from xleroy@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id VAA28834; Mon, 26 Oct 1998 21:27:53 +0100 (MET) Message-ID: <19981026212753.59546@pauillac.inria.fr> Date: Mon, 26 Oct 1998 21:27:53 +0100 From: Xavier Leroy To: surlog@club-internet.fr, Caml List Subject: Re: Types abstraits et Inferface C References: <36304C18.E728D95D@club-internet.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Mailer: Mutt 0.89.1 In-Reply-To: <36304C18.E728D95D@club-internet.fr>; from SURLOG on Fri, Oct 23, 1998 at 11:27:52AM +0200 Sender: weis > Peut-on remonter des types abstraits de données C dans un programme Caml > via l'interface C<->Caml. Oui, il suffit de les faire correspondre à un type abstrait Caml. Pour être plus concrets, supposons l'interface C suivante: typedef ... abstract_ty; abstract_ty make(int i); int read(abstract_ty a); En Caml, cela devient: type abstract_ty external make: int -> abstract_ty = "stub_make" external read: abstract_ty -> int = "stub_read" Dans le "stub code", on a plusieurs possibilités de conversion entre le type abstract_ty et le type value: 1- Si abstract_ty est un pointeur hors du tas et aligné sur une frontière de mots (comme le sont tous les pointeurs renvoyés par malloc()): un cast direct convient. value stub_make(value i) { return (value) make(Int_val(i)); } value stub_read(value a) { return Val_int(read((abstract_ty) a)); } 2- Dans les autres cas (abstract_ty pas forcément aligné, ou bien n'est pas un pointeur mais une struct, ou bien...), le mieux est d'envelopper les valeurs de type abstract_ty dans des blocs de type Abstract_tag: value stub_make(value i) { abstract_ty a = make(Int_val(i)); value res = alloc((sizeof(abstract_ty) + sizeof(value) - 1) / sizeof(value), Abstract_tag); *((abstract_ty *) res) = a; return res; } value stub_read(value a) { return Val_int(read(*((abstract_ty *) a))); } 3- Une variante du cas précédent, utile si une fonction de déallocation explicite free_ty() est fournie sur le type abstract_ty, est d'envelopper les abstract_ty dans des objets finalisés, de sorte que le GC appelle free_ty() lorsque l'objet finalisé devient inaccessible: #define Ty_val(v) (*((abstract_ty *) &Field(v, 1))) static void finalize_ty(value a) { free_ty(&Ty_val(a)); } value stub_make(value i) { abstract_ty a = make(Int_val(i)); value res = alloc_final(1 + (sizeof(abstract_ty) + sizeof(value) - 1) / sizeof(value), finalize_ty, 1, 1000); Ty_val(res) = a; return res; } value stub_read(value a) { return Val_int(Ty_val(a)); } Hope this helps, - Xavier Leroy