FFI Ptr question

paul@theV.net paul@theV.net
Thu, 3 Jul 2003 18:45:27 +0800


Thank you for the explanation!

So am I right to draw a picture like this?

 ---------        --------- 
| Haskell |      | Foreign |
| Ptr     |----->| Data    |
| Block   |      | Block   |
 ---------        --------- 

1. If I allocate the data block in a foreign language and returns
   the pointer as Ptr through FFI, I have to free it in the 
   foreign language after use.

2. If I allocate the data block through Marshal.Alloc, then I
   need to use Haskell free to deallocate it. (why the difference?
   GHC not using the default malloc/free in C lib?)

3. If the Haskell Ptr is no longer in use, the Haskell GC will
   collect it, regardless of whether it has a dangling pointer
   to Foreign Data Block.

I only hope the Ptr part of FFI documentation can include some
of the malloc/free guidelines, otherwise it is quite confusing
for beginners.

Regards,
.paul.

On Thu, Jul 03, 2003 at 03:49:21AM -0400, Derek Elkins wrote:
> On Thu, 3 Jul 2003 15:04:26 +0800
> paul@theV.net wrote:
> 
> > On Thu, Jul 03, 2003 at 01:40:46AM -0400, Derek Elkins wrote:
> > > On Thu, 3 Jul 2003 11:34:08 +0800
> > > paul@theV.net wrote:
> > > 
> > > > If a C function returns a (void*), let's say:
> > > > 
> > > > data MyObj = MyObj
> > > > 
> > > > foreign import ccall "static myobj_ffi.h new_obj" newMyObject ::
> > > > IO(Ptr MyObj)
> > > > 
> > > > ptr <- newMyObject
> > > > 
> > > > should I free the ptr afterwards or not?
> > > 
> > > Assuming that it should be freed even in C and nothing else is
> > > managing it then I believe the answer is yes.  You can use a
> > > finalizer to do it.
> > 
> > The wierd thing is, I cannot use the the function
> > Foreign.Marshal.Alloc.free to free the ptr. I must
> > use my own C function to do a simple free() call.
> 
> You didn't allocate it with the Foreign library, why would you expect to
> free it with it?  Actually, I'm kind of surprised it doesn't work,
> nevertheless I don't believe that the intent of the Alloc module is to
> free memory allocated by a foreign language, or allocate memory that
> will be freed by a foreign language.  If you need to create/destroy a
> foreign value in Haskell, you typically provide both a creation and
> destruction function.
> 
> > > > If I have another imported C function:
> > > > 
> > > > foreign import ccall "static myobj_ffi.h print_obj" printMyObject
> > > > :: Ptr MyObj -> IO ()
> > > > 
> > > > Can I safely assume the C function print_obj(void *) always get
> > > > the same pointer even if I call (printMyObject ptr) multiple
> > > > times?
> > > 
> > > What other pointer would it pass?
> > 
> > The same Haskell ptr. I wonder if they'll ever change after
> > creation.
> > 
> > My question is, if Ptr is equivalent to a raw void* pointer in 
> > C, and pointers created in foreign language (which is later
> > passed to Haskell as Ptr) has to be freed in the foreign
> > language, then can I safely assume that Ptr isn't affected
> > by Haskell's GC cycle? And what the real difference between Ptr
> > and StablePtr?
> 
> The GC won't free the memory pointed at by the void * unless you attach
> a finalizer, in which case you obviously shouldn't be freeing it in the
> foreign code.  The Ptr you get will be freed by Haskell's GC if it
> becomes unreferenced, but that won't affect what it points at. 
> StablePtr's are for pointing at -Haskell- values.
> 
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe