[lgtk-devel] Re: [PATCH] lgtk CVS on SBCL

Damien Diederen diederen at swing.be
Sun Dec 7 15:05:57 UTC 2003


Mario,

On Sat, Dec 06, 2003 at 07:51:00PM +0100, Mario Mommer wrote:
> Damien Diederen <diederen at swing.be> writes:
> > I am still thinking about how to clean up the mess I made of lgtk to get
> > it to run on SBCL.  While the #+ forest is ugly as hell, I'm afraid
> > simply USEing SB-ALIEN & friends in the DEFPACKAGE form instead does not
> > cut it: if anything, it will hide non-standard code, and hinder ports to
> > less similar implementations.
> > 
> > Of course, your `port.lisp' file is a start, and I was thinking about
> > completing it with lgtk-level abstractions of DEFCALLBACK and
> > ENABLE-INTERRUPTS (I suppose you agree such functions are way too
> > low-level to be scattered all around the code).
> 
> The problem is to find a good interface. In the case of DEFCALLBACK,
> I'd say that we can move it to port.lisp. As long as nobody attempts
> to port this to, say, CLisp, I see no hurry in wrapping
> ENABLE-INTERRUPTS.

I did some cleanup action (see attached patch), but I'm unsure the
result really is an improvement. Ideas on how to cleanup the sbcl-port
branch are very welcome...

> > I'm also a bit wary of the PEEK and POKE macros found in
> > `dynaslot.lisp', which I suppose have something to do with the lack
> > of accessors for some struct members in Gtk+.
> 
> Yes, that is exactly what they are for. They are dangerous, but I do
> not think they are too dangerous. They are low-level, that's all. They
> are only used internally by dynaslot.lisp. dynaslot compiles and
> executes a programm to find out the addresses of slots declared with
> (add-alien-slots ...); peek and poke are used to get/set stuff from
> there. I thing sb-grovel does something similar.

Well, they are no more dangerous than using Gtk+ from C anyway :)

> > my pie-in-the-sky dream would be to have lgtk as a strong link to
> > modern desktop environments, and to find a way to reconcile very
> > high-level GUI programming and fine tuning as a McCLIM backend.  Did
> > I say pie-in-the-sky? :)
> 
> :) Well, that's the idea. lgtk is only a low-level lib, a thin
> wrapper, to build this kind of thing on top of it.
> 
> > > Right now I am trying to add a bulk of functionality, mostly using
> > > pygtk .defs files.
> > 
> > That would be great!  Reusable metadata is cool :)
> > 
> > Were did you get these from?  Are they the ones from the Gtk+
> > distribution, or some improved breed only to be found in secret CVS
> > repositories?
> 
> I did not found them in the Gtk+ distribution. After Googling a bit it
> seems that they removed them a short while ago. I am currently looking
> at the .defs that come with the pygtk distribution.

Ok, I have downloaded the thing now. I have also been looking at the
`*-api.xml' files bundled with Gtk#, but it looks like they were
generated from the same source.

> I am currently just thinking on how to deal with
> 
> * Return types
> 
>      Lots of Gtk+ funcs return a GtkWidget, even when in the spec it
>      is said that they return a GtkRadioButton or whatever. For safety
>      reasons, and because Lisps type system can handle this, I would
>      prefer them to return the correct type. That implies either rtfm
>      (lots of it) or some other trick I haven't thought of.

Maybe I am missing something, but (at least for the gdk and gtk parts):

* The `is-constructor-of' property looks like a good guess for 
  constructors.

* The `define-method's have an implicit first parameter that is of type
  `of-object', single-dispatch-style.

The other uses of GtkWidget* I have encountered look quite legitimate.
Of course, the thing will require a bit of massaging, but at least the
metadata seems to be there.

Oh, and I suppose we can use a simple counting-the-stars heuristic to
detect 'out' parameters (in combination with value/reference type info).
>From `pango-attributes.h': 

| (define-function parse_markup
|   (c-name "pango_parse_markup")
|   (return-type "gboolean")
|   (parameters
|     '("const-char*" "markup_text")
|     '("int" "length")
|     '("gunichar" "accel_marker")
|     '("PangoAttrList**" "attr_list")
|     '("char**" "text")
|     '("gunichar*" "accel_char")
|     '("GError**" "error")
|   )
| )

> * Gdk, Atk, Pango, Gobject, Glib,....
> 
>      It is a shipload of stuff, some of it requires thought
>      (&key/&optional args, for instance), lots of it is simply
>      redundant (all the functions ending in _defaults, for
>      instance). Others need carefull wrapping, which implies to be
>      aware of that to begin with.

Do you have any actual examples of functions that would require careful
wrapping? I suppose other language bindings suffered the same problem;
maybe we could extract some awareness from the their generator code?

>      I don't even know how to manage that process. I do not want to
>      get lost in the middle of it, since it is really a daunting
>      amount of stuff. Ideas?

I will be looking at the Gtk# `glue' and `generator' stuff...

