guile-user
[Top][All Lists]
Advanced

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

Re: guile as extension language


From: Neil Jerram
Subject: Re: guile as extension language
Date: 07 Apr 2002 15:38:14 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

>>>>> "Paul" == Paul Emsley <address@hidden> writes:

    Paul> On Sun, 2002-04-07 at 00:47, Matthew R Wette wrote:
    >> Matthew R Wette writes ...
    >> > 
    >> > How is Guile intended to be used as an extension language?
    >> > 
    >> My interest here was in exploring the scope of work required to
    >> make a Guile extension for Dia (the gnome graphics app).
    >> 

    Paul> This is not a reply really, more of a me-too.

I've replied separately to Matthew's question, and most of what I say
there should apply to your case as well, when it comes to deciding
what you want your script to be able to control, and how to achieve that.

Which just leaves ...

    Paul> I have recently written a program in C/C++ using gtk [1] and now want 
to
    Paul> type a script (say) (or commands) at the console/terminal.  I would 
like
    Paul> this to be interpreted by guile but cannot see how since gtk has the
    Paul> control passed completely to it using gtk_main().  

This question keeps cropping up, so this time I'll try my best to give
a definitive answer.

1. Do you really want this I/O at the console?  You could choose
   instead to use a GtkEntry widget for typing in, and a GtkText for
   the output, and include these widgets in your overall GUI.  Then
   everything would be under the control of gtk_main(), so you avoid
   the main issue.

   If you followed this route, the basic mechanism for getting
   commands evaluated would be to add an "activate" signal handler to
   the GtkEntry widget that calls scm_c_eval_string to evaluate the
   line of input in the widget.

2. If you definitely want I/O at the console, you can use gtk_idle_add
   to register a function that gtk_main should call when nothing is
   happening in the GUI.  The function that you register should

   - do a non-blocking select on standard input to find whether
     there's anything to read

   - read characters 1 at a time into an input buffer

   - when newline is read, call scm_c_eval_string to evaluate the
     buffered input.

3. However, both the above are suboptimal for two main reasons:

   3.1. They only work if the expression entered on a line is always
        balanced.

   3.2. They don't support the reading of input that is not meant to
        be evaluated, or that should be evaluated in a different way.
        (e.g. input for the Guile debugger).

   What you really want, IMO, to overcome these issues, is for the
   GtkEntry widget (case 1) or the console (case 2) to act like input
   ports with two properties:

   - From the point of view of code like `(top-repl)' (which
     implements the standard Guile REPL), they can be used as input
     ports just like any others.

   - But, whenever there isn't any immediate input available, they
     call gtk_main.

   The good news is that Scheme continuations make it possible to do
   exactly this!  Suppose in C that you

   - define and export a Scheme primitive `call-gtk-main', which just
     calls gtk_main

   - define and export a Scheme primitive `store-continuation', which
     saves its continuation argument in a global variable

   - write a Gtk idle function `check_stdin', which checks for input
     available on standard input and, if there is any, calls the
     continuation stored above

   - use gtk_idle_add to register this idle function with gtk_main.

   Now you can make a soft input port with this read-char procedure:

       (lambda ()
         (call-with-current-continuation
           (lambda (cont)
             (store-continuation cont)
             (call-gtk-main)))
         (read-char standard-input))

   (This is for case 2.  For case 1 you need something a bit trickier,
   where the continuation is called from the "activate" handler, and
   the read-char procedure uses an input buffer.)

   Finally, to get everything rolling, you need to

   - do all your usual application initialization

   - define the soft port as shown above, and call it, say,
     `soft-port'

   - evaluate `(set-current-input-port soft-port)'

   - evaluate `(top-repl)'.

   (Probably the last 3 steps are most conveniently achieved by
   loading a Scheme file.)

For a working example of approach 3, using guile-gtk and the GtkEntry
widget, you might like to grab my guile-gui distro from
http://www.ossau.uklinux.net/guile.

    Paul> Is scm_init_guile() really the way to do it?  I got the impression 
that
    Paul> it was not, if I wanted portability (and I do).

scm_init_guile is mostly a red herring.  Since you have control of
your source code's main function, you can just as easily do the
scm_boot_guile structure:

- main ()
  - scm_boot_guile (..., inner_main, ...)

- inner_main ()
  - rest of application

as the scm_init_guile structure:

- main ()
  - scm_init_guile ()
  - rest of application

It may be true that scm_init_guile is marginally less portable; I
don't know for sure.

(scm_init_guile is designed for libraries that don't have access to
main().)

    Paul> I initially thought that that guile + gtk (not guile-gtk) would be
    Paul> common combination and tried to find examples to see how they did it,
    Paul> but I could not.  Can you recommend anything?

Bill Schottstaedt has previously posted examples using both Motif and
Gtk, and Ariel Rios has written a `GuileRepl' widget using Gtk.  All
of these are examples of case 1 above.  I'd guess that Bill's example
is available in the Snd source, and Ariel's in Gnome CVS.

    Paul> I thought that converting to guile-gtk, but since I was using glade 
and
    Paul> gtkglarea, I was a bit nervous about doing that.  Should I have been?

Suggest looking at guile-gtk (and perhaps also my guile-gui) to see
what guile-gtk can do for you.  Given that you're already using glade,
it might be that the only thing of use to you would be calling
`gtk-main' from Scheme instead of `gtk_main' from C - i.e. not much
difference!

        Neil




reply via email to

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