This is the mail archive of the guile@cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

A curses interface



I'd like to work through Klaus's curses questions in public, because I
think it might help us learn:
1) where the current smob interface is weak, and
2) how to best explain this in the manual, since most extension
   writers are going to come across this at some point.


> Would the following work for a wrapper for the ncurses library:
> 
> long WINDOW_type = scm_make_smob_type ("WINDOW_type", sizeof (WINDOW));
> #define SCM2WINDOW (x) ((WINDOW *)SCM_SMOB_DATA)
> 
> scm_size_t WINDOW_free (SCM object)
> {
>   WINDOW *w;
>   w = SCM2WINDOW (object);
>   gh_defer_ints ();
>   delwin (w);
>   gh_allow_ints ();
>   return sizeof (WINDOW);
> }
> 
> 
> scm_set_smob_free (WINDOW_type, &WINDOW_free);
> 
> SCM WINDOW2SCM (WINDOW *w)
> {
>  SCM z;
>  SCM_NEWSMOB (z, WINDOW_type, w);
>  return z;
> }

I think this looks okay, modulo the typo that Mikael pointed out.

> Or does the fact that windows may contain pointers to other windows which
> are subject to guile's memory administration make it impossible to use
> scm_make_smob?

The curses library, like most other C libraries, requires its users to
follow certain rules in the way they handle the objects it manages.
For example, if I call delwin(W) to delete W, then I can't use W any
more.  If I say V = subwin (W, ...), to make V a subwindow of W, then
I must call delwin (V) before I delwin (W).  And so on.

In C, if you violate these rules, everyone understands that your
program will just crash.  It's culturally acceptable.

In Scheme, this is not culturally acceptable.  If you do something
wrong, you should get a plausible error message, and the system should
be left in a consistent state.

So when you write a Scheme interface to a C library, you are turning a
vulnerable interface, which trusts you not to pass it bad pointers or
dead objects, into a rugged, bulletproof interface which makes it
impossible for the caller to mung the state of the system.


I don't really understand your question about windows pointing to
other windows.  But I think the answer is: as the author of the
Guile/ncurses interface, you are responsible for doing whatever is
necessary to turn any arbitrary sequence of Scheme-level operations on
Scheme curses objects into a safe sequence of C-level operations on C
curses objects.

Thus, if one window points to another, and the Scheme user deletes the
latter, then you're responsible for making sure things turn out okay.
How you handle it is up to you.  An error message is one possibility.
Doing extra work to make the request legal (e.g., automatically
deleting subwindows when a window is deleted) is another.


Questions to ponder:

If a Scheme window object gets GC'd, what should curses do with the C
window object?  Should it really delete the C window, or should it
leave it on the screen?  Just because I'm not doing anything with a
window any more doesn't mean I want it to disappear.

If I delete a C window, and then try to write text to it, the library
will just crash.  At the Scheme level, such a sequence should cause an
error.  Your library is responsible for detecting this situation.  How
will you implement that behavior?

Should users be able to link Guile and your library with their own C
code, and manipulate windows directly in C?  If so, when they delete a
window, how will your library find out?  Curses probably won't tell
you, so you'd have to require the C code to cooperate with your
library.  Or just decide that people can't call certain functions
directly, should go through your functions instead.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]