[cells-gtk-cvs] CVS root/gtk-ffi

pdenno pdenno at common-lisp.net
Thu Feb 16 18:04:29 UTC 2006


Update of /project/cells-gtk/cvsroot/root/gtk-ffi
In directory common-lisp:/tmp/cvs-serv8937/root/gtk-ffi

Modified Files:
	gtk-ffi.lisp 
Log Message:
Now native CFFI, use CFFI type translation. Reworked macros def-gtk-lib-function, def-gtk-function

--- /project/cells-gtk/cvsroot/root/gtk-ffi/gtk-ffi.lisp	2006/02/11 03:45:55	1.16
+++ /project/cells-gtk/cvsroot/root/gtk-ffi/gtk-ffi.lisp	2006/02/16 18:04:29	1.17
@@ -16,16 +16,56 @@
  
 |#
 
-
-(defpackage :gtk-ffi (:use :common-lisp :uffi))
+(defpackage :gtk-ffi (:use :common-lisp :pod :uffi)) ; pod remove uffi
 
 (in-package :gtk-ffi)
 
-(defconstant c-null (make-null-pointer '(* :void)))
-(defconstant c-null-int (make-null-pointer :int))
+;;; POD throw-away utility
+(defun gtk-lib2cffi (body)
+  "Convert hello-c to uffi to cffi types. Swap order of arguments."
+  (flet ((convert-type (type)
+	  (case type
+	    (c-string :gtk-string)
+	    (boolean :gtk-boolean)
+	    (t (cffi-uffi-compat::convert-uffi-type (ffi-to-uffi-type type))))))
+  (dbind (ignore module &rest funcs) body
+     (pprint `(,ignore 
+	       ,module
+	       ,@(mapcar
+		  #'(lambda (f)
+		      (dbind (name args &optional return-type) f
+			     ` (,name 
+				    ,(if return-type
+					 (convert-type return-type)
+				       :void)
+				    ,(mapcar #'(lambda (a)
+						 (list
+						  (car a)
+						  (convert-type (cadr a))))
+					     args))))
+		      funcs))
+	     *standard-output*))))
+
 
+(defconstant +c-null+ (cffi:null-pointer)) 
 (defvar *gtk-debug* nil)
 
+;;; ==============  Define CFFI types, and their translations.... 
+(cffi:defctype :gtk-string :pointer :documentation "string type for cffi type translation")
+(cffi:defctype :gtk-boolean :pointer :documentation "boolean type for cffi type translation")
+
+(defmethod cffi:translate-to-foreign (value (type (eql :gtk-boolean)))
+  (cffi:make-pointer (if value 1 0)))
+
+(defmethod cffi:translate-from-foreign (value (type (eql :gtk-boolean)))
+  (not (zerop (cffi::pointer-address value)))) ; pod strange!
+
+(defmethod cffi:translate-to-foreign (value (type (eql :gtk-string)))
+  (when (null value) (setf value "")) ; pod ??? 
+  (cffi:foreign-string-alloc value))
+
+(defmethod cffi:translate-from-foreign (value (type (eql :gtk-string)))
+  (cffi:foreign-string-to-lisp value))
 
 (defun int-slot-indexed (obj obj-type slot index)
   (declare (ignorable obj-type))
@@ -40,53 +80,69 @@
          '(:array :int) index)
     new-value))
 