> > > I'll try to write up today what these nexus/capsule/metacapsule stuff
> > > does and send it either to lgtk-devel or to clump.
> 
> I finally didn't manage. Maybe tomorrow - today I updated the website
> etc.

There is no urgency, as I'm starting to get a grasp on the way they work
anyway.

> > While I was planning to dig into the code to get the full picture
> > anyway, such documentation would indeed be a great help; notwithstanding
> > the hordes of young Lisp hackers waiting for some code to cut their
> > teeth on :)
> 
> I am no expert either! I've been doing lisp for ca. 2 years now. The
> code is thus probably not the best learning resource, among other
> things because it is, well, in a deep alpha stage.
> 
> The dephts of it, i.e. all the files that do not contain a reference
> to gtk, are (an attempt of a) general framework for managing bindings
> to C libs. I plan to separate that from lgtk some day and use it to
> write bindings for other libs too.

Yes, the DEF-BINDING stuff looks quite nice; in particular the way the
binding types are defined (with :IN, :OUT and :ALIEN)...

> In any case, don't hesitate to ask if you have questions!

I won't ;)

> Regards,
>         Mario.
> 
> > P.S.: Don't hesitate to forward this message to lgtk-devel as you see
> > fit.
> 
> Here it goes...

Regards,
Damien.

-- 
Let us not look back in anger or forward in fear, but around us in awareness.
		-- James Thurber
-- 
http://users.swing.be/diederen/
-------------- next part --------------
? examples/check-button.fasl
? examples/cool-button.fasl
? examples/dialog.fasl
? examples/entry.fasl
? examples/hello-world.fasl
? examples/hello-world2.fasl
? examples/packing-boxes.fasl
? examples/radio-buttons.fasl
? examples/splash-msg.fasl
? examples/tables-hw.fasl
? examples/toggle-button.fasl
? src/bindings.fasl
? src/dynaslot.fasl
? src/enums.fasl
? src/gtkbindings.fasl
? src/gtkclasshierarchy.fasl
? src/gtkenums.fasl
? src/gtklisp.fasl
? src/gtknexus.fasl
? src/gtkpackage.fasl
? src/nexus.fasl
? src/port.fasl
? src/probe
? src/probe.c
? src/probe.x
? src/widgets.fasl
Index: src/gtknexus.lisp
===================================================================
RCS file: /project/lgtk/cvsroot/lgtk/src/gtknexus.lisp,v
retrieving revision 1.4.4.1
diff -u -r1.4.4.1 gtknexus.lisp
--- src/gtknexus.lisp	5 Dec 2003 16:55:08 -0000	1.4.4.1
+++ src/gtknexus.lisp	7 Dec 2003 15:14:28 -0000
@@ -197,22 +197,26 @@
 	r))))
 
 ;; Trampolines
