From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by yquem.inria.fr (Postfix) with ESMTP id 2A61DBC57 for ; Wed, 3 Mar 2010 12:02:48 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Aq0BAMfQjUvZSMDdimdsb2JhbACbCxUBAQEKCQwHEQUfiBy3FoR8BA X-IronPort-AV: E=Sophos;i="4.49,573,1262559600"; d="scan'208";a="45824965" Received: from fmmailgate01.web.de ([217.72.192.221]) by mail2-smtp-roc.national.inria.fr with ESMTP; 03 Mar 2010 12:02:47 +0100 Received: from smtp07.web.de (fmsmtp07.dlan.cinetic.de [172.20.5.215]) by fmmailgate01.web.de (Postfix) with ESMTP id 2B3D414A9A9DD; Wed, 3 Mar 2010 12:02:47 +0100 (CET) Received: from [85.216.85.71] (helo=frosties.localdomain) by smtp07.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #314) id 1NmmLm-0000yZ-00; Wed, 03 Mar 2010 12:02:46 +0100 Received: from mrvn by frosties.localdomain with local (Exim 4.71) (envelope-from ) id 1NmmLm-0004bD-7Q; Wed, 03 Mar 2010 12:02:46 +0100 From: Goswin von Brederlow To: Florent Monnier Cc: caml-list@yquem.inria.fr, Goswin von Brederlow Subject: Re: [Caml-list] How to pass C pointers to Caml References: <9dfe358d1002281955k4cb9207bi4afe5d649fc20e05@mail.gmail.com> <201003020004.22232.monnier.florent@gmail.com> <87vddfhvox.fsf@frosties.localdomain> <201003021234.48943.monnier.florent@gmail.com> Date: Wed, 03 Mar 2010 12:02:46 +0100 In-Reply-To: <201003021234.48943.monnier.florent@gmail.com> (Florent Monnier's message of "Tue, 2 Mar 2010 12:34:48 +0100") Message-ID: <87fx4hllbd.fsf@frosties.localdomain> User-Agent: Gnus/5.110009 (No Gnus v0.9) XEmacs/21.4.22 (linux, no MULE) MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Sender: goswin-v-b@web.de X-Sender: goswin-v-b@web.de X-Provags-ID: V01U2FsdGVkX1/60PdLr7QNPUsELey97kjz5KTAggIRYV6cN4xJ yaxDm5AiUDIx8sLXUQpt0DbZpupgkvMCtEJo0xjqHNzpfvUwxO /tQiTjScs= X-Spam: no; 0.00; pointers:01 ocaml:01 pointers:01 ocaml:01 pointer:01 pointer:01 trivial:01 allocates:01 bindings:01 struct:01 struct:01 lib:01 finalizer:01 zhao:98 boom:98 Florent Monnier writes: > Le mardi 2 mars 2010 11:19:58, vous avez écrit : >> Florent Monnier writes: >> > Le lundi 1 mars 2010 14:24:45, Goswin von Brederlow a écrit : >> >> Florent Monnier writes: >> >> > Le lundi 1 mars 2010 04:55:00, Jianzhou Zhao a écrit : >> >> >> I have been calling OCaml code from C in my project. >> >> >> The C code has some pointers to C structures. >> >> >> I got 'seg fault' when calling the OCaml function receiving >> >> >> C structure pointers. >> >> >> >> >> >> 18.7 at http://caml.inria.fr/pub/docs/manual-ocaml/manual032.html >> >> >> gives the examples that pass int into OCaml. These examples work for >> >> >> me. But, Does OCaml support to pass C structure pointers to OCaml? >> >> > >> >> > Yes it does. Just cast your pointer to the type value. >> >> > >> >> > In this tutorial there is an example "Pointers to C structures": >> >> > http://www.linux-nantes.org/~fmonnier/OCaml/ocaml-wrapping-c.php#ref_p >> >> >tr >> >> > >> >> > the pointer to a C struct is wrapped on the ocaml side by an abstract >> >> > type called "t" here, and it is provided back to C with print_t / >> >> > dump_ptr. >> >> >> >> The problem with this trivial approach is that ocaml can store the >> >> pointer somewhere. When the C pointer is freeed then ocaml has a >> >> dangling pointer. Worse, if the GC allocates a new heap then the pointer >> >> might suddenly point into the heap and then BOOM. >> > >> > A lot of bindings wrap C pointer, it is known to be a technic that does >> > work. Dangerous that's true, be if you are very careful, it works. >> > What you can do is set the pointer to NULL when the struct is freed, and >> > then each function that uses this struct pointer can first check if the >> > pointer is NULL or not before to use it, and if it's NULL raise an >> > exception. >> >> let x = ref None >> >> let called_function c_ptr = x := Some c_ptr >> >> How will you get x to be Some NULL? > > I mean often in a C library pointers to C struct are just pointers to > something abstract because a lot of lib C API do hide the struct, and provide > a function to free the things pointed. So in your wrapper after you call the > destroy function you can set the pointer to NULL and in the other functions > test if the pointer is NULL before to use it to prevent a user of the wrapper > to call a function after having called the destroy function. > >> Your C code does not know about the >> copy. You need to wrap the C pointer into a custom or abstract block >> first to be able to NULL it. A finalizer in a custom block can also be >> helpfull here and free the pointer when ocaml no longer needs it. >> >> >> It is better to put the pointer into an abstract or custom block. >> > >> > You can do this too. >> >> Imho you must. Anything else is too dangerous. > > Yes it is dangerous, but as I explained with some C libraries this is the only > possible solution. If you can do it the other way, then do, while it's indeed > safer. It is always possible to wrap the C pointer into an abstract or custom block. The pointer can still become dangling when the C side frees the target before ocaml forgets the block but, as the GC does not look into abstract/custom blocks, it will never result in the GC exploding because a dangling pointer points into the GC heap. MfG Goswin