+(cffi:define-foreign-library 'gobject
+  (:linux "libgobject-2.0.so")
+  (:win32 "libgobject-2.0-0.dll")
+  (:macosx "libgobject-2.0-0.dylib"))
+
+(cffi:define-foreign-library :glib
+  (:linux "libglib-2.0.so")
+  (:win32 "libglib-2.0-0.dll")
+  (:macosx "libglib-2.0-0.dylib"))
+
+(cffi:define-foreign-library :gthread
+  (:linux "libgthread-2.0.so")
+  (:win32 "libgthread-2.0-0.dll")
+  (:macosx "libgthread-2.0-0.dylib"))
+
+(cffi:define-foreign-library :gdk
+  (:linux "libgdk-x11-2.0.so")
+  (:win32 "libgdk-win32-2.0-0.dll")
+  (:macosx "libgdk-win32-2.0-0.dylib")) ; pod ???
+
+(cffi:define-foreign-library :gtk
+  (:linux "libgtk-x11-2.0.so")
+  (:win32 "libgtk-win32-2.0-0.dll")
+  (:macosx "libgtk-win32-2.0-0.dylib")) ; pod ???
+
+#+libcellsgtk
+(cffi:define-foreign-library :cgtk
+  (:linux "libcellsgtk.so")
+  (:win32 "libcellsgtk.dll")
+  (:macosx "libcellsgtk.dylib"))
+
+;;; After doing this, should be able to do (g-thread-init c-null)
+;;; The above define-foreigh-library appears to be useless (doesn't
+;;; work through the symbols) use the names. 
+(defun load-gtk-libs ()
+  (handler-bind ((style-warning #'muffle-warning))
+    (cffi:load-foreign-library #+linux "libgobject-2.0.so" 
+			       #+win32 "libgobject-2.0-0.dll" 
+			       #+macosx "libgobject-2.0-0.dylib")
+    (cffi:load-foreign-library #+linux "libglib-2.0.so" 
+			       #+win32 "libglib-2.0-0.dll" 
+			       #+macosx "libglib-2.0-0.dylib")
+    (cffi:load-foreign-library #+linux "libgthread-2.0.so" 
+			       #+win32 "libgthread-2.0-0.dll" 
+			       #+macosx "libgthread-2.0-0.dylib")
+    (cffi:load-foreign-library #+linux "libgdk-x11-2.0.so" 
+			       #+win32 "libgdk-win32-2.0-0.dll" 
+			       #+macosx "libgdk-win32-2.0-0.dylib")
+    (cffi:load-foreign-library #+linux "libgtk-x11-2.0.so" 
+			       #+win32 "libgtk-win32-2.0-0.dll" 
+			       #+macosx "libgtk-win32-2.0-0.dylib")
+    #+libcellsgtk
+    (cffi:load-foreign-library #+linux "libcellsgtk.so" 
+			       #+win32 "libcellsgtk.dll" 
+			       #+macosx "libcellsgtk.dylib")))
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
-  (export '(c-null c-null-int int-slot-indexed load-gtk-libs))
+  (export '(+c-null+ int-slot-indexed load-gtk-libs))
   (defun gtk-function-name (lisp-name)
     (substitute #\_ #\- lisp-name))
-  (defun libname (lib)
-    (ecase lib
-      (:gobject #+win32 "libgobject-2.0-0.dll"
-		#-win32 "libgobject-2.0.so")
-      (:glib #+win32 "libglib-2.0-0.dll")
-      (:gthread #+win32 "libgthread-2.0-0.dll")
-      (:gdk #+win32 "libgdk-win32-2.0-0.dll")
-      (:gtk #+win32 "libgtk-win32-2.0-0.dll")
-      #+libcellsgtk (:cgtk  "libcellsgtk.dll")))
-  (defun load-gtk-libs ()
-    (macrolet ((loadit (libname module) 
-		       `(handler-bind ((style-warning #'muffle-warning))
-			  (uffi:load-foreign-library 		 
-			   (concatenate 'string cl-user::*gtk-lib-path* ,libname)
-			   :force-load #+lispworks t #-lispworks nil
-			   :module ,(string module)))))
-      #+(or win32 mswindows)
-      (progn 
-	(loadit "libgobject-2.0-0.dll" :gobject)
-	(loadit "libglib-2.0-0.dll" :glib)
- 	(loadit "libgthread-2.0-0.dll" :gthread)
-	(loadit "libgdk-win32-2.0-0.dll" :gdk)
-	(loadit "libgtk-win32-2.0-0.dll" :gtk)
-	#+libcellsgtk(loadit "libcellsgtk.dll" :cgtk))
-      #+macosx
-      (progn
-	(loadit "libgobject-2.0-0.dynlib" :gobject)
-	(loadit "libglib-2.0-0.dynlib" :glib)
-	(loadit "libgthread-2.0-0.dynlib" :gthread)
-	(loadit "libgdk-win32-2.0-0.dynlib" :gdk)
-	(loadit "libgtk-win32-2.0-0.dynlib" :gtk)
-	#+libcellsgtk(loadit "libcellsgtk.dynlib" :cgtk))
-      #-(or macosx win32 mswindows)
-      (progn 
-	(loadit "libgobject-2.0.so" :gobject)
-	(loadit "libglib-2.0.so" :glib)
-	(loadit "libgthread-2.0.so" :gthread)
-	(loadit "libgdk-x11-2.0.so" :gdk)
-	(loadit "libgtk-x11-2.0.so" :gtk)
-	#+libcellsgtk(loadit "libcellsgtk.so" :cgtk))))
-  #+cmu(load-gtk-libs)
-  #+clisp(load-gtk-libs)
+
+  #+(or cmu clisp)(load-gtk-libs)
+
   (defun ffi-to-uffi-type (clisp-type)
     
     (if (consp clisp-type)
@@ -110,85 +166,41 @@
 		(single-float :float)
 		(double-float :double)
 		(otherwise clisp-type))))
+) ;eval
 
-  (defun ffi-to-native-type (ffi-type)
-    (uffi::convert-from-uffi-type
-     (ffi-to-uffi-type ffi-type) :type))) ;; END eval-when
-
-(defmacro def-gtk-function (library name &key arguments return-type 
-                             (return-type-allocation :none)
-                             (call-direct t))
-  (declare (ignore return-type-allocation call-direct))
-  
+(defmacro def-gtk-function (library name return-type arguments)
+  (declare (ignore library))
   (let* ((gtk-name$ (gtk-function-name (string-downcase (symbol-name name))))
          (gtk-name (intern (string-upcase gtk-name$))))
-    (let ((arg-info
-           (loop for arg in arguments
-               for gsym = (gensym)
-               if (eql 'c-string (cadr arg))
-               collect (car arg) into arg$s
-               and collect gsym into gsyms
-               and collect gsym into pass-args
-               else if (eql 'boolean (cadr arg))
-               collect `(if ,(car arg) 1 0) into pass-args
-               else if (eql 'c-pointer (cadr arg))
-               collect `(or ,(car arg) c-null) into pass-args
-               else collect (car arg) into pass-args
-               finally (return (list (mapcar 'list gsyms arg$s)
-                                 pass-args)))))
-      `(progn
-	  (uffi:def-function (,gtk-name$ ,gtk-name)
-	     ,(mapcar (lambda (name-type)
-			(destructuring-bind (name type) name-type
-			  (list name (ffi-to-uffi-type type))))
-		      arguments)
-	     :module ,(string library)
-	     :returning ,(ffi-to-uffi-type return-type))
-         (defun ,name ,(mapcar 'car arguments)
-           (when *gtk-debug*
-             ,(unless (or (string= (symbol-name name) "GTK-EVENTS-PENDING")
-                          (string= (symbol-name name) "GTK-MAIN-ITERATION-DO"))
-                `(print (list ,(symbol-name name) :before ,@(mapcar 'car arguments)))))
-           (prog1
-               ,(let ((bodyform `(with-cstrings
-                                     ,(car arg-info)
-                                   (,gtk-name ,@(cadr arg-info)))))
-                  (if (eql return-type 'boolean)
-                      `(not (zerop ,bodyform))
-		    (if (eql return-type 'c-string)
-		      `(convert-from-cstring ,bodyform)
-		      bodyform)
-		    ))
-	          
-             (when *gtk-debug*
-               ,(unless (or (string= (symbol-name name) "GTK-EVENTS-PENDING")
-                            (string= (symbol-name name) "GTK-MAIN-ITERATION-DO"))
-                  `(print (list ,(symbol-name name) :after ,@(mapcar 'car arguments)))))))
-         (eval-when (compile load eval)
-           (export ',name))))))
+    `(progn
+       (cffi:defcfun (,gtk-name$ ,gtk-name) ,return-type , at arguments)
+       (defun ,name ,(mapcar 'car arguments)
+	 (when *gtk-debug*
+	   ,(unless (or (string= (symbol-name name) "GTK-EVENTS-PENDING")
+			(string= (symbol-name name) "GTK-MAIN-ITERATION-DO"))
+	      `(format *trace-output* "~%before (~A ~{~A~^ ~})" 
+		       ,(string-downcase (string name)) (list ,@(mapcar 'car arguments)))))
+	 (prog1
+	     (,gtk-name ,@(mapcar #'car arguments))
+	   (when *gtk-debug*
+	     ,(unless (or (string= (symbol-name name) "GTK-EVENTS-PENDING")
+			  (string= (symbol-name name) "GTK-MAIN-ITERATION-DO"))
+	      `(format *trace-output* "~%after (~A ~{~A~^ ~})" 
+		       ,(string-downcase (string name)) (list ,@(mapcar 'car arguments)))))))
+       (eval-when (:compile-toplevel :load-toplevel :execute)
+	 (export ',name)))))
 
 (defmacro def-gtk-lib-functions (library &rest functions)
   `(progn
      ,@(loop for function in functions collect
-             (destructuring-bind (name (&rest args)
-                                   &optional return-type
-                                   return-type-allocation
-                                   (call-direct t)) function
-               `(def-gtk-function ,library ,name
-                  ,@(when args `(:arguments ,args))
-                  :return-type ,return-type
-                  ,@(when return-type-allocation
-                      `(:return-type-allocation ,return-type-allocation))
-                  :call-direct ,call-direct)))))
-
+             (destructuring-bind (name return-type (&rest args)) function
+               `(def-gtk-function ,library ,name ,return-type ,args)))))
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (defmacro callback-function ((&rest arguments) &optional return-type)
     (declare (ignore arguments return-type))
         `'c-pointer))
 
-
-
 (defmacro def-c-struct (struct-name &rest fields)
   (let ((slot-defs (loop for field in fields
                          collecting (destructuring-bind (name type) field
@@ -313,7 +325,6 @@
     (32 :window_state)
     (33 :setting)))
 
-
 (uffi:def-struct list-boolean
     (value :unsigned-int)
   (end :pointer-void))
@@ -363,12 +374,11 @@
 (defmacro with-tree-iter ((iter-var) &body body)
   `(uffi:with-foreign-object (,iter-var 'gtk-tree-iter)
      (setf (get-slot-value ,iter-var 'gtk-tree-iter 'stamp) 0)
-     (setf (get-slot-value ,iter-var 'gtk-tree-iter 'user-data) c-null)
-     (setf (get-slot-value ,iter-var 'gtk-tree-iter 'user-data2) c-null)
-     (setf (get-slot-value ,iter-var 'gtk-tree-iter 'user-data3) c-null)
+     (setf (get-slot-value ,iter-var 'gtk-tree-iter 'user-data) +c-null+)
+     (setf (get-slot-value ,iter-var 'gtk-tree-iter 'user-data2) +c-null+)
+     (setf (get-slot-value ,iter-var 'gtk-tree-iter 'user-data3) +c-null+)
      , at body))
 
-
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (defun as-gtk-type-name (type)
     (ecase type




More information about the Cells-gtk-cvs mailing list