-(defcallback gtk-standard-decoy
-    #+cmu (c-call:void (w (* t)) (cookie c-call:int))
-    #+sbcl (sb-alien:void (w (* t)) (cookie sb-alien:int))
+(defmacro %defcallback (name (return-type &rest arg-specs) &rest body)
+  "Defines a callback using the `port' C type specifiers. Uses
+PORT-ALIEN-TYPE to convert the syntax to the implementation-dependant
+alien type specifiers."
+  `(defcallback ,name 
+    ,(list* (port-alien-type return-type)
+	    (mapcar (lambda (arg-spec)
+		      (destructuring-bind (name type) arg-spec
+			(list name (port-alien-type type))))
+		    arg-specs))
+    , at body))
+
+(%defcallback gtk-standard-decoy (:void (w (* t)) (cookie :int))
   (%standard-handler w cookie))
 
-(defcallback gtk-destroy-decoy 
-    #+cmu (c-call:void (w (* t)) (cookie c-call:int))
-    #+sbcl (sb-alien:void (w (* t)) (cookie sb-alien:int))
+(%defcallback gtk-destroy-decoy (:void (w (* t)) (cookie :int))
   (%destroy-handler w cookie))
 
-(defcallback gtk-evhandling-decoy 
-    #+cmu (c-call:int (w (* t)) (ev (* t)) (cookie c-call:int))
-    #+sbcl (sb-alien:int (w (* t)) (ev (* t)) (cookie sb-alien:int))
+(%defcallback gtk-evhandling-decoy (:int (w (* t)) (ev (* t)) (cookie :int))
   (%event-handler w ev cookie))
 
-(defcallback %gtk-itc-handler 
-    #+cmu (c-call:int (id c-call:int))
-    #+sbcl (sb-alien:int (id sb-alien:int))
+(%defcallback %gtk-itc-handler (:int (id :int))
   (%itc-handler id))
Index: src/gtkpackage.lisp
===================================================================
RCS file: /project/lgtk/cvsroot/lgtk/src/gtkpackage.lisp,v
retrieving revision 1.2
diff -u -r1.2 gtkpackage.lisp
--- src/gtkpackage.lisp	5 Nov 2003 21:20:41 -0000	1.2
+++ src/gtkpackage.lisp	7 Dec 2003 15:14:29 -0000
@@ -49,5 +49,5 @@
 	   ;; enums. Only export those which can be combined via | in
 	   ;; C. See file enums.lisp for details.
 	   :gtkattachoptions)
-  (:use common-lisp nexus widget-nexus callback enums defbinding clnexus-port
+  (:use common-lisp nexus widget-nexus enums defbinding clnexus-port
 	dynaslot))
Index: src/port.lisp
===================================================================
RCS file: /project/lgtk/cvsroot/lgtk/src/port.lisp,v
retrieving revision 1.3.4.1
diff -u -r1.3.4.1 port.lisp
--- src/port.lisp	5 Dec 2003 16:55:08 -0000	1.3.4.1
+++ src/port.lisp	7 Dec 2003 15:14:29 -0000
@@ -7,11 +7,12 @@
 
 ;; Portablility package.
 (defpackage #:clnexus-port
-  (:export #:alien-address #:finalize
-	   #:make-weak-pointer #:weak-pointer-value
-	   #:*weak-pointer-type* #:run-after-gc #:def-alien-routine
-	   #:port-alien-type)
-  (:use common-lisp))
+  (:export #:alien-address #:finalize #:make-weak-pointer
+	   #:weak-pointer-value #:*weak-pointer-type* #:run-after-gc
+	   #:def-alien-routine #:port-alien-type #:defcallback #:callback)
+  #+cmu (:use common-lisp ext system alien c-call callback)
+  #+sbcl (:use common-lisp sb-ext sb-sys sb-alien callback)
+  (:shadow def-alien-routine finalize make-weak-pointer weak-pointer-value))
 
 (in-package #:clnexus-port)
 
@@ -25,43 +26,25 @@
 ;;; Alien magic
 
 ;; basic C types
-#+cmu
 (defparameter *c-types*
-  '((:char c-call:char)
-    (:short c-call:short)
-    (:ushort c-call:unsigned-short)
-    (:int c-call:int)
-    (:uint c-call:unsigned-int)
-    (:long c-call:long)
-    (:ulong c-call:unsigned-long)
-    (:double c-call:double)
-    (:float c-call:float)
+  '((:char char)
+    (:short short)
+    (:ushort unsigned-short)
+    (:int int)
+    (:uint unsigned-int)
+    (:long long)
+    (:ulong unsigned-long)
+    (:double double)
+    (:float float)
 
-    (:c-string c-call:c-string)
+    (:c-string c-string)
 
-    (:void c-call:void)
+    (:void void)
     (:voidptr (* t))
     (* *)
-    (t t)))
-
-#+sbcl
-(defparameter *c-types*
-  '((:char sb-alien:char)
-    (:short sb-alien:short)
-    (:ushort sb-alien:unsigned-short)
-    (:int sb-alien:int)
-    (:uint sb-alien:unsigned-int)
-    (:long sb-alien:long)
-    (:ulong sb-alien:unsigned-long)
-    (:double sb-alien:double)
-    (:float sb-alien:float)
-
-    (:c-string sb-alien:c-string)
-
-    (:void sb-alien:void)
-    (:voidptr (* t))
-    (* *)
-    (t t)))
+    (t t))
+  "Maps `port' C type specifiers from the :KEYWORDS package to symbols
+from the the C-CALL (CMUCL) or SB-ALIEN (SBCL) packages.")
 
 (defun port-alien-type (key)
   (let ((it (cond ((atom key) (cadr (assoc key *c-types*)))
@@ -71,17 +54,15 @@
 
 ;; Get the actual pointer number
 (defun alien-address (it)
-  #+cmu (system:sap-int (alien:alien-sap it))
-  #+sbcl (sb-sys:sap-int (sb-alien:alien-sap it)))
+  (sap-int (alien-sap it)))
 
 (defmacro def-alien-routine (&rest stuff)
   #+cmu `(alien:def-alien-routine , at stuff)
-  #+sbcl `(sb-alien:def-alien-routine , at stuff))
+  #+sbcl `(define-alien-routine , at stuff))
 
 ;;; GC magic
 
-#+cmu (defvar *weak-pointer-type* 'ext:weak-pointer)
-#+sbcl (defvar *weak-pointer-type* 'sb-ext:weak-pointer)
+(defvar *weak-pointer-type* 'weak-pointer)
 
 (defun finalize (fun obj)
   #+cmu (ext:finalize fun obj)
@@ -96,5 +77,4 @@
   #+sbcl (sb-ext:weak-pointer-value obj))
 
 (defun run-after-gc (fun)
-  #+cmu (pushnew fun ext:*after-gc-hooks*)
-  #+sbcl (pushnew fun sb-ext:*after-gc-hooks*))
+  (pushnew fun *after-gc-hooks*))


More information about the lgtk-devel mailing list