emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Lisp object that refers to a C struct


From: Davis Herring
Subject: Re: Lisp object that refers to a C struct
Date: Wed, 17 Oct 2012 10:59:06 -0600
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.18) Gecko/20110717 Lanikai/3.1.11

> Then the code that GC's this new Lisp object will have to be entirely
> specific to the layout of the struct I'm using, right?  It won't be
> suitable even for the similar-but-different inotify code, right?  If
> so, it's too bad: I hoped I could come up with some Lisp object that
> could be a wrapper for an arbitrary C struct, so that any similar
> feature that will need to pass opaque objects to Lisp could do that,
> instead of adding yet another object type.
> 
> If it's possible to do this in some generic way, could you please
> explain how?

Python addresses this with the CObject API.  (It is being supplanted by
a newer Capsule API, but it's nice and simple as a comparison point.)
http://docs.python.org/c-api/cobject.html

Basically, you make your single new Lisp type contain a pair of
pointers: the first points to your struct, and the other points to a
function that frees the struct and does whatever other cleanup.  This
latter can also be used as a type tag (so that you can't accidentally
use this to cast a eli_file_watcher_struct* to a
stefan_smie_cache_struct* and turn a Lisp bug into a crash in C),
although that might involve creating several wrappers for free() in the
trivial case.  (The CObjects use a third pointer that can be used to
disambiguate; either way works.)

The advantage of this approach is that the pointer marshaling code (and
the object-printing code and so forth) need only be written once, and
only one true Lisp type is used.  The disadvantage is of course that two
layers of type checking must be performed: the usual CONSP variety, and
then you check the function pointer (or other tag) once you know that
it's a struct-wrapper of some sort.

>> If you make sure there's at most 1 file-watcher object per C struct,
>> then you can easily zero-out its pointer-field after freeing the
>> C struct, so you can make sure you protect yourself from
>> dangling pointers.  And if you make sure the GC calls you back when
>> freeing the file-watcher, then you can make sure that you don't leak the
>> C structs.
> 
> You mean, have the free_my_object function (to be called by GC) call
> my own code?  Or is there a more generic way?

Yet another approach is to make sure that your code keeps a reference to
the struct-wrapper Lisp object and frees that reference only when it
destroys the underlying thread.  Then if the thread is alive, the struct
is; you can have a field in the struct (again like the killed buffer)
that means "this has no thread, so you can't use it from Lisp anymore".
 Then when the Lisp client gives up and drops their reference, the
struct is freed.

(Of course, you could do it the other way around: have GC destroy the
thread when the last reference to the struct-wrapper dies.  Then client
Lisp merely drops their references to the wrapper when they're done,
although there is some nondeterminism about when GC will happen.)

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]