[Top][All Lists]

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

[MIT-Scheme-devel] GTk+ in MIT-Scheme?

From: Matt Birkholz
Subject: [MIT-Scheme-devel] GTk+ in MIT-Scheme?
Date: Sun, 9 Oct 2005 11:54:58 -0700

> From: Matt Birkholz <address@hidden>
> Date: Wed, 30 Mar 2005 21:50:37 +0100
> > [...]
> I heard a rumor someone was working on a Foreign Function Interface.
> Does anyone want to 'fess up?  How about just a Foreign Struct
> Interface?

Whoa.  Did you just see 6 months go by... ?  Anyway, it is well nigh
time to expose myself to my fellow MIT-Scheme developers...  weee.

So the FFI is coming along well, thanks for asking. :)

I had a simple GTk+ hello world program working, without callbacks.
Shouldda tooka snapshot.  I could not help fiddling with the callback
support.  My asynchronous callbacks were tiresome -- a C struct for
the C args, a callback trampoline to enqueue the "request", a
marshaller to cons the C args in the Scheme heap...  And what about
toolkits that depend on intelligent return values from the callback
(e.g. a callback that will be a predicate in a sort process)?

The siren of synchronous callbacks calls to me.

> Wrapping up GdkRectangle in 5 or 6 primitives was so much fun I had
> to stop and consider writing a simple Foreign Struct Interface. [...]
> I just want a few primitives that take a foreign pointer and a member
> offset and burp up a string/integer/float/pointer.

That got done.  I hope I do not find out why Elk, Scheme->C, many
others, were shy of member offset forecasting.  They generated a pair
of reader/writer primitives for each member of a struct and let the C
compiler figure the offsets.  Are there many systems where the layout
of struct members is too subtle for Mere Mortals to predict?

Perhaps if they had the prospect of open-coding these primitives, they
would have lead the way.

Here is my evolving "Hello, world!" program.  It stays REALLY close to
the metal.  All pointers into non-heap memory are encapsulated in
"aliens".  No C-array->list-like utilities are provided, but you can
walk the C array by incrementing an alien.  I would rather write a
C-array->list utility in Scheme, not generate it in C.  So this is a
little ugly without the fairings and nacelles.  Once wrapped up, this
can be just as tight as it was 6 months ago.

(load-option 'FFI)
(C-include "prhello" "hello-cdecl")

(define (hello)
  (let* ((window (let ((alien (make-alien '|GtkWidget|)))
                   (C-call "gtk_window_new" alien
                           (C-enum "GtkWindowType GTK_WINDOW_TOPLEVEL"))
         (button (let ((alien (make-alien '|GtkWidget|)))
                   (C-call "gtk_button_new" alien)
         (label (let ((alien (make-alien '|GtkWidget|)))
                  (C-call "gtk_label_new" alien "Hello, world!")
    (C-call "gtk_container_add" button label)
    (C-call "gtk_container_add" window button)
    (C-call "gtk_window_set_title" window "Hello")
    (C-call "gtk_container_set_border_width" button 10)
    (C-call "g_signal_connect" window "delete_event" 
            (C-callback "delete_event") ;trampoline
            (C-callback                 ;callback ID
             (lambda (window event)
               (C-call "gtk_widget_destroy" window))))
    (C-call "g_signal_connect" button "clicked"
            (C-callback "clicked")      ;trampoline
            (C-callback                 ;callback ID
             (lambda (widget)
              (let ((text (C-call "gtk_label_get_text" widget)))
                (C-call "gtk_label_set_text" widget
                        (list->string (reverse! (string->list text))))))))
    (C-call "gtk_widget_show_all" window))

The C declarations are separate, e.g. in this case-sensitive Scheme

(typedef gchar char)
(typedef gint int)
(typedef guint uint)
(typedef gpointer (* mumble))

(extern (* GtkWidget)                   ;gtk+-2.4.0/gtk/gtkwindow.h
        (type GtkWindowType))

(typedef GtkWindowType                  ;gtk+-2.4.0/gtk/gtkenums.h

(extern (* GtkWidget)                   ;gtk+-2.4.0/gtk/gtkbutton.h

(extern (* GtkWidget)                   ;gtk+-2.4.0/gtk/gtklabel.h
        (text (* char)))

(extern void                            ;gtk+-2.4.0/gtk/gtkcontainer.h
        (container (* GtkContainer))
        (widget    (* GtkWidget)))

(extern void                            ;gtk+-2.4.0/gtk/gtkwindow.h
        (window (* GtkWindow))
        (title  (* char)))

(extern void                            ;gtk+-2.4.0/gtk/gtkcontainer.h
        (container (* GtkContainer))
        (border_width guint))

(extern void                            ;gtk+-2.4.0/gtk/gtkwidget.h
        (widget (* GtkWidget)))

(extern void                            ;glib-2.6.3/gobject/gsignal.h
        (object (* GtkObject))
        (name (* gchar))
        (CALLBACK GtkSignalFunc)
        (ID gpointer))

(typedef GtkSignalFunc (* mumble))

(callback gint
          (window (* GtkWidget))
          (event (* GdkEventAny))
          (ID gpointer))

(callback void
          (widget (* GtkWidget))
          (ID gpointer))

(extern void                            ;gtk+-2.4.0/gtk/gtkwidget.h
        (widget (* GtkWidget)))

(extern (* gchar)                       ;gtk+-2.4.0/gtk/gtklabel.h
        (label (* GtkLabel)))

(extern void                            ;gtk+-2.4.0/gtk/gtklabel.h
        (label (* GtkLabel))
        (str (* char)))

reply via email to

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